Skip to content

Commit 76773ab

Browse files
committed
fix: type arguments passed to registerSingleton and registerTransient should themselves be allowed to receive type arguments, and these should not count towards the service/implementation name
1 parent f8c388b commit 76773ab

11 files changed

+280
-129
lines changed

LICENSE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright © 2020 [Frederik Wessberg](mailto:frederikwessberg@hotmail.com) ([@FredWessberg](https://twitter.com/FredWessberg)) ([Website](https://github.com/wessberg))
3+
Copyright © 2021 [Frederik Wessberg](mailto:frederikwessberg@hotmail.com) ([@FredWessberg](https://twitter.com/FredWessberg)) ([Website](https://github.com/wessberg))
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+19-19
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ This has been implemented as a TypeScript Custom Transformer in order to be so l
4646

4747
<!-- SHADOW_SECTION_FEATURE_IMAGE_END -->
4848

49+
<!-- SHADOW_SECTION_BACKERS_START -->
50+
51+
## Backers
52+
53+
| <a href="https://usebubbles.com"><img alt="Bubbles" src="https://uploads-ssl.webflow.com/5d682047c28b217055606673/5e5360be16879c1d0dca6514_icon-thin-128x128%402x.png" height="70" /></a> | <a href="https://github.com/cblanc"><img alt="Christopher Blanchard" src="https://avatars0.githubusercontent.com/u/2160685?s=400&v=4" height="70" /></a> | <a href="https://github.com/ideal-postcodes"><img alt="Ideal Postcodes" src="https://avatars.githubusercontent.com/u/4996310?s=200&v=4" height="70" /></a> | <a href="https://www.xerox.com"><img alt="Xerox" src="https://avatars.githubusercontent.com/u/9158512?s=200&v=4" height="70" /></a> |
54+
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
55+
| [Bubbles](https://usebubbles.com)<br><strong>Twitter</strong>: [@usebubbles](https://twitter.com/usebubbles) | [Christopher Blanchard](https://github.com/cblanc) | [Ideal Postcodes](https://github.com/ideal-postcodes) | [Xerox](https://www.xerox.com) |
56+
57+
### Patreon
58+
59+
<a href="https://www.patreon.com/bePatron?u=11315442"><img alt="Patrons on Patreon" src="https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dwessberg%26type%3Dpatrons" width="200" /></a>
60+
61+
<!-- SHADOW_SECTION_BACKERS_END -->
62+
4963
<!-- SHADOW_SECTION_TOC_START -->
5064

5165
## Table of Contents
@@ -70,12 +84,12 @@ This has been implemented as a TypeScript Custom Transformer in order to be so l
7084
- [Usage with ava](#usage-with-ava)
7185
- [Options](#options)
7286
- [Contributing](#contributing)
73-
- [Maintainers](#maintainers)
74-
- [Backers](#backers)
75-
- [Patreon](#patreon)
7687
- [FAQ](#faq)
7788
- [How does it work, exactly?](#how-does-it-work-exactly)
7889
- [License](#license)
90+
- [Backers](#backers)
91+
- [Patreon](#patreon)
92+
- [Maintainers](#maintainers)
7993

8094
<!-- SHADOW_SECTION_TOC_END -->
8195

@@ -103,7 +117,7 @@ $ pnpm add @wessberg/di-compiler
103117

104118
### Peer Dependencies
105119

106-
`@wessberg/di-compiler` depends on `typescript`, so you need to manually install these as well.
120+
`@wessberg/di-compiler` depends on `typescript`, so you need to manually install this as well.
107121

108122
<!-- SHADOW_SECTION_INSTALL_END -->
109123

@@ -321,20 +335,6 @@ Do you want to contribute? Awesome! Please follow [these recommendations](./CONT
321335

322336
<!-- SHADOW_SECTION_MAINTAINERS_END -->
323337

324-
<!-- SHADOW_SECTION_BACKERS_START -->
325-
326-
## Backers
327-
328-
| <a href="https://usebubbles.com"><img alt="Bubbles" src="https://uploads-ssl.webflow.com/5d682047c28b217055606673/5e5360be16879c1d0dca6514_icon-thin-128x128%402x.png" height="70" /></a> |
329-
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
330-
| [Bubbles](https://usebubbles.com)<br><strong>Twitter</strong>: [@use_bubbles](https://twitter.com/use_bubbles) |
331-
332-
### Patreon
333-
334-
<a href="https://www.patreon.com/bePatron?u=11315442"><img alt="Patrons on Patreon" src="https://img.shields.io/endpoint.svg?url=https://shieldsio-patreon.herokuapp.com/wessberg" width="200" /></a>
335-
336-
<!-- SHADOW_SECTION_BACKERS_END -->
337-
338338
<!-- SHADOW_SECTION_FAQ_START -->
339339

340340
## FAQ
@@ -361,7 +361,7 @@ Will be compiled into:
361361
```javascript
362362
// ...
363363
container.registerSingleton(undefined, {
364-
identifier: "MyInterface",
364+
identifier: `MyInterface`,
365365
implementation: MyImplementation,
366366
});
367367
```

pnpm-lock.yaml

-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/transformer/before/util.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { TS } from "../../type/type";
2+
import { VisitorContext } from "../visitor-context";
3+
4+
/**
5+
* A TypeNode such as IFoo<string> should still yield the service name "IFoo".
6+
* This helper generates a proper service name from a TypeNode
7+
*/
8+
export function pickServiceOrImplementationName(
9+
node: TS.Expression | TS.TypeNode | TS.EntityName,
10+
context: VisitorContext
11+
): string {
12+
const { typescript } = context;
13+
14+
if (typescript.isTypeReferenceNode(node)) {
15+
return pickServiceOrImplementationName(node.typeName, context);
16+
} else if (typescript.isIndexedAccessTypeNode(node)) {
17+
return `${pickServiceOrImplementationName(
18+
node.objectType,
19+
context
20+
)}[${pickServiceOrImplementationName(node.indexType, context)}]`;
21+
} else {
22+
return node.getFullText().trim();
23+
}
24+
}

src/transformer/before/visitor/visit-call-expression.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
moduleKindSupportsImportHelpers,
1212
updateCallExpression,
1313
} from "../../../util/ts-util";
14+
import { pickServiceOrImplementationName } from "../util";
1415

1516
export function visitCallExpression(
1617
options: BeforeVisitorOptions<TS.CallExpression>
@@ -58,7 +59,7 @@ export function visitCallExpression(
5859
case DiMethodKind.REGISTER_TRANSIENT: {
5960
let [typeArg, implementationArg] = (node.typeArguments ??
6061
[]) as unknown as [
61-
TS.TypeNode | TS.Expression | undefined,
62+
TS.TypeNode | undefined,
6263
TS.TypeNode | TS.Expression | undefined
6364
];
6465

@@ -76,8 +77,11 @@ export function visitCallExpression(
7677
return childContinuation(node);
7778
}
7879

79-
const typeArgText = typeArg.getFullText().trim();
80-
const implementationArgText = implementationArg.getFullText().trim();
80+
const typeArgText = pickServiceOrImplementationName(typeArg, context);
81+
const implementationArgText = pickServiceOrImplementationName(
82+
implementationArg,
83+
context
84+
);
8185

8286
// If the Implementation is a TypeNode, and if it originates from an ImportDeclaration, it may be stripped from the file since Typescript won't Type-check the updates from
8387
// a CustomTransformer and such a node would normally be removed from the imports.
@@ -190,7 +194,7 @@ export function visitCallExpression(
190194
createObjectLiteralExpression(context, [
191195
compatFactory.createPropertyAssignment(
192196
"identifier",
193-
compatFactory.createStringLiteral(typeArgText)
197+
compatFactory.createNoSubstitutionTemplateLiteral(typeArgText)
194198
),
195199
...(!typescript.isTypeNode(implementationArg)
196200
? []
@@ -342,7 +346,7 @@ function rewriteImplementationName(
342346
}
343347

344348
default:
345-
// TODO: Add support for SystemJS and UMD here
349+
// TODO: Add support for SystemJS here
346350
return name;
347351
}
348352
}

src/util/semver-util.ts

-48
This file was deleted.

test/amd.test.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ test("Preserves Type-only imports. #1", withTypeScript, (t, { typescript }) => {
4747
const Foo = require("./foo");
4848
console.log(foo_1.default);
4949
const container = new di_1.DIContainer();
50-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.default });
50+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.default });
5151
});
5252
`)
5353
);
@@ -94,7 +94,7 @@ test("Preserves type-only imports. #2", withTypeScript, (t, { typescript }) => {
9494
Object.defineProperty(exports, "__esModule", { value: true });
9595
const Foo = require("./foo");
9696
const container = new di_1.DIContainer();
97-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.default });
97+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.default });
9898
});
9999
`)
100100
);
@@ -141,7 +141,7 @@ test("Preserves type-only imports. #3", withTypeScript, (t, { typescript }) => {
141141
Object.defineProperty(exports, "__esModule", { value: true });
142142
const Foo = require("./foo");
143143
const container = new di_1.DIContainer();
144-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.Foo });
144+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.Foo });
145145
});
146146
`)
147147
);
@@ -189,7 +189,7 @@ test("Preserves type-only imports. #4", withTypeScript, (t, { typescript }) => {
189189
Object.defineProperty(exports, "__esModule", { value: true });
190190
const Foo = require("./foo");
191191
const container = new di_1.DIContainer();
192-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo });
192+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo });
193193
});
194194
`)
195195
);
@@ -236,7 +236,7 @@ test("Preserves type-only imports. #5", withTypeScript, (t, { typescript }) => {
236236
Object.defineProperty(exports, "__esModule", { value: true });
237237
const Foo = require("./foo");
238238
const container = new di_1.DIContainer();
239-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.Bar });
239+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.Bar });
240240
});
241241
`)
242242
);
@@ -283,7 +283,7 @@ test("Preserves type-only imports. #6", withTypeScript, (t, { typescript }) => {
283283
Object.defineProperty(exports, "__esModule", { value: true });
284284
const Foo = require("./foo");
285285
const container = new di_1.DIContainer();
286-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.default });
286+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.default });
287287
});
288288
`)
289289
);
@@ -333,7 +333,7 @@ test("Preserves type-only imports. #7", withTypeScript, (t, { typescript }) => {
333333
const Foo = require("./foo");
334334
console.log(foo_1.Bar);
335335
const container = new di_1.DIContainer();
336-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.Foo });
336+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.Foo });
337337
});
338338
`)
339339
);
@@ -385,7 +385,7 @@ test(
385385
Object.defineProperty(exports, "__esModule", { value: true });
386386
const Foo = require("tslib").__importDefault(require("./foo"));
387387
const container = new di_1.DIContainer();
388-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.default });
388+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.default });
389389
});
390390
`)
391391
);
@@ -438,7 +438,7 @@ test(
438438
Object.defineProperty(exports, "__esModule", { value: true });
439439
const Foo = __importDefault(require("./foo"));
440440
const container = new di_1.DIContainer();
441-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.default });
441+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.default });
442442
});
443443
`)
444444
);
@@ -494,7 +494,7 @@ test(
494494
foo_1 = __importDefault(foo_1);
495495
console.log(foo_1.default);
496496
const container = new di_1.DIContainer();
497-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo.default });
497+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo.default });
498498
});
499499
`)
500500
);
@@ -548,7 +548,7 @@ test(
548548
Object.defineProperty(exports, "__esModule", { value: true });
549549
const Foo = __importStar(require("./foo"));
550550
const container = new di_1.DIContainer();
551-
container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo });
551+
container.registerSingleton(undefined, { identifier: \`IFoo\`, implementation: Foo });
552552
});
553553
`)
554554
);

0 commit comments

Comments
 (0)