@monimesl/dot-script-parser 0.1.0-alpha.10

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.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @monimesl/dot-script-parser
@@ -0,0 +1,80 @@
1
+ import "oxc-parser";
2
+ import { SourceError } from "@monimesl/dot-core";
3
+ //#region src/globals.d.ts
4
+ export declare function unboundReferences(source: string, names: readonly string[], file?: string): string[];
5
+ //#endregion
6
+ //#region src/dot.d.ts
7
+ interface DotModuleIR {
8
+ readonly pages: readonly string[];
9
+ readonly lastPage: {
10
+ readonly start: number;
11
+ readonly end: number;
12
+ };
13
+ }
14
+ export declare function parseDotModule(source: string, file?: string): DotModuleIR;
15
+ //#endregion
16
+ //#region src/errors.d.ts
17
+ export declare class ScriptParseError extends SourceError {
18
+ readonly name = "ScriptParseError";
19
+ }
20
+ //#endregion
21
+ //#region src/ast/expression/types.d.ts
22
+ declare const UNARY_OPERATORS: readonly ["!", "-", "+", "typeof"];
23
+ declare const BINARY_OPERATORS: readonly ["==", "!=", "===", "!==", "<", "<=", ">", ">=", "+", "-", "*", "/", "%", "**", "&&", "||", "??"];
24
+ type LiteralValue = string | number | boolean | null;
25
+ type LiteralNode = {
26
+ readonly type: 'Literal';
27
+ readonly value: LiteralValue;
28
+ };
29
+ type IdentifierNode = {
30
+ readonly type: 'Identifier';
31
+ readonly name: string;
32
+ };
33
+ type MemberNode = {
34
+ readonly type: 'Member';
35
+ readonly object: ExprNode;
36
+ readonly property: ExprNode;
37
+ };
38
+ type UnaryOperator = (typeof UNARY_OPERATORS)[number];
39
+ type UnaryExprNode = {
40
+ readonly type: 'Unary';
41
+ readonly operator: UnaryOperator;
42
+ readonly argument: ExprNode;
43
+ };
44
+ type BinaryOperator = (typeof BINARY_OPERATORS)[number];
45
+ type BinaryExprNode = {
46
+ readonly type: 'Binary';
47
+ readonly operator: BinaryOperator;
48
+ readonly left: ExprNode;
49
+ readonly right: ExprNode;
50
+ };
51
+ type ConditionalExprNode = {
52
+ readonly type: 'Conditional';
53
+ readonly test: ExprNode;
54
+ readonly consequent: ExprNode;
55
+ readonly alternate: ExprNode;
56
+ };
57
+ type ExprNode = LiteralNode | IdentifierNode | MemberNode | UnaryExprNode | BinaryExprNode | ConditionalExprNode;
58
+ //#endregion
59
+ //#region src/ast/expression/parse.d.ts
60
+ export declare function parseExpression(source: string): ExprNode;
61
+ //#endregion
62
+ //#region src/ast/page/types.d.ts
63
+ interface PageStateModule {
64
+ readonly keys: readonly string[] | null;
65
+ readonly keyOffsets: Readonly<Record<string, number>>;
66
+ }
67
+ interface PageModule {
68
+ readonly id: string | null;
69
+ readonly hooks: readonly string[];
70
+ readonly mutations: readonly string[] | null;
71
+ readonly actions: readonly string[] | null;
72
+ readonly handlerOffsets: Readonly<Record<string, number>>;
73
+ }
74
+ //#endregion
75
+ //#region src/ast/page/parse.d.ts
76
+ export declare function parseStateModule(source: string, file?: string): PageStateModule;
77
+ export declare function parseLogicModule(source: string, file?: string): PageModule;
78
+ //#endregion
79
+ export type { BinaryOperator, DotModuleIR, ExprNode, LiteralValue, PageModule, PageStateModule, UnaryOperator };
80
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/globals.ts","../src/dot.ts","../src/errors.ts","../src/ast/expression/types.ts","../src/ast/expression/parse.ts","../src/ast/page/types.ts","../src/ast/page/parse.ts"],"mappings":";;;wBAWgB,kBACd,gBACA,0BACA;;;UCTe;WACN;WACA;aAAqB;aAAwB;;;wBAGxC,eAAe,gBAAgB,gBAAkB;;;qBCPpD,yBAAyB;WAClB;;;;cCJP;cAEA;KAoBD;KAEP;WAAyB;WAA0B,OAAO;;KAE1D;WAA4B;WAA6B;;KAEzD;WACM;WACA,QAAQ;WACR,UAAU;;KAGT,wBAAwB;KAE/B;WACM;WACA,UAAU;WACV,UAAU;;KAGT,yBAAyB;KAEhC;WACM;WACA,UAAU;WACV,MAAM;WACN,OAAO;;KAGb;WACM;WACA,MAAM;WACN,YAAY;WACZ,WAAW;;KAGV,WACV,cAAc,iBAAiB,aAAa,gBAAgB,iBAAiB;;;wBCpD/D,gBAAgB,iBAAiB;;;UCPhC;WAEN;WAEA,YAAY,SAAS;;UAGf;WACN;WACA;WACA;WACA;WAEA,gBAAgB,SAAS;;;;wBCFpB,iBAAiB,gBAAgB,gBAAoB;wBAarD,iBAAiB,gBAAgB,gBAAyB"}
package/dist/index.js ADDED
@@ -0,0 +1,358 @@
1
+ import { parseSync } from "oxc-parser";
2
+ import { PAGE_HOOKS, SourceError, isPageId, locationAt } from "@monimesl/dot-core";
3
+ //#region src/utils.ts
4
+ function propertyName(key) {
5
+ if (key.type === "Identifier") return key.name;
6
+ if (key.type === "Literal" && typeof key.value === "string") return key.value;
7
+ return null;
8
+ }
9
+ function unwrapExpression(node) {
10
+ while (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSNonNullExpression") node = node.expression;
11
+ return node;
12
+ }
13
+ function staticProperties(object) {
14
+ const properties = [];
15
+ for (const property of object.properties) {
16
+ if (property.type !== "Property" || property.computed) continue;
17
+ const name = propertyName(property.key);
18
+ if (name !== null) properties.push({
19
+ name,
20
+ value: property.value,
21
+ start: property.start
22
+ });
23
+ }
24
+ return properties;
25
+ }
26
+ function withoutExport(statement) {
27
+ if (statement.type === "ExportNamedDeclaration") return statement.declaration;
28
+ return statement;
29
+ }
30
+ //#endregion
31
+ //#region src/errors.ts
32
+ var ScriptParseError = class extends SourceError {
33
+ name = "ScriptParseError";
34
+ };
35
+ function failAt(reason, source, offset, file) {
36
+ throw new ScriptParseError(reason, file, locationAt(source, offset));
37
+ }
38
+ function failOnSyntaxError(errors, source, file) {
39
+ const [error] = errors;
40
+ if (error) failAt(error.message, source, error.labels[0]?.start ?? 0, file);
41
+ }
42
+ //#endregion
43
+ //#region src/module.ts
44
+ function parseModule(source, file) {
45
+ const { program, errors } = parseSync(file, source, {
46
+ lang: "ts",
47
+ sourceType: "module"
48
+ });
49
+ failOnSyntaxError(errors, source, file);
50
+ return program;
51
+ }
52
+ function defaultExport(program) {
53
+ for (const statement of program.body) {
54
+ if (statement.type !== "ExportDefaultDeclaration") continue;
55
+ const { declaration } = statement;
56
+ switch (declaration.type) {
57
+ case "FunctionDeclaration":
58
+ case "ClassDeclaration":
59
+ case "TSInterfaceDeclaration": return;
60
+ default: return declaration;
61
+ }
62
+ }
63
+ }
64
+ function defineCall(program, source, file, callee) {
65
+ const exported = defaultExport(program);
66
+ const call = exported && unwrapExpression(exported);
67
+ const options = call?.type === "CallExpression" ? call.arguments[0] : void 0;
68
+ if (call?.type !== "CallExpression" || call.callee.type !== "Identifier" || call.callee.name !== callee || options?.type !== "ObjectExpression") return failAt(`${fileName(file)} must \`export default ${callee}({ ... })\``, source, exported?.start ?? 0, file);
69
+ return options;
70
+ }
71
+ function fileName(path) {
72
+ const lastSeparator = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
73
+ return path.slice(lastSeparator + 1);
74
+ }
75
+ //#endregion
76
+ //#region src/globals.ts
77
+ function unboundReferences(source, names, file = "module.ts") {
78
+ const program = parseModule(source, file);
79
+ const bound = topLevelBindings(program);
80
+ const references = /* @__PURE__ */ new Set();
81
+ collectReferences(program, null, "", references);
82
+ return names.filter((name) => references.has(name) && !bound.has(name));
83
+ }
84
+ function topLevelBindings(program) {
85
+ const names = /* @__PURE__ */ new Set();
86
+ for (const statement of program.body) {
87
+ const declaration = withoutExport(statement);
88
+ switch (declaration?.type) {
89
+ case "ImportDeclaration":
90
+ for (const specifier of declaration.specifiers) names.add(specifier.local.name);
91
+ break;
92
+ case "VariableDeclaration":
93
+ for (const declarator of declaration.declarations) collectPatternNames(declarator.id, names);
94
+ break;
95
+ case "FunctionDeclaration":
96
+ case "ClassDeclaration": if (declaration.id) names.add(declaration.id.name);
97
+ }
98
+ }
99
+ return names;
100
+ }
101
+ function collectPatternNames(pattern, names) {
102
+ const visit = (child) => {
103
+ if (isNode(child)) collectPatternNames(child, names);
104
+ };
105
+ switch (pattern.type) {
106
+ case "Identifier":
107
+ names.add(pattern.name);
108
+ break;
109
+ case "ObjectPattern":
110
+ for (const property of pattern.properties) visit(property.type === "RestElement" ? property.argument : property.value);
111
+ break;
112
+ case "ArrayPattern":
113
+ for (const element of pattern.elements) visit(element);
114
+ break;
115
+ case "RestElement":
116
+ visit(pattern.argument);
117
+ break;
118
+ case "AssignmentPattern": visit(pattern.left);
119
+ }
120
+ }
121
+ function collectReferences(node, parent, key, out) {
122
+ if (node.type === "ImportDeclaration") return;
123
+ if (node.type === "Identifier" && isReference(parent, key)) out.add(node.name);
124
+ for (const [childKey, value] of Object.entries(node)) for (const child of Array.isArray(value) ? value : [value]) if (isNode(child)) collectReferences(child, node, childKey, out);
125
+ }
126
+ /** False for identifiers that name a property or label rather than refer to a variable. */
127
+ function isReference(parent, key) {
128
+ switch (parent?.type) {
129
+ case "MemberExpression": return key !== "property" || parent.computed === true;
130
+ case "Property":
131
+ case "MethodDefinition":
132
+ case "PropertyDefinition": return key !== "key" || parent.computed === true;
133
+ case "LabeledStatement":
134
+ case "BreakStatement":
135
+ case "ContinueStatement": return key !== "label";
136
+ default: return true;
137
+ }
138
+ }
139
+ function isNode(value) {
140
+ return typeof value?.type === "string";
141
+ }
142
+ //#endregion
143
+ //#region src/ast/page/parse.ts
144
+ const HOOKS = new Set(PAGE_HOOKS);
145
+ function parseStateModule(source, file = "state.ts") {
146
+ const program = parseModule(source, file);
147
+ const exported = defaultExport(program);
148
+ if (!exported) return failAt("state.ts must have a default export", source, 0, file);
149
+ const properties = resolvedProperties(program, exported);
150
+ return {
151
+ keys: namesOf(properties),
152
+ keyOffsets: offsetsOf(properties ?? [])
153
+ };
154
+ }
155
+ function parseLogicModule(source, file = "controller.ts") {
156
+ const program = parseModule(source, file);
157
+ const options = defineCall(program, source, file, "definePage");
158
+ let id = null;
159
+ let mutations = [];
160
+ let actions = [];
161
+ const hooks = [];
162
+ for (const { name, value, start } of staticProperties(options)) switch (name) {
163
+ case "initialState":
164
+ case "configs": break;
165
+ case "id":
166
+ id = pageId(value, source, file);
167
+ break;
168
+ case "hooks":
169
+ if (value.type !== "ObjectExpression") break;
170
+ for (const hook of staticProperties(value)) {
171
+ if (!HOOKS.has(hook.name)) failAt(`Unknown page hook \`${hook.name}\`. The hooks are ${PAGE_HOOKS.join(", ")}`, source, hook.start, file);
172
+ hooks.push(hook.name);
173
+ }
174
+ break;
175
+ case "mutations":
176
+ mutations = resolvedProperties(program, value);
177
+ break;
178
+ case "actions":
179
+ actions = resolvedProperties(program, value);
180
+ break;
181
+ default: if (isFunction(value)) failAt(`\`${name}\` must go in \`mutations\` or \`actions\``, source, start, file);
182
+ else failAt(`Unknown option \`${name}\`. definePage takes id, initialState, configs, hooks, mutations and actions`, source, start, file);
183
+ }
184
+ const mutationNames = namesOf(mutations);
185
+ const actionNames = namesOf(actions);
186
+ const clash = mutationNames?.find((name) => actionNames?.includes(name));
187
+ if (clash) failAt(`\`${clash}\` is both a mutation and an action`, source, options.start, file);
188
+ return {
189
+ id,
190
+ mutations: mutationNames,
191
+ actions: actionNames,
192
+ hooks,
193
+ handlerOffsets: offsetsOf([...mutations ?? [], ...actions ?? []])
194
+ };
195
+ }
196
+ function isFunction(node) {
197
+ return node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
198
+ }
199
+ function resolvedProperties(program, node) {
200
+ const object = resolveObject(program, node);
201
+ if (!object) return null;
202
+ const properties = staticProperties(object);
203
+ return properties.length === object.properties.length ? properties : null;
204
+ }
205
+ function namesOf(properties) {
206
+ return properties?.map((property) => property.name) ?? null;
207
+ }
208
+ function offsetsOf(properties) {
209
+ const offsets = {};
210
+ for (const property of properties) offsets[property.name] = property.start;
211
+ return offsets;
212
+ }
213
+ /** Follows `export default state` back to `const state = { ... }`. */
214
+ function resolveObject(program, node) {
215
+ const target = unwrapExpression(node);
216
+ if (target.type === "ObjectExpression") return target;
217
+ if (target.type !== "Identifier") return null;
218
+ for (const statement of program.body) {
219
+ const declaration = withoutExport(statement);
220
+ if (declaration?.type !== "VariableDeclaration" || declaration.kind !== "const") continue;
221
+ for (const declarator of declaration.declarations) if (declarator.id.type === "Identifier" && declarator.id.name === target.name) return declarator.init ? resolveObject(program, declarator.init) : null;
222
+ }
223
+ return null;
224
+ }
225
+ /** Reads a page id, which must be a string literal made of safe characters. */
226
+ function pageId(node, source, file) {
227
+ const value = unwrapExpression(node);
228
+ if (value.type !== "Literal" || typeof value.value !== "string") return failAt("A page id must be written as a string, such as 'cart'", source, node.start, file);
229
+ if (!isPageId(value.value)) return failAt(`"${value.value}" isn't a valid page id. Use letters, digits, "-" and "_", with "/" between folders`, source, node.start, file);
230
+ return value.value;
231
+ }
232
+ //#endregion
233
+ //#region src/dot.ts
234
+ function parseDotModule(source, file = "dot.ts") {
235
+ const options = defineCall(parseModule(source, file), source, file, "defineDot");
236
+ const pagesProperty = staticProperties(options).find((property) => property.name === "pages");
237
+ if (!pagesProperty) return failAt("defineDot needs `pages`, a list of page folders with the entry page first", source, options.start, file);
238
+ const { value, start } = pagesProperty;
239
+ const array = unwrapExpression(value);
240
+ if (array.type !== "ArrayExpression") return failAt("`pages` must be a list of page folders", source, start, file);
241
+ if (array.elements.length === 0) return failAt("`pages` needs at least one page", source, start, file);
242
+ const pages = array.elements.map((element) => {
243
+ if (!element || element.type === "SpreadElement") return failAt("`pages` must list each page folder as a string", source, element?.start ?? start, file);
244
+ return pageId(element, source, file);
245
+ });
246
+ const last = array.elements.at(-1);
247
+ return {
248
+ pages,
249
+ lastPage: {
250
+ start: last.start,
251
+ end: last.end
252
+ }
253
+ };
254
+ }
255
+ //#endregion
256
+ //#region src/ast/expression/types.ts
257
+ const UNARY_OPERATORS = [
258
+ "!",
259
+ "-",
260
+ "+",
261
+ "typeof"
262
+ ];
263
+ const BINARY_OPERATORS = [
264
+ "==",
265
+ "!=",
266
+ "===",
267
+ "!==",
268
+ "<",
269
+ "<=",
270
+ ">",
271
+ ">=",
272
+ "+",
273
+ "-",
274
+ "*",
275
+ "/",
276
+ "%",
277
+ "**",
278
+ "&&",
279
+ "||",
280
+ "??"
281
+ ];
282
+ //#endregion
283
+ //#region src/ast/expression/parse.ts
284
+ function parseExpression(source) {
285
+ if (source.trim().length === 0) failAt("The binding is empty", source, 0);
286
+ const { program, errors } = parseSync("binding.js", source, { preserveParens: false });
287
+ failOnSyntaxError(errors, source);
288
+ const [statement, extra] = program.body;
289
+ if (!statement || extra || statement.type !== "ExpressionStatement") return failAt("A binding must be one expression", source, statement?.start ?? 0);
290
+ return convert(statement.expression, source);
291
+ }
292
+ function convert(node, source) {
293
+ switch (node.type) {
294
+ case "Literal":
295
+ if (typeof node.value === "bigint" || node.value instanceof RegExp) break;
296
+ return {
297
+ type: "Literal",
298
+ value: node.value
299
+ };
300
+ case "Identifier": return {
301
+ type: "Identifier",
302
+ name: node.name
303
+ };
304
+ case "MemberExpression": {
305
+ if (node.object.type === "Super" || node.property.type === "PrivateIdentifier") break;
306
+ const object = convert(node.object, source);
307
+ if (node.computed) return {
308
+ type: "Member",
309
+ object,
310
+ property: convert(node.property, source)
311
+ };
312
+ return {
313
+ type: "Member",
314
+ object,
315
+ property: {
316
+ type: "Literal",
317
+ value: node.property.name
318
+ }
319
+ };
320
+ }
321
+ case "UnaryExpression":
322
+ if (!isOneOf(UNARY_OPERATORS, node.operator)) break;
323
+ return {
324
+ type: "Unary",
325
+ operator: node.operator,
326
+ argument: convert(node.argument, source)
327
+ };
328
+ case "BinaryExpression":
329
+ case "LogicalExpression":
330
+ if (node.left.type === "PrivateIdentifier" || !isOneOf(BINARY_OPERATORS, node.operator)) break;
331
+ return {
332
+ type: "Binary",
333
+ operator: node.operator,
334
+ left: convert(node.left, source),
335
+ right: convert(node.right, source)
336
+ };
337
+ case "ConditionalExpression": return {
338
+ type: "Conditional",
339
+ test: convert(node.test, source),
340
+ consequent: convert(node.consequent, source),
341
+ alternate: convert(node.alternate, source)
342
+ };
343
+ case "CallExpression":
344
+ case "NewExpression": return failAt("Bindings can't call functions", source, node.start);
345
+ case "AssignmentExpression":
346
+ case "UpdateExpression": return failAt("Bindings can't change values", source, node.start);
347
+ }
348
+ let detail = "";
349
+ if ("operator" in node) detail = ` \`${node.operator}\``;
350
+ return failAt(`Bindings can't use ${node.type}${detail}`, source, node.start);
351
+ }
352
+ function isOneOf(list, value) {
353
+ return list.includes(value);
354
+ }
355
+ //#endregion
356
+ export { ScriptParseError, parseDotModule, parseExpression, parseLogicModule, parseStateModule, unboundReferences };
357
+
358
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/utils.ts","../src/errors.ts","../src/module.ts","../src/globals.ts","../src/ast/page/parse.ts","../src/dot.ts","../src/ast/expression/types.ts","../src/ast/expression/parse.ts"],"sourcesContent":["import type { Expression, ObjectExpression, Program, PropertyKey } from 'oxc-parser';\n\ntype TopLevelStatement = Program['body'][number];\n\nfunction propertyName(key: PropertyKey): string | null {\n if (key.type === 'Identifier') {\n return key.name;\n }\n if (key.type === 'Literal' && typeof key.value === 'string') {\n return key.value;\n }\n return null;\n}\n\nexport function unwrapExpression(node: Expression): Expression {\n while (\n node.type === 'TSAsExpression' ||\n node.type === 'TSSatisfiesExpression' ||\n node.type === 'TSNonNullExpression'\n ) {\n node = node.expression;\n }\n return node;\n}\n\nexport interface StaticProperty {\n readonly name: string;\n readonly value: Expression;\n readonly start: number;\n}\n\n// The properties of an object literal whose names are written out. Computed ones are skipped.\nexport function staticProperties(object: ObjectExpression): StaticProperty[] {\n const properties: StaticProperty[] = [];\n for (const property of object.properties) {\n if (property.type !== 'Property' || property.computed) {\n continue;\n }\n const name = propertyName(property.key);\n if (name !== null) {\n properties.push({ name, value: property.value, start: property.start });\n }\n }\n return properties;\n}\n\n// Unwraps `export const ...` and the like to the declaration. Other statements pass through.\nexport function withoutExport(statement: TopLevelStatement): TopLevelStatement | null {\n if (statement.type === 'ExportNamedDeclaration') {\n return statement.declaration;\n }\n return statement;\n}\n","import type { OxcError } from 'oxc-parser';\nimport { locationAt, SourceError } from '@monimesl/dot-core';\n\nexport class ScriptParseError extends SourceError {\n override readonly name = 'ScriptParseError';\n}\n\nexport function failAt(reason: string, source: string, offset: number, file?: string): never {\n throw new ScriptParseError(reason, file, locationAt(source, offset));\n}\n\nexport function failOnSyntaxError(\n errors: readonly OxcError[],\n source: string,\n file?: string,\n): void {\n const [error] = errors;\n if (error) {\n failAt(error.message, source, error.labels[0]?.start ?? 0, file);\n }\n}\n","import { parseSync } from 'oxc-parser';\nimport type { Expression, ObjectExpression, Program } from 'oxc-parser';\n\nimport { unwrapExpression } from './utils';\nimport { failAt, failOnSyntaxError } from './errors';\n\nexport function parseModule(source: string, file: string): Program {\n const { program, errors } = parseSync(file, source, { lang: 'ts', sourceType: 'module' });\n failOnSyntaxError(errors, source, file);\n return program;\n}\n\nexport function defaultExport(program: Program): Expression | undefined {\n for (const statement of program.body) {\n if (statement.type !== 'ExportDefaultDeclaration') {\n continue;\n }\n const { declaration } = statement;\n switch (declaration.type) {\n case 'FunctionDeclaration':\n case 'ClassDeclaration':\n case 'TSInterfaceDeclaration':\n return undefined;\n default:\n return declaration;\n }\n }\n return undefined;\n}\n\nexport function defineCall(\n program: Program,\n source: string,\n file: string,\n callee: string,\n): ObjectExpression {\n const exported = defaultExport(program);\n const call = exported && unwrapExpression(exported);\n const options = call?.type === 'CallExpression' ? call.arguments[0] : undefined;\n if (\n call?.type !== 'CallExpression' ||\n call.callee.type !== 'Identifier' ||\n call.callee.name !== callee ||\n options?.type !== 'ObjectExpression'\n ) {\n return failAt(\n `${fileName(file)} must \\`export default ${callee}({ ... })\\``,\n source,\n exported?.start ?? 0,\n file,\n );\n }\n return options;\n}\n\n// The last segment of a path, with either separator.\nfunction fileName(path: string): string {\n const lastSeparator = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\'));\n return path.slice(lastSeparator + 1);\n}\n","import type { Program } from 'oxc-parser';\n\nimport { parseModule } from './module';\nimport { withoutExport } from './utils';\n\ninterface Node {\n readonly type: string;\n readonly [key: string]: unknown;\n}\n\n// Which of `names` a module uses without declaring or importing, for the compiler to import.\nexport function unboundReferences(\n source: string,\n names: readonly string[],\n file = 'module.ts',\n): string[] {\n const program = parseModule(source, file);\n const bound = topLevelBindings(program);\n const references = new Set<string>();\n collectReferences(program as unknown as Node, null, '', references);\n return names.filter((name) => references.has(name) && !bound.has(name));\n}\n\nfunction topLevelBindings(program: Program): Set<string> {\n const names = new Set<string>();\n for (const statement of program.body) {\n const declaration = withoutExport(statement);\n switch (declaration?.type) {\n case 'ImportDeclaration':\n for (const specifier of declaration.specifiers) {\n names.add(specifier.local.name);\n }\n break;\n case 'VariableDeclaration':\n for (const declarator of declaration.declarations) {\n collectPatternNames(declarator.id as unknown as Node, names);\n }\n break;\n case 'FunctionDeclaration':\n case 'ClassDeclaration':\n if (declaration.id) {\n names.add(declaration.id.name);\n }\n break;\n }\n }\n return names;\n}\n\nfunction collectPatternNames(pattern: Node, names: Set<string>): void {\n const visit = (child: unknown) => {\n if (isNode(child)) {\n collectPatternNames(child, names);\n }\n };\n switch (pattern.type) {\n case 'Identifier':\n names.add(pattern.name as string);\n break;\n case 'ObjectPattern':\n for (const property of pattern.properties as Node[]) {\n visit(property.type === 'RestElement' ? property.argument : property.value);\n }\n break;\n case 'ArrayPattern':\n for (const element of pattern.elements as unknown[]) {\n visit(element);\n }\n break;\n case 'RestElement':\n visit(pattern.argument);\n break;\n case 'AssignmentPattern':\n visit(pattern.left);\n break;\n }\n}\n\nfunction collectReferences(node: Node, parent: Node | null, key: string, out: Set<string>): void {\n if (node.type === 'ImportDeclaration') {\n return;\n }\n if (node.type === 'Identifier' && isReference(parent, key)) {\n out.add(node.name as string);\n }\n for (const [childKey, value] of Object.entries(node)) {\n for (const child of Array.isArray(value) ? value : [value]) {\n if (isNode(child)) {\n collectReferences(child, node, childKey, out);\n }\n }\n }\n}\n\n/** False for identifiers that name a property or label rather than refer to a variable. */\nfunction isReference(parent: Node | null, key: string): boolean {\n switch (parent?.type) {\n case 'MemberExpression':\n return key !== 'property' || parent.computed === true;\n case 'Property':\n case 'MethodDefinition':\n case 'PropertyDefinition':\n return key !== 'key' || parent.computed === true;\n case 'LabeledStatement':\n case 'BreakStatement':\n case 'ContinueStatement':\n return key !== 'label';\n default:\n return true;\n }\n}\n\nfunction isNode(value: unknown): value is Node {\n return typeof (value as Node | null)?.type === 'string';\n}\n","import { isPageId, PAGE_HOOKS } from '@monimesl/dot-core';\nimport type { Expression, ObjectExpression, Program } from 'oxc-parser';\n\nimport type { PageModule, PageStateModule } from './types';\nimport { failAt } from '../../errors';\nimport { defaultExport, defineCall, parseModule } from '../../module';\nimport type { StaticProperty } from '../../utils';\nimport { staticProperties, unwrapExpression, withoutExport } from '../../utils';\n\nconst HOOKS = new Set<string>(PAGE_HOOKS);\n\nexport function parseStateModule(source: string, file = 'state.ts'): PageStateModule {\n const program = parseModule(source, file);\n const exported = defaultExport(program);\n if (!exported) {\n return failAt('state.ts must have a default export', source, 0, file);\n }\n const properties = resolvedProperties(program, exported);\n return {\n keys: namesOf(properties),\n keyOffsets: offsetsOf(properties ?? []),\n };\n}\n\nexport function parseLogicModule(source: string, file = 'controller.ts'): PageModule {\n const program = parseModule(source, file);\n const options = defineCall(program, source, file, 'definePage');\n let id: string | null = null;\n let mutations: StaticProperty[] | null = [];\n let actions: StaticProperty[] | null = [];\n const hooks: string[] = [];\n for (const { name, value, start } of staticProperties(options)) {\n switch (name) {\n case 'initialState':\n case 'configs':\n break;\n case 'id':\n id = pageId(value, source, file);\n break;\n case 'hooks':\n if (value.type !== 'ObjectExpression') {\n break;\n }\n for (const hook of staticProperties(value)) {\n if (!HOOKS.has(hook.name)) {\n failAt(\n `Unknown page hook \\`${hook.name}\\`. The hooks are ${PAGE_HOOKS.join(', ')}`,\n source,\n hook.start,\n file,\n );\n }\n hooks.push(hook.name);\n }\n break;\n case 'mutations':\n mutations = resolvedProperties(program, value);\n break;\n case 'actions':\n actions = resolvedProperties(program, value);\n break;\n default:\n if (isFunction(value)) {\n failAt(`\\`${name}\\` must go in \\`mutations\\` or \\`actions\\``, source, start, file);\n } else {\n failAt(\n `Unknown option \\`${name}\\`. definePage takes id, initialState, configs, hooks, mutations and actions`,\n source,\n start,\n file,\n );\n }\n }\n }\n const mutationNames = namesOf(mutations);\n const actionNames = namesOf(actions);\n const clash = mutationNames?.find((name) => actionNames?.includes(name));\n if (clash) {\n failAt(`\\`${clash}\\` is both a mutation and an action`, source, options.start, file);\n }\n return {\n id,\n mutations: mutationNames,\n actions: actionNames,\n hooks,\n handlerOffsets: offsetsOf([...(mutations ?? []), ...(actions ?? [])]),\n };\n}\n\nfunction isFunction(node: Expression): boolean {\n return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';\n}\n\n// The properties of the object literal that `node` is or names. Null when any can't be read\n// without running the code.\nfunction resolvedProperties(program: Program, node: Expression): StaticProperty[] | null {\n const object = resolveObject(program, node);\n if (!object) {\n return null;\n }\n const properties = staticProperties(object);\n return properties.length === object.properties.length ? properties : null;\n}\n\nfunction namesOf(properties: readonly StaticProperty[] | null): string[] | null {\n return properties?.map((property) => property.name) ?? null;\n}\n\nfunction offsetsOf(properties: readonly StaticProperty[]): Record<string, number> {\n const offsets: Record<string, number> = {};\n for (const property of properties) {\n offsets[property.name] = property.start;\n }\n return offsets;\n}\n\n/** Follows `export default state` back to `const state = { ... }`. */\nfunction resolveObject(program: Program, node: Expression): ObjectExpression | null {\n const target = unwrapExpression(node);\n if (target.type === 'ObjectExpression') {\n return target;\n }\n if (target.type !== 'Identifier') {\n return null;\n }\n\n for (const statement of program.body) {\n const declaration = withoutExport(statement);\n if (declaration?.type !== 'VariableDeclaration' || declaration.kind !== 'const') {\n continue;\n }\n for (const declarator of declaration.declarations) {\n if (declarator.id.type === 'Identifier' && declarator.id.name === target.name) {\n return declarator.init ? resolveObject(program, declarator.init) : null;\n }\n }\n }\n return null;\n}\n\n/** Reads a page id, which must be a string literal made of safe characters. */\nexport function pageId(node: Expression, source: string, file: string): string {\n const value = unwrapExpression(node);\n if (value.type !== 'Literal' || typeof value.value !== 'string') {\n return failAt(\n \"A page id must be written as a string, such as 'cart'\",\n source,\n node.start,\n file,\n );\n }\n if (!isPageId(value.value)) {\n return failAt(\n `\"${value.value}\" isn't a valid page id. Use letters, digits, \"-\" and \"_\", with \"/\" between folders`,\n source,\n node.start,\n file,\n );\n }\n return value.value;\n}\n","import { failAt } from './errors';\nimport { pageId } from './ast/page/parse';\nimport { defineCall, parseModule } from './module';\nimport { staticProperties, unwrapExpression } from './utils';\n\nexport interface DotModuleIR {\n readonly pages: readonly string[];\n readonly lastPage: { readonly start: number; readonly end: number };\n}\n\nexport function parseDotModule(source: string, file = 'dot.ts'): DotModuleIR {\n const program = parseModule(source, file);\n const options = defineCall(program, source, file, 'defineDot');\n const pagesProperty = staticProperties(options).find((property) => property.name === 'pages');\n if (!pagesProperty) {\n return failAt(\n 'defineDot needs `pages`, a list of page folders with the entry page first',\n source,\n options.start,\n file,\n );\n }\n const { value, start } = pagesProperty;\n const array = unwrapExpression(value);\n if (array.type !== 'ArrayExpression') {\n return failAt('`pages` must be a list of page folders', source, start, file);\n }\n if (array.elements.length === 0) {\n return failAt('`pages` needs at least one page', source, start, file);\n }\n const pages = array.elements.map((element) => {\n if (!element || element.type === 'SpreadElement') {\n return failAt(\n '`pages` must list each page folder as a string',\n source,\n element?.start ?? start,\n file,\n );\n }\n return pageId(element, source, file);\n });\n const last = array.elements.at(-1)!;\n return { pages, lastPage: { start: last.start, end: last.end } };\n}\n","export const UNARY_OPERATORS = ['!', '-', '+', 'typeof'] as const;\n\nexport const BINARY_OPERATORS = [\n '==',\n '!=',\n '===',\n '!==',\n '<',\n '<=',\n '>',\n '>=',\n '+',\n '-',\n '*',\n '/',\n '%',\n '**',\n '&&',\n '||',\n '??',\n] as const;\n\nexport type LiteralValue = string | number | boolean | null;\n\ntype LiteralNode = { readonly type: 'Literal'; readonly value: LiteralValue };\n\ntype IdentifierNode = { readonly type: 'Identifier'; readonly name: string };\n\ntype MemberNode = {\n readonly type: 'Member';\n readonly object: ExprNode;\n readonly property: ExprNode;\n};\n\nexport type UnaryOperator = (typeof UNARY_OPERATORS)[number];\n\ntype UnaryExprNode = {\n readonly type: 'Unary';\n readonly operator: UnaryOperator;\n readonly argument: ExprNode;\n};\n\nexport type BinaryOperator = (typeof BINARY_OPERATORS)[number];\n\ntype BinaryExprNode = {\n readonly type: 'Binary';\n readonly operator: BinaryOperator;\n readonly left: ExprNode;\n readonly right: ExprNode;\n};\n\ntype ConditionalExprNode = {\n readonly type: 'Conditional';\n readonly test: ExprNode;\n readonly consequent: ExprNode;\n readonly alternate: ExprNode;\n};\n\nexport type ExprNode =\n LiteralNode | IdentifierNode | MemberNode | UnaryExprNode | BinaryExprNode | ConditionalExprNode;\n","import type { Expression } from 'oxc-parser';\nimport { parseSync } from 'oxc-parser';\n\nimport { failAt, failOnSyntaxError } from '../../errors';\nimport { BINARY_OPERATORS, type ExprNode, UNARY_OPERATORS } from './types';\n\n// Parses what's inside a `{{ }}` binding into an expression tree.\nexport function parseExpression(source: string): ExprNode {\n if (source.trim().length === 0) {\n failAt('The binding is empty', source, 0);\n }\n const { program, errors } = parseSync('binding.js', source, { preserveParens: false });\n failOnSyntaxError(errors, source);\n const [statement, extra] = program.body;\n if (!statement || extra || statement.type !== 'ExpressionStatement') {\n return failAt('A binding must be one expression', source, statement?.start ?? 0);\n }\n return convert(statement.expression, source);\n}\n\nfunction convert(node: Expression, source: string): ExprNode {\n switch (node.type) {\n case 'Literal':\n if (typeof node.value === 'bigint' || node.value instanceof RegExp) {\n break;\n }\n return { type: 'Literal', value: node.value };\n case 'Identifier':\n return { type: 'Identifier', name: node.name };\n case 'MemberExpression': {\n if (node.object.type === 'Super' || node.property.type === 'PrivateIdentifier') {\n break;\n }\n const object = convert(node.object, source);\n if (node.computed) {\n return { type: 'Member', object, property: convert(node.property, source) };\n }\n return { type: 'Member', object, property: { type: 'Literal', value: node.property.name } };\n }\n case 'UnaryExpression':\n if (!isOneOf(UNARY_OPERATORS, node.operator)) {\n break;\n }\n return { type: 'Unary', operator: node.operator, argument: convert(node.argument, source) };\n case 'BinaryExpression':\n case 'LogicalExpression':\n if (node.left.type === 'PrivateIdentifier' || !isOneOf(BINARY_OPERATORS, node.operator)) {\n break;\n }\n return {\n type: 'Binary',\n operator: node.operator,\n left: convert(node.left, source),\n right: convert(node.right, source),\n };\n case 'ConditionalExpression':\n return {\n type: 'Conditional',\n test: convert(node.test, source),\n consequent: convert(node.consequent, source),\n alternate: convert(node.alternate, source),\n };\n case 'CallExpression':\n case 'NewExpression':\n return failAt(\"Bindings can't call functions\", source, node.start);\n case 'AssignmentExpression':\n case 'UpdateExpression':\n return failAt(\"Bindings can't change values\", source, node.start);\n }\n let detail = '';\n if ('operator' in node) {\n detail = ` \\`${node.operator}\\``;\n }\n return failAt(`Bindings can't use ${node.type}${detail}`, source, node.start);\n}\n\nfunction isOneOf<T extends string>(list: readonly T[], value: string): value is T {\n return (list as readonly string[]).includes(value);\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@monimesl/dot-script-parser",
3
+ "version": "0.1.0-alpha.10",
4
+ "description": "Dot page script parser: page state and logic -> intermediary representation",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/monime-lab/dot.git",
9
+ "directory": "packages/parsers/script"
10
+ },
11
+ "sideEffects": false,
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "@monimesl/dot-source": "./src/index.ts",
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "./package.json": "./package.json"
23
+ },
24
+ "main": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "devDependencies": {
27
+ "publint": "^0.3.24",
28
+ "rimraf": "^6.1.3",
29
+ "tsdown": "^0.23.0",
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^5.0.1"
32
+ },
33
+ "dependencies": {
34
+ "oxc-parser": "^0.151.0",
35
+ "@monimesl/dot-core": "0.1.0-alpha.10"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "scripts": {
41
+ "build": "tsdown",
42
+ "dev": "tsdown --watch",
43
+ "typecheck": "tsc --noEmit -p tsconfig.json",
44
+ "test": "vitest run",
45
+ "clean": "rimraf dist *.tsbuildinfo"
46
+ }
47
+ }