@vesk/compiler 0.0.1

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.
Files changed (84) hide show
  1. package/README.md +23 -0
  2. package/dist/acorn-ts-plugin/index.d.ts +482 -0
  3. package/dist/acorn-ts-plugin/index.d.ts.map +1 -0
  4. package/dist/acorn-ts-plugin/index.js +5028 -0
  5. package/dist/actions.d.ts +22 -0
  6. package/dist/actions.d.ts.map +1 -0
  7. package/dist/actions.js +167 -0
  8. package/dist/api-routes.d.ts +30 -0
  9. package/dist/api-routes.d.ts.map +1 -0
  10. package/dist/api-routes.js +350 -0
  11. package/dist/client-codegen.d.ts +19 -0
  12. package/dist/client-codegen.d.ts.map +1 -0
  13. package/dist/client-codegen.js +1523 -0
  14. package/dist/config.d.ts +6 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +106 -0
  17. package/dist/errors.d.ts +33 -0
  18. package/dist/errors.d.ts.map +1 -0
  19. package/dist/errors.js +210 -0
  20. package/dist/index.d.ts +16 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +8 -0
  23. package/dist/ir-generator.d.ts +10 -0
  24. package/dist/ir-generator.d.ts.map +1 -0
  25. package/dist/ir-generator.js +1062 -0
  26. package/dist/ir.d.ts +160 -0
  27. package/dist/ir.d.ts.map +1 -0
  28. package/dist/ir.js +219 -0
  29. package/dist/middleware.d.ts +15 -0
  30. package/dist/middleware.d.ts.map +1 -0
  31. package/dist/middleware.js +183 -0
  32. package/dist/package.json +15 -0
  33. package/dist/parser.d.ts +38 -0
  34. package/dist/parser.d.ts.map +1 -0
  35. package/dist/parser.js +242 -0
  36. package/dist/router.d.ts +31 -0
  37. package/dist/router.d.ts.map +1 -0
  38. package/dist/router.js +451 -0
  39. package/dist/scan.d.ts +106 -0
  40. package/dist/scan.d.ts.map +1 -0
  41. package/dist/scan.js +438 -0
  42. package/dist/server-codegen.d.ts +5 -0
  43. package/dist/server-codegen.d.ts.map +1 -0
  44. package/dist/server-codegen.js +4 -0
  45. package/dist/server-cookies.d.ts +2 -0
  46. package/dist/server-cookies.d.ts.map +1 -0
  47. package/dist/server-cookies.js +15 -0
  48. package/dist/server-head.d.ts +10 -0
  49. package/dist/server-head.d.ts.map +1 -0
  50. package/dist/server-head.js +289 -0
  51. package/dist/server-jsgen.d.ts +6 -0
  52. package/dist/server-jsgen.d.ts.map +1 -0
  53. package/dist/server-jsgen.js +446 -0
  54. package/dist/server-render.d.ts +16 -0
  55. package/dist/server-render.d.ts.map +1 -0
  56. package/dist/server-render.js +397 -0
  57. package/dist/server-utils.d.ts +93 -0
  58. package/dist/server-utils.d.ts.map +1 -0
  59. package/dist/server-utils.js +747 -0
  60. package/dist/ssr-store.d.ts +4 -0
  61. package/dist/ssr-store.d.ts.map +1 -0
  62. package/dist/ssr-store.js +29 -0
  63. package/dist/strip-ts.d.ts +25 -0
  64. package/dist/strip-ts.d.ts.map +1 -0
  65. package/dist/strip-ts.js +171 -0
  66. package/dist/tokens.d.ts +50 -0
  67. package/dist/tokens.d.ts.map +1 -0
  68. package/dist/tokens.js +334 -0
  69. package/dist/typecheck.d.ts +19 -0
  70. package/dist/typecheck.d.ts.map +1 -0
  71. package/dist/typecheck.js +365 -0
  72. package/dist/types.d.ts +147 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +13 -0
  75. package/dist/vesk-plugin.d.ts +53 -0
  76. package/dist/vesk-plugin.d.ts.map +1 -0
  77. package/dist/vesk-plugin.js +413 -0
  78. package/dist/vsk-imports.d.ts +30 -0
  79. package/dist/vsk-imports.d.ts.map +1 -0
  80. package/dist/vsk-imports.js +141 -0
  81. package/dist/vsk-tsx.d.ts +3 -0
  82. package/dist/vsk-tsx.d.ts.map +1 -0
  83. package/dist/vsk-tsx.js +604 -0
  84. package/package.json +52 -0
