svelte-origin 0.0.0 → 1.0.0-next.15
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.
Potentially problematic release.
This version of svelte-origin might be problematic. Click here for more details.
- package/LLM.md +754 -0
- package/README.md +412 -1
- package/dist/aliases.d.ts +44 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +3440 -0
- package/dist/generate-dts.d.ts +31 -0
- package/dist/globals.d.ts +576 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +6685 -0
- package/dist/plugin.d.ts +143 -0
- package/dist/plugin.js +3467 -0
- package/dist/post-process.d.ts +27 -0
- package/dist/post-process.js +3071 -0
- package/dist/preprocess.d.ts +73 -0
- package/dist/preprocess.js +3360 -0
- package/dist/runtime/attrs.d.ts +52 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +3665 -0
- package/dist/runtime/origin.d.ts +144 -0
- package/dist/runtime/types.d.ts +173 -0
- package/dist/transform/attrs-for-transform.d.ts +24 -0
- package/dist/transform/attrs-origin-transform.d.ts +62 -0
- package/dist/transform/attrs-schema.d.ts +52 -0
- package/dist/transform/codegen.d.ts +15 -0
- package/dist/transform/core.d.ts +62 -0
- package/dist/transform/declaration-parser.d.ts +77 -0
- package/dist/transform/element-types.d.ts +10 -0
- package/dist/transform/origin-transform.d.ts +51 -0
- package/dist/transform/patterns.d.ts +82 -0
- package/dist/transform/schema.d.ts +116 -0
- package/dist/transform/standalone-attrs-transform.d.ts +36 -0
- package/dist/vite-dts.d.ts +17 -0
- package/dist/vite-dts.js +606 -0
- package/package.json +73 -3
package/dist/vite-dts.js
ADDED
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
// src/vite-dts.ts
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { writeFile, readFile, unlink } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
// src/transform/patterns.ts
|
|
7
|
+
var patterns = {
|
|
8
|
+
hasMacros: /\$origin|\$attrs\.(origin|for)|\$attrs\s*\(/,
|
|
9
|
+
origin: /\$origin\s*\(/g,
|
|
10
|
+
originWithParents: /\$origin\s*\(\s*\[/,
|
|
11
|
+
attrsInOrigin: /\$attrs\s*\(\s*\{/g,
|
|
12
|
+
standaloneAttrs: /(?:let|const|export\s+const|export\s+let)\s+\w+\s*=\s*\$attrs\s*\(/g,
|
|
13
|
+
bindableInAttrs: /\$bindable\s*\(/g,
|
|
14
|
+
attrsOrigin: /\$attrs\s*\.\s*origin\s*\(\s*(\w+)\s*\)/g,
|
|
15
|
+
attrsForOrigin: /\$attrs\s*\.\s*for\s*\(\s*(\w+)\s*\)/g,
|
|
16
|
+
attrsForElement: /\$attrs\s*\.\s*for\s*\(\s*['"]([\w-]+)['"]\s*\)/g
|
|
17
|
+
};
|
|
18
|
+
function containsMacros(source) {
|
|
19
|
+
return patterns.hasMacros.test(source);
|
|
20
|
+
}
|
|
21
|
+
function isInsideStringOrComment(source, position) {
|
|
22
|
+
let i = 0;
|
|
23
|
+
while (i < position) {
|
|
24
|
+
const char = source[i];
|
|
25
|
+
if (char === "/" && source[i + 1] === "/") {
|
|
26
|
+
const endLine = source.indexOf(`
|
|
27
|
+
`, i + 2);
|
|
28
|
+
if (endLine === -1) {
|
|
29
|
+
return position > i;
|
|
30
|
+
}
|
|
31
|
+
if (position > i && position <= endLine) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
i = endLine + 1;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (char === "/" && source[i + 1] === "*") {
|
|
38
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
39
|
+
if (endComment === -1) {
|
|
40
|
+
return position > i;
|
|
41
|
+
}
|
|
42
|
+
if (position > i && position < endComment + 2) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
i = endComment + 2;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
49
|
+
const quote = char;
|
|
50
|
+
const stringStart = i;
|
|
51
|
+
i++;
|
|
52
|
+
while (i < source.length) {
|
|
53
|
+
if (source[i] === "\\") {
|
|
54
|
+
i += 2;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (source[i] === quote) {
|
|
58
|
+
if (position > stringStart && position <= i) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
i++;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
if (quote === "`" && source[i] === "$" && source[i + 1] === "{") {
|
|
65
|
+
const exprStart = i;
|
|
66
|
+
i += 2;
|
|
67
|
+
let depth = 1;
|
|
68
|
+
while (i < source.length && depth > 0) {
|
|
69
|
+
if (source[i] === "{")
|
|
70
|
+
depth++;
|
|
71
|
+
else if (source[i] === "}")
|
|
72
|
+
depth--;
|
|
73
|
+
else if (source[i] === "\\")
|
|
74
|
+
i++;
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
if (position > stringStart && position < exprStart) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
i++;
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
function extractBindable(value) {
|
|
91
|
+
if (!value.startsWith("$bindable"))
|
|
92
|
+
return { isBindable: false };
|
|
93
|
+
let i = 9;
|
|
94
|
+
if (value[i] === "<") {
|
|
95
|
+
let depth = 1;
|
|
96
|
+
i++;
|
|
97
|
+
while (i < value.length && depth > 0) {
|
|
98
|
+
const char = value[i];
|
|
99
|
+
if (char === "=" && value[i + 1] === ">") {
|
|
100
|
+
i += 2;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (char === "<")
|
|
104
|
+
depth++;
|
|
105
|
+
else if (char === ">")
|
|
106
|
+
depth--;
|
|
107
|
+
i++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
while (i < value.length && /\s/.test(value[i]))
|
|
111
|
+
i++;
|
|
112
|
+
if (value[i] !== "(")
|
|
113
|
+
return { isBindable: false };
|
|
114
|
+
const openParen = i;
|
|
115
|
+
const closeParen = findMatchingBracket(value, openParen);
|
|
116
|
+
if (closeParen === -1)
|
|
117
|
+
return { isBindable: false };
|
|
118
|
+
const innerValue = value.slice(openParen + 1, closeParen).trim() || "undefined";
|
|
119
|
+
return { isBindable: true, innerValue };
|
|
120
|
+
}
|
|
121
|
+
function findTopLevelAs(value) {
|
|
122
|
+
let depth = 0;
|
|
123
|
+
let angleDepth = 0;
|
|
124
|
+
for (let i = 0;i < value.length - 4; i++) {
|
|
125
|
+
const char = value[i];
|
|
126
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
127
|
+
const quote = char;
|
|
128
|
+
i++;
|
|
129
|
+
while (i < value.length && value[i] !== quote) {
|
|
130
|
+
if (value[i] === "\\")
|
|
131
|
+
i++;
|
|
132
|
+
i++;
|
|
133
|
+
}
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (char === "{" || char === "(" || char === "[") {
|
|
137
|
+
depth++;
|
|
138
|
+
} else if (char === "}" || char === ")" || char === "]") {
|
|
139
|
+
depth--;
|
|
140
|
+
} else if (char === "<") {
|
|
141
|
+
const prevChar = i > 0 ? value[i - 1] : "";
|
|
142
|
+
if (/[\w$)]/.test(prevChar)) {
|
|
143
|
+
angleDepth++;
|
|
144
|
+
}
|
|
145
|
+
} else if (char === ">") {
|
|
146
|
+
if (i > 0 && value[i - 1] === "=") {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (angleDepth > 0) {
|
|
150
|
+
angleDepth--;
|
|
151
|
+
}
|
|
152
|
+
} else if (depth === 0 && angleDepth === 0 && value.slice(i, i + 4) === " as ") {
|
|
153
|
+
return i;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return -1;
|
|
157
|
+
}
|
|
158
|
+
function findMatchingBracket(source, openIndex, openChar = "(", closeChar = ")") {
|
|
159
|
+
let depth = 0;
|
|
160
|
+
for (let i = openIndex;i < source.length; i++) {
|
|
161
|
+
const char = source[i];
|
|
162
|
+
if (char === "/" && source[i + 1] === "/") {
|
|
163
|
+
const endLine = source.indexOf(`
|
|
164
|
+
`, i + 2);
|
|
165
|
+
if (endLine !== -1) {
|
|
166
|
+
i = endLine;
|
|
167
|
+
} else {
|
|
168
|
+
i = source.length;
|
|
169
|
+
}
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (char === "/" && source[i + 1] === "*") {
|
|
173
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
174
|
+
if (endComment !== -1) {
|
|
175
|
+
i = endComment + 1;
|
|
176
|
+
} else {
|
|
177
|
+
i = source.length;
|
|
178
|
+
}
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
182
|
+
const quote = char;
|
|
183
|
+
i++;
|
|
184
|
+
while (i < source.length && source[i] !== quote) {
|
|
185
|
+
if (source[i] === "\\")
|
|
186
|
+
i++;
|
|
187
|
+
i++;
|
|
188
|
+
}
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (char === openChar) {
|
|
192
|
+
depth++;
|
|
193
|
+
} else if (char === closeChar) {
|
|
194
|
+
depth--;
|
|
195
|
+
if (depth === 0) {
|
|
196
|
+
return i;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return -1;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/transform/schema.ts
|
|
204
|
+
function parseOriginSchemaFromSource(source, exportName) {
|
|
205
|
+
const exportPattern = new RegExp(`export\\s+const\\s+${exportName}\\s*=\\s*\\$origin\\s*\\(`, "s");
|
|
206
|
+
const match = exportPattern.exec(source);
|
|
207
|
+
if (!match)
|
|
208
|
+
return null;
|
|
209
|
+
const originStart = match.index + match[0].length - 1;
|
|
210
|
+
const originEnd = findMatchingBracket(source, originStart);
|
|
211
|
+
if (originEnd === -1)
|
|
212
|
+
return null;
|
|
213
|
+
const originContent = source.slice(originStart + 1, originEnd);
|
|
214
|
+
let parentNames = [];
|
|
215
|
+
let bodyContent = originContent.trim();
|
|
216
|
+
if (bodyContent.startsWith("[")) {
|
|
217
|
+
const closeBracket = findMatchingBracket(bodyContent, 0, "[", "]");
|
|
218
|
+
if (closeBracket !== -1) {
|
|
219
|
+
const parentsContent = bodyContent.slice(1, closeBracket);
|
|
220
|
+
parentNames = parentsContent.split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
|
|
221
|
+
let i = closeBracket + 1;
|
|
222
|
+
while (i < bodyContent.length && /[\s,]/.test(bodyContent[i]))
|
|
223
|
+
i++;
|
|
224
|
+
bodyContent = bodyContent.slice(i);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const attrsMatch = bodyContent.match(/(\w+)\s*:\s*\$attrs\s*\(\s*\{/);
|
|
228
|
+
if (!attrsMatch) {
|
|
229
|
+
return { attrs: [], parentNames };
|
|
230
|
+
}
|
|
231
|
+
const attrsStart = attrsMatch.index;
|
|
232
|
+
const attrsObjStart = bodyContent.indexOf("{", attrsStart + attrsMatch[0].length - 1);
|
|
233
|
+
const attrsObjEnd = findMatchingBracket(bodyContent, attrsObjStart, "{", "}");
|
|
234
|
+
if (attrsObjEnd === -1) {
|
|
235
|
+
return { attrs: [], parentNames };
|
|
236
|
+
}
|
|
237
|
+
const attrsContent = bodyContent.slice(attrsObjStart + 1, attrsObjEnd);
|
|
238
|
+
const attrs = parseAttrsContent(attrsContent);
|
|
239
|
+
return { attrs, parentNames };
|
|
240
|
+
}
|
|
241
|
+
function parseAttrsContent(content) {
|
|
242
|
+
const result = [];
|
|
243
|
+
const parts = splitByTopLevelCommas(content);
|
|
244
|
+
for (const part of parts) {
|
|
245
|
+
let trimmed = part.trim();
|
|
246
|
+
if (!trimmed)
|
|
247
|
+
continue;
|
|
248
|
+
trimmed = stripComments(trimmed);
|
|
249
|
+
if (!trimmed)
|
|
250
|
+
continue;
|
|
251
|
+
const colonIndex = trimmed.indexOf(":");
|
|
252
|
+
if (colonIndex === -1)
|
|
253
|
+
continue;
|
|
254
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
255
|
+
let value = trimmed.slice(colonIndex + 1).trim();
|
|
256
|
+
const asIndex = findTopLevelAs(value);
|
|
257
|
+
if (asIndex !== -1) {
|
|
258
|
+
value = value.slice(0, asIndex).trim();
|
|
259
|
+
}
|
|
260
|
+
const bindableResult = extractBindable(value);
|
|
261
|
+
if (bindableResult.isBindable) {
|
|
262
|
+
const defaultVal = bindableResult.innerValue;
|
|
263
|
+
const hasDefault = defaultVal !== "" && defaultVal !== "undefined";
|
|
264
|
+
result.push({
|
|
265
|
+
key,
|
|
266
|
+
defaultValue: defaultVal,
|
|
267
|
+
bindable: true,
|
|
268
|
+
hasDefault
|
|
269
|
+
});
|
|
270
|
+
} else {
|
|
271
|
+
const hasDefault = value !== "undefined";
|
|
272
|
+
result.push({
|
|
273
|
+
key,
|
|
274
|
+
defaultValue: value,
|
|
275
|
+
bindable: false,
|
|
276
|
+
hasDefault
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
function splitByTopLevelCommas(source) {
|
|
283
|
+
const parts = [];
|
|
284
|
+
let current = "";
|
|
285
|
+
let depth = 0;
|
|
286
|
+
let angleDepth = 0;
|
|
287
|
+
for (let i = 0;i < source.length; i++) {
|
|
288
|
+
const char = source[i];
|
|
289
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
290
|
+
const quote = char;
|
|
291
|
+
current += char;
|
|
292
|
+
i++;
|
|
293
|
+
while (i < source.length && source[i] !== quote) {
|
|
294
|
+
if (source[i] === "\\") {
|
|
295
|
+
current += source[i];
|
|
296
|
+
i++;
|
|
297
|
+
}
|
|
298
|
+
if (i < source.length) {
|
|
299
|
+
current += source[i];
|
|
300
|
+
i++;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (i < source.length) {
|
|
304
|
+
current += source[i];
|
|
305
|
+
}
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (char === "<") {
|
|
309
|
+
const prevChar = current.length > 0 ? current[current.length - 1] : "";
|
|
310
|
+
if (/[\w$)]/.test(prevChar)) {
|
|
311
|
+
angleDepth++;
|
|
312
|
+
}
|
|
313
|
+
current += char;
|
|
314
|
+
} else if (char === ">") {
|
|
315
|
+
if (current.length > 0 && current[current.length - 1] === "=") {
|
|
316
|
+
current += char;
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (angleDepth > 0) {
|
|
320
|
+
angleDepth--;
|
|
321
|
+
}
|
|
322
|
+
current += char;
|
|
323
|
+
} else if (char === "{" || char === "(" || char === "[") {
|
|
324
|
+
depth++;
|
|
325
|
+
current += char;
|
|
326
|
+
} else if (char === "}" || char === ")" || char === "]") {
|
|
327
|
+
depth--;
|
|
328
|
+
current += char;
|
|
329
|
+
} else if (char === "," && depth === 0 && angleDepth === 0) {
|
|
330
|
+
parts.push(current);
|
|
331
|
+
current = "";
|
|
332
|
+
} else {
|
|
333
|
+
current += char;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (current.trim()) {
|
|
337
|
+
parts.push(current);
|
|
338
|
+
}
|
|
339
|
+
return parts;
|
|
340
|
+
}
|
|
341
|
+
function stripComments(str) {
|
|
342
|
+
let result = str.trim();
|
|
343
|
+
while (result.startsWith("/*")) {
|
|
344
|
+
const endComment = result.indexOf("*/");
|
|
345
|
+
if (endComment !== -1) {
|
|
346
|
+
result = result.slice(endComment + 2).trim();
|
|
347
|
+
} else {
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
while (result.startsWith("//")) {
|
|
352
|
+
const endLine = result.indexOf(`
|
|
353
|
+
`);
|
|
354
|
+
if (endLine !== -1) {
|
|
355
|
+
result = result.slice(endLine + 1).trim();
|
|
356
|
+
} else {
|
|
357
|
+
result = "";
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
function generatePropsDestructuring(attrs, factoryName) {
|
|
364
|
+
const parts = [];
|
|
365
|
+
for (const attr of attrs) {
|
|
366
|
+
if (attr.bindable) {
|
|
367
|
+
if (attr.hasDefault) {
|
|
368
|
+
parts.push(`${attr.key} = $bindable(${attr.defaultValue})`);
|
|
369
|
+
} else {
|
|
370
|
+
parts.push(`${attr.key} = $bindable()`);
|
|
371
|
+
}
|
|
372
|
+
} else if (attr.hasDefault) {
|
|
373
|
+
parts.push(`${attr.key} = ${attr.defaultValue}`);
|
|
374
|
+
} else {
|
|
375
|
+
parts.push(attr.key);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return `let { ${parts.join(", ")} }: $attrs.Of<typeof ${factoryName}> = $props()`;
|
|
379
|
+
}
|
|
380
|
+
function generateFactoryCallFromAttrs(factoryName, attrs) {
|
|
381
|
+
const parts = [];
|
|
382
|
+
for (const attr of attrs) {
|
|
383
|
+
parts.push(`get ${attr.key}() { return ${attr.key} }`);
|
|
384
|
+
if (attr.bindable) {
|
|
385
|
+
parts.push(`set ${attr.key}(v) { ${attr.key} = v }`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return `${factoryName}({ ${parts.join(", ")} })`;
|
|
389
|
+
}
|
|
390
|
+
function findImportPath(source, identifier) {
|
|
391
|
+
const patterns2 = [
|
|
392
|
+
new RegExp(`import\\s*\\{[^}]*\\b${identifier}\\b[^}]*\\}\\s*from\\s*['"]([^'"]+)['"]`),
|
|
393
|
+
new RegExp(`import\\s*\\{[^}]*\\bas\\s+${identifier}\\b[^}]*\\}\\s*from\\s*['"]([^'"]+)['"]`),
|
|
394
|
+
new RegExp(`import\\s+${identifier}\\s+from\\s*['"]([^'"]+)['"]`),
|
|
395
|
+
new RegExp(`import\\s*\\*\\s*as\\s+${identifier}\\s+from\\s*['"]([^'"]+)['"]`)
|
|
396
|
+
];
|
|
397
|
+
for (const pattern of patterns2) {
|
|
398
|
+
const match = pattern.exec(source);
|
|
399
|
+
if (match) {
|
|
400
|
+
return match[1];
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
function generatePropsInterface(schema) {
|
|
406
|
+
const lines = [];
|
|
407
|
+
const bindings = [];
|
|
408
|
+
for (const attr of schema.attrs) {
|
|
409
|
+
const type = inferTypeFromDefault(attr.defaultValue);
|
|
410
|
+
const optional = attr.hasDefault ? "?" : "";
|
|
411
|
+
lines.push(`${attr.key}${optional}: ${type}`);
|
|
412
|
+
if (attr.bindable) {
|
|
413
|
+
bindings.push(attr.key);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const interfaceContent = lines.length > 0 ? `{ ${lines.join("; ")} }` : "{}";
|
|
417
|
+
return { interfaceContent, bindings };
|
|
418
|
+
}
|
|
419
|
+
function inferTypeFromDefault(defaultValue) {
|
|
420
|
+
if (defaultValue === "undefined")
|
|
421
|
+
return "unknown";
|
|
422
|
+
if (defaultValue === "true" || defaultValue === "false")
|
|
423
|
+
return "boolean";
|
|
424
|
+
if (/^-?\d+$/.test(defaultValue))
|
|
425
|
+
return "number";
|
|
426
|
+
if (/^-?\d+\.\d+$/.test(defaultValue))
|
|
427
|
+
return "number";
|
|
428
|
+
if (/^['"]/.test(defaultValue))
|
|
429
|
+
return "string";
|
|
430
|
+
if (defaultValue.startsWith("["))
|
|
431
|
+
return "unknown[]";
|
|
432
|
+
if (defaultValue.startsWith("{"))
|
|
433
|
+
return "Record<string, unknown>";
|
|
434
|
+
if (defaultValue === "null")
|
|
435
|
+
return "null";
|
|
436
|
+
return "unknown";
|
|
437
|
+
}
|
|
438
|
+
function generateDtsContent(factoryName, importPath, schema, comment = "regenerated on save") {
|
|
439
|
+
const propsLines = [];
|
|
440
|
+
const bindableProps = [];
|
|
441
|
+
for (const attr of schema.attrs) {
|
|
442
|
+
const type = inferTypeFromDefault(attr.defaultValue);
|
|
443
|
+
const optional = attr.hasDefault ? "?" : "";
|
|
444
|
+
propsLines.push(` ${attr.key}${optional}: ${type};`);
|
|
445
|
+
if (attr.bindable) {
|
|
446
|
+
bindableProps.push(`"${attr.key}"`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
const propsType = propsLines.length > 0 ? `{
|
|
450
|
+
${propsLines.join(`
|
|
451
|
+
`)}
|
|
452
|
+
}` : "{}";
|
|
453
|
+
const bindingsType = bindableProps.length > 0 ? bindableProps.join(" | ") : "never";
|
|
454
|
+
return `// Auto-generated by svelte-origin
|
|
455
|
+
// Do not edit manually - ${comment}
|
|
456
|
+
|
|
457
|
+
import type { Component } from 'svelte';
|
|
458
|
+
import type { ${factoryName} } from '${importPath}';
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Props derived from ${factoryName} origin factory.
|
|
462
|
+
*
|
|
463
|
+
* Bindable props: ${bindableProps.length > 0 ? bindableProps.join(", ") : "none"}
|
|
464
|
+
*/
|
|
465
|
+
type Props = ${propsType};
|
|
466
|
+
|
|
467
|
+
declare const __component: Component<Props, {}, ${bindingsType}>;
|
|
468
|
+
export default __component;
|
|
469
|
+
`;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// src/vite-dts.ts
|
|
473
|
+
function svelteOriginDts(options = {}) {
|
|
474
|
+
const { debug = false } = options;
|
|
475
|
+
const schemaCache = new Map;
|
|
476
|
+
return {
|
|
477
|
+
name: "svelte-origin-dts",
|
|
478
|
+
enforce: "pre",
|
|
479
|
+
async transform(code, id) {
|
|
480
|
+
if (!id.endsWith(".svelte"))
|
|
481
|
+
return null;
|
|
482
|
+
const originMatch = code.match(/\$attrs\s*\.\s*origin\s*\(\s*(\w+)\s*\)/);
|
|
483
|
+
if (!originMatch)
|
|
484
|
+
return null;
|
|
485
|
+
const factoryName = originMatch[1];
|
|
486
|
+
if (debug) {
|
|
487
|
+
console.log(`[svelte-origin-dts] Found $attrs.origin(${factoryName}) in ${id}`);
|
|
488
|
+
}
|
|
489
|
+
const importPath = findImportPath(code, factoryName);
|
|
490
|
+
if (!importPath) {
|
|
491
|
+
if (debug) {
|
|
492
|
+
console.log(`[svelte-origin-dts] Could not find import for ${factoryName}`);
|
|
493
|
+
}
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
const schema = await resolveSchema(id, importPath, factoryName, schemaCache, debug);
|
|
497
|
+
if (!schema || schema.attrs.length === 0) {
|
|
498
|
+
if (debug) {
|
|
499
|
+
console.log(`[svelte-origin-dts] No schema found for ${factoryName}`);
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
const dtsContent = generateDtsContent(factoryName, importPath, schema);
|
|
504
|
+
const dtsPath = id + ".d.ts";
|
|
505
|
+
await writeFile(dtsPath, dtsContent, "utf-8");
|
|
506
|
+
if (debug) {
|
|
507
|
+
console.log(`[svelte-origin-dts] Generated ${dtsPath}`);
|
|
508
|
+
}
|
|
509
|
+
return null;
|
|
510
|
+
},
|
|
511
|
+
async handleHotUpdate({ file }) {
|
|
512
|
+
if (file.endsWith(".svelte")) {
|
|
513
|
+
const dtsPath = file + ".d.ts";
|
|
514
|
+
if (!existsSync(file) && existsSync(dtsPath)) {
|
|
515
|
+
await unlink(dtsPath);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
async function resolveSchema(importerPath, importPath, factoryName, cache, debug) {
|
|
522
|
+
const cacheKey = `${importPath}::${factoryName}`;
|
|
523
|
+
if (cache.has(cacheKey)) {
|
|
524
|
+
return cache.get(cacheKey) || null;
|
|
525
|
+
}
|
|
526
|
+
try {
|
|
527
|
+
const importerDir = dirname(importerPath);
|
|
528
|
+
let resolvedPath;
|
|
529
|
+
if (importPath.startsWith(".")) {
|
|
530
|
+
resolvedPath = join(importerDir, importPath);
|
|
531
|
+
} else {
|
|
532
|
+
cache.set(cacheKey, null);
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
const extensions = [".ts", ".svelte.ts", ".svelte.js", ".js"];
|
|
536
|
+
let filePath = resolvedPath;
|
|
537
|
+
if (!existsSync(filePath)) {
|
|
538
|
+
if (resolvedPath.endsWith(".svelte")) {
|
|
539
|
+
const svelteTs = resolvedPath + ".ts";
|
|
540
|
+
if (existsSync(svelteTs)) {
|
|
541
|
+
filePath = svelteTs;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (!existsSync(filePath)) {
|
|
545
|
+
for (const ext of extensions) {
|
|
546
|
+
const candidate = resolvedPath + ext;
|
|
547
|
+
if (existsSync(candidate)) {
|
|
548
|
+
filePath = candidate;
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (!existsSync(filePath)) {
|
|
555
|
+
cache.set(cacheKey, null);
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
const source = await readFile(filePath, "utf-8");
|
|
559
|
+
const schema = parseOriginSchemaFromSource(source, factoryName);
|
|
560
|
+
if (!schema) {
|
|
561
|
+
cache.set(cacheKey, null);
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
if (schema.parentNames.length > 0) {
|
|
565
|
+
const mergedAttrs = [];
|
|
566
|
+
for (const parentName of schema.parentNames) {
|
|
567
|
+
const parentImportPath = findImportPath(source, parentName);
|
|
568
|
+
if (parentImportPath) {
|
|
569
|
+
const parentSchema = await resolveSchema(filePath, parentImportPath, parentName, cache, debug);
|
|
570
|
+
if (parentSchema) {
|
|
571
|
+
for (const attr of parentSchema.attrs) {
|
|
572
|
+
const existing = mergedAttrs.findIndex((a) => a.key === attr.key);
|
|
573
|
+
if (existing === -1) {
|
|
574
|
+
mergedAttrs.push(attr);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
for (const attr of schema.attrs) {
|
|
581
|
+
const existing = mergedAttrs.findIndex((a) => a.key === attr.key);
|
|
582
|
+
if (existing !== -1) {
|
|
583
|
+
mergedAttrs[existing] = attr;
|
|
584
|
+
} else {
|
|
585
|
+
mergedAttrs.push(attr);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const mergedSchema = { attrs: mergedAttrs, parentNames: schema.parentNames };
|
|
589
|
+
cache.set(cacheKey, mergedSchema);
|
|
590
|
+
return mergedSchema;
|
|
591
|
+
}
|
|
592
|
+
cache.set(cacheKey, schema);
|
|
593
|
+
return schema;
|
|
594
|
+
} catch (error) {
|
|
595
|
+
if (debug) {
|
|
596
|
+
console.error(`[svelte-origin-dts] Error resolving ${importPath}:`, error);
|
|
597
|
+
}
|
|
598
|
+
cache.set(cacheKey, null);
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
var vite_dts_default = svelteOriginDts;
|
|
603
|
+
export {
|
|
604
|
+
svelteOriginDts,
|
|
605
|
+
vite_dts_default as default
|
|
606
|
+
};
|
package/package.json
CHANGED
|
@@ -1,4 +1,74 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "svelte-origin",
|
|
3
|
-
"version": "0.0.
|
|
1
|
+
{
|
|
2
|
+
"name": "svelte-origin",
|
|
3
|
+
"version": "1.0.0-next.15",
|
|
4
|
+
"description": "Compiler-assisted state and prop ergonomics for Svelte 5",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"svelte-origin": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"README.md",
|
|
13
|
+
"LLM.md",
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./runtime": {
|
|
22
|
+
"types": "./dist/runtime/index.d.ts",
|
|
23
|
+
"import": "./dist/runtime/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./plugin": {
|
|
26
|
+
"types": "./dist/plugin.d.ts",
|
|
27
|
+
"import": "./dist/plugin.js"
|
|
28
|
+
},
|
|
29
|
+
"./preprocess": {
|
|
30
|
+
"types": "./dist/preprocess.d.ts",
|
|
31
|
+
"import": "./dist/preprocess.js"
|
|
32
|
+
},
|
|
33
|
+
"./vite-dts": {
|
|
34
|
+
"types": "./dist/vite-dts.d.ts",
|
|
35
|
+
"import": "./dist/vite-dts.js"
|
|
36
|
+
},
|
|
37
|
+
"./post-process": {
|
|
38
|
+
"types": "./dist/post-process.d.ts",
|
|
39
|
+
"import": "./dist/post-process.js"
|
|
40
|
+
},
|
|
41
|
+
"./globals": "./dist/globals.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "bun run build:types && bun run build:globals && bun run build:esm",
|
|
45
|
+
"build:esm": "bun build src/index.ts src/plugin.ts src/preprocess.ts src/vite-dts.ts src/cli.ts src/post-process.ts src/runtime/index.ts --outdir dist --format esm --external node:fs --external node:path --external node:fs/promises --target node",
|
|
46
|
+
"build:types": "tsc --project tsconfig.build.json",
|
|
47
|
+
"build:globals": "bun -e \"require('fs').copyFileSync('src/globals.d.ts', 'dist/globals.d.ts')\"",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"test:watch": "vitest",
|
|
50
|
+
"typecheck": "tsc --noEmit"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"svelte": "^5.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"vite": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"magic-string": "^0.30.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
65
|
+
"@testing-library/svelte": "^5.0.0",
|
|
66
|
+
"bun-types": "latest",
|
|
67
|
+
"jsdom": "^25.0.0",
|
|
68
|
+
"svelte": "^5.0.0",
|
|
69
|
+
"svelte2tsx": "^0.7.45",
|
|
70
|
+
"typescript": "^5.0.0",
|
|
71
|
+
"vite": "^6.0.0",
|
|
72
|
+
"vitest": "^2.0.0"
|
|
73
|
+
}
|
|
4
74
|
}
|