@vaadin/hilla-generator-plugin-signals 24.7.0-alpha9 → 24.7.0-beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,7 @@
1
- import type Plugin from '@vaadin/hilla-generator-core/Plugin.js';
2
- import { type SourceFile } from 'typescript';
1
+ import type Plugin from "@vaadin/hilla-generator-core/Plugin.js";
2
+ import { type SourceFile } from "typescript";
3
3
  export default class SignalProcessor {
4
- #private;
5
- constructor(service: string, methods: Map<string, string>, sourceFile: SourceFile, owner: Plugin);
6
- process(): SourceFile;
4
+ #private;
5
+ constructor(service: string, methods: Map<string, string>, sourceFile: SourceFile, owner: Plugin);
6
+ process(): SourceFile;
7
7
  }
8
- //# sourceMappingURL=SignalProcessor.d.ts.map
@@ -3,157 +3,208 @@ import createFullyUniqueIdentifier from "@vaadin/hilla-generator-utils/createFul
3
3
  import createSourceFile from "@vaadin/hilla-generator-utils/createSourceFile.js";
4
4
  import DependencyManager from "@vaadin/hilla-generator-utils/dependencies/DependencyManager.js";
5
5
  import PathManager from "@vaadin/hilla-generator-utils/dependencies/PathManager.js";
6
- import ts, {} from "typescript";
6
+ import ts from "typescript";
7
7
  const HILLA_REACT_SIGNALS = "@vaadin/hilla-react-signals";
8
8
  const CONNECT_CLIENT = "$CONNECT_CLIENT$";
9
9
  const METHOD_NAME = "$METHOD_NAME$";
10
10
  const SIGNAL = "$SIGNAL$";
11
11
  const RETURN_TYPE = "$RETURN_TYPE$";
12
12
  const INITIAL_VALUE = "$INITIAL_VALUE$";
13
- const signals = ["NumberSignal", "ValueSignal", "ListSignal"];
13
+ const signals = [
14
+ "NumberSignal",
15
+ "ValueSignal",
16
+ "ListSignal"
17
+ ];
14
18
  const genericSignals = ["ValueSignal", "ListSignal"];
15
19
  const collectionSignals = ["ListSignal"];