package/dist/parser.js ADDED
@@ -0,0 +1,242 @@
1
+ import * as acorn from 'acorn';
2
+ import { tsPlugin } from './acorn-ts-plugin/index.js';
3
+ import { VeskParserPlugin } from '@vesk/compiler/src/vesk-plugin';
4
+ import { containsForOfIn } from '@vesk/compiler/src/scan';
5
+ function isIdentChar(code) {
6
+ return ((code >= 97 && code <= 122) || (code >= 65 && code <= 90) || (code >= 48 && code <= 57) || code === 95 || code === 36);
7
+ }
8
+ function isWhitespaceChar(ch) {
9
+ return ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r' || ch === '\f' || ch === '\v' || ch === '\u00a0' || ch === '\ufeff';
10
+ }
11
+ /**
12
+ * Scans the source and blanks `; key <expr>` / `; index <ident>` clauses
13
+ * found in `for (...)` headers, returning the rewritten code (same length
14
+ * as the input, so every source offset is preserved) plus annotations.
15
+ */
16
+ export function preprocessForClauses(source) {
17
+ const annotations = [];
18
+ const chars = source.split('');
19
+ const isString = (ch) => ch === '"' || ch === "'" || ch === '`';
20
+ let i = 0;
21
+ while (i < source.length) {
22
+ const ch = source[i];
23
+ // Skip strings and comments (nested backtick templates keep depth).
24
+ if (isString(ch)) {
25
+ const quote = ch;
26
+ let j = i + 1;
27
+ let tplDepth = 0;
28
+ while (j < source.length) {
29
+ const c = source[j];
30
+ if (c === '\\') {
31
+ j += 2;
32
+ continue;
33
+ }
34
+ if (quote === '`' && c === '$' && source[j + 1] === '{') {
35
+ tplDepth++;
36
+ j += 2;
37
+ continue;
38
+ }
39
+ if (quote === '`' && c === '}' && tplDepth > 0) {
40
+ tplDepth--;
41
+ j++;
42
+ continue;
43
+ }
44
+ if (c === quote && tplDepth === 0) {
45
+ j++;
46
+ break;
47
+ }
48
+ j++;
49
+ }
50
+ i = j;
51
+ continue;
52
+ }
53
+ if (ch === '/' && source[i + 1] === '/') {
54
+ let j = i + 2;
55
+ while (j < source.length && source[j] !== '\n')
56
+ j++;
57
+ i = j;
58
+ continue;
59
+ }
60
+ if (ch === '/' && source[i + 1] === '*') {
61
+ let j = i + 2;
62
+ while (j < source.length && !(source[j] === '*' && source[j + 1] === '/'))
63
+ j++;
64
+ i = Math.min(j + 2, source.length);
65
+ continue;
66
+ }
67
+ // `for` keyword followed by `(` — scan the header.
68
+ if (ch === 'f' && source.startsWith('for', i)) {
69
+ const before = i === 0 ? ' ' : source[i - 1];
70
+ if (!isIdentChar(source.charCodeAt(i + 3) || 0) && (i === 0 || !isIdentChar(before.charCodeAt(0)))) {
71
+ let p = i + 3;
72
+ while (p < source.length && isWhitespaceChar(source[p]))
73
+ p++;
74
+ if (source[p] === '(') {
75
+ let depth = 0;
76
+ let j = p;
77
+ while (j < source.length) {
78
+ const c = source[j];
79
+ if (isString(c)) {
80
+ const quote = c;
81
+ let k = j + 1;
82
+ while (k < source.length) {
83
+ if (source[k] === '\\') {
84
+ k += 2;
85
+ continue;
86
+ }
87
+ if (source[k] === quote) {
88
+ k++;
89
+ break;
90
+ }
91
+ k++;
92
+ }
93
+ j = k;
94
+ continue;
95
+ }
96
+ if (c === '(' || c === '[' || c === '{')
97
+ depth++;
98
+ else if (c === ')' || c === ']' || c === '}') {
99
+ depth--;
100
+ if (c === ')' && depth === 0)
101
+ break;
102
+ }
103
+ j++;
104
+ }
105
+ const headerEnd = Math.min(j, source.length - 1);
106
+ // Only `for (... of ...)` / `for (... in ...)` headers may carry
107
+ // `; key` / `; index` clauses. Classic for-loops keep their `;`
108
+ // separated clauses untouched (`for (let key = 0; key < 5; ...)`
109
+ // must not be blanked).
110
+ let firstSemi = -1;
111
+ let depth1 = 0;
112
+ for (let q = p + 1; q < headerEnd; q++) {
113
+ const c = source[q];
114
+ if (c === '(' || c === '[' || c === '{')
115
+ depth1++;
116
+ else if (c === ')' || c === ']' || c === '}')
117
+ depth1--;
118
+ else if (c === ';' && depth1 === 0) {
119
+ firstSemi = q;
120
+ break;
121
+ }
122
+ }
123
+ const preSemi = source.slice(p + 1, firstSemi === -1 ? headerEnd : firstSemi);
124
+ if (!containsForOfIn(preSemi)) {
125
+ i = headerEnd;
126
+ continue;
127
+ }
128
+ // Collect top-level `;` clause starts inside the header.
129
+ const clauseStarts = [];
130
+ let depth2 = 0;
131
+ for (let q = p + 1; q < headerEnd; q++) {
132
+ const c = source[q];
133
+ if (isString(c)) {
134
+ const quote = c;
135
+ let k = q + 1;
136
+ while (k < source.length) {
137
+ if (source[k] === '\\') {
138
+ k += 2;
139
+ continue;
140
+ }
141
+ if (source[k] === quote) {
142
+ k++;
143
+ break;
144
+ }
145
+ k++;
146
+ }
147
+ q = k - 1;
148
+ continue;
149
+ }
150
+ if (c === '(' || c === '[' || c === '{')
151
+ depth2++;
152
+ else if (c === ')' || c === ']' || c === '}')
153
+ depth2--;
154
+ else if (c === ';' && depth2 === 0)
155
+ clauseStarts.push(q);
156
+ }
157
+ for (let c = 0; c < clauseStarts.length; c++) {
158
+ const start = clauseStarts[c];
159
+ const end = c + 1 < clauseStarts.length ? clauseStarts[c + 1] : headerEnd;
160
+ // `clause` includes the leading `;` — it must be blanked too,
161
+ // otherwise the header no longer parses as a for-of/for-in.
162
+ const clause = source.slice(start, end);
163
+ let clauseCode = clause;
164
+ let keyRange;
165
+ let indexName;
166
+ // `clause` starts with the `;` — parse the keyword by hand so no
167
+ // regex is involved: `; key <expr>` or `; index <ident>`.
168
+ let q = start;
169
+ if (source[q] === ';')
170
+ q++;
171
+ while (q < end && isWhitespaceChar(source[q]))
172
+ q++;
173
+ let kwStart = q;
174
+ while (q < end && isIdentChar(source.charCodeAt(q)))
175
+ q++;
176
+ const keyword = source.slice(kwStart, q);
177
+ if (keyword === 'key') {
178
+ let k = q;
179
+ while (k < end && isWhitespaceChar(source[k]))
180
+ k++;
181
+ const expr = source.slice(k, end).trim();
182
+ if (expr) {
183
+ keyRange = [k, start + clause.length];
184
+ clauseCode = ' '.repeat(clause.length);
185
+ }
186
+ }
187
+ else if (keyword === 'index') {
188
+ let k = q;
189
+ while (k < end && isWhitespaceChar(source[k]))
190
+ k++;
191
+ const identStart = k;
192
+ while (k < end && isIdentChar(source.charCodeAt(k)))
193
+ k++;
194
+ const ident = source.slice(identStart, k);
195
+ let m = k;
196
+ while (m < end && isWhitespaceChar(source[m]))
197
+ m++;
198
+ if (ident && m === end) {
199
+ indexName = ident;
200
+ clauseCode = ' '.repeat(clause.length);
201
+ }
202
+ }
203
+ if (keyRange || indexName) {
204
+ for (let q = 0; q < clause.length; q++)
205
+ chars[start + q] = clauseCode[q];
206
+ annotations.push({
207
+ kind: 'for-clause',
208
+ forStart: i,
209
+ clauseStart: start,
210
+ clauseEnd: end,
211
+ ...(keyRange ? { keyRange } : {}),
212
+ ...(indexName !== undefined ? { indexName } : {}),
213
+ });
214
+ }
215
+ }
216
+ i = headerEnd;
217
+ continue;
218
+ }
219
+ }
220
+ }
221
+ i++;
222
+ }
223
+ return { code: chars.join(''), annotations };
224
+ }
225
+ export function createBaseParser() {
226
+ return acorn.Parser.extend(tsPlugin({}), VeskParserPlugin());
227
+ }
228
+ export function parse(source, options = {}) {
229
+ const ParserClass = createBaseParser();
230
+ const { code, annotations } = preprocessForClauses(source);
231
+ const ast = ParserClass.parse(code, {
232
+ ecmaVersion: 'latest',
233
+ sourceType: 'module',
234
+ locations: true,
235
+ ranges: true,
236
+ ...(options.filename ? { sourceFilename: options.filename } : {}),
237
+ });
238
+ if (annotations.length > 0) {
239
+ ast.__vskAnnotations = annotations;
240
+ }
241
+ return ast;
242
+ }
@@ -0,0 +1,31 @@
1
+ import type { RouteNode } from '@vesk/compiler/src/types';
2
+ export interface ScanOptions {
3
+ layoutCompName?: string;
4
+ pageCompName?: string;
5
+ compName?: string;
6
+ }
7
+ export interface MatchResult {
8
+ nodes: RouteNode[];
9
+ params: Record<string, string>;
10
+ }
11
+ /**
12
+ * Extracts `export (async) function middleware(params) { body }` from
13
+ * middleware source text. Parses with acorn (via the Vesk parser) so
14
+ * default params, nested parens and strings in the parameter list are
15
+ * handled correctly; falls back to the old regex + brace balance when the
16
+ * source does not parse.
17
+ */
18
+ export declare function extractMiddlewareParts(src: string): {
19
+ params: string;
20
+ body: string;
21
+ } | null;
22
+ export declare function extractMiddleware(sourcePath: string): string | null;
23
+ export declare function scanRoutes(appDir: string, options?: ScanOptions): RouteNode[];
24
+ export declare function scanComponents(componentsDir: string): Map<string, string>;
25
+ export declare function collectSources(tree: RouteNode[]): Map<string, string>;
26
+ export interface RouteManifestOptions {
27
+ importPrefix?: string;
28
+ }
29
+ export declare function generateRouteManifest(tree: RouteNode[], options?: RouteManifestOptions): string;
30
+ export declare function matchUrl(tree: RouteNode[], pathname: string): MatchResult | null;
31
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAM1D,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAsB3F;AAkDD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUnE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,SAAS,EAAE,CAKjF;AAMD,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BzE;AAmHD,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAcrE;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAgCnG;AAkBD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAiFhF"}