16
- class SignalProcessor {
17
- #dependencyManager;
18
- #owner;
19
- #service;
20
- #methods;
21
- #sourceFile;
22
- constructor(service, methods, sourceFile, owner) {
23
- this.#service = service;
24
- this.#methods = methods;
25
- this.#sourceFile = sourceFile;
26
- this.#owner = owner;
27
- this.#dependencyManager = new DependencyManager(new PathManager({ extension: ".js" }));
28
- this.#dependencyManager.imports.fromCode(this.#sourceFile);
29
- }
30
- process() {
31
- this.#owner.logger.debug(`Processing signals: ${this.#service}`);
32
- const { imports } = this.#dependencyManager;
33
- const [, connectClientId] = imports.default.iter().find(([path]) => path.includes("connect-client"));
34
- const initTypeId = imports.named.getIdentifier("@vaadin/hilla-frontend", "EndpointRequestInit");
35
- let initTypeUsageCount = 0;
36
- const functionParams = /* @__PURE__ */ new Map();
37
- const [file] = ts.transform(this.#sourceFile, [
38
- transform((tsNode) => {
39
- if (ts.isFunctionDeclaration(tsNode) && tsNode.name && this.#methods.has(tsNode.name.text)) {
40
- const signalId = this.#replaceSignalImport(tsNode);
41
- let initialValue = signalId.text.startsWith("NumberSignal") ? ts.factory.createNumericLiteral("0") : ts.factory.createIdentifier("undefined");
42
- const filteredParams = tsNode.parameters.filter(
43
- (p) => !p.type || !ts.isTypeReferenceNode(p.type) || p.type.typeName !== initTypeId
44
- );
45
- const paramNames = filteredParams.map((p) => p.name.text).join(", ");
46
- const isCollectionSignal = collectionSignals.includes(signalId.text);
47
- let genericReturnType;
48
- if (genericSignals.includes(signalId.text)) {
49
- genericReturnType = tsNode.type.typeArguments[0];
50
- if (!isCollectionSignal) {
51
- const defaultValueType = SignalProcessor.#getDefaultValueType(genericReturnType);
52
- if (defaultValueType) {
53
- const { alias, param } = SignalProcessor.#createDefaultValueParameter(defaultValueType);
54
- initialValue = alias;
55
- filteredParams.push(param);
56
- }
57
- }
58
- }
59
- const returnType = genericReturnType ?? signalId;
60
- if (filteredParams.length > 0) {
61
- functionParams.set(tsNode.name.text, filteredParams);
62
- }
63
- return template(
64
- `function ${METHOD_NAME}(): ${RETURN_TYPE} {
20
+ const primitiveModels = Object.freeze(new Map([
21
+ [ts.SyntaxKind.StringKeyword, "StringModel"],
22
+ [ts.SyntaxKind.NumberKeyword, "NumberModel"],
23
+ [ts.SyntaxKind.BooleanKeyword, "BooleanModel"],
24
+ [ts.SyntaxKind.ArrayType, "ArrayModel"]
25
+ ]));
26
+ export default class SignalProcessor {
27
+ #dependencyManager;
28
+ #owner;
29
+ #service;
30
+ #methods;
31
+ #sourceFile;
32
+ constructor(service, methods, sourceFile, owner) {
33
+ this.#service = service;
34
+ this.#methods = methods;
35
+ this.#sourceFile = sourceFile;
36
+ this.#owner = owner;
37
+ this.#dependencyManager = new DependencyManager(new PathManager({ extension: ".js" }));
38
+ this.#dependencyManager.imports.fromCode(this.#sourceFile);
39
+ }
40
+ process() {
41
+ this.#owner.logger.debug(`Processing signals: ${this.#service}`);
42
+ const { imports } = this.#dependencyManager;
43
+ const [, connectClientId] = imports.default.iter().find(([path]) => path.includes("connect-client"));
44
+ const initTypeId = imports.named.getIdentifier("@vaadin/hilla-frontend", "EndpointRequestInit");
45
+ let initTypeUsageCount = 0;
46
+ const functionParams = new Map();
47
+ const [file] = ts.transform(this.#sourceFile, [
48
+ transform((tsNode) => {
49
+ if (ts.isFunctionDeclaration(tsNode) && tsNode.name && this.#methods.has(tsNode.name.text)) {
50
+ const signalId = this.#replaceSignalImport(tsNode);
51
+ const filteredParams = tsNode.parameters.filter((p) => !p.type || !ts.isTypeReferenceNode(p.type) || p.type.typeName !== initTypeId);
52
+ const paramNames = filteredParams.map((p) => p.name.text).join(", ");
53
+ const isCollectionSignal = collectionSignals.includes(signalId.text);
54
+ const { defaultValueExpression, defaultValueParam, genericReturnType } = this.#createDefaultValue(signalId, tsNode);
55
+ if (defaultValueParam) {
56
+ filteredParams.push(defaultValueParam);
57
+ }
58
+ const returnType = genericReturnType ?? signalId;
59
+ if (filteredParams.length > 0) {
60
+ functionParams.set(tsNode.name.text, filteredParams);
61
+ }
62
+ return template(`function ${METHOD_NAME}(): ${RETURN_TYPE} {
65
63
  return new ${SIGNAL}(${isCollectionSignal ? "" : `${INITIAL_VALUE}, `}{ client: ${CONNECT_CLIENT}, endpoint: '${this.#service}', method: '${tsNode.name.text}'${paramNames.length ? `, params: { ${paramNames} }` : ""} });
66
- }`,
67
- (statements) => statements,
68
- [
69
- transform((node) => ts.isIdentifier(node) && node.text === METHOD_NAME ? tsNode.name : node),
70
- transform((node) => ts.isIdentifier(node) && node.text === SIGNAL ? signalId : node),
71
- transform((node) => ts.isIdentifier(node) && node.text === RETURN_TYPE ? returnType : node),
72
- transform((node) => ts.isIdentifier(node) && node.text === CONNECT_CLIENT ? connectClientId : node),
73
- transform((node) => ts.isIdentifier(node) && node.text === INITIAL_VALUE ? initialValue : node)
74
- ]
75
- );
76
- }
77
- return tsNode;
78
- }),
79
- transform((tsNode) => {
80
- if (ts.isFunctionDeclaration(tsNode) && tsNode.name && this.#methods.has(tsNode.name.text) && functionParams.has(tsNode.name.text)) {
81
- return ts.factory.updateFunctionDeclaration(
82
- tsNode,
83
- tsNode.modifiers,
84
- tsNode.asteriskToken,
85
- tsNode.name,
86
- tsNode.typeParameters,
87
- functionParams.get(tsNode.name.text),
88
- tsNode.type,
89
- tsNode.body
90
- );
91
- }
92
- return tsNode;
93
- }),
94
- transform((tsNode) => {
95
- if (ts.isFunctionDeclaration(tsNode)) {
96
- if (!(tsNode.name && this.#methods.has(tsNode.name.text)) && tsNode.parameters.some((p) => p.type && ts.isTypeReferenceNode(p.type) && p.type.typeName === initTypeId)) {
97
- initTypeUsageCount += 1;
98
- }
99
- }
100
- return tsNode;
101
- })
102
- ]).transformed;
103
- if (initTypeUsageCount === 0) {
104
- imports.named.remove("@vaadin/hilla-frontend", "EndpointRequestInit");
105
- }
106
- return createSourceFile(
107
- [
108
- ...this.#dependencyManager.imports.toCode(),
109
- ...file.statements.filter((statement) => !ts.isImportDeclaration(statement))
110
- ],
111
- file.fileName
112
- );
113
- }
114
- static #getDefaultValueType(node) {
115
- if (ts.isUnionTypeNode(node) && node.types.length && ts.isTypeReferenceNode(node.types[0]) && node.types[0].typeArguments?.length === 1 && ts.isUnionTypeNode(node.types[0].typeArguments[0])) {
116
- return node.types[0].typeArguments[0];
117
- }
118
- return void 0;
119
- }
120
- static #createDefaultValueParameter(returnType) {
121
- const alias = createFullyUniqueIdentifier("defaultValue");
122
- const bindingPattern = ts.factory.createObjectBindingPattern([
123
- ts.factory.createBindingElement(void 0, ts.factory.createIdentifier("defaultValue"), alias, void 0)
124
- ]);
125
- const paramType = ts.factory.createTypeLiteralNode([
126
- ts.factory.createPropertySignature(void 0, ts.factory.createIdentifier("defaultValue"), void 0, returnType)
127
- ]);
128
- return {
129
- alias,
130
- param: ts.factory.createParameterDeclaration(void 0, void 0, bindingPattern, void 0, paramType)
131
- };
132
- }
133
- #replaceSignalImport(method) {
134
- const { imports } = this.#dependencyManager;
135
- if (method.type) {
136
- const type = traverse(
137
- method.type,
138
- (node) => ts.isIdentifier(node) && signals.includes(node.text) ? node : void 0
139
- );
140
- if (type) {
141
- const signalId = imports.named.getIdentifier(HILLA_REACT_SIGNALS, type.text);
142
- if (signalId) {
143
- return signalId;
144
- }
145
- const result = imports.default.iter().find(([_p, id]) => id.text === type.text);
146
- if (result) {
147
- const [path] = result;
148
- imports.default.remove(path);
149
- return imports.named.add(HILLA_REACT_SIGNALS, type.text, false, type);
150
- }
151
- }
152
- }
153
- throw new Error("Signal type not found");
154
- }
64
+ }`, (statements) => statements, [
65
+ transform((node) => ts.isIdentifier(node) && node.text === METHOD_NAME ? tsNode.name : node),
66
+ transform((node) => ts.isIdentifier(node) && node.text === SIGNAL ? signalId : node),
67
+ transform((node) => ts.isIdentifier(node) && node.text === RETURN_TYPE ? returnType : node),
68
+ transform((node) => ts.isIdentifier(node) && node.text === CONNECT_CLIENT ? connectClientId : node),
69
+ transform((node) => ts.isIdentifier(node) && node.text === INITIAL_VALUE ? defaultValueExpression : node)
70
+ ]);
71
+ }
72
+ return tsNode;
73
+ }),
74
+ transform((tsNode) => {
75
+ if (ts.isFunctionDeclaration(tsNode) && tsNode.name && this.#methods.has(tsNode.name.text) && functionParams.has(tsNode.name.text)) {
76
+ return ts.factory.updateFunctionDeclaration(tsNode, tsNode.modifiers, tsNode.asteriskToken, tsNode.name, tsNode.typeParameters, functionParams.get(tsNode.name.text), tsNode.type, tsNode.body);
77
+ }
78
+ return tsNode;
79
+ }),
80
+ transform((tsNode) => {
81
+ if (ts.isFunctionDeclaration(tsNode)) {
82
+ if (!(tsNode.name && this.#methods.has(tsNode.name.text)) && tsNode.parameters.some((p) => p.type && ts.isTypeReferenceNode(p.type) && p.type.typeName === initTypeId)) {
83
+ initTypeUsageCount += 1;
84
+ }
85
+ }
86
+ return tsNode;
87
+ })
88
+ ]).transformed;
89
+ if (initTypeUsageCount === 0) {
90
+ imports.named.remove("@vaadin/hilla-frontend", "EndpointRequestInit");
91
+ }
92
+ return createSourceFile([...this.#dependencyManager.imports.toCode(), ...file.statements.filter((statement) => !ts.isImportDeclaration(statement))], file.fileName);
93
+ }
94
+ #createDefaultValue(signalId, functionDeclaration) {
95
+ const defaultValue = {
96
+ defaultValueExpression: signalId.text.startsWith("NumberSignal") ? ts.factory.createNumericLiteral("0") : ts.factory.createIdentifier("undefined"),
97
+ defaultValueParam: undefined,
98
+ genericReturnType: undefined
99
+ };
100
+ if (!genericSignals.includes(signalId.text)) {
101
+ return defaultValue;
102
+ }
103
+ [defaultValue.genericReturnType] = functionDeclaration.type.typeArguments;
104
+ if (collectionSignals.includes(signalId.text)) {
105
+ return defaultValue;
106
+ }
107
+ const defaultValueType = SignalProcessor.#getDefaultValueType(defaultValue.genericReturnType);
108
+ if (!defaultValueType) {
109
+ return defaultValue;
110
+ }
111
+ defaultValue.defaultValueParam = SignalProcessor.#createDefaultValueParameter(defaultValueType);
112
+ const emptyValueExpression = this.#createEmptyValueExpression(defaultValueType);
113
+ defaultValue.defaultValueExpression = ts.factory.createBinaryExpression(ts.factory.createPropertyAccessChain(ts.factory.createIdentifier("options"), ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), ts.factory.createIdentifier("defaultValue")), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), emptyValueExpression);
114
+ return defaultValue;
115
+ }
116
+ static #getDefaultValueType(node) {
117
+ if (ts.isUnionTypeNode(node) && node.types.length && ts.isTypeReferenceNode(node.types[0]) && node.types[0].typeArguments?.length === 1 && ts.isUnionTypeNode(node.types[0].typeArguments[0])) {
118
+ return node.types[0].typeArguments[0];
119
+ }
120
+ return undefined;
121
+ }
122
+ static #createDefaultValueParameter(defaultValueType) {
123
+ const paramType = ts.factory.createTypeLiteralNode([ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier("defaultValue"), undefined, defaultValueType)]);
124
+ return ts.factory.createParameterDeclaration(undefined, undefined, "options", ts.factory.createToken(ts.SyntaxKind.QuestionToken), paramType);
125
+ }
126
+ static #isDefaultValueTypeNullable(defaultValueType) {
127
+ return ts.isUnionTypeNode(defaultValueType) && defaultValueType.types.length && defaultValueType.types.length > 1 && defaultValueType.types.map((t) => t.kind).includes(ts.SyntaxKind.UndefinedKeyword);
128
+ }
129
+ #createEmptyValueExpression(defaultValueType) {
130
+ if (SignalProcessor.#isDefaultValueTypeNullable(defaultValueType)) {
131
+ return ts.factory.createIdentifier("undefined");
132
+ }
133
+ const importedModelUniqueId = this.#determineModelImportUniqueIdentifier(defaultValueType);
134
+ return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(importedModelUniqueId, "createEmptyValue"), undefined, []);
135
+ }
136
+ #determineModelImportUniqueIdentifier(returnTypeNode) {
137
+ let modelName = primitiveModels.get(returnTypeNode.types[0].kind);
138
+ let entityName;
139
+ if (modelName === undefined) {
140
+ const { entityName: e, modelName: m } = SignalProcessor.#extractModelNameFromTypeNode(returnTypeNode);
141
+ modelName = m;
142
+ entityName = e;
143
+ }
144
+ const modelImportUniqueId = this.#getExistingEntityModelUniqueIdentifier(modelName) ?? createFullyUniqueIdentifier(modelName);
145
+ this.#addModelImport(entityName, modelName, modelImportUniqueId);
146
+ return modelImportUniqueId;
147
+ }
148
+ static #extractModelNameFromTypeNode(returnTypeNode) {
149
+ if (ts.isTypeReferenceNode(returnTypeNode.types[0])) {
150
+ const typeIdentifier = returnTypeNode.types[0].typeName;
151
+ if (ts.isIdentifier(typeIdentifier)) {
152
+ const entityName = typeIdentifier.text;
153
+ const modelName = `${entityName}Model`;
154
+ return {
155
+ entityName,
156
+ modelName
157
+ };
158
+ }
159
+ }
160
+ throw new Error("Unsupported type reference node");
161
+ }
162
+ #getExistingEntityModelUniqueIdentifier(modelName) {
163
+ const { imports } = this.#dependencyManager;
164
+ return imports.named.getIdentifier("@vaadin/hilla-lit-form", modelName) ?? imports.default.iter().find(([path]) => path.endsWith(`/${modelName}.js`))?.[1];
165
+ }
166
+ #addModelImport(entityName, modelName, modelNameUniqueId) {
167
+ if (modelName) {
168
+ if (primitiveModels.values().find((primitiveModel) => primitiveModel === modelName)) {
169
+ const { imports } = this.#dependencyManager;
170
+ const importedModel = imports.named.getIdentifier("@vaadin/hilla-lit-form", modelName);
171
+ if (importedModel === undefined) {
172
+ imports.named.add("@vaadin/hilla-lit-form", modelName, false, modelNameUniqueId);
173
+ }
174
+ } else {
175
+ this.#addObjectModelImport(entityName, modelName, modelNameUniqueId);
176
+ }
177
+ }
178
+ }
179
+ #addObjectModelImport(entityName, modelName, modelNameUniqueId) {
180
+ const { imports } = this.#dependencyManager;
181
+ const entityImport = imports.default.iter().map(([path]) => path).find((path) => path.startsWith("./") && path.endsWith(`/${entityName}.js`));
182
+ if (entityImport) {
183
+ const entityModelImportPath = entityImport.replace(`/${entityName}.js`, `/${modelName}.js`);
184
+ const importedModel = imports.default.paths().find((path) => path === entityModelImportPath);
185
+ if (importedModel === undefined) {
186
+ imports.default.add(entityModelImportPath, modelName, false, modelNameUniqueId);
187
+ }
188
+ }
189
+ }
190
+ #replaceSignalImport(method) {
191
+ const { imports } = this.#dependencyManager;
192
+ if (method.type) {
193
+ const type = traverse(method.type, (node) => ts.isIdentifier(node) && signals.includes(node.text) ? node : undefined);
194
+ if (type) {
195
+ const signalId = imports.named.getIdentifier(HILLA_REACT_SIGNALS, type.text);
196
+ if (signalId) {
197
+ return signalId;
198
+ }
199
+ const result = imports.default.iter().find(([_p, id]) => id.text === type.text);
200
+ if (result) {
201
+ const [path] = result;
202
+ imports.default.remove(path);
203
+ return imports.named.add(HILLA_REACT_SIGNALS, type.text, false, type);
204
+ }
205
+ }
206
+ }
207
+ throw new Error("Signal type not found");
208
+ }
155
209
  }
156
- export {
157
- SignalProcessor as default
158
- };
159
- //# sourceMappingURL=SignalProcessor.js.map
210
+ //# sourceMappingURL=./SignalProcessor.js.map
@@ -1,7 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["src/SignalProcessor.ts"],
4
- "sourcesContent": ["import type Plugin from '@vaadin/hilla-generator-core/Plugin.js';\nimport { template, transform, traverse } from '@vaadin/hilla-generator-utils/ast.js';\nimport createFullyUniqueIdentifier from '@vaadin/hilla-generator-utils/createFullyUniqueIdentifier.js';\nimport createSourceFile from '@vaadin/hilla-generator-utils/createSourceFile.js';\nimport DependencyManager from '@vaadin/hilla-generator-utils/dependencies/DependencyManager.js';\nimport PathManager from '@vaadin/hilla-generator-utils/dependencies/PathManager.js';\nimport ts, { type FunctionDeclaration, type Identifier, type SourceFile } from 'typescript';\n\nconst HILLA_REACT_SIGNALS = '@vaadin/hilla-react-signals';\n\nconst CONNECT_CLIENT = '$CONNECT_CLIENT$';\nconst METHOD_NAME = '$METHOD_NAME$';\nconst SIGNAL = '$SIGNAL$';\nconst RETURN_TYPE = '$RETURN_TYPE$';\nconst INITIAL_VALUE = '$INITIAL_VALUE$';\n\nconst signals = ['NumberSignal', 'ValueSignal', 'ListSignal'];\nconst genericSignals = ['ValueSignal', 'ListSignal'];\nconst collectionSignals = ['ListSignal'];\n\nexport default class SignalProcessor {\n readonly #dependencyManager: DependencyManager;\n readonly #owner: Plugin;\n readonly #service: string;\n readonly #methods: Map<string, string>;\n readonly #sourceFile: SourceFile;\n\n constructor(service: string, methods: Map<string, string>, sourceFile: SourceFile, owner: Plugin) {\n this.#service = service;\n this.#methods = methods;\n this.#sourceFile = sourceFile;\n this.#owner = owner;\n this.#dependencyManager = new DependencyManager(new PathManager({ extension: '.js' }));\n this.#dependencyManager.imports.fromCode(this.#sourceFile);\n }\n\n process(): SourceFile {\n this.#owner.logger.debug(`Processing signals: ${this.#service}`);\n const { imports } = this.#dependencyManager;\n\n const [, connectClientId] = imports.default.iter().find(([path]) => path.includes('connect-client'))!;\n\n const initTypeId = imports.named.getIdentifier('@vaadin/hilla-frontend', 'EndpointRequestInit');\n let initTypeUsageCount = 0;\n const functionParams: Map<string, ts.ParameterDeclaration[]> = new Map<string, ts.ParameterDeclaration[]>();\n\n const [file] = ts.transform<SourceFile>(this.#sourceFile, [\n transform((tsNode) => {\n if (ts.isFunctionDeclaration(tsNode) && tsNode.name && this.#methods.has(tsNode.name.text)) {\n const signalId = this.#replaceSignalImport(tsNode);\n let initialValue: ts.Expression = signalId.text.startsWith('NumberSignal')\n ? ts.factory.createNumericLiteral('0')\n : ts.factory.createIdentifier('undefined');\n const filteredParams = tsNode.parameters.filter(\n (p) => !p.type || !ts.isTypeReferenceNode(p.type) || p.type.typeName !== initTypeId,\n );\n // `filteredParams` can be altered after, need to store the param names now\n const paramNames = filteredParams.map((p) => (p.name as ts.Identifier).text).join(', ');\n const isCollectionSignal = collectionSignals.includes(signalId.text);\n let genericReturnType;\n if (genericSignals.includes(signalId.text)) {\n genericReturnType = (tsNode.type as ts.TypeReferenceNode).typeArguments![0];\n if (!isCollectionSignal) {\n const defaultValueType = SignalProcessor.#getDefaultValueType(genericReturnType);\n if (defaultValueType) {\n const { alias, param } = SignalProcessor.#createDefaultValueParameter(defaultValueType);\n initialValue = alias;\n filteredParams.push(param);\n }\n }\n }\n const returnType = genericReturnType ?? signalId;\n if (filteredParams.length > 0) {\n functionParams.set(tsNode.name.text, filteredParams);\n }\n return template(\n `function ${METHOD_NAME}(): ${RETURN_TYPE} {\n return new ${SIGNAL}(${isCollectionSignal ? '' : `${INITIAL_VALUE}, `}{ client: ${CONNECT_CLIENT}, endpoint: '${this.#service}', method: '${tsNode.name.text}'${paramNames.length ? `, params: { ${paramNames} }` : ''} });\n}`,\n (statements) => statements,\n [\n transform((node) => (ts.isIdentifier(node) && node.text === METHOD_NAME ? tsNode.name : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === SIGNAL ? signalId : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === RETURN_TYPE ? returnType : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === CONNECT_CLIENT ? connectClientId : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === INITIAL_VALUE ? initialValue : node)),\n ],\n );\n }\n return tsNode;\n }),\n transform((tsNode) => {\n if (\n ts.isFunctionDeclaration(tsNode) &&\n tsNode.name &&\n this.#methods.has(tsNode.name.text) &&\n functionParams.has(tsNode.name.text)\n ) {\n return ts.factory.updateFunctionDeclaration(\n tsNode,\n tsNode.modifiers,\n tsNode.asteriskToken,\n tsNode.name,\n tsNode.typeParameters,\n functionParams.get(tsNode.name.text)!,\n tsNode.type,\n tsNode.body,\n );\n }\n return tsNode;\n }),\n transform((tsNode) => {\n if (ts.isFunctionDeclaration(tsNode)) {\n if (\n !(tsNode.name && this.#methods.has(tsNode.name.text)) &&\n tsNode.parameters.some((p) => p.type && ts.isTypeReferenceNode(p.type) && p.type.typeName === initTypeId)\n ) {\n initTypeUsageCount += 1;\n }\n }\n return tsNode;\n }),\n ]).transformed;\n\n if (initTypeUsageCount === 0) {\n imports.named.remove('@vaadin/hilla-frontend', 'EndpointRequestInit');\n }\n\n return createSourceFile(\n [\n ...this.#dependencyManager.imports.toCode(),\n ...file.statements.filter((statement) => !ts.isImportDeclaration(statement)),\n ],\n file.fileName,\n );\n }\n\n static #getDefaultValueType(node: ts.Node) {\n if (\n ts.isUnionTypeNode(node) &&\n node.types.length &&\n ts.isTypeReferenceNode(node.types[0]) &&\n node.types[0].typeArguments?.length === 1 &&\n ts.isUnionTypeNode(node.types[0].typeArguments[0])\n ) {\n return node.types[0].typeArguments[0];\n }\n\n return undefined;\n }\n\n static #createDefaultValueParameter(returnType: ts.TypeNode) {\n const alias = createFullyUniqueIdentifier('defaultValue');\n const bindingPattern = ts.factory.createObjectBindingPattern([\n ts.factory.createBindingElement(undefined, ts.factory.createIdentifier('defaultValue'), alias, undefined),\n ]);\n const paramType = ts.factory.createTypeLiteralNode([\n ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('defaultValue'), undefined, returnType),\n ]);\n // Return both the alias and the full parameter\n return {\n alias,\n param: ts.factory.createParameterDeclaration(undefined, undefined, bindingPattern, undefined, paramType),\n };\n }\n\n #replaceSignalImport(method: FunctionDeclaration): Identifier {\n const { imports } = this.#dependencyManager;\n\n if (method.type) {\n const type = traverse(method.type, (node) =>\n ts.isIdentifier(node) && signals.includes(node.text) ? node : undefined,\n );\n\n if (type) {\n const signalId = imports.named.getIdentifier(HILLA_REACT_SIGNALS, type.text);\n\n if (signalId) {\n return signalId;\n }\n\n const result = imports.default.iter().find(([_p, id]) => id.text === type.text);\n\n if (result) {\n const [path] = result;\n imports.default.remove(path);\n return imports.named.add(HILLA_REACT_SIGNALS, type.text, false, type);\n }\n }\n }\n\n throw new Error('Signal type not found');\n }\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
1
+ {"mappings":"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","names":["#dependencyManager","#owner","#service","#methods","#sourceFile","service: string","methods: Map<string, string>","sourceFile: SourceFile","owner: Plugin","functionParams: Map<string, ts.ParameterDeclaration[]>","#replaceSignalImport","#createDefaultValue","signalId: ts.Identifier","functionDeclaration: FunctionDeclaration","defaultValue: {\n defaultValueExpression: ts.Expression | ts.Identifier;\n defaultValueParam: ts.ParameterDeclaration | undefined;\n genericReturnType: ts.TypeNode | undefined;\n }","#getDefaultValueType","#createDefaultValueParameter","#createEmptyValueExpression","node: ts.Node","defaultValueType: ts.TypeNode","#isDefaultValueTypeNullable","defaultValueType: ts.UnionTypeNode","#determineModelImportUniqueIdentifier","returnTypeNode: ts.UnionTypeNode","#extractModelNameFromTypeNode","#getExistingEntityModelUniqueIdentifier","#addModelImport","modelName: string","entityName: string | undefined","modelName: string | undefined","modelNameUniqueId: ts.Identifier | undefined","#addObjectModelImport","entityName: string","modelNameUniqueId: ts.Identifier","method: FunctionDeclaration"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/generator-plugin-signals/src/SignalProcessor.ts"],"sourcesContent":["import type Plugin from '@vaadin/hilla-generator-core/Plugin.js';\nimport { template, transform, traverse } from '@vaadin/hilla-generator-utils/ast.js';\nimport createFullyUniqueIdentifier from '@vaadin/hilla-generator-utils/createFullyUniqueIdentifier.js';\nimport createSourceFile from '@vaadin/hilla-generator-utils/createSourceFile.js';\nimport DependencyManager from '@vaadin/hilla-generator-utils/dependencies/DependencyManager.js';\nimport PathManager from '@vaadin/hilla-generator-utils/dependencies/PathManager.js';\nimport ts, { type FunctionDeclaration, type Identifier, type SourceFile } from 'typescript';\n\nconst HILLA_REACT_SIGNALS = '@vaadin/hilla-react-signals';\n\nconst CONNECT_CLIENT = '$CONNECT_CLIENT$';\nconst METHOD_NAME = '$METHOD_NAME$';\nconst SIGNAL = '$SIGNAL$';\nconst RETURN_TYPE = '$RETURN_TYPE$';\nconst INITIAL_VALUE = '$INITIAL_VALUE$';\n\nconst signals = ['NumberSignal', 'ValueSignal', 'ListSignal'];\nconst genericSignals = ['ValueSignal', 'ListSignal'];\nconst collectionSignals = ['ListSignal'];\n\nconst primitiveModels = Object.freeze(\n new Map<ts.SyntaxKind, string>([\n [ts.SyntaxKind.StringKeyword, 'StringModel'],\n [ts.SyntaxKind.NumberKeyword, 'NumberModel'],\n [ts.SyntaxKind.BooleanKeyword, 'BooleanModel'],\n [ts.SyntaxKind.ArrayType, 'ArrayModel'],\n ]),\n);\n\nexport default class SignalProcessor {\n readonly #dependencyManager: DependencyManager;\n readonly #owner: Plugin;\n readonly #service: string;\n readonly #methods: Map<string, string>;\n readonly #sourceFile: SourceFile;\n\n constructor(service: string, methods: Map<string, string>, sourceFile: SourceFile, owner: Plugin) {\n this.#service = service;\n this.#methods = methods;\n this.#sourceFile = sourceFile;\n this.#owner = owner;\n this.#dependencyManager = new DependencyManager(new PathManager({ extension: '.js' }));\n this.#dependencyManager.imports.fromCode(this.#sourceFile);\n }\n\n process(): SourceFile {\n this.#owner.logger.debug(`Processing signals: ${this.#service}`);\n const { imports } = this.#dependencyManager;\n\n const [, connectClientId] = imports.default.iter().find(([path]) => path.includes('connect-client'))!;\n\n const initTypeId = imports.named.getIdentifier('@vaadin/hilla-frontend', 'EndpointRequestInit');\n let initTypeUsageCount = 0;\n const functionParams: Map<string, ts.ParameterDeclaration[]> = new Map<string, ts.ParameterDeclaration[]>();\n\n const [file] = ts.transform<SourceFile>(this.#sourceFile, [\n transform((tsNode) => {\n if (ts.isFunctionDeclaration(tsNode) && tsNode.name && this.#methods.has(tsNode.name.text)) {\n const signalId = this.#replaceSignalImport(tsNode);\n const filteredParams = tsNode.parameters.filter(\n (p) => !p.type || !ts.isTypeReferenceNode(p.type) || p.type.typeName !== initTypeId,\n );\n // `filteredParams` can be altered after, need to store the param names now\n const paramNames = filteredParams.map((p) => (p.name as ts.Identifier).text).join(', ');\n const isCollectionSignal = collectionSignals.includes(signalId.text);\n\n const { defaultValueExpression, defaultValueParam, genericReturnType } = this.#createDefaultValue(\n signalId,\n tsNode,\n );\n if (defaultValueParam) {\n filteredParams.push(defaultValueParam);\n }\n\n const returnType = genericReturnType ?? signalId;\n if (filteredParams.length > 0) {\n functionParams.set(tsNode.name.text, filteredParams);\n }\n return template(\n `function ${METHOD_NAME}(): ${RETURN_TYPE} {\n return new ${SIGNAL}(${\n isCollectionSignal ? '' : `${INITIAL_VALUE}, `\n }{ client: ${CONNECT_CLIENT}, endpoint: '${this.#service}', method: '${tsNode.name.text}'${\n paramNames.length ? `, params: { ${paramNames} }` : ''\n } });\n}`,\n (statements) => statements,\n [\n transform((node) => (ts.isIdentifier(node) && node.text === METHOD_NAME ? tsNode.name : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === SIGNAL ? signalId : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === RETURN_TYPE ? returnType : node)),\n transform((node) => (ts.isIdentifier(node) && node.text === CONNECT_CLIENT ? connectClientId : node)),\n transform((node) =>\n ts.isIdentifier(node) && node.text === INITIAL_VALUE ? defaultValueExpression : node,\n ),\n ],\n );\n }\n return tsNode;\n }),\n transform((tsNode) => {\n if (\n ts.isFunctionDeclaration(tsNode) &&\n tsNode.name &&\n this.#methods.has(tsNode.name.text) &&\n functionParams.has(tsNode.name.text)\n ) {\n return ts.factory.updateFunctionDeclaration(\n tsNode,\n tsNode.modifiers,\n tsNode.asteriskToken,\n tsNode.name,\n tsNode.typeParameters,\n functionParams.get(tsNode.name.text)!,\n tsNode.type,\n tsNode.body,\n );\n }\n return tsNode;\n }),\n transform((tsNode) => {\n if (ts.isFunctionDeclaration(tsNode)) {\n if (\n !(tsNode.name && this.#methods.has(tsNode.name.text)) &&\n tsNode.parameters.some((p) => p.type && ts.isTypeReferenceNode(p.type) && p.type.typeName === initTypeId)\n ) {\n initTypeUsageCount += 1;\n }\n }\n return tsNode;\n }),\n ]).transformed;\n\n if (initTypeUsageCount === 0) {\n imports.named.remove('@vaadin/hilla-frontend', 'EndpointRequestInit');\n }\n\n return createSourceFile(\n [\n ...this.#dependencyManager.imports.toCode(),\n ...file.statements.filter((statement) => !ts.isImportDeclaration(statement)),\n ],\n file.fileName,\n );\n }\n\n #createDefaultValue(signalId: ts.Identifier, functionDeclaration: FunctionDeclaration) {\n const defaultValue: {\n defaultValueExpression: ts.Expression | ts.Identifier;\n defaultValueParam: ts.ParameterDeclaration | undefined;\n genericReturnType: ts.TypeNode | undefined;\n } = {\n defaultValueExpression: signalId.text.startsWith('NumberSignal')\n ? ts.factory.createNumericLiteral('0')\n : ts.factory.createIdentifier('undefined'),\n defaultValueParam: undefined,\n genericReturnType: undefined,\n };\n\n if (!genericSignals.includes(signalId.text)) {\n return defaultValue;\n }\n\n [defaultValue.genericReturnType] = (functionDeclaration.type as ts.TypeReferenceNode).typeArguments!;\n\n if (collectionSignals.includes(signalId.text)) {\n return defaultValue;\n }\n\n const defaultValueType = SignalProcessor.#getDefaultValueType(defaultValue.genericReturnType);\n if (!defaultValueType) {\n return defaultValue;\n }\n\n defaultValue.defaultValueParam = SignalProcessor.#createDefaultValueParameter(defaultValueType);\n const emptyValueExpression = this.#createEmptyValueExpression(defaultValueType);\n\n defaultValue.defaultValueExpression = ts.factory.createBinaryExpression(\n ts.factory.createPropertyAccessChain(\n ts.factory.createIdentifier('options'),\n ts.factory.createToken(ts.SyntaxKind.QuestionDotToken),\n ts.factory.createIdentifier('defaultValue'),\n ),\n ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken),\n emptyValueExpression,\n );\n\n return defaultValue;\n }\n\n static #getDefaultValueType(node: ts.Node) {\n if (\n ts.isUnionTypeNode(node) &&\n node.types.length &&\n ts.isTypeReferenceNode(node.types[0]) &&\n node.types[0].typeArguments?.length === 1 &&\n ts.isUnionTypeNode(node.types[0].typeArguments[0])\n ) {\n return node.types[0].typeArguments[0];\n }\n return undefined;\n }\n\n static #createDefaultValueParameter(defaultValueType: ts.TypeNode) {\n const paramType = ts.factory.createTypeLiteralNode([\n ts.factory.createPropertySignature(\n undefined,\n ts.factory.createIdentifier('defaultValue'),\n undefined,\n defaultValueType,\n ),\n ]);\n\n return ts.factory.createParameterDeclaration(\n undefined,\n undefined,\n 'options',\n ts.factory.createToken(ts.SyntaxKind.QuestionToken),\n paramType,\n );\n }\n\n static #isDefaultValueTypeNullable(defaultValueType: ts.TypeNode) {\n return (\n ts.isUnionTypeNode(defaultValueType) &&\n defaultValueType.types.length &&\n defaultValueType.types.length > 1 &&\n defaultValueType.types.map((t) => t.kind).includes(ts.SyntaxKind.UndefinedKeyword)\n );\n }\n\n #createEmptyValueExpression(defaultValueType: ts.UnionTypeNode) {\n if (SignalProcessor.#isDefaultValueTypeNullable(defaultValueType)) {\n return ts.factory.createIdentifier('undefined');\n }\n const importedModelUniqueId = this.#determineModelImportUniqueIdentifier(defaultValueType);\n return ts.factory.createCallExpression(\n ts.factory.createPropertyAccessExpression(importedModelUniqueId, 'createEmptyValue'),\n undefined,\n [],\n );\n }\n\n #determineModelImportUniqueIdentifier(returnTypeNode: ts.UnionTypeNode) {\n let modelName = primitiveModels.get(returnTypeNode.types[0].kind);\n let entityName;\n if (modelName === undefined) {\n const { entityName: e, modelName: m } = SignalProcessor.#extractModelNameFromTypeNode(returnTypeNode);\n modelName = m;\n entityName = e;\n }\n const modelImportUniqueId =\n this.#getExistingEntityModelUniqueIdentifier(modelName) ?? createFullyUniqueIdentifier(modelName);\n\n this.#addModelImport(entityName, modelName, modelImportUniqueId);\n return modelImportUniqueId;\n }\n\n static #extractModelNameFromTypeNode(returnTypeNode: ts.UnionTypeNode) {\n if (ts.isTypeReferenceNode(returnTypeNode.types[0])) {\n const typeIdentifier = returnTypeNode.types[0].typeName;\n if (ts.isIdentifier(typeIdentifier)) {\n const entityName = typeIdentifier.text;\n const modelName = `${entityName}Model`;\n return { entityName, modelName };\n }\n }\n throw new Error('Unsupported type reference node');\n }\n\n #getExistingEntityModelUniqueIdentifier(modelName: string) {\n const { imports } = this.#dependencyManager;\n return (\n imports.named.getIdentifier('@vaadin/hilla-lit-form', modelName) ??\n imports.default.iter().find(([path]) => path.endsWith(`/${modelName}.js`))?.[1]\n );\n }\n\n #addModelImport(\n entityName: string | undefined,\n modelName: string | undefined,\n modelNameUniqueId: ts.Identifier | undefined,\n ) {\n if (modelName) {\n if (primitiveModels.values().find((primitiveModel) => primitiveModel === modelName)) {\n const { imports } = this.#dependencyManager;\n const importedModel = imports.named.getIdentifier('@vaadin/hilla-lit-form', modelName);\n if (importedModel === undefined) {\n imports.named.add('@vaadin/hilla-lit-form', modelName, false, modelNameUniqueId);\n }\n } else {\n this.#addObjectModelImport(entityName!, modelName, modelNameUniqueId!);\n }\n }\n }\n\n #addObjectModelImport(entityName: string, modelName: string, modelNameUniqueId: ts.Identifier) {\n const { imports } = this.#dependencyManager;\n const entityImport = imports.default\n .iter()\n .map(([path]) => path)\n .find((path) => path.startsWith('./') && path.endsWith(`/${entityName}.js`));\n if (entityImport) {\n const entityModelImportPath = entityImport.replace(`/${entityName}.js`, `/${modelName}.js`);\n const importedModel = imports.default.paths().find((path) => path === entityModelImportPath);\n if (importedModel === undefined) {\n imports.default.add(entityModelImportPath, modelName, false, modelNameUniqueId);\n }\n }\n }\n\n #replaceSignalImport(method: FunctionDeclaration): Identifier {\n const { imports } = this.#dependencyManager;\n\n if (method.type) {\n const type = traverse(method.type, (node) =>\n ts.isIdentifier(node) && signals.includes(node.text) ? node : undefined,\n );\n\n if (type) {\n const signalId = imports.named.getIdentifier(HILLA_REACT_SIGNALS, type.text);\n\n if (signalId) {\n return signalId;\n }\n\n const result = imports.default.iter().find(([_p, id]) => id.text === type.text);\n\n if (result) {\n const [path] = result;\n imports.default.remove(path);\n return imports.named.add(HILLA_REACT_SIGNALS, type.text, false, type);\n }\n }\n }\n\n throw new Error('Signal type not found');\n }\n}\n"],"version":3}
package/index.d.ts CHANGED
@@ -1,12 +1,11 @@
1
- import Plugin from '@vaadin/hilla-generator-core/Plugin.js';
2
- import type SharedStorage from '@vaadin/hilla-generator-core/SharedStorage.js';
1
+ import Plugin from "@vaadin/hilla-generator-core/Plugin.js";
2
+ import type { SharedStorage } from "@vaadin/hilla-generator-core/SharedStorage.js";
3
3
  export type PathSignalType = Readonly<{
4
- path: string;
5
- signalType: string;
4
+ path: string
5
+ signalType: string
6
6
  }>;
7
7
  export default class SignalsPlugin extends Plugin {
8
- execute(sharedStorage: SharedStorage): Promise<void>;
9
- ['constructor']: typeof SignalsPlugin;
10
- get path(): string;
8
+ execute(sharedStorage: SharedStorage): Promise<void>;
9
+ ["constructor"]: typeof SignalsPlugin;
10
+ get path(): string;
11
11
  }
12
- //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,58 +1,49 @@
1
1
  import Plugin from "@vaadin/hilla-generator-core/Plugin.js";
2
2
  import SignalProcessor from "./SignalProcessor.js";
3
3
  if (!("Iterator" in globalThis)) {
4
- const { installIntoGlobal } = await import("iterator-helpers-polyfill");
5
- installIntoGlobal();
4
+ const { installIntoGlobal } = await import("iterator-helpers-polyfill");
5
+ installIntoGlobal();
6
6
  }
7
7
  const SIGNAL_CLASSES = [
8
- "#/components/schemas/com.vaadin.hilla.signals.NumberSignal",
9
- "#/components/schemas/com.vaadin.hilla.signals.ValueSignal",
10
- "#/components/schemas/com.vaadin.hilla.signals.ListSignal"
8
+ "#/components/schemas/com.vaadin.hilla.signals.NumberSignal",
9
+ "#/components/schemas/com.vaadin.hilla.signals.ValueSignal",
10
+ "#/components/schemas/com.vaadin.hilla.signals.ListSignal"
11
11
  ];
12
12
  function extractEndpointMethodsWithSignalsAsReturnType(storage) {
13
- return Object.entries(storage.api.paths).filter(([_, pathObject]) => {
14
- const response200 = pathObject?.post?.responses["200"];
15
- return response200 && !("$ref" in response200);
16
- }).flatMap(([path, pathObject]) => {
17
- const response200 = pathObject?.post?.responses["200"];
18
- const responseSchema = response200.content?.["application/json"]?.schema;
19
- return responseSchema && "anyOf" in responseSchema ? responseSchema.anyOf?.filter((c) => "$ref" in c && c.$ref && SIGNAL_CLASSES.includes(c.$ref)).map((c) => ({
20
- path,
21
- signalType: "$ref" in c ? c.$ref : ""
22
- })) : [];
23
- }).filter((signalArray) => signalArray != null);
13
+ return Object.entries(storage.api.paths).filter(([_, pathObject]) => {
14
+ const response200 = pathObject?.post?.responses["200"];
15
+ return response200 && !("$ref" in response200);
16
+ }).flatMap(([path, pathObject]) => {
17
+ const response200 = pathObject?.post?.responses["200"];
18
+ const responseSchema = response200.content?.["application/json"]?.schema;
19
+ return responseSchema && "anyOf" in responseSchema ? responseSchema.anyOf?.filter((c) => "$ref" in c && c.$ref && SIGNAL_CLASSES.includes(c.$ref)).map((c) => ({
20
+ path,
21
+ signalType: "$ref" in c ? c.$ref : ""
22
+ })) : [];
23
+ }).filter((signalArray) => signalArray != null);
24
24
  }
25
25
  function groupByService(signals) {
26
- return signals.reduce((serviceMap, signal) => {
27
- const [_, service, method] = signal.path.split("/");
28
- const serviceMethods = serviceMap.get(service) ?? /* @__PURE__ */ new Map();
29
- serviceMethods.set(method, signal.signalType);
30
- serviceMap.set(service, serviceMethods);
31
- return serviceMap;
32
- }, /* @__PURE__ */ new Map());
26
+ return signals.reduce((serviceMap, signal) => {
27
+ const [_, service, method] = signal.path.split("/");
28
+ const serviceMethods = serviceMap.get(service) ?? new Map();
29
+ serviceMethods.set(method, signal.signalType);
30
+ serviceMap.set(service, serviceMethods);
31
+ return serviceMap;
32
+ }, new Map());
33
33
  }
34
- class SignalsPlugin extends Plugin {
35
- // eslint-disable-next-line @typescript-eslint/require-await
36
- async execute(sharedStorage) {
37
- const methodsWithSignals = extractEndpointMethodsWithSignalsAsReturnType(sharedStorage);
38
- const services = groupByService(methodsWithSignals);
39
- services.forEach((methods, service) => {
40
- const index = sharedStorage.sources.findIndex((source) => source.fileName === `${service}.ts`);
41
- if (index >= 0) {
42
- sharedStorage.sources[index] = new SignalProcessor(
43
- service,
44
- methods,
45
- sharedStorage.sources[index],
46
- this
47
- ).process();
48
- }
49
- });
50
- }
51
- get path() {
52
- return import.meta.url;
53
- }
34
+ export default class SignalsPlugin extends Plugin {
35
+ async execute(sharedStorage) {
36
+ const methodsWithSignals = extractEndpointMethodsWithSignalsAsReturnType(sharedStorage);
37
+ const services = groupByService(methodsWithSignals);
38
+ services.forEach((methods, service) => {
39
+ const index = sharedStorage.sources.findIndex((source) => source.fileName === `${service}.ts`);
40
+ if (index >= 0) {
41
+ sharedStorage.sources[index] = new SignalProcessor(service, methods, sharedStorage.sources[index], this).process();
42
+ }
43
+ });
44
+ }
45
+ get path() {
46
+ return import.meta.url;
47
+ }
54
48
  }
55
- export {
56
- SignalsPlugin as default
57
- };
58
- //# sourceMappingURL=index.js.map
49
+ //# sourceMappingURL=./index.js.map
package/index.js.map CHANGED
@@ -1,7 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["src/index.ts"],
4
- "sourcesContent": ["import Plugin from '@vaadin/hilla-generator-core/Plugin.js';\nimport type SharedStorage from '@vaadin/hilla-generator-core/SharedStorage.js';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport SignalProcessor from './SignalProcessor.js';\n\n// Polyfill for iterator helpers (Stage 3 proposal)\nif (!('Iterator' in globalThis)) {\n const { installIntoGlobal } = await import('iterator-helpers-polyfill');\n installIntoGlobal();\n}\n\nexport type PathSignalType = Readonly<{\n path: string;\n signalType: string;\n}>;\n\nconst SIGNAL_CLASSES = [\n '#/components/schemas/com.vaadin.hilla.signals.NumberSignal',\n '#/components/schemas/com.vaadin.hilla.signals.ValueSignal',\n '#/components/schemas/com.vaadin.hilla.signals.ListSignal',\n];\n\nfunction extractEndpointMethodsWithSignalsAsReturnType(storage: SharedStorage): PathSignalType[] {\n return Object.entries(storage.api.paths)\n .filter(([_, pathObject]) => {\n const response200 = pathObject?.post?.responses['200'];\n return response200 && !('$ref' in response200);\n })\n .flatMap(([path, pathObject]) => {\n const response200 = pathObject?.post?.responses['200'];\n const responseSchema = (response200 as OpenAPIV3.ResponseObject).content?.['application/json']?.schema;\n\n return responseSchema && 'anyOf' in responseSchema\n ? responseSchema.anyOf\n ?.filter((c) => '$ref' in c && c.$ref && SIGNAL_CLASSES.includes(c.$ref))\n .map((c: OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject) => ({\n path,\n signalType: '$ref' in c ? c.$ref : '',\n }))\n : [];\n })\n .filter((signalArray) => signalArray != null);\n}\n\nfunction groupByService(signals: readonly PathSignalType[]): Map<string, Map<string, string>> {\n return signals.reduce((serviceMap, signal) => {\n const [_, service, method] = signal.path.split('/');\n const serviceMethods = serviceMap.get(service) ?? new Map<string, string>();\n serviceMethods.set(method, signal.signalType);\n serviceMap.set(service, serviceMethods);\n return serviceMap;\n }, new Map<string, Map<string, string>>());\n}\n\nexport default class SignalsPlugin extends Plugin {\n // eslint-disable-next-line @typescript-eslint/require-await\n override async execute(sharedStorage: SharedStorage): Promise<void> {\n const methodsWithSignals = extractEndpointMethodsWithSignalsAsReturnType(sharedStorage);\n const services = groupByService(methodsWithSignals);\n services.forEach((methods, service) => {\n const index = sharedStorage.sources.findIndex((source) => source.fileName === `${service}.ts`);\n if (index >= 0) {\n sharedStorage.sources[index] = new SignalProcessor(\n service,\n methods,\n sharedStorage.sources[index],\n this,\n ).process();\n }\n });\n }\n\n declare ['constructor']: typeof SignalsPlugin;\n\n override get path(): string {\n return import.meta.url;\n }\n}\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AAGnB,OAAO,qBAAqB;AAG5B,IAAI,EAAE,cAAc,aAAa;AAC/B,QAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,2BAA2B;AACtE,oBAAkB;AACpB;AAOA,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,8CAA8C,SAA0C;AAC/F,SAAO,OAAO,QAAQ,QAAQ,IAAI,KAAK,EACpC,OAAO,CAAC,CAAC,GAAG,UAAU,MAAM;AAC3B,UAAM,cAAc,YAAY,MAAM,UAAU,KAAK;AACrD,WAAO,eAAe,EAAE,UAAU;AAAA,EACpC,CAAC,EACA,QAAQ,CAAC,CAAC,MAAM,UAAU,MAAM;AAC/B,UAAM,cAAc,YAAY,MAAM,UAAU,KAAK;AACrD,UAAM,iBAAkB,YAAyC,UAAU,kBAAkB,GAAG;AAEhG,WAAO,kBAAkB,WAAW,iBAChC,eAAe,OACX,OAAO,CAAC,MAAM,UAAU,KAAK,EAAE,QAAQ,eAAe,SAAS,EAAE,IAAI,CAAC,EACvE,IAAI,CAAC,OAA2D;AAAA,MAC/D;AAAA,MACA,YAAY,UAAU,IAAI,EAAE,OAAO;AAAA,IACrC,EAAE,IACJ,CAAC;AAAA,EACP,CAAC,EACA,OAAO,CAAC,gBAAgB,eAAe,IAAI;AAChD;AAEA,SAAS,eAAe,SAAsE;AAC5F,SAAO,QAAQ,OAAO,CAAC,YAAY,WAAW;AAC5C,UAAM,CAAC,GAAG,SAAS,MAAM,IAAI,OAAO,KAAK,MAAM,GAAG;AAClD,UAAM,iBAAiB,WAAW,IAAI,OAAO,KAAK,oBAAI,IAAoB;AAC1E,mBAAe,IAAI,QAAQ,OAAO,UAAU;AAC5C,eAAW,IAAI,SAAS,cAAc;AACtC,WAAO;AAAA,EACT,GAAG,oBAAI,IAAiC,CAAC;AAC3C;AAEA,MAAO,sBAAoC,OAAO;AAAA;AAAA,EAEhD,MAAe,QAAQ,eAA6C;AAClE,UAAM,qBAAqB,8CAA8C,aAAa;AACtF,UAAM,WAAW,eAAe,kBAAkB;AAClD,aAAS,QAAQ,CAAC,SAAS,YAAY;AACrC,YAAM,QAAQ,cAAc,QAAQ,UAAU,CAAC,WAAW,OAAO,aAAa,GAAG,OAAO,KAAK;AAC7F,UAAI,SAAS,GAAG;AACd,sBAAc,QAAQ,KAAK,IAAI,IAAI;AAAA,UACjC;AAAA,UACA;AAAA,UACA,cAAc,QAAQ,KAAK;AAAA,UAC3B;AAAA,QACF,EAAE,QAAQ;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAIA,IAAa,OAAe;AAC1B,WAAO,YAAY;AAAA,EACrB;AACF;",
6
- "names": []
7
- }
1
+ {"mappings":"AAAA,OAAO,oDAAqD;AAG5D,OAAO,2CAA4C;AAGnD,MAAM,cAAc,aAAa;CAC/B,MAAM,EAAE,mBAAmB,GAAG,MAAM,OAAO;AAC3C,oBAAmB;AACpB;AAOD,MAAM,iBAAiB;CACrB;CACA;CACA;AACD;AAED,SAAS,8CAA8CA,SAA0C;AAC/F,QAAO,OAAO,QAAQ,QAAQ,IAAI,MAAM,CACrC,OAAO,CAAC,CAAC,GAAG,WAAW,KAAK;EAC3B,MAAM,cAAc,YAAY,MAAM,UAAU;AAChD,SAAO,iBAAiB,UAAU;CACnC,EAAC,CACD,QAAQ,CAAC,CAAC,MAAM,WAAW,KAAK;EAC/B,MAAM,cAAc,YAAY,MAAM,UAAU;EAChD,MAAM,iBAAkB,YAAyC,UAAU,qBAAqB;AAEhG,SAAO,kBAAkB,WAAW,iBAChC,eAAe,OACX,OAAO,CAAC,MAAM,UAAU,KAAK,EAAE,QAAQ,eAAe,SAAS,EAAE,KAAK,CAAC,CACxE,IAAI,CAACC,OAA2D;GAC/D;GACA,YAAY,UAAU,IAAI,EAAE,OAAO;EACpC,GAAE,GACL,CAAE;CACP,EAAC,CACD,OAAO,CAAC,gBAAgB,eAAe,KAAK;AAChD;AAED,SAAS,eAAeC,SAAsE;AAC5F,QAAO,QAAQ,OAAO,CAAC,YAAY,WAAW;EAC5C,MAAM,CAAC,GAAG,SAAS,OAAO,GAAG,OAAO,KAAK,MAAM,IAAI;EACnD,MAAM,iBAAiB,WAAW,IAAI,QAAQ,IAAI,IAAI;AACtD,iBAAe,IAAI,QAAQ,OAAO,WAAW;AAC7C,aAAW,IAAI,SAAS,eAAe;AACvC,SAAO;CACR,GAAE,IAAI,MAAmC;AAC3C;AAED,eAAe,MAAM,sBAAsB,OAAO;CAEhD,MAAe,QAAQC,eAA6C;EAClE,MAAM,qBAAqB,8CAA8C,cAAc;EACvF,MAAM,WAAW,eAAe,mBAAmB;AACnD,WAAS,QAAQ,CAAC,SAAS,YAAY;GACrC,MAAM,QAAQ,cAAc,QAAQ,UAAU,CAAC,WAAW,OAAO,cAAc,EAAE,QAAQ,KAAK;AAC9F,OAAI,SAAS,GAAG;AACd,kBAAc,QAAQ,SAAS,IAAI,gBACjC,SACA,SACA,cAAc,QAAQ,QACtB,MACA,SAAS;GACZ;EACF,EAAC;CACH;CAID,IAAa,OAAe;AAC1B,SAAO,OAAO,KAAK;CACpB;AACF","names":["storage: SharedStorage","c: OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject","signals: readonly PathSignalType[]","sharedStorage: SharedStorage"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/generator-plugin-signals/src/index.ts"],"sourcesContent":["import Plugin from '@vaadin/hilla-generator-core/Plugin.js';\nimport type { SharedStorage } from '@vaadin/hilla-generator-core/SharedStorage.js';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport SignalProcessor from './SignalProcessor.js';\n\n// Polyfill for iterator helpers (Stage 3 proposal)\nif (!('Iterator' in globalThis)) {\n const { installIntoGlobal } = await import('iterator-helpers-polyfill');\n installIntoGlobal();\n}\n\nexport type PathSignalType = Readonly<{\n path: string;\n signalType: string;\n}>;\n\nconst SIGNAL_CLASSES = [\n '#/components/schemas/com.vaadin.hilla.signals.NumberSignal',\n '#/components/schemas/com.vaadin.hilla.signals.ValueSignal',\n '#/components/schemas/com.vaadin.hilla.signals.ListSignal',\n];\n\nfunction extractEndpointMethodsWithSignalsAsReturnType(storage: SharedStorage): PathSignalType[] {\n return Object.entries(storage.api.paths)\n .filter(([_, pathObject]) => {\n const response200 = pathObject?.post?.responses['200'];\n return response200 && !('$ref' in response200);\n })\n .flatMap(([path, pathObject]) => {\n const response200 = pathObject?.post?.responses['200'];\n const responseSchema = (response200 as OpenAPIV3.ResponseObject).content?.['application/json']?.schema;\n\n return responseSchema && 'anyOf' in responseSchema\n ? responseSchema.anyOf\n ?.filter((c) => '$ref' in c && c.$ref && SIGNAL_CLASSES.includes(c.$ref))\n .map((c: OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject) => ({\n path,\n signalType: '$ref' in c ? c.$ref : '',\n }))\n : [];\n })\n .filter((signalArray) => signalArray != null);\n}\n\nfunction groupByService(signals: readonly PathSignalType[]): Map<string, Map<string, string>> {\n return signals.reduce((serviceMap, signal) => {\n const [_, service, method] = signal.path.split('/');\n const serviceMethods = serviceMap.get(service) ?? new Map<string, string>();\n serviceMethods.set(method, signal.signalType);\n serviceMap.set(service, serviceMethods);\n return serviceMap;\n }, new Map<string, Map<string, string>>());\n}\n\nexport default class SignalsPlugin extends Plugin {\n // eslint-disable-next-line @typescript-eslint/require-await\n override async execute(sharedStorage: SharedStorage): Promise<void> {\n const methodsWithSignals = extractEndpointMethodsWithSignalsAsReturnType(sharedStorage);\n const services = groupByService(methodsWithSignals);\n services.forEach((methods, service) => {\n const index = sharedStorage.sources.findIndex((source) => source.fileName === `${service}.ts`);\n if (index >= 0) {\n sharedStorage.sources[index] = new SignalProcessor(\n service,\n methods,\n sharedStorage.sources[index],\n this,\n ).process();\n }\n });\n }\n\n declare ['constructor']: typeof SignalsPlugin;\n\n override get path(): string {\n return import.meta.url;\n }\n}\n"],"version":3}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-generator-plugin-signals",
3
- "version": "24.7.0-alpha9",
3
+ "version": "24.7.0-beta3",
4
4
  "description": "A Hilla TypeScript Generator plugin to add Shared Signals support",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -9,15 +9,13 @@
9
9
  },
10
10
  "scripts": {
11
11
  "clean:build": "git clean -fx . -e .vite -e node_modules",
12
- "build": "concurrently npm:build:*",
13
- "build:esbuild": "tsx ../../../scripts/build.ts",
14
- "build:dts": "tsc --isolatedModules -p tsconfig.build.json",
15
- "build:copy": "cd src && copyfiles **/*.d.ts ..",
12
+ "build": "tsx ../../../scripts/fast-build.ts",
16
13
  "lint": "eslint src test",
17
14
  "lint:fix": "eslint src test --fix",
18
- "test": "mocha test/**/*.spec.ts --config ../../../.mocharc.cjs",
19
- "test:update": "npm run test -- --update",
20
- "test:coverage": "c8 -c ../../../.c8rc.json npm test",
15
+ "test": "vitest --run",
16
+ "test:coverage": "vitest --run --coverage",
17
+ "test:update": "vitest --run --update",
18
+ "test:watch": "vitest",
21
19
  "typecheck": "tsc --noEmit"
22
20
  },
23
21
  "exports": {
@@ -51,32 +49,13 @@
51
49
  "access": "public"
52
50
  },
53
51
  "dependencies": {
54
- "@vaadin/hilla-generator-core": "24.7.0-alpha9",
55
- "@vaadin/hilla-generator-plugin-backbone": "24.7.0-alpha9",
56
- "@vaadin/hilla-generator-plugin-client": "24.7.0-alpha9",
57
- "@vaadin/hilla-generator-utils": "24.7.0-alpha9",
58
- "fast-deep-equal": "^3.1.3",
59
- "iterator-helpers-polyfill": "^3.0.1",
60
- "openapi-types": "^12.1.3",
52
+ "@vaadin/hilla-generator-core": "24.7.0-beta3",
53
+ "@vaadin/hilla-generator-plugin-backbone": "24.7.0-beta3",
54
+ "@vaadin/hilla-generator-plugin-client": "24.7.0-beta3",
55
+ "@vaadin/hilla-generator-utils": "24.7.0-beta3",
56
+ "fast-deep-equal": "3.1.3",
57
+ "iterator-helpers-polyfill": "3.0.1",
58
+ "openapi-types": "12.1.3",
61
59
  "typescript": "5.7.3"
62
- },
63
- "devDependencies": {
64
- "@types/chai": "^4.3.20",
65
- "@types/mocha": "^10.0.10",
66
- "@types/node": "^20.17.12",
67
- "@types/sinon": "^10.0.20",
68
- "@types/sinon-chai": "^3.2.12",
69
- "@vaadin/hilla-generator-core": "24.7.0-alpha9",
70
- "@vaadin/hilla-generator-plugin-client": "24.7.0-alpha9",
71
- "c8": "^10.1.3",
72
- "chai": "^4.5.0",
73
- "concurrently": "^9.1.2",
74
- "copyfiles": "^2.4.1",
75
- "mocha": "^11.1.0",
76
- "monocart-coverage-reports": "^2.11.5",
77
- "pino": "^9.6.0",
78
- "sinon": "^16.1.3",
79
- "sinon-chai": "^3.7.0",
80
- "type-fest": "^4.32.0"
81
60
  }
82
61
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"SignalProcessor.d.ts","sourceRoot":"","sources":["src/SignalProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,wCAAwC,CAAC;AAMjE,OAAW,EAA6C,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAc5F,MAAM,CAAC,OAAO,OAAO,eAAe;;gBAOtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM;IAShG,OAAO,IAAI,UAAU;CA6JtB"}
package/index.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,wCAAwC,CAAC;AAC5D,OAAO,KAAK,aAAa,MAAM,+CAA+C,CAAC;AAU/E,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAwCH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,MAAM;IAEhC,OAAO,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB3D,CAAC,aAAa,CAAC,EAAE,OAAO,aAAa,CAAC;IAE9C,IAAa,IAAI,IAAI,MAAM,CAE1B;CACF"}