sv 0.9.6 → 0.9.7

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.
@@ -0,0 +1,3180 @@
1
+ import { Element, MagicString, T, Tag, __toESM, any, be, detect, getUserAgent, parseCss, parseHtml, parseHtml$1, parseJson, parseScript, parseScript$1, parseSvelte, require_picocolors, resolveCommand, serializeScript, stripAst, walk } from "./create-CyyvJXoi.js";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import process from "node:process";
5
+
6
+ //#region ../core/addon/config.ts
7
+ function defineAddon(config) {
8
+ return config;
9
+ }
10
+ function defineAddonOptions() {
11
+ return createOptionBuilder({});
12
+ }
13
+ function createOptionBuilder(options$6) {
14
+ return {
15
+ add(key, question) {
16
+ const newOptions = {
17
+ ...options$6,
18
+ [key]: question
19
+ };
20
+ return createOptionBuilder(newOptions);
21
+ },
22
+ build() {
23
+ return options$6;
24
+ }
25
+ };
26
+ }
27
+
28
+ //#endregion
29
+ //#region ../../node_modules/.pnpm/dedent@1.6.0/node_modules/dedent/dist/dedent.mjs
30
+ function ownKeys(object, enumerableOnly) {
31
+ var keys = Object.keys(object);
32
+ if (Object.getOwnPropertySymbols) {
33
+ var symbols = Object.getOwnPropertySymbols(object);
34
+ enumerableOnly && (symbols = symbols.filter(function(sym) {
35
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
36
+ })), keys.push.apply(keys, symbols);
37
+ }
38
+ return keys;
39
+ }
40
+ function _objectSpread(target) {
41
+ for (var i = 1; i < arguments.length; i++) {
42
+ var source = null != arguments[i] ? arguments[i] : {};
43
+ i % 2 ? ownKeys(Object(source), !0).forEach(function(key) {
44
+ _defineProperty(target, key, source[key]);
45
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function(key) {
46
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
47
+ });
48
+ }
49
+ return target;
50
+ }
51
+ function _defineProperty(obj, key, value) {
52
+ key = _toPropertyKey(key);
53
+ if (key in obj) Object.defineProperty(obj, key, {
54
+ value,
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true
58
+ });
59
+ else obj[key] = value;
60
+ return obj;
61
+ }
62
+ function _toPropertyKey(arg) {
63
+ var key = _toPrimitive(arg, "string");
64
+ return typeof key === "symbol" ? key : String(key);
65
+ }
66
+ function _toPrimitive(input, hint) {
67
+ if (typeof input !== "object" || input === null) return input;
68
+ var prim = input[Symbol.toPrimitive];
69
+ if (prim !== void 0) {
70
+ var res = prim.call(input, hint || "default");
71
+ if (typeof res !== "object") return res;
72
+ throw new TypeError("@@toPrimitive must return a primitive value.");
73
+ }
74
+ return (hint === "string" ? String : Number)(input);
75
+ }
76
+ const dedent = createDedent({});
77
+ var dedent_default = dedent;
78
+ function createDedent(options$6) {
79
+ dedent$1.withOptions = (newOptions) => createDedent(_objectSpread(_objectSpread({}, options$6), newOptions));
80
+ return dedent$1;
81
+ function dedent$1(strings, ...values) {
82
+ const raw = typeof strings === "string" ? [strings] : strings.raw;
83
+ const { escapeSpecialCharacters = Array.isArray(strings), trimWhitespace = true } = options$6;
84
+ let result = "";
85
+ for (let i = 0; i < raw.length; i++) {
86
+ let next = raw[i];
87
+ if (escapeSpecialCharacters) next = next.replace(/\\\n[ \t]*/g, "").replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\\{/g, "{");
88
+ result += next;
89
+ if (i < values.length) result += values[i];
90
+ }
91
+ const lines = result.split("\n");
92
+ let mindent = null;
93
+ for (const l of lines) {
94
+ const m = l.match(/^(\s+)\S+/);
95
+ if (m) {
96
+ const indent = m[1].length;
97
+ if (!mindent) mindent = indent;
98
+ else mindent = Math.min(mindent, indent);
99
+ }
100
+ }
101
+ if (mindent !== null) {
102
+ const m = mindent;
103
+ result = lines.map((l) => l[0] === " " || l[0] === " " ? l.slice(m) : l).join("\n");
104
+ }
105
+ if (trimWhitespace) result = result.trim();
106
+ if (escapeSpecialCharacters) result = result.replace(/\\n/g, "\n");
107
+ return result;
108
+ }
109
+ }
110
+
111
+ //#endregion
112
+ //#region ../core/utils.ts
113
+ function createPrinter(...conditions) {
114
+ return conditions.map((condition) => {
115
+ return (content, alt = "") => condition ? content : alt;
116
+ });
117
+ }
118
+
119
+ //#endregion
120
+ //#region ../core/common.ts
121
+ function splitVersion(str) {
122
+ const [major, minor, patch] = str?.split(".") ?? [];
123
+ function toVersionNumber(val) {
124
+ return val !== void 0 && val !== "" && !isNaN(Number(val)) ? Number(val) : void 0;
125
+ }
126
+ return {
127
+ major: toVersionNumber(major),
128
+ minor: toVersionNumber(minor),
129
+ patch: toVersionNumber(patch)
130
+ };
131
+ }
132
+ function isVersionUnsupportedBelow(versionStr, belowStr) {
133
+ const version = splitVersion(versionStr);
134
+ const below = splitVersion(belowStr);
135
+ if (version.major === void 0 || below.major === void 0) return void 0;
136
+ if (version.major < below.major) return true;
137
+ if (version.major > below.major) return false;
138
+ if (version.minor === void 0 || below.minor === void 0) if (version.major === below.major) return false;
139
+ else return true;
140
+ if (version.minor < below.minor) return true;
141
+ if (version.minor > below.minor) return false;
142
+ if (version.patch === void 0 || below.patch === void 0) if (version.minor === below.minor) return false;
143
+ else return true;
144
+ if (version.patch < below.patch) return true;
145
+ if (version.patch > below.patch) return false;
146
+ if (version.patch === below.patch) return false;
147
+ }
148
+
149
+ //#endregion
150
+ //#region ../core/index.ts
151
+ var import_picocolors$2 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
152
+
153
+ //#endregion
154
+ //#region ../../node_modules/.pnpm/decircular@1.0.0/node_modules/decircular/index.js
155
+ function decircular(object) {
156
+ const seenObjects = /* @__PURE__ */ new WeakMap();
157
+ function internalDecircular(value, path$1 = []) {
158
+ if (!(value !== null && typeof value === "object")) return value;
159
+ const existingPath = seenObjects.get(value);
160
+ if (existingPath) return `[Circular *${existingPath.join(".")}]`;
161
+ seenObjects.set(value, path$1);
162
+ const newValue = Array.isArray(value) ? [] : {};
163
+ for (const [key2, value2] of Object.entries(value)) newValue[key2] = internalDecircular(value2, [...path$1, key2]);
164
+ seenObjects.delete(value);
165
+ return newValue;
166
+ }
167
+ return internalDecircular(object);
168
+ }
169
+
170
+ //#endregion
171
+ //#region ../core/tooling/js/common.ts
172
+ function addJsDocTypeComment(node, options$6) {
173
+ const comment = {
174
+ type: "Block",
175
+ value: `* @type {${options$6.type}} `
176
+ };
177
+ addComment(node, comment);
178
+ }
179
+ function addComment(node, comment) {
180
+ node.leadingComments ??= [];
181
+ if (!node.leadingComments.find((item) => item.type === "Block" && item.value === comment.value)) node.leadingComments.push(comment);
182
+ }
183
+ function createSpread(argument) {
184
+ return {
185
+ type: "SpreadElement",
186
+ argument
187
+ };
188
+ }
189
+ function createLiteral(value) {
190
+ return {
191
+ type: "Literal",
192
+ value: value ?? null
193
+ };
194
+ }
195
+ function areNodesEqual(node, otherNode) {
196
+ const nodeClone = stripAst(decircular(node), ["loc", "raw"]);
197
+ const otherNodeClone = stripAst(decircular(otherNode), ["loc", "raw"]);
198
+ return serializeScript(nodeClone) === serializeScript(otherNodeClone);
199
+ }
200
+ function appendFromString(node, options$6) {
201
+ const program = parseScript$1(dedent_default(options$6.code));
202
+ for (const childNode of program.body) node.body.push(childNode);
203
+ }
204
+ function parseExpression(code) {
205
+ const program = parseScript$1(dedent_default(code));
206
+ stripAst(program, ["raw"]);
207
+ const statement = program.body[0];
208
+ if (statement.type !== "ExpressionStatement") throw new Error("Code provided was not an expression");
209
+ return statement.expression;
210
+ }
211
+ function parseStatement(code) {
212
+ return parseFromString(code);
213
+ }
214
+ function parseFromString(code) {
215
+ return parseScript$1(dedent_default(code)).body[0];
216
+ }
217
+ /** Appends the statement to body of the block if it doesn't already exist */
218
+ function appendStatement(node, options$6) {
219
+ if (!contains(node, options$6.statement)) node.body.push(options$6.statement);
220
+ }
221
+ /** Returns `true` if the provided node exists in the AST */
222
+ function contains(node, targetNode) {
223
+ let found = false;
224
+ walk(node, null, { _(currentNode, { next, stop }) {
225
+ if (currentNode.type === targetNode.type) {
226
+ found = areNodesEqual(currentNode, targetNode);
227
+ if (found) stop();
228
+ }
229
+ next();
230
+ } });
231
+ return found;
232
+ }
233
+ function hasTypeProperty(node, options$6) {
234
+ return node.type === "TSPropertySignature" && node.key.type === "Identifier" && node.key.name === options$6.name;
235
+ }
236
+
237
+ //#endregion
238
+ //#region ../core/tooling/js/array.ts
239
+ function create$1() {
240
+ return {
241
+ type: "ArrayExpression",
242
+ elements: []
243
+ };
244
+ }
245
+ function append(node, element) {
246
+ insertElement(node, element, { insertEnd: true });
247
+ }
248
+ function prepend(node, element) {
249
+ insertElement(node, element, { insertEnd: false });
250
+ }
251
+ function insertElement(node, element, options$6) {
252
+ if (typeof element === "string") {
253
+ let literal = node.elements.filter((item) => item !== null && item.type === "Literal").find((item) => item.value === element);
254
+ if (!literal) {
255
+ literal = {
256
+ type: "Literal",
257
+ value: element
258
+ };
259
+ if (options$6.insertEnd) node.elements.push(literal);
260
+ else node.elements.unshift(literal);
261
+ }
262
+ } else if (!node.elements.some((item) => item && areNodesEqual(element, item))) if (options$6.insertEnd) node.elements.push(element);
263
+ else node.elements.unshift(element);
264
+ }
265
+
266
+ //#endregion
267
+ //#region ../core/tooling/js/object.ts
268
+ function property(node, options$6) {
269
+ return propertyNode(node, options$6).value;
270
+ }
271
+ function propertyNode(node, options$6) {
272
+ let prop = node.properties.filter((x$1) => x$1.type === "Property").find((x$1) => x$1.key.name === options$6.name);
273
+ if (!prop) {
274
+ let isShorthand = false;
275
+ if (options$6.fallback.type === "Identifier") isShorthand = options$6.fallback.name === options$6.name;
276
+ prop = {
277
+ type: "Property",
278
+ shorthand: isShorthand,
279
+ key: {
280
+ type: "Identifier",
281
+ name: options$6.name
282
+ },
283
+ value: options$6.fallback,
284
+ kind: "init",
285
+ computed: false,
286
+ method: false
287
+ };
288
+ node.properties.push(prop);
289
+ }
290
+ return prop;
291
+ }
292
+ function create(properties) {
293
+ return populateObjectExpression({
294
+ objectExpression: {
295
+ type: "ObjectExpression",
296
+ properties: []
297
+ },
298
+ properties,
299
+ override: false
300
+ });
301
+ }
302
+ function overrideProperties(objectExpression, properties) {
303
+ populateObjectExpression({
304
+ objectExpression,
305
+ properties,
306
+ override: true
307
+ });
308
+ }
309
+ function overrideProperty(node, options$6) {
310
+ const prop = node.properties.filter((x$1) => x$1.type === "Property").find((x$1) => x$1.key.name === options$6.name);
311
+ if (!prop) return property(node, {
312
+ name: options$6.name,
313
+ fallback: options$6.value
314
+ });
315
+ prop.value = options$6.value;
316
+ return options$6.value;
317
+ }
318
+ function populateObjectExpression(options$6) {
319
+ const getExpression = (value, existingExpression) => {
320
+ let expression;
321
+ if (Array.isArray(value)) {
322
+ expression = create$1();
323
+ for (const v of value) append(expression, getExpression(v));
324
+ } else if (typeof value === "object" && value !== null) if (value.type !== void 0) expression = value;
325
+ else if (options$6.override && existingExpression && existingExpression.type === "ObjectExpression") expression = populateObjectExpression({
326
+ objectExpression: existingExpression,
327
+ properties: value,
328
+ override: options$6.override
329
+ });
330
+ else expression = populateObjectExpression({
331
+ objectExpression: create({}),
332
+ properties: value,
333
+ override: options$6.override
334
+ });
335
+ else expression = createLiteral(value);
336
+ return expression;
337
+ };
338
+ for (const [prop, value] of Object.entries(options$6.properties)) {
339
+ if (value === void 0) continue;
340
+ if (options$6.override) {
341
+ const existingProperty = options$6.objectExpression.properties.filter((x$1) => x$1.type === "Property").find((x$1) => x$1.key.name === prop);
342
+ const existingExpression = existingProperty?.value.type === "ObjectExpression" ? existingProperty.value : void 0;
343
+ overrideProperty(options$6.objectExpression, {
344
+ name: prop,
345
+ value: getExpression(value, existingExpression)
346
+ });
347
+ } else property(options$6.objectExpression, {
348
+ name: prop,
349
+ fallback: getExpression(value)
350
+ });
351
+ }
352
+ return options$6.objectExpression;
353
+ }
354
+
355
+ //#endregion
356
+ //#region ../core/tooling/js/function.ts
357
+ function createCall(options$6) {
358
+ const callExpression = {
359
+ type: "CallExpression",
360
+ callee: {
361
+ type: "Identifier",
362
+ name: options$6.name
363
+ },
364
+ arguments: [],
365
+ optional: false
366
+ };
367
+ for (const arg of options$6.args) {
368
+ let argNode;
369
+ if (options$6.useIdentifiers) argNode = {
370
+ type: "Identifier",
371
+ name: arg
372
+ };
373
+ else argNode = {
374
+ type: "Literal",
375
+ value: arg
376
+ };
377
+ callExpression.arguments.push(argNode);
378
+ }
379
+ return callExpression;
380
+ }
381
+ function getArgument(node, options$6) {
382
+ if (options$6.index < node.arguments.length) return node.arguments[options$6.index];
383
+ node.arguments.push(options$6.fallback);
384
+ return options$6.fallback;
385
+ }
386
+
387
+ //#endregion
388
+ //#region ../core/tooling/js/imports.ts
389
+ function addEmpty(node, options$6) {
390
+ const expectedImportDeclaration = {
391
+ type: "ImportDeclaration",
392
+ source: {
393
+ type: "Literal",
394
+ value: options$6.from
395
+ },
396
+ specifiers: [],
397
+ attributes: [],
398
+ importKind: "value"
399
+ };
400
+ addImportIfNecessary(node, expectedImportDeclaration);
401
+ }
402
+ function addNamespace(node, options$6) {
403
+ const expectedImportDeclaration = {
404
+ type: "ImportDeclaration",
405
+ importKind: "value",
406
+ source: {
407
+ type: "Literal",
408
+ value: options$6.from
409
+ },
410
+ specifiers: [{
411
+ type: "ImportNamespaceSpecifier",
412
+ local: {
413
+ type: "Identifier",
414
+ name: options$6.as
415
+ }
416
+ }],
417
+ attributes: []
418
+ };
419
+ addImportIfNecessary(node, expectedImportDeclaration);
420
+ }
421
+ function addDefault(node, options$6) {
422
+ const expectedImportDeclaration = {
423
+ type: "ImportDeclaration",
424
+ source: {
425
+ type: "Literal",
426
+ value: options$6.from
427
+ },
428
+ specifiers: [{
429
+ type: "ImportDefaultSpecifier",
430
+ local: {
431
+ type: "Identifier",
432
+ name: options$6.as
433
+ }
434
+ }],
435
+ attributes: [],
436
+ importKind: "value"
437
+ };
438
+ addImportIfNecessary(node, expectedImportDeclaration);
439
+ }
440
+ function addNamed(node, options$6) {
441
+ const o_imports = Array.isArray(options$6.imports) ? Object.fromEntries(options$6.imports.map((n) => [n, n])) : options$6.imports;
442
+ const specifiers = Object.entries(o_imports).map(([key, value]) => {
443
+ return {
444
+ type: "ImportSpecifier",
445
+ imported: {
446
+ type: "Identifier",
447
+ name: key
448
+ },
449
+ local: {
450
+ type: "Identifier",
451
+ name: value
452
+ }
453
+ };
454
+ });
455
+ let importDecl;
456
+ walk(node, null, { ImportDeclaration(declaration$1) {
457
+ if (declaration$1.source.value === options$6.from && declaration$1.specifiers) importDecl = declaration$1;
458
+ } });
459
+ if (importDecl) {
460
+ specifiers.forEach((specifierToAdd) => {
461
+ if (importDecl?.specifiers?.every((existingSpecifier) => existingSpecifier.type === "ImportSpecifier" && existingSpecifier.local?.name !== specifierToAdd.local?.name && existingSpecifier.imported.type === "Identifier" && specifierToAdd.imported.type === "Identifier" && existingSpecifier.imported.name !== specifierToAdd.imported.name)) importDecl?.specifiers?.push(specifierToAdd);
462
+ });
463
+ return;
464
+ }
465
+ const expectedImportDeclaration = {
466
+ type: "ImportDeclaration",
467
+ source: {
468
+ type: "Literal",
469
+ value: options$6.from
470
+ },
471
+ specifiers,
472
+ attributes: [],
473
+ importKind: options$6.isType ? "type" : "value"
474
+ };
475
+ node.body.unshift(expectedImportDeclaration);
476
+ }
477
+ function addImportIfNecessary(node, expectedImportDeclaration) {
478
+ if (!node.body.filter((item) => item.type === "ImportDeclaration").find((item) => areNodesEqual(item, expectedImportDeclaration))) node.body.unshift(expectedImportDeclaration);
479
+ }
480
+ function find(ast, options$6) {
481
+ let alias = options$6.name;
482
+ let statement;
483
+ walk(ast, null, { ImportDeclaration(node) {
484
+ if (node.specifiers && node.source.value === options$6.from) {
485
+ const specifier = node.specifiers.find((sp) => sp.type === "ImportSpecifier" && sp.imported.type === "Identifier" && sp.imported.name === options$6.name);
486
+ if (specifier) {
487
+ statement = node;
488
+ alias = specifier.local?.name ?? alias;
489
+ return;
490
+ }
491
+ }
492
+ } });
493
+ if (statement) return {
494
+ statement,
495
+ alias
496
+ };
497
+ return {
498
+ statement: void 0,
499
+ alias: void 0
500
+ };
501
+ }
502
+ function remove(ast, options$6) {
503
+ const statement = options$6.statement ?? find(ast, {
504
+ name: options$6.name,
505
+ from: options$6.from
506
+ }).statement;
507
+ if (!statement) return;
508
+ if (statement.specifiers?.length === 1) {
509
+ const idxToRemove = ast.body.indexOf(statement);
510
+ ast.body.splice(idxToRemove, 1);
511
+ } else {
512
+ const idxToRemove = statement.specifiers?.findIndex((s) => s.type === "ImportSpecifier" && s.imported.type === "Identifier" && s.imported.name === options$6.name);
513
+ if (idxToRemove !== void 0 && idxToRemove !== -1) statement.specifiers?.splice(idxToRemove, 1);
514
+ }
515
+ }
516
+
517
+ //#endregion
518
+ //#region ../core/tooling/js/variables.ts
519
+ function declaration(node, options$6) {
520
+ let declaration$1 = (node.type === "Program" ? node.body.filter((x$1) => x$1.type === "VariableDeclaration") : [node]).find((x$1) => {
521
+ return x$1.declarations[0].id.name === options$6.name;
522
+ });
523
+ if (declaration$1) return declaration$1;
524
+ declaration$1 = {
525
+ type: "VariableDeclaration",
526
+ kind: options$6.kind,
527
+ declarations: [{
528
+ type: "VariableDeclarator",
529
+ id: {
530
+ type: "Identifier",
531
+ name: options$6.name
532
+ },
533
+ init: options$6.value
534
+ }]
535
+ };
536
+ return declaration$1;
537
+ }
538
+ function createIdentifier(name) {
539
+ return {
540
+ type: "Identifier",
541
+ name
542
+ };
543
+ }
544
+ function typeAnnotateDeclarator(node, options$6) {
545
+ if (node.id.type === "Identifier") node.id.typeAnnotation = {
546
+ type: "TSTypeAnnotation",
547
+ typeAnnotation: {
548
+ type: "TSTypeReference",
549
+ typeName: {
550
+ type: "Identifier",
551
+ name: options$6.typeName
552
+ }
553
+ }
554
+ };
555
+ return node;
556
+ }
557
+
558
+ //#endregion
559
+ //#region ../core/tooling/js/exports.ts
560
+ function createDefault(node, options$6) {
561
+ const existingNode = node.body.find((item) => item.type === "ExportDefaultDeclaration");
562
+ if (!existingNode) {
563
+ const exportNode = {
564
+ type: "ExportDefaultDeclaration",
565
+ declaration: options$6.fallback
566
+ };
567
+ node.body.push(exportNode);
568
+ return {
569
+ astNode: exportNode,
570
+ value: options$6.fallback,
571
+ isFallback: true
572
+ };
573
+ }
574
+ const exportDefaultDeclaration = existingNode;
575
+ if (exportDefaultDeclaration.declaration.type === "Identifier") {
576
+ const identifier = exportDefaultDeclaration.declaration;
577
+ let variableDeclaration;
578
+ let variableDeclarator;
579
+ for (const declaration$2 of node.body) {
580
+ if (declaration$2.type !== "VariableDeclaration") continue;
581
+ variableDeclarator = declaration$2.declarations.find((declarator) => declarator.type === "VariableDeclarator" && declarator.id.type === "Identifier" && declarator.id.name === identifier.name);
582
+ variableDeclaration = declaration$2;
583
+ }
584
+ if (!variableDeclaration || !variableDeclarator) throw new Error(`Unable to find exported variable '${identifier.name}'`);
585
+ const value = variableDeclarator.init;
586
+ return {
587
+ astNode: exportDefaultDeclaration,
588
+ value,
589
+ isFallback: false
590
+ };
591
+ }
592
+ const declaration$1 = exportDefaultDeclaration.declaration;
593
+ return {
594
+ astNode: exportDefaultDeclaration,
595
+ value: declaration$1,
596
+ isFallback: false
597
+ };
598
+ }
599
+ function createNamed(node, options$6) {
600
+ let namedExport = node.body.filter((item) => item.type === "ExportNamedDeclaration").find((exportNode) => {
601
+ return exportNode.declaration.declarations[0].id.name === options$6.name;
602
+ });
603
+ if (namedExport) return namedExport;
604
+ namedExport = {
605
+ type: "ExportNamedDeclaration",
606
+ declaration: options$6.fallback,
607
+ specifiers: [],
608
+ attributes: []
609
+ };
610
+ node.body.push(namedExport);
611
+ return namedExport;
612
+ }
613
+
614
+ //#endregion
615
+ //#region ../core/tooling/js/kit.ts
616
+ function addGlobalAppInterface(node, options$6) {
617
+ let globalDecl = node.body.filter((n) => n.type === "TSModuleDeclaration").find((m) => m.global && m.declare);
618
+ if (!globalDecl) {
619
+ globalDecl = parseFromString("declare global {}");
620
+ node.body.push(globalDecl);
621
+ }
622
+ if (globalDecl.body?.type !== "TSModuleBlock") throw new Error("Unexpected body type of `declare global` in `src/app.d.ts`");
623
+ let app;
624
+ let interfaceNode;
625
+ walk(globalDecl, null, {
626
+ TSModuleDeclaration(node$1, { next }) {
627
+ if (node$1.id.type === "Identifier" && node$1.id.name === "App") app = node$1;
628
+ next();
629
+ },
630
+ TSInterfaceDeclaration(node$1) {
631
+ if (node$1.id.type === "Identifier" && node$1.id.name === options$6.name) interfaceNode = node$1;
632
+ }
633
+ });
634
+ if (!app) {
635
+ app = parseFromString("namespace App {}");
636
+ globalDecl.body.body.push(app);
637
+ }
638
+ if (app.body?.type !== "TSModuleBlock") throw new Error("Unexpected body type of `namespace App` in `src/app.d.ts`");
639
+ if (!interfaceNode) {
640
+ interfaceNode = parseFromString(`interface ${options$6.name} {}`);
641
+ app.body.body.push(interfaceNode);
642
+ }
643
+ return interfaceNode;
644
+ }
645
+ function addHooksHandle(node, options$6) {
646
+ if (options$6.typescript) addNamed(node, {
647
+ from: "@sveltejs/kit",
648
+ imports: { Handle: "Handle" },
649
+ isType: true
650
+ });
651
+ let isSpecifier = false;
652
+ let handleName = "handle";
653
+ let exportDecl;
654
+ let originalHandleDecl;
655
+ walk(node, null, { ExportNamedDeclaration(declaration$1) {
656
+ let maybeHandleDecl;
657
+ const handleSpecifier = declaration$1.specifiers?.find((specifier) => specifier.exported.type === "Identifier" && specifier.exported.name === "handle");
658
+ if (handleSpecifier && handleSpecifier.local.type === "Identifier" && handleSpecifier.exported.type === "Identifier") {
659
+ isSpecifier = true;
660
+ handleName = handleSpecifier.local?.name ?? handleSpecifier.exported.name;
661
+ const handleFunc = node.body.find((item) => isFunctionDeclaration(item, handleName));
662
+ const handleVar = node.body.find((item) => isVariableDeclaration(item, handleName));
663
+ maybeHandleDecl = handleFunc ?? handleVar;
664
+ }
665
+ maybeHandleDecl ??= declaration$1.declaration ?? void 0;
666
+ if (maybeHandleDecl && isVariableDeclaration(maybeHandleDecl, handleName)) {
667
+ exportDecl = declaration$1;
668
+ originalHandleDecl = maybeHandleDecl;
669
+ }
670
+ if (maybeHandleDecl && isFunctionDeclaration(maybeHandleDecl, handleName)) {
671
+ exportDecl = declaration$1;
672
+ originalHandleDecl = maybeHandleDecl;
673
+ }
674
+ } });
675
+ const newHandle = parseExpression(options$6.handleContent);
676
+ if (contains(node, newHandle)) return;
677
+ if (!originalHandleDecl || !exportDecl) {
678
+ const newHandleDecl$1 = declaration(node, {
679
+ kind: "const",
680
+ name: options$6.newHandleName,
681
+ value: newHandle
682
+ });
683
+ if (options$6.typescript) {
684
+ const declarator = newHandleDecl$1.declarations[0];
685
+ typeAnnotateDeclarator(declarator, { typeName: "Handle" });
686
+ }
687
+ node.body.push(newHandleDecl$1);
688
+ const handleDecl = declaration(node, {
689
+ kind: "const",
690
+ name: handleName,
691
+ value: createIdentifier(options$6.newHandleName)
692
+ });
693
+ if (options$6.typescript) {
694
+ const declarator = handleDecl.declarations[0];
695
+ typeAnnotateDeclarator(declarator, { typeName: "Handle" });
696
+ }
697
+ createNamed(node, {
698
+ name: handleName,
699
+ fallback: handleDecl
700
+ });
701
+ return;
702
+ }
703
+ const newHandleDecl = declaration(node, {
704
+ kind: "const",
705
+ name: options$6.newHandleName,
706
+ value: newHandle
707
+ });
708
+ if (options$6.typescript) {
709
+ const declarator = newHandleDecl.declarations[0];
710
+ typeAnnotateDeclarator(declarator, { typeName: "Handle" });
711
+ }
712
+ let sequence;
713
+ if (originalHandleDecl.type === "VariableDeclaration") sequence = originalHandleDecl.declarations.find((declarator) => declarator.type === "VariableDeclarator" && usingSequence(declarator, handleName))?.init;
714
+ if (sequence) {
715
+ if (!sequence.arguments.some((arg) => arg.type === "Identifier" && arg.name === options$6.newHandleName)) sequence.arguments.push(createIdentifier(options$6.newHandleName));
716
+ node.body = node.body.filter((item) => item !== originalHandleDecl && item !== exportDecl && item !== newHandleDecl);
717
+ if (isSpecifier) node.body.push(newHandleDecl, originalHandleDecl, exportDecl);
718
+ else node.body.push(newHandleDecl, exportDecl);
719
+ }
720
+ const NEW_HANDLE_NAME = "originalHandle";
721
+ const sequenceCall = createCall({
722
+ name: "sequence",
723
+ args: [NEW_HANDLE_NAME, options$6.newHandleName],
724
+ useIdentifiers: true
725
+ });
726
+ const finalHandleDecl = declaration(node, {
727
+ kind: "const",
728
+ name: handleName,
729
+ value: sequenceCall
730
+ });
731
+ addNamed(node, {
732
+ from: "@sveltejs/kit/hooks",
733
+ imports: { sequence: "sequence" }
734
+ });
735
+ let renameRequired = false;
736
+ if (originalHandleDecl && isVariableDeclaration(originalHandleDecl, handleName)) {
737
+ const handle = getVariableDeclarator(originalHandleDecl, handleName);
738
+ if (handle && handle.id.type === "Identifier" && handle.init?.type !== "Identifier") {
739
+ renameRequired = true;
740
+ handle.id.name = NEW_HANDLE_NAME;
741
+ }
742
+ }
743
+ if (originalHandleDecl && isFunctionDeclaration(originalHandleDecl, handleName)) {
744
+ renameRequired = true;
745
+ originalHandleDecl.id.name = NEW_HANDLE_NAME;
746
+ }
747
+ node.body = node.body.filter((item) => item !== originalHandleDecl && item !== exportDecl && item !== newHandleDecl);
748
+ if (isSpecifier) node.body.push(originalHandleDecl, newHandleDecl, finalHandleDecl, exportDecl);
749
+ if (exportDecl.declaration && renameRequired) {
750
+ node.body.push(exportDecl.declaration, newHandleDecl);
751
+ createNamed(node, {
752
+ name: handleName,
753
+ fallback: finalHandleDecl
754
+ });
755
+ } else if (exportDecl.declaration && isVariableDeclaration(originalHandleDecl, handleName)) {
756
+ const variableDeclarator = getVariableDeclarator(originalHandleDecl, handleName);
757
+ const sequenceCall$1 = createCall({
758
+ name: "sequence",
759
+ args: [(variableDeclarator?.init).name, options$6.newHandleName],
760
+ useIdentifiers: true
761
+ });
762
+ const finalHandleDecl$1 = declaration(node, {
763
+ kind: "const",
764
+ name: handleName,
765
+ value: sequenceCall$1
766
+ });
767
+ if (options$6.typescript) {
768
+ const declarator = finalHandleDecl$1.declarations[0];
769
+ typeAnnotateDeclarator(declarator, { typeName: "Handle" });
770
+ }
771
+ node.body.push(newHandleDecl);
772
+ createNamed(node, {
773
+ name: handleName,
774
+ fallback: finalHandleDecl$1
775
+ });
776
+ }
777
+ }
778
+ function usingSequence(node, handleName) {
779
+ return node.id.type === "Identifier" && node.id.name === handleName && node.init?.type === "CallExpression" && node.init.callee.type === "Identifier" && node.init.callee.name === "sequence";
780
+ }
781
+ function isVariableDeclaration(node, variableName) {
782
+ return node.type === "VariableDeclaration" && getVariableDeclarator(node, variableName) !== void 0;
783
+ }
784
+ function getVariableDeclarator(node, variableName) {
785
+ return node.declarations.find((d) => d.type === "VariableDeclarator" && d.id.type === "Identifier" && d.id.name === variableName);
786
+ }
787
+ function isFunctionDeclaration(node, funcName) {
788
+ return node.type === "FunctionDeclaration" && node.id?.name === funcName;
789
+ }
790
+
791
+ //#endregion
792
+ //#region ../core/tooling/js/vite.ts
793
+ function isConfigWrapper(callExpression, knownWrappers) {
794
+ if (callExpression.callee.type !== "Identifier") return false;
795
+ const calleeName = callExpression.callee.name;
796
+ if (knownWrappers.includes(calleeName)) return true;
797
+ const isObjectCall = callExpression.arguments.length === 1 && callExpression.arguments[0]?.type === "ObjectExpression";
798
+ return knownWrappers.includes(calleeName) || isObjectCall;
799
+ }
800
+ function exportDefaultConfig(ast, options$6) {
801
+ const { fallback, ignoreWrapper } = options$6;
802
+ let fallbackExpression;
803
+ if (fallback) fallbackExpression = typeof fallback.code === "string" ? parseExpression(fallback.code) : fallback.code;
804
+ else fallbackExpression = create({});
805
+ const { value, isFallback } = createDefault(ast, { fallback: fallbackExpression });
806
+ if (isFallback) options$6.fallback?.additional?.(ast);
807
+ const rootObject = value.type === "TSSatisfiesExpression" ? value.expression : value;
808
+ let configObject;
809
+ if (!("arguments" in rootObject) || !Array.isArray(rootObject.arguments)) {
810
+ configObject = rootObject;
811
+ return configObject;
812
+ }
813
+ if (rootObject.type !== "CallExpression" || rootObject.callee.type !== "Identifier") {
814
+ configObject = rootObject;
815
+ return configObject;
816
+ }
817
+ if (!isConfigWrapper(rootObject, ignoreWrapper)) {
818
+ configObject = rootObject;
819
+ return configObject;
820
+ }
821
+ const firstArg = getArgument(rootObject, {
822
+ index: 0,
823
+ fallback: create({})
824
+ });
825
+ if (firstArg.type === "ArrowFunctionExpression") {
826
+ const arrowFunction = firstArg;
827
+ if (arrowFunction.body.type === "BlockStatement") {
828
+ const returnStatement = arrowFunction.body.body.find((stmt) => stmt.type === "ReturnStatement");
829
+ if (returnStatement && returnStatement.argument?.type === "ObjectExpression") configObject = returnStatement.argument;
830
+ else {
831
+ configObject = create({});
832
+ const newReturnStatement = {
833
+ type: "ReturnStatement",
834
+ argument: configObject
835
+ };
836
+ arrowFunction.body.body.push(newReturnStatement);
837
+ }
838
+ } else if (arrowFunction.body.type === "ObjectExpression") configObject = arrowFunction.body;
839
+ else {
840
+ configObject = create({});
841
+ arrowFunction.body = configObject;
842
+ arrowFunction.expression = true;
843
+ }
844
+ } else if (firstArg.type === "ObjectExpression") configObject = firstArg;
845
+ else configObject = create({});
846
+ return configObject;
847
+ }
848
+ function addInArrayOfObject(ast, options$6) {
849
+ const { code, arrayProperty, mode = "append" } = options$6;
850
+ const targetArray = property(ast, {
851
+ name: arrayProperty,
852
+ fallback: create$1()
853
+ });
854
+ const expression = parseExpression(code);
855
+ if (mode === "prepend") prepend(targetArray, expression);
856
+ else append(targetArray, expression);
857
+ }
858
+ const addPlugin = (ast, options$6) => {
859
+ const configObject = getConfig(ast);
860
+ addInArrayOfObject(configObject, {
861
+ arrayProperty: "plugins",
862
+ ...options$6
863
+ });
864
+ };
865
+ const getConfig = (ast) => {
866
+ return exportDefaultConfig(ast, {
867
+ fallback: {
868
+ code: "defineConfig()",
869
+ additional: (ast$1) => addNamed(ast$1, {
870
+ imports: ["defineConfig"],
871
+ from: "vite"
872
+ })
873
+ },
874
+ ignoreWrapper: ["defineConfig"]
875
+ });
876
+ };
877
+
878
+ //#endregion
879
+ //#region ../addons/devtools-json/index.ts
880
+ var devtools_json_default = defineAddon({
881
+ id: "devtools-json",
882
+ shortDescription: "devtools json",
883
+ homepage: "https://github.com/ChromeDevTools/vite-plugin-devtools-json",
884
+ options: {},
885
+ run: ({ sv, viteConfigFile }) => {
886
+ sv.devDependency("vite-plugin-devtools-json", "^1.0.0");
887
+ sv.file(viteConfigFile, (content) => {
888
+ const { ast, generateCode } = parseScript(content);
889
+ const vitePluginName = "devtoolsJson";
890
+ addDefault(ast, {
891
+ as: vitePluginName,
892
+ from: "vite-plugin-devtools-json"
893
+ });
894
+ addPlugin(ast, { code: `${vitePluginName}()` });
895
+ return generateCode();
896
+ });
897
+ }
898
+ });
899
+
900
+ //#endregion
901
+ //#region ../addons/common.ts
902
+ function addEslintConfigPrettier(content) {
903
+ const { ast, generateCode } = parseScript(content);
904
+ const sveltePluginImport = ast.body.filter((n) => n.type === "ImportDeclaration").find((n) => n.type === "ImportDeclaration" && n.source.value === "eslint-plugin-svelte" && n.specifiers?.some((n$1) => n$1.type === "ImportDefaultSpecifier"));
905
+ let svelteImportName;
906
+ for (const specifier of sveltePluginImport?.specifiers ?? []) if (specifier.type === "ImportDefaultSpecifier" && specifier.local?.name) svelteImportName = specifier.local.name;
907
+ svelteImportName ??= "svelte";
908
+ addDefault(ast, {
909
+ from: "eslint-plugin-svelte",
910
+ as: svelteImportName
911
+ });
912
+ addDefault(ast, {
913
+ from: "eslint-config-prettier",
914
+ as: "prettier"
915
+ });
916
+ const fallbackConfig = parseExpression("[]");
917
+ const eslintConfig = createDefault(ast, { fallback: fallbackConfig }).value;
918
+ if (eslintConfig.type !== "ArrayExpression" && eslintConfig.type !== "CallExpression") return content;
919
+ const prettier = parseExpression("prettier");
920
+ const sveltePrettierConfig = parseExpression(`${svelteImportName}.configs.prettier`);
921
+ const configSpread = createSpread(sveltePrettierConfig);
922
+ const nodesToInsert = [];
923
+ if (!contains(eslintConfig, prettier)) nodesToInsert.push(prettier);
924
+ if (!contains(eslintConfig, configSpread)) nodesToInsert.push(configSpread);
925
+ const elements = eslintConfig.type === "ArrayExpression" ? eslintConfig.elements : eslintConfig.arguments;
926
+ const idx = elements.findIndex((el) => el?.type === "SpreadElement" && el.argument.type === "MemberExpression" && el.argument.object.type === "MemberExpression" && el.argument.object.property.type === "Identifier" && el.argument.object.property.name === "configs" && el.argument.object.object.type === "Identifier" && el.argument.object.object.name === svelteImportName);
927
+ if (idx !== -1) elements.splice(idx + 1, 0, ...nodesToInsert);
928
+ else elements.push(...nodesToInsert);
929
+ return generateCode();
930
+ }
931
+ function addToDemoPage(content, path$1) {
932
+ const { template, generateCode } = parseSvelte(content);
933
+ for (const node of template.ast.childNodes) if (node.type === "tag" && node.attribs["href"] === `/demo/${path$1}`) return content;
934
+ const newLine = template.source ? "\n" : "";
935
+ const src = template.source + `${newLine}<a href="/demo/${path$1}">${path$1}</a>`;
936
+ return generateCode({ template: src });
937
+ }
938
+ /**
939
+ * Returns the corresponding `@types/node` version for the version of Node.js running in the current process.
940
+ *
941
+ * If the installed version of Node.js is from a `Current` release, then the major is decremented to
942
+ * the nearest `LTS` release version.
943
+ */
944
+ function getNodeTypesVersion() {
945
+ const nodeVersion = process.versions.node;
946
+ const isDenoOrBun = Boolean(process.versions.deno ?? process.versions.bun);
947
+ const [major] = nodeVersion.split(".");
948
+ const majorNum = Number(major);
949
+ const isEvenMajor = majorNum % 2 === 0;
950
+ if (!!process.release.lts || isDenoOrBun && isEvenMajor) return `^${major}`;
951
+ return `^${isEvenMajor ? majorNum - 2 : majorNum - 1}`;
952
+ }
953
+
954
+ //#endregion
955
+ //#region ../addons/drizzle/index.ts
956
+ const PORTS = {
957
+ mysql: "3306",
958
+ postgresql: "5432",
959
+ sqlite: ""
960
+ };
961
+ const options$5 = defineAddonOptions().add("database", {
962
+ question: "Which database would you like to use?",
963
+ type: "select",
964
+ default: "sqlite",
965
+ options: [
966
+ {
967
+ value: "postgresql",
968
+ label: "PostgreSQL"
969
+ },
970
+ {
971
+ value: "mysql",
972
+ label: "MySQL"
973
+ },
974
+ {
975
+ value: "sqlite",
976
+ label: "SQLite"
977
+ }
978
+ ]
979
+ }).add("postgresql", {
980
+ question: "Which PostgreSQL client would you like to use?",
981
+ type: "select",
982
+ group: "client",
983
+ default: "postgres.js",
984
+ options: [{
985
+ value: "postgres.js",
986
+ label: "Postgres.JS",
987
+ hint: "recommended for most users"
988
+ }, {
989
+ value: "neon",
990
+ label: "Neon",
991
+ hint: "popular hosted platform"
992
+ }],
993
+ condition: ({ database }) => database === "postgresql"
994
+ }).add("mysql", {
995
+ question: "Which MySQL client would you like to use?",
996
+ type: "select",
997
+ group: "client",
998
+ default: "mysql2",
999
+ options: [{
1000
+ value: "mysql2",
1001
+ hint: "recommended for most users"
1002
+ }, {
1003
+ value: "planetscale",
1004
+ label: "PlanetScale",
1005
+ hint: "popular hosted platform"
1006
+ }],
1007
+ condition: ({ database }) => database === "mysql"
1008
+ }).add("sqlite", {
1009
+ question: "Which SQLite client would you like to use?",
1010
+ type: "select",
1011
+ group: "client",
1012
+ default: "libsql",
1013
+ options: [
1014
+ {
1015
+ value: "better-sqlite3",
1016
+ hint: "for traditional Node environments"
1017
+ },
1018
+ {
1019
+ value: "libsql",
1020
+ label: "libSQL",
1021
+ hint: "for serverless environments"
1022
+ },
1023
+ {
1024
+ value: "turso",
1025
+ label: "Turso",
1026
+ hint: "popular hosted platform"
1027
+ }
1028
+ ],
1029
+ condition: ({ database }) => database === "sqlite"
1030
+ }).add("docker", {
1031
+ question: "Do you want to run the database locally with docker-compose?",
1032
+ default: false,
1033
+ type: "boolean",
1034
+ condition: ({ database, mysql, postgresql }) => database === "mysql" && mysql === "mysql2" || database === "postgresql" && postgresql === "postgres.js"
1035
+ }).build();
1036
+ var drizzle_default = defineAddon({
1037
+ id: "drizzle",
1038
+ shortDescription: "database orm",
1039
+ homepage: "https://orm.drizzle.team",
1040
+ options: options$5,
1041
+ setup: ({ kit, unsupported, runsAfter, cwd, typescript }) => {
1042
+ runsAfter("prettier");
1043
+ const ext = typescript ? "ts" : "js";
1044
+ if (!kit) return unsupported("Requires SvelteKit");
1045
+ const baseDBPath = path.resolve(kit.libDirectory, "server", "db");
1046
+ const paths = {
1047
+ "drizzle config": path.relative(cwd, path.resolve(cwd, `drizzle.config.${ext}`)),
1048
+ "database schema": path.relative(cwd, path.resolve(baseDBPath, `schema.${ext}`)),
1049
+ database: path.relative(cwd, path.resolve(baseDBPath, `index.${ext}`))
1050
+ };
1051
+ for (const [fileType, filePath] of Object.entries(paths)) if (fs.existsSync(filePath)) unsupported(`Preexisting ${fileType} file at '${filePath}'`);
1052
+ },
1053
+ run: ({ sv, typescript, options: options$6, kit, dependencyVersion }) => {
1054
+ const ext = typescript ? "ts" : "js";
1055
+ sv.devDependency("drizzle-orm", "^0.44.5");
1056
+ sv.devDependency("drizzle-kit", "^0.31.4");
1057
+ sv.devDependency("@types/node", getNodeTypesVersion());
1058
+ if (options$6.mysql === "mysql2") sv.dependency("mysql2", "^3.15.0");
1059
+ if (options$6.mysql === "planetscale") sv.dependency("@planetscale/database", "^1.19.0");
1060
+ if (options$6.postgresql === "neon") sv.dependency("@neondatabase/serverless", "^1.0.1");
1061
+ if (options$6.postgresql === "postgres.js") sv.dependency("postgres", "^3.4.7");
1062
+ if (options$6.sqlite === "better-sqlite3") {
1063
+ sv.dependency("better-sqlite3", "^12.4.1");
1064
+ sv.devDependency("@types/better-sqlite3", "^7.6.13");
1065
+ sv.pnpmBuildDependency("better-sqlite3");
1066
+ }
1067
+ if (options$6.sqlite === "libsql" || options$6.sqlite === "turso") sv.devDependency("@libsql/client", "^0.15.15");
1068
+ sv.file(".env", (content) => generateEnvFileContent(content, options$6));
1069
+ sv.file(".env.example", (content) => generateEnvFileContent(content, options$6));
1070
+ if (options$6.docker && (options$6.mysql === "mysql2" || options$6.postgresql === "postgres.js")) sv.file("docker-compose.yml", (content) => {
1071
+ if (content.length > 0) return content;
1072
+ const imageName = options$6.database === "mysql" ? "mysql" : "postgres";
1073
+ const port = PORTS[options$6.database];
1074
+ const USER = "root";
1075
+ const PASSWORD = "mysecretpassword";
1076
+ const DB_NAME = "local";
1077
+ let dbSpecificContent = "";
1078
+ if (options$6.mysql === "mysql2") dbSpecificContent = `
1079
+ MYSQL_ROOT_PASSWORD: ${PASSWORD}
1080
+ MYSQL_DATABASE: ${DB_NAME}
1081
+ volumes:
1082
+ - mysqldata:/var/lib/mysql
1083
+ volumes:
1084
+ mysqldata:
1085
+ `;
1086
+ if (options$6.postgresql === "postgres.js") dbSpecificContent = `
1087
+ POSTGRES_USER: ${USER}
1088
+ POSTGRES_PASSWORD: ${PASSWORD}
1089
+ POSTGRES_DB: ${DB_NAME}
1090
+ volumes:
1091
+ - pgdata:/var/lib/postgresql/data
1092
+ volumes:
1093
+ pgdata:
1094
+ `;
1095
+ content = dedent_default`
1096
+ services:
1097
+ db:
1098
+ image: ${imageName}
1099
+ restart: always
1100
+ ports:
1101
+ - ${port}:${port}
1102
+ environment: ${dbSpecificContent}
1103
+ `;
1104
+ return content;
1105
+ });
1106
+ sv.file("package.json", (content) => {
1107
+ const { data, generateCode } = parseJson(content);
1108
+ data.scripts ??= {};
1109
+ const scripts = data.scripts;
1110
+ if (options$6.docker) scripts["db:start"] ??= "docker compose up";
1111
+ scripts["db:push"] ??= "drizzle-kit push";
1112
+ scripts["db:generate"] ??= "drizzle-kit generate";
1113
+ scripts["db:migrate"] ??= "drizzle-kit migrate";
1114
+ scripts["db:studio"] ??= "drizzle-kit studio";
1115
+ return generateCode();
1116
+ });
1117
+ if (Boolean(dependencyVersion("prettier"))) sv.file(".prettierignore", (content) => {
1118
+ if (!content.includes(`/drizzle/`)) return content.trimEnd() + "\n/drizzle/";
1119
+ return content;
1120
+ });
1121
+ if (options$6.database === "sqlite") sv.file(".gitignore", (content) => {
1122
+ if (content.length === 0) return content;
1123
+ if (!content.includes("\n*.db")) content = content.trimEnd() + "\n\n# SQLite\n*.db";
1124
+ return content;
1125
+ });
1126
+ sv.file(`drizzle.config.${ext}`, (content) => {
1127
+ const { ast, generateCode } = parseScript(content);
1128
+ addNamed(ast, {
1129
+ from: "drizzle-kit",
1130
+ imports: { defineConfig: "defineConfig" }
1131
+ });
1132
+ ast.body.push(parseStatement("if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set');"));
1133
+ createDefault(ast, { fallback: parseExpression(`
1134
+ defineConfig({
1135
+ schema: "./src/lib/server/db/schema.${typescript ? "ts" : "js"}",
1136
+ dialect: "${options$6.sqlite === "turso" ? "turso" : options$6.database}",
1137
+ dbCredentials: {
1138
+ ${options$6.sqlite === "turso" ? "authToken: process.env.DATABASE_AUTH_TOKEN," : ""}
1139
+ url: process.env.DATABASE_URL
1140
+ },
1141
+ verbose: true,
1142
+ strict: true
1143
+ })`) });
1144
+ return generateCode();
1145
+ });
1146
+ sv.file(`${kit?.libDirectory}/server/db/schema.${ext}`, (content) => {
1147
+ const { ast, generateCode } = parseScript(content);
1148
+ let userSchemaExpression;
1149
+ if (options$6.database === "sqlite") {
1150
+ addNamed(ast, {
1151
+ from: "drizzle-orm/sqlite-core",
1152
+ imports: ["sqliteTable", "integer"]
1153
+ });
1154
+ userSchemaExpression = parseExpression(`sqliteTable('user', {
1155
+ id: integer('id').primaryKey(),
1156
+ age: integer('age')
1157
+ })`);
1158
+ }
1159
+ if (options$6.database === "mysql") {
1160
+ addNamed(ast, {
1161
+ from: "drizzle-orm/mysql-core",
1162
+ imports: [
1163
+ "mysqlTable",
1164
+ "serial",
1165
+ "int"
1166
+ ]
1167
+ });
1168
+ userSchemaExpression = parseExpression(`mysqlTable('user', {
1169
+ id: serial('id').primaryKey(),
1170
+ age: int('age'),
1171
+ })`);
1172
+ }
1173
+ if (options$6.database === "postgresql") {
1174
+ addNamed(ast, {
1175
+ from: "drizzle-orm/pg-core",
1176
+ imports: [
1177
+ "pgTable",
1178
+ "serial",
1179
+ "integer"
1180
+ ]
1181
+ });
1182
+ userSchemaExpression = parseExpression(`pgTable('user', {
1183
+ id: serial('id').primaryKey(),
1184
+ age: integer('age'),
1185
+ })`);
1186
+ }
1187
+ if (!userSchemaExpression) throw new Error("unreachable state...");
1188
+ const userIdentifier = declaration(ast, {
1189
+ kind: "const",
1190
+ name: "user",
1191
+ value: userSchemaExpression
1192
+ });
1193
+ createNamed(ast, {
1194
+ name: "user",
1195
+ fallback: userIdentifier
1196
+ });
1197
+ return generateCode();
1198
+ });
1199
+ sv.file(`${kit?.libDirectory}/server/db/index.${ext}`, (content) => {
1200
+ const { ast, generateCode } = parseScript(content);
1201
+ addNamed(ast, {
1202
+ from: "$env/dynamic/private",
1203
+ imports: ["env"]
1204
+ });
1205
+ addNamespace(ast, {
1206
+ from: "./schema",
1207
+ as: "schema"
1208
+ });
1209
+ const dbURLCheck = parseStatement("if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set');");
1210
+ ast.body.push(dbURLCheck);
1211
+ let clientExpression;
1212
+ if (options$6.sqlite === "better-sqlite3") {
1213
+ addDefault(ast, {
1214
+ from: "better-sqlite3",
1215
+ as: "Database"
1216
+ });
1217
+ addNamed(ast, {
1218
+ from: "drizzle-orm/better-sqlite3",
1219
+ imports: ["drizzle"]
1220
+ });
1221
+ clientExpression = parseExpression("new Database(env.DATABASE_URL)");
1222
+ }
1223
+ if (options$6.sqlite === "libsql" || options$6.sqlite === "turso") {
1224
+ addNamed(ast, {
1225
+ from: "@libsql/client",
1226
+ imports: ["createClient"]
1227
+ });
1228
+ addNamed(ast, {
1229
+ from: "drizzle-orm/libsql",
1230
+ imports: ["drizzle"]
1231
+ });
1232
+ if (options$6.sqlite === "turso") {
1233
+ addNamed(ast, {
1234
+ from: "$app/environment",
1235
+ imports: ["dev"]
1236
+ });
1237
+ const authTokenCheck = parseStatement("if (!dev && !env.DATABASE_AUTH_TOKEN) throw new Error('DATABASE_AUTH_TOKEN is not set');");
1238
+ ast.body.push(authTokenCheck);
1239
+ clientExpression = parseExpression("createClient({ url: env.DATABASE_URL, authToken: env.DATABASE_AUTH_TOKEN })");
1240
+ } else clientExpression = parseExpression("createClient({ url: env.DATABASE_URL })");
1241
+ }
1242
+ if (options$6.mysql === "mysql2" || options$6.mysql === "planetscale") {
1243
+ addDefault(ast, {
1244
+ from: "mysql2/promise",
1245
+ as: "mysql"
1246
+ });
1247
+ addNamed(ast, {
1248
+ from: "drizzle-orm/mysql2",
1249
+ imports: ["drizzle"]
1250
+ });
1251
+ clientExpression = parseExpression("mysql.createPool(env.DATABASE_URL)");
1252
+ }
1253
+ if (options$6.postgresql === "neon") {
1254
+ addNamed(ast, {
1255
+ from: "@neondatabase/serverless",
1256
+ imports: ["neon"]
1257
+ });
1258
+ addNamed(ast, {
1259
+ from: "drizzle-orm/neon-http",
1260
+ imports: ["drizzle"]
1261
+ });
1262
+ clientExpression = parseExpression("neon(env.DATABASE_URL)");
1263
+ }
1264
+ if (options$6.postgresql === "postgres.js") {
1265
+ addDefault(ast, {
1266
+ from: "postgres",
1267
+ as: "postgres"
1268
+ });
1269
+ addNamed(ast, {
1270
+ from: "drizzle-orm/postgres-js",
1271
+ imports: ["drizzle"]
1272
+ });
1273
+ clientExpression = parseExpression("postgres(env.DATABASE_URL)");
1274
+ }
1275
+ if (!clientExpression) throw new Error("unreachable state...");
1276
+ ast.body.push(declaration(ast, {
1277
+ kind: "const",
1278
+ name: "client",
1279
+ value: clientExpression
1280
+ }));
1281
+ const drizzleCall = createCall({
1282
+ name: "drizzle",
1283
+ args: ["client"],
1284
+ useIdentifiers: true
1285
+ });
1286
+ const paramObject = create({ schema: createIdentifier("schema") });
1287
+ if (options$6.database === "mysql") {
1288
+ const mode = options$6.mysql === "planetscale" ? "planetscale" : "default";
1289
+ property(paramObject, {
1290
+ name: "mode",
1291
+ fallback: createLiteral(mode)
1292
+ });
1293
+ }
1294
+ drizzleCall.arguments.push(paramObject);
1295
+ const db = declaration(ast, {
1296
+ kind: "const",
1297
+ name: "db",
1298
+ value: drizzleCall
1299
+ });
1300
+ createNamed(ast, {
1301
+ name: "db",
1302
+ fallback: db
1303
+ });
1304
+ return generateCode();
1305
+ });
1306
+ },
1307
+ nextSteps: ({ options: options$6, highlighter, packageManager }) => {
1308
+ const steps = [`You will need to set ${highlighter.env("DATABASE_URL")} in your production environment`];
1309
+ if (options$6.docker) {
1310
+ const { command: command$1, args: args$1 } = resolveCommand(packageManager, "run", ["db:start"]);
1311
+ steps.push(`Run ${highlighter.command(`${command$1} ${args$1.join(" ")}`)} to start the docker container`);
1312
+ } else steps.push(`Check ${highlighter.env("DATABASE_URL")} in ${highlighter.path(".env")} and adjust it to your needs`);
1313
+ const { command, args } = resolveCommand(packageManager, "run", ["db:push"]);
1314
+ steps.push(`Run ${highlighter.command(`${command} ${args.join(" ")}`)} to update your database schema`);
1315
+ return steps;
1316
+ }
1317
+ });
1318
+ function generateEnvFileContent(content, opts) {
1319
+ const DB_URL_KEY = "DATABASE_URL";
1320
+ if (opts.docker) {
1321
+ const protocol = opts.database === "mysql" ? "mysql" : "postgres";
1322
+ const port = PORTS[opts.database];
1323
+ content = addEnvVar(content, DB_URL_KEY, `"${protocol}://root:mysecretpassword@localhost:${port}/local"`);
1324
+ return content;
1325
+ }
1326
+ if (opts.sqlite === "better-sqlite3" || opts.sqlite === "libsql") {
1327
+ const dbFile = opts.sqlite === "libsql" ? "file:local.db" : "local.db";
1328
+ content = addEnvVar(content, DB_URL_KEY, dbFile);
1329
+ return content;
1330
+ }
1331
+ content = addEnvComment(content, "Replace with your DB credentials!");
1332
+ if (opts.sqlite === "turso") {
1333
+ content = addEnvVar(content, DB_URL_KEY, "\"libsql://db-name-user.turso.io\"");
1334
+ content = addEnvVar(content, "DATABASE_AUTH_TOKEN", "\"\"");
1335
+ content = addEnvComment(content, "A local DB can also be used in dev as well");
1336
+ content = addEnvComment(content, `${DB_URL_KEY}="file:local.db"`);
1337
+ }
1338
+ if (opts.database === "mysql") content = addEnvVar(content, DB_URL_KEY, "\"mysql://user:password@host:port/db-name\"");
1339
+ if (opts.database === "postgresql") content = addEnvVar(content, DB_URL_KEY, "\"postgres://user:password@host:port/db-name\"");
1340
+ return content;
1341
+ }
1342
+ function addEnvVar(content, key, value) {
1343
+ if (!content.includes(key + "=")) content = appendEnvContent(content, `${key}=${value}`);
1344
+ return content;
1345
+ }
1346
+ function addEnvComment(content, comment) {
1347
+ const commented = `# ${comment}`;
1348
+ if (!content.includes(commented)) content = appendEnvContent(content, commented);
1349
+ return content;
1350
+ }
1351
+ function appendEnvContent(existing, content) {
1352
+ return (!existing.length || existing.endsWith("\n") ? existing : existing + "\n") + content + "\n";
1353
+ }
1354
+
1355
+ //#endregion
1356
+ //#region ../addons/eslint/index.ts
1357
+ var eslint_default = defineAddon({
1358
+ id: "eslint",
1359
+ shortDescription: "linter",
1360
+ homepage: "https://eslint.org",
1361
+ options: {},
1362
+ run: ({ sv, typescript, dependencyVersion }) => {
1363
+ const prettierInstalled = Boolean(dependencyVersion("prettier"));
1364
+ sv.devDependency("eslint", "^9.36.0");
1365
+ sv.devDependency("@eslint/compat", "^1.4.0");
1366
+ sv.devDependency("eslint-plugin-svelte", "^3.12.4");
1367
+ sv.devDependency("globals", "^16.4.0");
1368
+ sv.devDependency("@eslint/js", "^9.36.0");
1369
+ sv.devDependency("@types/node", getNodeTypesVersion());
1370
+ if (typescript) sv.devDependency("typescript-eslint", "^8.44.1");
1371
+ if (prettierInstalled) sv.devDependency("eslint-config-prettier", "^10.1.8");
1372
+ sv.file("package.json", (content) => {
1373
+ const { data, generateCode } = parseJson(content);
1374
+ data.scripts ??= {};
1375
+ const scripts = data.scripts;
1376
+ const LINT_CMD = "eslint .";
1377
+ scripts["lint"] ??= LINT_CMD;
1378
+ if (!scripts["lint"].includes(LINT_CMD)) scripts["lint"] += ` && ${LINT_CMD}`;
1379
+ return generateCode();
1380
+ });
1381
+ sv.file(".vscode/settings.json", (content) => {
1382
+ if (!content) return content;
1383
+ const { data, generateCode } = parseJson(content);
1384
+ const validate = data["eslint.validate"];
1385
+ if (validate && !validate.includes("svelte")) validate.push("svelte");
1386
+ return generateCode();
1387
+ });
1388
+ sv.file("eslint.config.js", (content) => {
1389
+ const { ast, generateCode } = parseScript(content);
1390
+ const eslintConfigs = [];
1391
+ addDefault(ast, {
1392
+ from: "./svelte.config.js",
1393
+ as: "svelteConfig"
1394
+ });
1395
+ const gitIgnorePathStatement = parseStatement("\nconst gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));");
1396
+ appendStatement(ast, { statement: gitIgnorePathStatement });
1397
+ const ignoresConfig = parseExpression("includeIgnoreFile(gitignorePath)");
1398
+ eslintConfigs.push(ignoresConfig);
1399
+ const jsConfig = parseExpression("js.configs.recommended");
1400
+ eslintConfigs.push(jsConfig);
1401
+ if (typescript) {
1402
+ const tsConfig = parseExpression("ts.configs.recommended");
1403
+ eslintConfigs.push(createSpread(tsConfig));
1404
+ }
1405
+ const svelteConfig = parseExpression("svelte.configs.recommended");
1406
+ eslintConfigs.push(createSpread(svelteConfig));
1407
+ const globalsBrowser = createSpread(parseExpression("globals.browser"));
1408
+ const globalsNode = createSpread(parseExpression("globals.node"));
1409
+ const globalsObjLiteral = create({});
1410
+ globalsObjLiteral.properties = [globalsBrowser, globalsNode];
1411
+ const rules = create({ "\"no-undef\"": "off" });
1412
+ if (rules.properties[0].type !== "Property") throw new Error("rules.properties[0].type !== \"Property\"");
1413
+ rules.properties[0].key.leadingComments = [{
1414
+ type: "Line",
1415
+ value: " typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects."
1416
+ }, {
1417
+ type: "Line",
1418
+ value: " see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors"
1419
+ }];
1420
+ const globalsConfig = create({
1421
+ languageOptions: { globals: globalsObjLiteral },
1422
+ rules: typescript ? rules : void 0
1423
+ });
1424
+ eslintConfigs.push(globalsConfig);
1425
+ if (typescript) {
1426
+ const svelteTSParserConfig = create({
1427
+ files: [
1428
+ "**/*.svelte",
1429
+ "**/*.svelte.ts",
1430
+ "**/*.svelte.js"
1431
+ ],
1432
+ languageOptions: { parserOptions: {
1433
+ projectService: true,
1434
+ extraFileExtensions: [".svelte"],
1435
+ parser: createIdentifier("ts.parser"),
1436
+ svelteConfig: createIdentifier("svelteConfig")
1437
+ } }
1438
+ });
1439
+ eslintConfigs.push(svelteTSParserConfig);
1440
+ } else {
1441
+ const svelteTSParserConfig = create({
1442
+ files: ["**/*.svelte", "**/*.svelte.js"],
1443
+ languageOptions: { parserOptions: { svelteConfig: createIdentifier("svelteConfig") } }
1444
+ });
1445
+ eslintConfigs.push(svelteTSParserConfig);
1446
+ }
1447
+ let exportExpression;
1448
+ if (typescript) {
1449
+ const tsConfigCall = createCall({
1450
+ name: "defineConfig",
1451
+ args: []
1452
+ });
1453
+ tsConfigCall.arguments.push(...eslintConfigs);
1454
+ exportExpression = tsConfigCall;
1455
+ } else {
1456
+ const eslintArray = create$1();
1457
+ eslintConfigs.map((x$1) => append(eslintArray, x$1));
1458
+ exportExpression = eslintArray;
1459
+ }
1460
+ const { value: defaultExport, astNode } = createDefault(ast, { fallback: exportExpression });
1461
+ if (defaultExport !== exportExpression) {
1462
+ T.warn("An eslint config is already defined. Skipping initialization.");
1463
+ return content;
1464
+ }
1465
+ if (!typescript) addJsDocTypeComment(astNode, { type: "import('eslint').Linter.Config[]" });
1466
+ if (typescript) addDefault(ast, {
1467
+ from: "typescript-eslint",
1468
+ as: "ts"
1469
+ });
1470
+ addDefault(ast, {
1471
+ from: "globals",
1472
+ as: "globals"
1473
+ });
1474
+ if (typescript) addNamed(ast, {
1475
+ from: "eslint/config",
1476
+ imports: ["defineConfig"]
1477
+ });
1478
+ addDefault(ast, {
1479
+ from: "eslint-plugin-svelte",
1480
+ as: "svelte"
1481
+ });
1482
+ addDefault(ast, {
1483
+ from: "@eslint/js",
1484
+ as: "js"
1485
+ });
1486
+ addNamed(ast, {
1487
+ from: "@eslint/compat",
1488
+ imports: ["includeIgnoreFile"]
1489
+ });
1490
+ addNamed(ast, {
1491
+ from: "node:url",
1492
+ imports: ["fileURLToPath"]
1493
+ });
1494
+ return generateCode();
1495
+ });
1496
+ if (prettierInstalled) sv.file("eslint.config.js", addEslintConfigPrettier);
1497
+ }
1498
+ });
1499
+
1500
+ //#endregion
1501
+ //#region ../addons/lucia/index.ts
1502
+ const TABLE_TYPE = {
1503
+ mysql: "mysqlTable",
1504
+ postgresql: "pgTable",
1505
+ sqlite: "sqliteTable",
1506
+ turso: "sqliteTable"
1507
+ };
1508
+ let drizzleDialect;
1509
+ let schemaPath;
1510
+ const options$4 = defineAddonOptions().add("demo", {
1511
+ type: "boolean",
1512
+ default: true,
1513
+ question: `Do you want to include a demo? ${import_picocolors$2.default.dim("(includes a login/register page)")}`
1514
+ }).build();
1515
+ var lucia_default = defineAddon({
1516
+ id: "lucia",
1517
+ shortDescription: "auth guide",
1518
+ homepage: "https://lucia-auth.com",
1519
+ options: options$4,
1520
+ setup: ({ kit, dependencyVersion, unsupported, dependsOn, runsAfter }) => {
1521
+ if (!kit) unsupported("Requires SvelteKit");
1522
+ if (!dependencyVersion("drizzle-orm")) dependsOn("drizzle");
1523
+ runsAfter("tailwindcss");
1524
+ },
1525
+ run: ({ sv, typescript, options: options$6, kit, dependencyVersion }) => {
1526
+ const ext = typescript ? "ts" : "js";
1527
+ sv.devDependency("@oslojs/crypto", "^1.0.1");
1528
+ sv.devDependency("@oslojs/encoding", "^1.1.0");
1529
+ if (options$6.demo) sv.dependency("@node-rs/argon2", "^2.0.2");
1530
+ sv.file(`drizzle.config.${ext}`, (content) => {
1531
+ const { ast, generateCode } = parseScript(content);
1532
+ const isProp = (name, node) => node.key.type === "Identifier" && node.key.name === name;
1533
+ walk(ast, null, { Property(node) {
1534
+ if (isProp("dialect", node) && node.value.type === "Literal" && typeof node.value.value === "string") drizzleDialect = node.value.value;
1535
+ if (isProp("schema", node) && node.value.type === "Literal" && typeof node.value.value === "string") schemaPath = node.value.value;
1536
+ } });
1537
+ if (!drizzleDialect) throw new Error("Failed to detect DB dialect in your `drizzle.config.[js|ts]` file");
1538
+ if (!schemaPath) throw new Error("Failed to find schema path in your `drizzle.config.[js|ts]` file");
1539
+ return generateCode();
1540
+ });
1541
+ sv.file(schemaPath, (content) => {
1542
+ const { ast, generateCode } = parseScript(content);
1543
+ const createTable = (name) => createCall({
1544
+ name: TABLE_TYPE[drizzleDialect],
1545
+ args: [name]
1546
+ });
1547
+ const userDecl = declaration(ast, {
1548
+ kind: "const",
1549
+ name: "user",
1550
+ value: createTable("user")
1551
+ });
1552
+ const sessionDecl = declaration(ast, {
1553
+ kind: "const",
1554
+ name: "session",
1555
+ value: createTable("session")
1556
+ });
1557
+ const user = createNamed(ast, {
1558
+ name: "user",
1559
+ fallback: userDecl
1560
+ });
1561
+ const session = createNamed(ast, {
1562
+ name: "session",
1563
+ fallback: sessionDecl
1564
+ });
1565
+ const userTable = getCallExpression(user);
1566
+ const sessionTable = getCallExpression(session);
1567
+ if (!userTable || !sessionTable) throw new Error("failed to find call expression of `user` or `session`");
1568
+ if (userTable.arguments.length === 1) userTable.arguments.push(create({}));
1569
+ if (sessionTable.arguments.length === 1) sessionTable.arguments.push(create({}));
1570
+ const userAttributes = userTable.arguments[1];
1571
+ const sessionAttributes = sessionTable.arguments[1];
1572
+ if (userAttributes?.type !== "ObjectExpression" || sessionAttributes?.type !== "ObjectExpression") throw new Error("unexpected shape of `user` or `session` table definition");
1573
+ if (drizzleDialect === "sqlite" || drizzleDialect === "turso") {
1574
+ addNamed(ast, {
1575
+ from: "drizzle-orm/sqlite-core",
1576
+ imports: [
1577
+ "sqliteTable",
1578
+ "text",
1579
+ "integer"
1580
+ ]
1581
+ });
1582
+ overrideProperties(userAttributes, { id: parseExpression("text('id').primaryKey()") });
1583
+ if (options$6.demo) overrideProperties(userAttributes, {
1584
+ username: parseExpression("text('username').notNull().unique()"),
1585
+ passwordHash: parseExpression("text('password_hash').notNull()")
1586
+ });
1587
+ overrideProperties(sessionAttributes, {
1588
+ id: parseExpression("text('id').primaryKey()"),
1589
+ userId: parseExpression("text('user_id').notNull().references(() => user.id)"),
1590
+ expiresAt: parseExpression("integer('expires_at', { mode: 'timestamp' }).notNull()")
1591
+ });
1592
+ }
1593
+ if (drizzleDialect === "mysql") {
1594
+ addNamed(ast, {
1595
+ from: "drizzle-orm/mysql-core",
1596
+ imports: [
1597
+ "mysqlTable",
1598
+ "varchar",
1599
+ "datetime"
1600
+ ]
1601
+ });
1602
+ overrideProperties(userAttributes, { id: parseExpression("varchar('id', { length: 255 }).primaryKey()") });
1603
+ if (options$6.demo) overrideProperties(userAttributes, {
1604
+ username: parseExpression("varchar('username', { length: 32 }).notNull().unique()"),
1605
+ passwordHash: parseExpression("varchar('password_hash', { length: 255 }).notNull()")
1606
+ });
1607
+ overrideProperties(sessionAttributes, {
1608
+ id: parseExpression("varchar('id', { length: 255 }).primaryKey()"),
1609
+ userId: parseExpression("varchar('user_id', { length: 255 }).notNull().references(() => user.id)"),
1610
+ expiresAt: parseExpression("datetime('expires_at').notNull()")
1611
+ });
1612
+ }
1613
+ if (drizzleDialect === "postgresql") {
1614
+ addNamed(ast, {
1615
+ from: "drizzle-orm/pg-core",
1616
+ imports: [
1617
+ "pgTable",
1618
+ "text",
1619
+ "timestamp"
1620
+ ]
1621
+ });
1622
+ overrideProperties(userAttributes, { id: parseExpression("text('id').primaryKey()") });
1623
+ if (options$6.demo) overrideProperties(userAttributes, {
1624
+ username: parseExpression("text('username').notNull().unique()"),
1625
+ passwordHash: parseExpression("text('password_hash').notNull()")
1626
+ });
1627
+ overrideProperties(sessionAttributes, {
1628
+ id: parseExpression("text('id').primaryKey()"),
1629
+ userId: parseExpression("text('user_id').notNull().references(() => user.id)"),
1630
+ expiresAt: parseExpression("timestamp('expires_at', { withTimezone: true, mode: 'date' }).notNull()")
1631
+ });
1632
+ }
1633
+ let code = generateCode();
1634
+ if (typescript) {
1635
+ if (!code.includes("export type Session =")) code += "\n\nexport type Session = typeof session.$inferSelect;";
1636
+ if (!code.includes("export type User =")) code += "\n\nexport type User = typeof user.$inferSelect;";
1637
+ }
1638
+ return code;
1639
+ });
1640
+ sv.file(`${kit?.libDirectory}/server/auth.${ext}`, (content) => {
1641
+ const { ast, generateCode } = parseScript(content);
1642
+ addNamespace(ast, {
1643
+ from: "$lib/server/db/schema",
1644
+ as: "table"
1645
+ });
1646
+ addNamed(ast, {
1647
+ from: "$lib/server/db",
1648
+ imports: ["db"]
1649
+ });
1650
+ addNamed(ast, {
1651
+ from: "@oslojs/encoding",
1652
+ imports: ["encodeBase64url", "encodeHexLowerCase"]
1653
+ });
1654
+ addNamed(ast, {
1655
+ from: "@oslojs/crypto/sha2",
1656
+ imports: ["sha256"]
1657
+ });
1658
+ addNamed(ast, {
1659
+ from: "drizzle-orm",
1660
+ imports: ["eq"]
1661
+ });
1662
+ if (typescript) addNamed(ast, {
1663
+ from: "@sveltejs/kit",
1664
+ imports: ["RequestEvent"],
1665
+ isType: true
1666
+ });
1667
+ const ms = new MagicString(generateCode().trim());
1668
+ const [ts] = createPrinter(typescript);
1669
+ if (!ms.original.includes("const DAY_IN_MS")) ms.append("\n\nconst DAY_IN_MS = 1000 * 60 * 60 * 24;");
1670
+ if (!ms.original.includes("export const sessionCookieName")) ms.append("\n\nexport const sessionCookieName = 'auth-session';");
1671
+ if (!ms.original.includes("export function generateSessionToken")) {
1672
+ const generateSessionToken = dedent_default`
1673
+ export function generateSessionToken() {
1674
+ const bytes = crypto.getRandomValues(new Uint8Array(18));
1675
+ const token = encodeBase64url(bytes);
1676
+ return token;
1677
+ }`;
1678
+ ms.append(`\n\n${generateSessionToken}`);
1679
+ }
1680
+ if (!ms.original.includes("async function createSession")) {
1681
+ const createSession = dedent_default`
1682
+ ${ts("", "/**")}
1683
+ ${ts("", " * @param {string} token")}
1684
+ ${ts("", " * @param {string} userId")}
1685
+ ${ts("", " */")}
1686
+ export async function createSession(token${ts(": string")}, userId${ts(": string")}) {
1687
+ const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
1688
+ const session${ts(": table.Session")} = {
1689
+ id: sessionId,
1690
+ userId,
1691
+ expiresAt: new Date(Date.now() + DAY_IN_MS * 30)
1692
+ };
1693
+ await db.insert(table.session).values(session);
1694
+ return session;
1695
+ }`;
1696
+ ms.append(`\n\n${createSession}`);
1697
+ }
1698
+ if (!ms.original.includes("async function validateSessionToken")) {
1699
+ const validateSessionToken = dedent_default`
1700
+ ${ts("", "/** @param {string} token */")}
1701
+ export async function validateSessionToken(token${ts(": string")}) {
1702
+ const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
1703
+ const [result] = await db
1704
+ .select({
1705
+ // Adjust user table here to tweak returned data
1706
+ user: { id: table.user.id, username: table.user.username },
1707
+ session: table.session
1708
+ })
1709
+ .from(table.session)
1710
+ .innerJoin(table.user, eq(table.session.userId, table.user.id))
1711
+ .where(eq(table.session.id, sessionId));
1712
+
1713
+ if (!result) {
1714
+ return { session: null, user: null };
1715
+ }
1716
+ const { session, user } = result;
1717
+
1718
+ const sessionExpired = Date.now() >= session.expiresAt.getTime();
1719
+ if (sessionExpired) {
1720
+ await db.delete(table.session).where(eq(table.session.id, session.id));
1721
+ return { session: null, user: null };
1722
+ }
1723
+
1724
+ const renewSession = Date.now() >= session.expiresAt.getTime() - DAY_IN_MS * 15;
1725
+ if (renewSession) {
1726
+ session.expiresAt = new Date(Date.now() + DAY_IN_MS * 30);
1727
+ await db
1728
+ .update(table.session)
1729
+ .set({ expiresAt: session.expiresAt })
1730
+ .where(eq(table.session.id, session.id));
1731
+ }
1732
+
1733
+ return { session, user };
1734
+ }`;
1735
+ ms.append(`\n\n${validateSessionToken}`);
1736
+ }
1737
+ if (typescript && !ms.original.includes("export type SessionValidationResult")) ms.append(`\n\nexport type SessionValidationResult = Awaited<ReturnType<typeof validateSessionToken>>;`);
1738
+ if (!ms.original.includes("async function invalidateSession")) {
1739
+ const invalidateSession = dedent_default`
1740
+ ${ts("", "/** @param {string} sessionId */")}
1741
+ export async function invalidateSession(sessionId${ts(": string")}) {
1742
+ await db.delete(table.session).where(eq(table.session.id, sessionId));
1743
+ }`;
1744
+ ms.append(`\n\n${invalidateSession}`);
1745
+ }
1746
+ if (!ms.original.includes("export function setSessionTokenCookie")) {
1747
+ const setSessionTokenCookie = dedent_default`
1748
+ ${ts("", "/**")}
1749
+ ${ts("", " * @param {import(\"@sveltejs/kit\").RequestEvent} event")}
1750
+ ${ts("", " * @param {string} token")}
1751
+ ${ts("", " * @param {Date} expiresAt")}
1752
+ ${ts("", " */")}
1753
+ export function setSessionTokenCookie(event${ts(": RequestEvent")}, token${ts(": string")}, expiresAt${ts(": Date")}) {
1754
+ event.cookies.set(sessionCookieName, token, {
1755
+ expires: expiresAt,
1756
+ path: '/'
1757
+ });
1758
+ }`;
1759
+ ms.append(`\n\n${setSessionTokenCookie}`);
1760
+ }
1761
+ if (!ms.original.includes("export function deleteSessionTokenCookie")) {
1762
+ const deleteSessionTokenCookie = dedent_default`
1763
+ ${ts("", "/** @param {import(\"@sveltejs/kit\").RequestEvent} event */")}
1764
+ export function deleteSessionTokenCookie(event${ts(": RequestEvent")}) {
1765
+ event.cookies.delete(sessionCookieName, {
1766
+ path: '/'
1767
+ });
1768
+ }`;
1769
+ ms.append(`\n\n${deleteSessionTokenCookie}`);
1770
+ }
1771
+ return ms.toString();
1772
+ });
1773
+ if (typescript) sv.file("src/app.d.ts", (content) => {
1774
+ const { ast, generateCode } = parseScript(content);
1775
+ const locals = addGlobalAppInterface(ast, { name: "Locals" });
1776
+ if (!locals) throw new Error("Failed detecting `locals` interface in `src/app.d.ts`");
1777
+ const user = locals.body.body.find((prop) => hasTypeProperty(prop, { name: "user" }));
1778
+ const session = locals.body.body.find((prop) => hasTypeProperty(prop, { name: "session" }));
1779
+ if (!user) locals.body.body.push(createLuciaType("user"));
1780
+ if (!session) locals.body.body.push(createLuciaType("session"));
1781
+ return generateCode();
1782
+ });
1783
+ sv.file(`src/hooks.server.${ext}`, (content) => {
1784
+ const { ast, generateCode } = parseScript(content);
1785
+ addNamespace(ast, {
1786
+ from: "$lib/server/auth",
1787
+ as: "auth"
1788
+ });
1789
+ addHooksHandle(ast, {
1790
+ typescript,
1791
+ newHandleName: "handleAuth",
1792
+ handleContent: getAuthHandleContent()
1793
+ });
1794
+ return generateCode();
1795
+ });
1796
+ if (options$6.demo) {
1797
+ sv.file(`${kit?.routesDirectory}/demo/+page.svelte`, (content) => {
1798
+ return addToDemoPage(content, "lucia");
1799
+ });
1800
+ sv.file(`${kit.routesDirectory}/demo/lucia/login/+page.server.${ext}`, (content) => {
1801
+ if (content) {
1802
+ const filePath = `${kit.routesDirectory}/demo/lucia/login/+page.server.${typescript ? "ts" : "js"}`;
1803
+ T.warn(`Existing ${import_picocolors$2.default.yellow(filePath)} file. Could not update.`);
1804
+ return content;
1805
+ }
1806
+ const [ts] = createPrinter(typescript);
1807
+ return dedent_default`
1808
+ import { hash, verify } from '@node-rs/argon2';
1809
+ import { encodeBase32LowerCase } from '@oslojs/encoding';
1810
+ import { fail, redirect } from '@sveltejs/kit';
1811
+ import { eq } from 'drizzle-orm';
1812
+ import * as auth from '$lib/server/auth';
1813
+ import { db } from '$lib/server/db';
1814
+ import * as table from '$lib/server/db/schema';
1815
+ ${ts("import type { Actions, PageServerLoad } from './$types';\n")}
1816
+ export const load${ts(": PageServerLoad")} = async (event) => {
1817
+ if (event.locals.user) {
1818
+ return redirect(302, '/demo/lucia');
1819
+ }
1820
+ return {};
1821
+ };
1822
+
1823
+ export const actions${ts(": Actions")} = {
1824
+ login: async (event) => {
1825
+ const formData = await event.request.formData();
1826
+ const username = formData.get('username');
1827
+ const password = formData.get('password');
1828
+
1829
+ if (!validateUsername(username)) {
1830
+ return fail(400, { message: 'Invalid username (min 3, max 31 characters, alphanumeric only)' });
1831
+ }
1832
+ if (!validatePassword(password)) {
1833
+ return fail(400, { message: 'Invalid password (min 6, max 255 characters)' });
1834
+ }
1835
+
1836
+ const results = await db
1837
+ .select()
1838
+ .from(table.user)
1839
+ .where(eq(table.user.username, username));
1840
+
1841
+ const existingUser = results.at(0);
1842
+ if (!existingUser) {
1843
+ return fail(400, { message: 'Incorrect username or password' });
1844
+ }
1845
+
1846
+ const validPassword = await verify(existingUser.passwordHash, password, {
1847
+ memoryCost: 19456,
1848
+ timeCost: 2,
1849
+ outputLen: 32,
1850
+ parallelism: 1,
1851
+ });
1852
+ if (!validPassword) {
1853
+ return fail(400, { message: 'Incorrect username or password' });
1854
+ }
1855
+
1856
+ const sessionToken = auth.generateSessionToken();
1857
+ const session = await auth.createSession(sessionToken, existingUser.id);
1858
+ auth.setSessionTokenCookie(event, sessionToken, session.expiresAt);
1859
+
1860
+ return redirect(302, '/demo/lucia');
1861
+ },
1862
+ register: async (event) => {
1863
+ const formData = await event.request.formData();
1864
+ const username = formData.get('username');
1865
+ const password = formData.get('password');
1866
+
1867
+ if (!validateUsername(username)) {
1868
+ return fail(400, { message: 'Invalid username' });
1869
+ }
1870
+ if (!validatePassword(password)) {
1871
+ return fail(400, { message: 'Invalid password' });
1872
+ }
1873
+
1874
+ const userId = generateUserId();
1875
+ const passwordHash = await hash(password, {
1876
+ // recommended minimum parameters
1877
+ memoryCost: 19456,
1878
+ timeCost: 2,
1879
+ outputLen: 32,
1880
+ parallelism: 1,
1881
+ });
1882
+
1883
+ try {
1884
+ await db.insert(table.user).values({ id: userId, username, passwordHash });
1885
+
1886
+ const sessionToken = auth.generateSessionToken();
1887
+ const session = await auth.createSession(sessionToken, userId);
1888
+ auth.setSessionTokenCookie(event, sessionToken, session.expiresAt);
1889
+ } catch {
1890
+ return fail(500, { message: 'An error has occurred' });
1891
+ }
1892
+ return redirect(302, '/demo/lucia');
1893
+ },
1894
+ };
1895
+
1896
+ function generateUserId() {
1897
+ // ID with 120 bits of entropy, or about the same as UUID v4.
1898
+ const bytes = crypto.getRandomValues(new Uint8Array(15));
1899
+ const id = encodeBase32LowerCase(bytes);
1900
+ return id;
1901
+ }
1902
+
1903
+ function validateUsername(username${ts(": unknown")})${ts(": username is string")} {
1904
+ return (
1905
+ typeof username === 'string' &&
1906
+ username.length >= 3 &&
1907
+ username.length <= 31 &&
1908
+ /^[a-z0-9_-]+$/.test(username)
1909
+ );
1910
+ }
1911
+
1912
+ function validatePassword(password${ts(": unknown")})${ts(": password is string")} {
1913
+ return (
1914
+ typeof password === 'string' &&
1915
+ password.length >= 6 &&
1916
+ password.length <= 255
1917
+ );
1918
+ }
1919
+ `;
1920
+ });
1921
+ sv.file(`${kit.routesDirectory}/demo/lucia/login/+page.svelte`, (content) => {
1922
+ if (content) {
1923
+ const filePath = `${kit.routesDirectory}/demo/lucia/login/+page.svelte`;
1924
+ T.warn(`Existing ${import_picocolors$2.default.yellow(filePath)} file. Could not update.`);
1925
+ return content;
1926
+ }
1927
+ const tailwind = dependencyVersion("@tailwindcss/vite") !== void 0;
1928
+ const twInputClasses = "class=\"mt-1 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"";
1929
+ const twBtnClasses = "class=\"bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition\"";
1930
+ const svelte5 = !!dependencyVersion("svelte")?.startsWith("5");
1931
+ const [ts, s5] = createPrinter(typescript, svelte5);
1932
+ return dedent_default`
1933
+ <script ${ts("lang='ts'")}>
1934
+ import { enhance } from '$app/forms';
1935
+ ${ts("import type { ActionData } from './$types';\n")}
1936
+ ${s5(`let { form }${ts(": { form: ActionData }")} = $props();`, `export let form${ts(": ActionData")};`)}
1937
+ <\/script>
1938
+
1939
+ <h1>Login/Register</h1>
1940
+ <form method="post" action="?/login" use:enhance>
1941
+ <label>
1942
+ Username
1943
+ <input
1944
+ name="username"
1945
+ ${tailwind ? twInputClasses : ""}
1946
+ />
1947
+ </label>
1948
+ <label>
1949
+ Password
1950
+ <input
1951
+ type="password"
1952
+ name="password"
1953
+ ${tailwind ? twInputClasses : ""}
1954
+ />
1955
+ </label>
1956
+ <button ${tailwind ? twBtnClasses : ""}
1957
+ >Login</button>
1958
+ <button
1959
+ formaction="?/register"
1960
+ ${tailwind ? twBtnClasses : ""}
1961
+ >Register</button>
1962
+ </form>
1963
+ <p style='color: red'>{form?.message ?? ''}</p>
1964
+ `;
1965
+ });
1966
+ sv.file(`${kit.routesDirectory}/demo/lucia/+page.server.${ext}`, (content) => {
1967
+ if (content) {
1968
+ const filePath = `${kit.routesDirectory}/demo/lucia/+page.server.${typescript ? "ts" : "js"}`;
1969
+ T.warn(`Existing ${import_picocolors$2.default.yellow(filePath)} file. Could not update.`);
1970
+ return content;
1971
+ }
1972
+ const [ts] = createPrinter(typescript);
1973
+ return dedent_default`
1974
+ import * as auth from '$lib/server/auth';
1975
+ import { fail, redirect } from '@sveltejs/kit';
1976
+ import { getRequestEvent } from '$app/server';
1977
+ ${ts("import type { Actions, PageServerLoad } from './$types';\n")}
1978
+ export const load${ts(": PageServerLoad")} = async () => {
1979
+ const user = requireLogin()
1980
+ return { user };
1981
+ };
1982
+
1983
+ export const actions${ts(": Actions")} = {
1984
+ logout: async (event) => {
1985
+ if (!event.locals.session) {
1986
+ return fail(401);
1987
+ }
1988
+ await auth.invalidateSession(event.locals.session.id);
1989
+ auth.deleteSessionTokenCookie(event);
1990
+
1991
+ return redirect(302, '/demo/lucia/login');
1992
+ },
1993
+ };
1994
+
1995
+ function requireLogin() {
1996
+ const { locals } = getRequestEvent();
1997
+
1998
+ if (!locals.user) {
1999
+ return redirect(302, "/demo/lucia/login");
2000
+ }
2001
+
2002
+ return locals.user;
2003
+ }
2004
+ `;
2005
+ });
2006
+ sv.file(`${kit.routesDirectory}/demo/lucia/+page.svelte`, (content) => {
2007
+ if (content) {
2008
+ const filePath = `${kit.routesDirectory}/demo/lucia/+page.svelte`;
2009
+ T.warn(`Existing ${import_picocolors$2.default.yellow(filePath)} file. Could not update.`);
2010
+ return content;
2011
+ }
2012
+ const svelte5 = !!dependencyVersion("svelte")?.startsWith("5");
2013
+ const [ts, s5] = createPrinter(typescript, svelte5);
2014
+ return dedent_default`
2015
+ <script ${ts("lang='ts'")}>
2016
+ import { enhance } from '$app/forms';
2017
+ ${ts("import type { PageServerData } from './$types';\n")}
2018
+ ${s5(`let { data }${ts(": { data: PageServerData }")} = $props();`, `export let data${ts(": PageServerData")};`)}
2019
+ <\/script>
2020
+
2021
+ <h1>Hi, {data.user.username}!</h1>
2022
+ <p>Your user ID is {data.user.id}.</p>
2023
+ <form method='post' action='?/logout' use:enhance>
2024
+ <button>Sign out</button>
2025
+ </form>
2026
+ `;
2027
+ });
2028
+ }
2029
+ },
2030
+ nextSteps: ({ highlighter, options: options$6, packageManager }) => {
2031
+ const { command, args } = resolveCommand(packageManager, "run", ["db:push"]);
2032
+ const steps = [`Run ${highlighter.command(`${command} ${args.join(" ")}`)} to update your database schema`];
2033
+ if (options$6.demo) steps.push(`Visit ${highlighter.route("/demo/lucia")} route to view the demo`);
2034
+ return steps;
2035
+ }
2036
+ });
2037
+ function createLuciaType(name) {
2038
+ return {
2039
+ type: "TSPropertySignature",
2040
+ key: {
2041
+ type: "Identifier",
2042
+ name
2043
+ },
2044
+ computed: false,
2045
+ typeAnnotation: {
2046
+ type: "TSTypeAnnotation",
2047
+ typeAnnotation: {
2048
+ type: "TSIndexedAccessType",
2049
+ objectType: {
2050
+ type: "TSImportType",
2051
+ argument: {
2052
+ type: "Literal",
2053
+ value: "$lib/server/auth"
2054
+ },
2055
+ qualifier: {
2056
+ type: "Identifier",
2057
+ name: "SessionValidationResult"
2058
+ }
2059
+ },
2060
+ indexType: {
2061
+ type: "TSLiteralType",
2062
+ literal: {
2063
+ type: "Literal",
2064
+ value: name
2065
+ }
2066
+ }
2067
+ }
2068
+ }
2069
+ };
2070
+ }
2071
+ function getAuthHandleContent() {
2072
+ return `
2073
+ async ({ event, resolve }) => {
2074
+ const sessionToken = event.cookies.get(auth.sessionCookieName);
2075
+ if (!sessionToken) {
2076
+ event.locals.user = null;
2077
+ event.locals.session = null;
2078
+ return resolve(event);
2079
+ }
2080
+
2081
+ const { session, user } = await auth.validateSessionToken(sessionToken);
2082
+ if (session) {
2083
+ auth.setSessionTokenCookie(event, sessionToken, session.expiresAt);
2084
+ } else {
2085
+ auth.deleteSessionTokenCookie(event);
2086
+ }
2087
+
2088
+ event.locals.user = user;
2089
+ event.locals.session = session;
2090
+
2091
+ return resolve(event);
2092
+ };`;
2093
+ }
2094
+ function getCallExpression(ast) {
2095
+ let callExpression;
2096
+ walk(ast, null, { CallExpression(node) {
2097
+ callExpression ??= node;
2098
+ } });
2099
+ return callExpression;
2100
+ }
2101
+
2102
+ //#endregion
2103
+ //#region ../addons/mdsvex/index.ts
2104
+ var mdsvex_default = defineAddon({
2105
+ id: "mdsvex",
2106
+ shortDescription: "svelte + markdown",
2107
+ homepage: "https://mdsvex.pngwn.io",
2108
+ options: {},
2109
+ run: ({ sv }) => {
2110
+ sv.devDependency("mdsvex", "^0.12.6");
2111
+ sv.file("svelte.config.js", (content) => {
2112
+ const { ast, generateCode } = parseScript(content);
2113
+ addNamed(ast, {
2114
+ from: "mdsvex",
2115
+ imports: ["mdsvex"]
2116
+ });
2117
+ const { value: exportDefault } = createDefault(ast, { fallback: create({}) });
2118
+ let preprocessorArray = property(exportDefault, {
2119
+ name: "preprocess",
2120
+ fallback: create$1()
2121
+ });
2122
+ if (!(preprocessorArray.type === "ArrayExpression")) {
2123
+ const previousElement = preprocessorArray;
2124
+ preprocessorArray = create$1();
2125
+ append(preprocessorArray, previousElement);
2126
+ overrideProperties(exportDefault, { preprocess: preprocessorArray });
2127
+ }
2128
+ const mdsvexCall = createCall({
2129
+ name: "mdsvex",
2130
+ args: []
2131
+ });
2132
+ append(preprocessorArray, mdsvexCall);
2133
+ const extensionsArray = property(exportDefault, {
2134
+ name: "extensions",
2135
+ fallback: create$1()
2136
+ });
2137
+ append(extensionsArray, ".svelte");
2138
+ append(extensionsArray, ".svx");
2139
+ return generateCode();
2140
+ });
2141
+ }
2142
+ });
2143
+
2144
+ //#endregion
2145
+ //#region ../core/tooling/html/index.ts
2146
+ function createElement(tagName, attributes = {}) {
2147
+ const element = new Element(tagName, {}, void 0, Tag);
2148
+ element.attribs = attributes;
2149
+ return element;
2150
+ }
2151
+ function appendElement(childNodes, elementToAppend) {
2152
+ childNodes.push(elementToAppend);
2153
+ }
2154
+ function addFromRawHtml(childNodes, html) {
2155
+ const document = parseHtml$1(html);
2156
+ for (const childNode of document.childNodes) childNodes.push(childNode);
2157
+ }
2158
+ function addSlot(jsAst, options$6) {
2159
+ if (options$6.svelteVersion && (options$6.svelteVersion.startsWith("4") || options$6.svelteVersion.startsWith("3"))) {
2160
+ const slot = createElement("slot");
2161
+ appendElement(options$6.htmlAst.childNodes, slot);
2162
+ return;
2163
+ }
2164
+ appendFromString(jsAst, { code: "let { children } = $props();" });
2165
+ addFromRawHtml(options$6.htmlAst.childNodes, "{@render children()}");
2166
+ }
2167
+
2168
+ //#endregion
2169
+ //#region ../addons/paraglide/index.ts
2170
+ const DEFAULT_INLANG_PROJECT = {
2171
+ $schema: "https://inlang.com/schema/project-settings",
2172
+ modules: ["https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js"],
2173
+ "plugin.inlang.messageFormat": { pathPattern: "./messages/{locale}.json" }
2174
+ };
2175
+ const options$3 = defineAddonOptions().add("languageTags", {
2176
+ question: `Which languages would you like to support? ${import_picocolors$2.default.gray("(e.g. en,de-ch)")}`,
2177
+ type: "string",
2178
+ default: "en, es",
2179
+ validate(input) {
2180
+ if (!input) return;
2181
+ const { invalidLanguageTags, validLanguageTags } = parseLanguageTagInput(input);
2182
+ if (invalidLanguageTags.length > 0) if (invalidLanguageTags.length === 1) return `The input "${invalidLanguageTags[0]}" is not a valid IETF BCP 47 language tag`;
2183
+ else return `The inputs ${new Intl.ListFormat("en", {
2184
+ style: "long",
2185
+ type: "conjunction"
2186
+ }).format(invalidLanguageTags.map((x$1) => `"${x$1}"`))} are not valid BCP47 language tags`;
2187
+ if (validLanguageTags.length === 0) return "Please enter at least one valid BCP47 language tag. Eg: en";
2188
+ }
2189
+ }).add("demo", {
2190
+ type: "boolean",
2191
+ default: true,
2192
+ question: "Do you want to include a demo?"
2193
+ }).build();
2194
+ var paraglide_default = defineAddon({
2195
+ id: "paraglide",
2196
+ shortDescription: "i18n",
2197
+ homepage: "https://inlang.com/m/gerre34r/library-inlang-paraglideJs",
2198
+ options: options$3,
2199
+ setup: ({ kit, unsupported }) => {
2200
+ if (!kit) unsupported("Requires SvelteKit");
2201
+ },
2202
+ run: ({ sv, options: options$6, viteConfigFile, typescript, kit }) => {
2203
+ const ext = typescript ? "ts" : "js";
2204
+ if (!kit) throw new Error("SvelteKit is required");
2205
+ const paraglideOutDir = "src/lib/paraglide";
2206
+ sv.devDependency("@inlang/paraglide-js", "^2.3.2");
2207
+ sv.file("project.inlang/settings.json", (content) => {
2208
+ if (content) return content;
2209
+ const { data, generateCode } = parseJson(content);
2210
+ for (const key in DEFAULT_INLANG_PROJECT) data[key] = DEFAULT_INLANG_PROJECT[key];
2211
+ const { validLanguageTags: validLanguageTags$1 } = parseLanguageTagInput(options$6.languageTags);
2212
+ data.baseLocale = validLanguageTags$1[0];
2213
+ data.locales = validLanguageTags$1;
2214
+ return generateCode();
2215
+ });
2216
+ sv.file(viteConfigFile, (content) => {
2217
+ const { ast, generateCode } = parseScript(content);
2218
+ const vitePluginName = "paraglideVitePlugin";
2219
+ addNamed(ast, {
2220
+ imports: [vitePluginName],
2221
+ from: "@inlang/paraglide-js"
2222
+ });
2223
+ addPlugin(ast, { code: `${vitePluginName}({
2224
+ project: './project.inlang',
2225
+ outdir: './${paraglideOutDir}'
2226
+ })` });
2227
+ return generateCode();
2228
+ });
2229
+ sv.file(`src/hooks.${ext}`, (content) => {
2230
+ const { ast, generateCode } = parseScript(content);
2231
+ addNamed(ast, {
2232
+ from: "$lib/paraglide/runtime",
2233
+ imports: ["deLocalizeUrl"]
2234
+ });
2235
+ const expression = parseExpression("(request) => deLocalizeUrl(request.url).pathname");
2236
+ const rerouteIdentifier = declaration(ast, {
2237
+ kind: "const",
2238
+ name: "reroute",
2239
+ value: expression
2240
+ });
2241
+ if (createNamed(ast, {
2242
+ name: "reroute",
2243
+ fallback: rerouteIdentifier
2244
+ }).declaration !== rerouteIdentifier) T.warn("Adding the reroute hook automatically failed. Add it manually");
2245
+ return generateCode();
2246
+ });
2247
+ sv.file(`src/hooks.server.${ext}`, (content) => {
2248
+ const { ast, generateCode } = parseScript(content);
2249
+ addNamed(ast, {
2250
+ from: "$lib/paraglide/server",
2251
+ imports: ["paraglideMiddleware"]
2252
+ });
2253
+ addHooksHandle(ast, {
2254
+ typescript,
2255
+ newHandleName: "handleParaglide",
2256
+ handleContent: `({ event, resolve }) => paraglideMiddleware(event.request, ({ request, locale }) => {
2257
+ event.request = request;
2258
+ return resolve(event, {
2259
+ transformPageChunk: ({ html }) => html.replace('%paraglide.lang%', locale)
2260
+ });
2261
+ });`
2262
+ });
2263
+ return generateCode();
2264
+ });
2265
+ sv.file("src/app.html", (content) => {
2266
+ const { ast, generateCode } = parseHtml(content);
2267
+ const htmlNode = ast.children.find((child) => child.type === Tag && child.name === "html");
2268
+ if (!htmlNode) {
2269
+ T.warn("Could not find <html> node in app.html. You'll need to add the language placeholder manually");
2270
+ return generateCode();
2271
+ }
2272
+ htmlNode.attribs = {
2273
+ ...htmlNode.attribs,
2274
+ lang: "%paraglide.lang%"
2275
+ };
2276
+ return generateCode();
2277
+ });
2278
+ sv.file(".gitignore", (content) => {
2279
+ if (!content) return content;
2280
+ if (!content.includes(`\n${paraglideOutDir}`)) content = content.trimEnd() + `\n\n# Paraglide\n${paraglideOutDir}`;
2281
+ return content;
2282
+ });
2283
+ if (options$6.demo) {
2284
+ sv.file(`${kit.routesDirectory}/demo/+page.svelte`, (content) => {
2285
+ return addToDemoPage(content, "paraglide");
2286
+ });
2287
+ sv.file(`${kit.routesDirectory}/demo/paraglide/+page.svelte`, (content) => {
2288
+ const { script, template, generateCode } = parseSvelte(content, { typescript });
2289
+ addNamed(script.ast, {
2290
+ from: "$lib/paraglide/messages.js",
2291
+ imports: ["m"]
2292
+ });
2293
+ addNamed(script.ast, {
2294
+ from: "$app/navigation",
2295
+ imports: ["goto"]
2296
+ });
2297
+ addNamed(script.ast, {
2298
+ from: "$app/state",
2299
+ imports: ["page"]
2300
+ });
2301
+ addNamed(script.ast, {
2302
+ from: "$lib/paraglide/runtime",
2303
+ imports: ["setLocale"]
2304
+ });
2305
+ const scriptCode = new MagicString(script.generateCode());
2306
+ const templateCode = new MagicString(template.source);
2307
+ templateCode.append("\n\n<h1>{m.hello_world({ name: 'SvelteKit User' })}</h1>\n");
2308
+ const { validLanguageTags: validLanguageTags$1 } = parseLanguageTagInput(options$6.languageTags);
2309
+ const links = validLanguageTags$1.map((x$1) => `${templateCode.getIndentString()}<button onclick={() => setLocale('${x$1}')}>${x$1}</button>`).join("\n");
2310
+ templateCode.append(`<div>\n${links}\n</div>`);
2311
+ templateCode.append("<p>\nIf you use VSCode, install the <a href=\"https://marketplace.visualstudio.com/items?itemName=inlang.vs-code-extension\" target=\"_blank\">Sherlock i18n extension</a> for a better i18n experience.\n</p>");
2312
+ return generateCode({
2313
+ script: scriptCode.toString(),
2314
+ template: templateCode.toString()
2315
+ });
2316
+ });
2317
+ }
2318
+ const { validLanguageTags } = parseLanguageTagInput(options$6.languageTags);
2319
+ for (const languageTag of validLanguageTags) sv.file(`messages/${languageTag}.json`, (content) => {
2320
+ const { data, generateCode } = parseJson(content);
2321
+ data["$schema"] = "https://inlang.com/schema/inlang-message-format";
2322
+ data.hello_world = `Hello, {name} from ${languageTag}!`;
2323
+ return generateCode();
2324
+ });
2325
+ },
2326
+ nextSteps: ({ highlighter }) => {
2327
+ const steps = [`Edit your messages in ${highlighter.path("messages/en.json")}`];
2328
+ if (options$3.demo) steps.push(`Visit ${highlighter.route("/demo/paraglide")} route to view the demo`);
2329
+ return steps;
2330
+ }
2331
+ });
2332
+ const isValidLanguageTag = (languageTag) => RegExp("^((?<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?))(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?(-(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*))$").test(languageTag);
2333
+ function parseLanguageTagInput(input) {
2334
+ const probablyLanguageTags = input.replace(/[,:\s]/g, " ").split(" ").filter(Boolean).map((tag) => tag.toLowerCase());
2335
+ const validLanguageTags = [];
2336
+ const invalidLanguageTags = [];
2337
+ for (const tag of probablyLanguageTags) if (isValidLanguageTag(tag)) validLanguageTags.push(tag);
2338
+ else invalidLanguageTags.push(tag);
2339
+ return {
2340
+ validLanguageTags,
2341
+ invalidLanguageTags
2342
+ };
2343
+ }
2344
+
2345
+ //#endregion
2346
+ //#region ../addons/playwright/index.ts
2347
+ var playwright_default = defineAddon({
2348
+ id: "playwright",
2349
+ shortDescription: "browser testing",
2350
+ homepage: "https://playwright.dev",
2351
+ options: {},
2352
+ run: ({ sv, typescript }) => {
2353
+ const ext = typescript ? "ts" : "js";
2354
+ sv.devDependency("@playwright/test", "^1.55.1");
2355
+ sv.file("package.json", (content) => {
2356
+ const { data, generateCode } = parseJson(content);
2357
+ data.scripts ??= {};
2358
+ const scripts = data.scripts;
2359
+ const TEST_CMD = "playwright test";
2360
+ const RUN_TEST = "npm run test:e2e";
2361
+ scripts["test:e2e"] ??= TEST_CMD;
2362
+ scripts["test"] ??= RUN_TEST;
2363
+ if (!scripts["test"].includes(RUN_TEST)) scripts["test"] += ` && ${RUN_TEST}`;
2364
+ return generateCode();
2365
+ });
2366
+ sv.file(".gitignore", (content) => {
2367
+ if (!content) return content;
2368
+ if (content.includes("test-results")) return content;
2369
+ return "test-results\n" + content.trim();
2370
+ });
2371
+ sv.file(`e2e/demo.test.${ext}`, (content) => {
2372
+ if (content) return content;
2373
+ return dedent_default`
2374
+ import { expect, test } from '@playwright/test';
2375
+
2376
+ test('home page has expected h1', async ({ page }) => {
2377
+ await page.goto('/');
2378
+ await expect(page.locator('h1')).toBeVisible();
2379
+ });
2380
+ `;
2381
+ });
2382
+ sv.file(`playwright.config.${ext}`, (content) => {
2383
+ const { ast, generateCode } = parseScript(content);
2384
+ const defineConfig = parseExpression("defineConfig({})");
2385
+ const { value: defaultExport } = createDefault(ast, { fallback: defineConfig });
2386
+ const config = {
2387
+ webServer: {
2388
+ command: "npm run build && npm run preview",
2389
+ port: 4173
2390
+ },
2391
+ testDir: "e2e"
2392
+ };
2393
+ if (defaultExport.type === "CallExpression" && defaultExport.arguments[0]?.type === "ObjectExpression") {
2394
+ addNamed(ast, {
2395
+ imports: ["defineConfig"],
2396
+ from: "@playwright/test"
2397
+ });
2398
+ overrideProperties(defaultExport.arguments[0], config);
2399
+ } else if (defaultExport.type === "ObjectExpression") overrideProperties(defaultExport, config);
2400
+ else T.warn("Unexpected playwright config for playwright add-on. Could not update.");
2401
+ return generateCode();
2402
+ });
2403
+ }
2404
+ });
2405
+
2406
+ //#endregion
2407
+ //#region ../addons/prettier/index.ts
2408
+ var prettier_default = defineAddon({
2409
+ id: "prettier",
2410
+ shortDescription: "formatter",
2411
+ homepage: "https://prettier.io",
2412
+ options: {},
2413
+ run: ({ sv, dependencyVersion }) => {
2414
+ sv.devDependency("prettier", "^3.6.2");
2415
+ sv.devDependency("prettier-plugin-svelte", "^3.4.0");
2416
+ sv.file(".prettierignore", (content) => {
2417
+ if (content) return content;
2418
+ return dedent_default`
2419
+ # Package Managers
2420
+ package-lock.json
2421
+ pnpm-lock.yaml
2422
+ yarn.lock
2423
+ bun.lock
2424
+ bun.lockb
2425
+
2426
+ # Miscellaneous
2427
+ /static/
2428
+ `;
2429
+ });
2430
+ sv.file(".prettierrc", (content) => {
2431
+ let data, generateCode;
2432
+ try {
2433
+ ({data, generateCode} = parseJson(content));
2434
+ } catch {
2435
+ T.warn(`A ${import_picocolors$2.default.yellow(".prettierrc")} config already exists and cannot be parsed as JSON. Skipping initialization.`);
2436
+ return content;
2437
+ }
2438
+ if (Object.keys(data).length === 0) {
2439
+ data.useTabs = true;
2440
+ data.singleQuote = true;
2441
+ data.trailingComma = "none";
2442
+ data.printWidth = 100;
2443
+ }
2444
+ data.plugins ??= [];
2445
+ data.overrides ??= [];
2446
+ if (!data.plugins.includes("prettier-plugin-svelte")) data.plugins.unshift("prettier-plugin-svelte");
2447
+ const overrides = data.overrides;
2448
+ if (!overrides.find((o) => o?.options?.parser === "svelte")) overrides.push({
2449
+ files: "*.svelte",
2450
+ options: { parser: "svelte" }
2451
+ });
2452
+ return generateCode();
2453
+ });
2454
+ const eslintVersion = dependencyVersion("eslint");
2455
+ const eslintInstalled = hasEslint(eslintVersion);
2456
+ sv.file("package.json", (content) => {
2457
+ const { data, generateCode } = parseJson(content);
2458
+ data.scripts ??= {};
2459
+ const scripts = data.scripts;
2460
+ const CHECK_CMD = "prettier --check .";
2461
+ scripts["format"] ??= "prettier --write .";
2462
+ if (eslintInstalled) {
2463
+ scripts["lint"] ??= `${CHECK_CMD} && eslint .`;
2464
+ if (!scripts["lint"].includes(CHECK_CMD)) scripts["lint"] += ` && ${CHECK_CMD}`;
2465
+ } else scripts["lint"] ??= CHECK_CMD;
2466
+ return generateCode();
2467
+ });
2468
+ if (eslintVersion?.startsWith(SUPPORTED_ESLINT_VERSION) === false) T.warn(`An older major version of ${import_picocolors$2.default.yellow("eslint")} was detected. Skipping ${import_picocolors$2.default.yellow("eslint-config-prettier")} installation.`);
2469
+ if (eslintInstalled) {
2470
+ sv.devDependency("eslint-config-prettier", "^10.1.8");
2471
+ sv.file("eslint.config.js", addEslintConfigPrettier);
2472
+ }
2473
+ }
2474
+ });
2475
+ const SUPPORTED_ESLINT_VERSION = "9";
2476
+ function hasEslint(version) {
2477
+ return !!version && version.startsWith(SUPPORTED_ESLINT_VERSION);
2478
+ }
2479
+
2480
+ //#endregion
2481
+ //#region ../addons/storybook/index.ts
2482
+ var storybook_default = defineAddon({
2483
+ id: "storybook",
2484
+ shortDescription: "frontend workshop",
2485
+ homepage: "https://storybook.js.org",
2486
+ options: {},
2487
+ setup: ({ runsAfter }) => {
2488
+ runsAfter("vitest");
2489
+ runsAfter("eslint");
2490
+ },
2491
+ run: async ({ sv }) => {
2492
+ const args = [
2493
+ "create-storybook@latest",
2494
+ "--skip-install",
2495
+ "--no-dev"
2496
+ ];
2497
+ if (process.env.NODE_ENV?.toLowerCase() === "test") args.push("--yes");
2498
+ await sv.execute(args, "inherit");
2499
+ sv.devDependency(`@types/node`, getNodeTypesVersion());
2500
+ }
2501
+ });
2502
+
2503
+ //#endregion
2504
+ //#region ../addons/sveltekit-adapter/index.ts
2505
+ const adapters = [
2506
+ {
2507
+ id: "auto",
2508
+ package: "@sveltejs/adapter-auto",
2509
+ version: "^6.1.0"
2510
+ },
2511
+ {
2512
+ id: "node",
2513
+ package: "@sveltejs/adapter-node",
2514
+ version: "^5.3.2"
2515
+ },
2516
+ {
2517
+ id: "static",
2518
+ package: "@sveltejs/adapter-static",
2519
+ version: "^3.0.9"
2520
+ },
2521
+ {
2522
+ id: "vercel",
2523
+ package: "@sveltejs/adapter-vercel",
2524
+ version: "^5.10.2"
2525
+ },
2526
+ {
2527
+ id: "cloudflare",
2528
+ package: "@sveltejs/adapter-cloudflare",
2529
+ version: "^7.2.3"
2530
+ },
2531
+ {
2532
+ id: "netlify",
2533
+ package: "@sveltejs/adapter-netlify",
2534
+ version: "^5.2.3"
2535
+ }
2536
+ ];
2537
+ const options$2 = defineAddonOptions().add("adapter", {
2538
+ type: "select",
2539
+ question: "Which SvelteKit adapter would you like to use?",
2540
+ default: "auto",
2541
+ options: adapters.map((p) => ({
2542
+ value: p.id,
2543
+ label: p.id,
2544
+ hint: p.package
2545
+ }))
2546
+ }).build();
2547
+ var sveltekit_adapter_default = defineAddon({
2548
+ id: "sveltekit-adapter",
2549
+ alias: "adapter",
2550
+ shortDescription: "deployment",
2551
+ homepage: "https://svelte.dev/docs/kit/adapters",
2552
+ options: options$2,
2553
+ setup: ({ kit, unsupported }) => {
2554
+ if (!kit) unsupported("Requires SvelteKit");
2555
+ },
2556
+ run: ({ sv, options: options$6 }) => {
2557
+ const adapter = adapters.find((a) => a.id === options$6.adapter);
2558
+ sv.file("package.json", (content) => {
2559
+ const { data, generateCode } = parseJson(content);
2560
+ const devDeps = data["devDependencies"];
2561
+ for (const pkg of Object.keys(devDeps)) if (pkg.startsWith("@sveltejs/adapter-")) delete devDeps[pkg];
2562
+ return generateCode();
2563
+ });
2564
+ sv.devDependency(adapter.package, adapter.version);
2565
+ sv.file("svelte.config.js", (content) => {
2566
+ const { ast, generateCode } = parseScript(content);
2567
+ const adapterImportDecl = ast.body.filter((n) => n.type === "ImportDeclaration").find((importDecl) => typeof importDecl.source.value === "string" && importDecl.source.value.startsWith("@sveltejs/adapter-") && importDecl.importKind === "value");
2568
+ let adapterName = "adapter";
2569
+ if (adapterImportDecl) {
2570
+ adapterImportDecl.source.value = adapter.package;
2571
+ adapterImportDecl.source.raw = void 0;
2572
+ adapterName = adapterImportDecl.specifiers?.find((s) => s.type === "ImportDefaultSpecifier")?.local?.name;
2573
+ } else addDefault(ast, {
2574
+ from: adapter.package,
2575
+ as: adapterName
2576
+ });
2577
+ const { value: config } = createDefault(ast, { fallback: create({}) });
2578
+ overrideProperties(config, { kit: { adapter: createCall({
2579
+ name: adapterName,
2580
+ args: [],
2581
+ useIdentifiers: true
2582
+ }) } });
2583
+ if (adapter.package !== "@sveltejs/adapter-auto") {
2584
+ const fallback = create({});
2585
+ const cfgKitValue = property(config, {
2586
+ name: "kit",
2587
+ fallback
2588
+ });
2589
+ const cfgAdapter = propertyNode(cfgKitValue, {
2590
+ name: "adapter",
2591
+ fallback
2592
+ });
2593
+ cfgAdapter.leadingComments = [];
2594
+ }
2595
+ return generateCode();
2596
+ });
2597
+ }
2598
+ });
2599
+
2600
+ //#endregion
2601
+ //#region ../addons/tailwindcss/index.ts
2602
+ const plugins = [{
2603
+ id: "typography",
2604
+ package: "@tailwindcss/typography",
2605
+ version: "^0.5.18"
2606
+ }, {
2607
+ id: "forms",
2608
+ package: "@tailwindcss/forms",
2609
+ version: "^0.5.10"
2610
+ }];
2611
+ const options$1 = defineAddonOptions().add("plugins", {
2612
+ type: "multiselect",
2613
+ question: "Which plugins would you like to add?",
2614
+ options: plugins.map((p) => ({
2615
+ value: p.id,
2616
+ label: p.id,
2617
+ hint: p.package
2618
+ })),
2619
+ default: [],
2620
+ required: false
2621
+ }).build();
2622
+ var tailwindcss_default = defineAddon({
2623
+ id: "tailwindcss",
2624
+ alias: "tailwind",
2625
+ shortDescription: "css framework",
2626
+ homepage: "https://tailwindcss.com",
2627
+ options: options$1,
2628
+ run: ({ sv, options: options$6, viteConfigFile, typescript, kit, dependencyVersion }) => {
2629
+ const prettierInstalled = Boolean(dependencyVersion("prettier"));
2630
+ sv.devDependency("tailwindcss", "^4.1.13");
2631
+ sv.devDependency("@tailwindcss/vite", "^4.1.13");
2632
+ if (prettierInstalled) sv.devDependency("prettier-plugin-tailwindcss", "^0.6.14");
2633
+ for (const plugin of plugins) {
2634
+ if (!options$6.plugins.includes(plugin.id)) continue;
2635
+ sv.devDependency(plugin.package, plugin.version);
2636
+ }
2637
+ sv.file(viteConfigFile, (content) => {
2638
+ const { ast, generateCode } = parseScript(content);
2639
+ const vitePluginName = "tailwindcss";
2640
+ addDefault(ast, {
2641
+ as: vitePluginName,
2642
+ from: "@tailwindcss/vite"
2643
+ });
2644
+ addPlugin(ast, {
2645
+ code: `${vitePluginName}()`,
2646
+ mode: "prepend"
2647
+ });
2648
+ return generateCode();
2649
+ });
2650
+ sv.file("src/app.css", (content) => {
2651
+ let atRules = parseCss(content).ast.nodes.filter((node) => node.type === "atrule");
2652
+ const findAtRule = (name, params) => atRules.find((rule) => rule.name === name && rule.params.replace(/['"]/g, "") === params);
2653
+ let code = content;
2654
+ if (!findAtRule("import", "tailwindcss")) {
2655
+ code = "@import 'tailwindcss';\n" + code;
2656
+ atRules = parseCss(code).ast.nodes.filter((node) => node.type === "atrule");
2657
+ }
2658
+ const pluginPos = atRules.findLast((rule) => ["plugin", "import"].includes(rule.name)).source.end.offset;
2659
+ for (const plugin of plugins) {
2660
+ if (!options$6.plugins.includes(plugin.id)) continue;
2661
+ if (!findAtRule("plugin", plugin.package)) {
2662
+ const pluginImport = `\n@plugin '${plugin.package}';`;
2663
+ code = code.substring(0, pluginPos) + pluginImport + code.substring(pluginPos);
2664
+ }
2665
+ }
2666
+ return code;
2667
+ });
2668
+ if (!kit) sv.file("src/App.svelte", (content) => {
2669
+ const { script, generateCode } = parseSvelte(content, { typescript });
2670
+ addEmpty(script.ast, { from: "./app.css" });
2671
+ return generateCode({ script: script.generateCode() });
2672
+ });
2673
+ else sv.file(`${kit?.routesDirectory}/+layout.svelte`, (content) => {
2674
+ const { script, template, generateCode } = parseSvelte(content, { typescript });
2675
+ addEmpty(script.ast, { from: "../app.css" });
2676
+ if (content.length === 0) {
2677
+ const svelteVersion = dependencyVersion("svelte");
2678
+ if (!svelteVersion) throw new Error("Failed to determine svelte version");
2679
+ addSlot(script.ast, {
2680
+ htmlAst: template.ast,
2681
+ svelteVersion
2682
+ });
2683
+ }
2684
+ return generateCode({
2685
+ script: script.generateCode(),
2686
+ template: content.length === 0 ? template.generateCode() : void 0
2687
+ });
2688
+ });
2689
+ if (dependencyVersion("prettier")) sv.file(".prettierrc", (content) => {
2690
+ const { data, generateCode } = parseJson(content);
2691
+ const PLUGIN_NAME = "prettier-plugin-tailwindcss";
2692
+ data.plugins ??= [];
2693
+ const plugins$1 = data.plugins;
2694
+ if (!plugins$1.includes(PLUGIN_NAME)) plugins$1.push(PLUGIN_NAME);
2695
+ data.tailwindStylesheet ??= "./src/app.css";
2696
+ return generateCode();
2697
+ });
2698
+ }
2699
+ });
2700
+
2701
+ //#endregion
2702
+ //#region ../addons/vitest-addon/index.ts
2703
+ const options = defineAddonOptions().add("usages", {
2704
+ question: "What do you want to use vitest for?",
2705
+ type: "multiselect",
2706
+ default: ["unit", "component"],
2707
+ options: [{
2708
+ value: "unit",
2709
+ label: "unit testing"
2710
+ }, {
2711
+ value: "component",
2712
+ label: "component testing"
2713
+ }],
2714
+ required: true
2715
+ }).build();
2716
+ var vitest_addon_default = defineAddon({
2717
+ id: "vitest",
2718
+ shortDescription: "unit testing",
2719
+ homepage: "https://vitest.dev",
2720
+ options,
2721
+ run: ({ sv, viteConfigFile, typescript, kit, options: options$6 }) => {
2722
+ const ext = typescript ? "ts" : "js";
2723
+ const unitTesting = options$6.usages.includes("unit");
2724
+ const componentTesting = options$6.usages.includes("component");
2725
+ sv.devDependency("vitest", "^3.2.4");
2726
+ if (componentTesting) {
2727
+ sv.devDependency("@vitest/browser", "^3.2.4");
2728
+ sv.devDependency("vitest-browser-svelte", "^1.1.0");
2729
+ sv.devDependency("playwright", "^1.55.1");
2730
+ }
2731
+ sv.file("package.json", (content) => {
2732
+ const { data, generateCode } = parseJson(content);
2733
+ data.scripts ??= {};
2734
+ const scripts = data.scripts;
2735
+ const TEST_CMD = "vitest";
2736
+ const RUN_TEST = "npm run test:unit -- --run";
2737
+ scripts["test:unit"] ??= TEST_CMD;
2738
+ scripts["test"] ??= RUN_TEST;
2739
+ if (!scripts["test"].includes(RUN_TEST)) scripts["test"] += ` && ${RUN_TEST}`;
2740
+ return generateCode();
2741
+ });
2742
+ if (unitTesting) sv.file(`src/demo.spec.${ext}`, (content) => {
2743
+ if (content) return content;
2744
+ return dedent_default`
2745
+ import { describe, it, expect } from 'vitest';
2746
+
2747
+ describe('sum test', () => {
2748
+ it('adds 1 + 2 to equal 3', () => {
2749
+ expect(1 + 2).toBe(3);
2750
+ });
2751
+ });
2752
+ `;
2753
+ });
2754
+ if (componentTesting) {
2755
+ const fileName = kit ? `${kit.routesDirectory}/page.svelte.spec.${ext}` : `src/App.svelte.test.${ext}`;
2756
+ sv.file(fileName, (content) => {
2757
+ if (content) return content;
2758
+ return dedent_default`
2759
+ import { page } from '@vitest/browser/context';
2760
+ import { describe, expect, it } from 'vitest';
2761
+ import { render } from 'vitest-browser-svelte';
2762
+ ${kit ? "import Page from './+page.svelte';" : "import App from './App.svelte';"}
2763
+
2764
+ describe('${kit ? "/+page.svelte" : "App.svelte"}', () => {
2765
+ it('should render h1', async () => {
2766
+ render(${kit ? "Page" : "App"});
2767
+
2768
+ const heading = page.getByRole('heading', { level: 1 });
2769
+ await expect.element(heading).toBeInTheDocument();
2770
+ });
2771
+ });
2772
+ `;
2773
+ });
2774
+ sv.file(`vitest-setup-client.${ext}`, (content) => {
2775
+ if (content) return content;
2776
+ return dedent_default`
2777
+ /// <reference types="@vitest/browser/matchers" />
2778
+ /// <reference types="@vitest/browser/providers/playwright" />
2779
+ `;
2780
+ });
2781
+ }
2782
+ sv.file(viteConfigFile, (content) => {
2783
+ const { ast, generateCode } = parseScript(content);
2784
+ const clientObjectExpression = create({
2785
+ extends: `./${viteConfigFile}`,
2786
+ test: {
2787
+ name: "client",
2788
+ environment: "browser",
2789
+ browser: {
2790
+ enabled: true,
2791
+ provider: "playwright",
2792
+ instances: [{ browser: "chromium" }]
2793
+ },
2794
+ include: ["src/**/*.svelte.{test,spec}.{js,ts}"],
2795
+ exclude: ["src/lib/server/**"],
2796
+ setupFiles: [`./vitest-setup-client.${ext}`]
2797
+ }
2798
+ });
2799
+ const serverObjectExpression = create({
2800
+ extends: `./${viteConfigFile}`,
2801
+ test: {
2802
+ name: "server",
2803
+ environment: "node",
2804
+ include: ["src/**/*.{test,spec}.{js,ts}"],
2805
+ exclude: ["src/**/*.svelte.{test,spec}.{js,ts}"]
2806
+ }
2807
+ });
2808
+ const viteConfig = getConfig(ast);
2809
+ const testObject = property(viteConfig, {
2810
+ name: "test",
2811
+ fallback: create({ expect: { requireAssertions: true } })
2812
+ });
2813
+ const workspaceArray = property(testObject, {
2814
+ name: "projects",
2815
+ fallback: create$1()
2816
+ });
2817
+ if (componentTesting) append(workspaceArray, clientObjectExpression);
2818
+ if (unitTesting) append(workspaceArray, serverObjectExpression);
2819
+ const importName = "defineConfig";
2820
+ const { statement, alias } = find(ast, {
2821
+ name: importName,
2822
+ from: "vite"
2823
+ });
2824
+ if (statement) {
2825
+ addNamed(ast, {
2826
+ imports: { defineConfig: alias },
2827
+ from: "vitest/config"
2828
+ });
2829
+ remove(ast, {
2830
+ name: importName,
2831
+ from: "vite",
2832
+ statement
2833
+ });
2834
+ }
2835
+ return generateCode();
2836
+ });
2837
+ }
2838
+ });
2839
+
2840
+ //#endregion
2841
+ //#region ../addons/_config/official.ts
2842
+ const officialAddons = {
2843
+ prettier: prettier_default,
2844
+ eslint: eslint_default,
2845
+ vitest: vitest_addon_default,
2846
+ playwright: playwright_default,
2847
+ tailwindcss: tailwindcss_default,
2848
+ sveltekitAdapter: sveltekit_adapter_default,
2849
+ devtoolsJson: devtools_json_default,
2850
+ drizzle: drizzle_default,
2851
+ lucia: lucia_default,
2852
+ mdsvex: mdsvex_default,
2853
+ paraglide: paraglide_default,
2854
+ storybook: storybook_default
2855
+ };
2856
+ function getAddonDetails(id) {
2857
+ const details = Object.values(officialAddons).find((a) => a.id === id);
2858
+ if (!details) throw new Error(`Invalid add-on: ${id}`);
2859
+ return details;
2860
+ }
2861
+
2862
+ //#endregion
2863
+ //#region ../addons/_config/community.ts
2864
+ /** EVALUATED AT BUILD TIME */
2865
+ const communityAddonIds = ["unocss", "unplugin-icons"];
2866
+ async function getCommunityAddon(name) {
2867
+ const { default: details } = await import(`../../../community-addons/${name}.ts`);
2868
+ return details;
2869
+ }
2870
+
2871
+ //#endregion
2872
+ //#region commands/add/utils.ts
2873
+ var import_picocolors$1 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
2874
+ function getPackageJson(cwd) {
2875
+ const packageText = readFile(cwd, commonFilePaths.packageJson);
2876
+ if (!packageText) {
2877
+ const pkgPath = path.join(cwd, commonFilePaths.packageJson);
2878
+ throw new Error(`Invalid workspace: missing '${pkgPath}'`);
2879
+ }
2880
+ const { data, generateCode } = parseJson(packageText);
2881
+ return {
2882
+ source: packageText,
2883
+ data,
2884
+ generateCode
2885
+ };
2886
+ }
2887
+ async function formatFiles(options$6) {
2888
+ const args = [
2889
+ "prettier",
2890
+ "--write",
2891
+ "--ignore-unknown",
2892
+ ...options$6.paths
2893
+ ];
2894
+ const cmd = resolveCommand(options$6.packageManager, "execute-local", args);
2895
+ await be(cmd.command, cmd.args, {
2896
+ nodeOptions: {
2897
+ cwd: options$6.cwd,
2898
+ stdio: "pipe"
2899
+ },
2900
+ throwOnError: true
2901
+ });
2902
+ }
2903
+ function readFile(cwd, filePath) {
2904
+ const fullFilePath = path.resolve(cwd, filePath);
2905
+ if (!fileExists(cwd, filePath)) return "";
2906
+ return fs.readFileSync(fullFilePath, "utf8");
2907
+ }
2908
+ function installPackages(dependencies, workspace) {
2909
+ const { data, generateCode } = getPackageJson(workspace.cwd);
2910
+ for (const dependency of dependencies) if (dependency.dev) {
2911
+ data.devDependencies ??= {};
2912
+ data.devDependencies[dependency.pkg] = dependency.version;
2913
+ } else {
2914
+ data.dependencies ??= {};
2915
+ data.dependencies[dependency.pkg] = dependency.version;
2916
+ }
2917
+ if (data.dependencies) data.dependencies = alphabetizeProperties(data.dependencies);
2918
+ if (data.devDependencies) data.devDependencies = alphabetizeProperties(data.devDependencies);
2919
+ writeFile(workspace, commonFilePaths.packageJson, generateCode());
2920
+ return commonFilePaths.packageJson;
2921
+ }
2922
+ function alphabetizeProperties(obj) {
2923
+ const orderedObj = {};
2924
+ const sortedEntries = Object.entries(obj).sort(([a], [b]) => a.localeCompare(b));
2925
+ for (const [key, value] of sortedEntries) orderedObj[key] = value;
2926
+ return orderedObj;
2927
+ }
2928
+ function writeFile(workspace, filePath, content) {
2929
+ const fullFilePath = path.resolve(workspace.cwd, filePath);
2930
+ const fullDirectoryPath = path.dirname(fullFilePath);
2931
+ if (content && !content.endsWith("\n")) content += "\n";
2932
+ if (!fs.existsSync(fullDirectoryPath)) fs.mkdirSync(fullDirectoryPath, { recursive: true });
2933
+ fs.writeFileSync(fullFilePath, content, "utf8");
2934
+ }
2935
+ function fileExists(cwd, filePath) {
2936
+ const fullFilePath = path.resolve(cwd, filePath);
2937
+ return fs.existsSync(fullFilePath);
2938
+ }
2939
+ const commonFilePaths = {
2940
+ packageJson: "package.json",
2941
+ svelteConfig: "svelte.config.js",
2942
+ jsconfig: "jsconfig.json",
2943
+ tsconfig: "tsconfig.json",
2944
+ viteConfig: "vite.config.js",
2945
+ viteConfigTS: "vite.config.ts"
2946
+ };
2947
+ function getHighlighter() {
2948
+ return {
2949
+ command: (str) => import_picocolors$1.default.bold(import_picocolors$1.default.cyanBright(str)),
2950
+ env: (str) => import_picocolors$1.default.yellow(str),
2951
+ path: (str) => import_picocolors$1.default.green(str),
2952
+ route: (str) => import_picocolors$1.default.bold(str),
2953
+ website: (str) => import_picocolors$1.default.whiteBright(str)
2954
+ };
2955
+ }
2956
+
2957
+ //#endregion
2958
+ //#region commands/add/workspace.ts
2959
+ async function createWorkspace({ cwd, options: options$6 = {}, packageManager }) {
2960
+ const resolvedCwd = path.resolve(cwd);
2961
+ const usesTypescript = !any([commonFilePaths.jsconfig, commonFilePaths.tsconfig], { cwd })?.endsWith(commonFilePaths.jsconfig);
2962
+ const viteConfigPath = path.join(resolvedCwd, commonFilePaths.viteConfigTS);
2963
+ const viteConfigFile = fs.existsSync(viteConfigPath) ? commonFilePaths.viteConfigTS : commonFilePaths.viteConfig;
2964
+ let dependencies = {};
2965
+ let directory = resolvedCwd;
2966
+ const root = findRoot(resolvedCwd);
2967
+ while (directory && directory !== root) {
2968
+ if (fs.existsSync(path.join(directory, commonFilePaths.packageJson))) {
2969
+ const { data: packageJson } = getPackageJson(directory);
2970
+ dependencies = {
2971
+ ...packageJson.devDependencies,
2972
+ ...packageJson.dependencies,
2973
+ ...dependencies
2974
+ };
2975
+ }
2976
+ directory = path.dirname(directory);
2977
+ }
2978
+ for (const [key, value] of Object.entries(dependencies)) dependencies[key] = value.replaceAll(/[^\d|.]/g, "");
2979
+ return {
2980
+ cwd: resolvedCwd,
2981
+ options: options$6,
2982
+ packageManager: packageManager ?? (await detect({ cwd }))?.name ?? getUserAgent() ?? "npm",
2983
+ typescript: usesTypescript,
2984
+ viteConfigFile,
2985
+ kit: dependencies["@sveltejs/kit"] ? parseKitOptions(resolvedCwd) : void 0,
2986
+ dependencyVersion: (pkg) => dependencies[pkg]
2987
+ };
2988
+ }
2989
+ function findRoot(cwd) {
2990
+ const { root } = path.parse(cwd);
2991
+ let directory = cwd;
2992
+ while (directory && directory !== root) {
2993
+ if (fs.existsSync(path.join(directory, commonFilePaths.packageJson))) {
2994
+ if (fs.existsSync(path.join(directory, "pnpm-workspace.yaml"))) return directory;
2995
+ const { data } = getPackageJson(directory);
2996
+ if (data.workspaces) return directory;
2997
+ }
2998
+ directory = path.dirname(directory);
2999
+ }
3000
+ return root;
3001
+ }
3002
+ function parseKitOptions(cwd) {
3003
+ const configSource = readFile(cwd, commonFilePaths.svelteConfig);
3004
+ const { ast } = parseScript(configSource);
3005
+ const defaultExport = ast.body.find((s) => s.type === "ExportDefaultDeclaration");
3006
+ if (!defaultExport) throw Error("Missing default export in `svelte.config.js`");
3007
+ let objectExpression;
3008
+ if (defaultExport.declaration.type === "Identifier") {
3009
+ const identifier = defaultExport.declaration;
3010
+ for (const declaration$1 of ast.body) {
3011
+ if (declaration$1.type !== "VariableDeclaration") continue;
3012
+ const declarator = declaration$1.declarations.find((d) => d.type === "VariableDeclarator" && d.id.type === "Identifier" && d.id.name === identifier.name);
3013
+ if (declarator?.init?.type !== "ObjectExpression") continue;
3014
+ objectExpression = declarator.init;
3015
+ }
3016
+ if (!objectExpression) throw Error("Unable to find svelte config object expression from `svelte.config.js`");
3017
+ } else if (defaultExport.declaration.type === "ObjectExpression") objectExpression = defaultExport.declaration;
3018
+ if (!objectExpression) throw new Error("Unexpected svelte config shape from `svelte.config.js`");
3019
+ const kit = property(objectExpression, {
3020
+ name: "kit",
3021
+ fallback: create({})
3022
+ });
3023
+ const files = property(kit, {
3024
+ name: "files",
3025
+ fallback: create({})
3026
+ });
3027
+ const routes = property(files, {
3028
+ name: "routes",
3029
+ fallback: createLiteral("")
3030
+ });
3031
+ const lib = property(files, {
3032
+ name: "lib",
3033
+ fallback: createLiteral("")
3034
+ });
3035
+ const routesDirectory = routes.value || "src/routes";
3036
+ const libDirectory = lib.value || "src/lib";
3037
+ return {
3038
+ routesDirectory,
3039
+ libDirectory
3040
+ };
3041
+ }
3042
+
3043
+ //#endregion
3044
+ //#region utils/env.ts
3045
+ const TESTING = process.env.NODE_ENV?.toLowerCase() === "test";
3046
+
3047
+ //#endregion
3048
+ //#region lib/install.ts
3049
+ var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
3050
+ async function installAddon({ addons, cwd, options: options$6, packageManager = "npm" }) {
3051
+ const workspace = await createWorkspace({
3052
+ cwd,
3053
+ packageManager
3054
+ });
3055
+ const addonSetupResults = setupAddons(Object.values(addons), workspace);
3056
+ return await applyAddons({
3057
+ addons,
3058
+ workspace,
3059
+ options: options$6,
3060
+ addonSetupResults
3061
+ });
3062
+ }
3063
+ async function applyAddons({ addons, workspace, addonSetupResults, options: options$6 }) {
3064
+ const filesToFormat = /* @__PURE__ */ new Set();
3065
+ const allPnpmBuildDependencies = [];
3066
+ const mapped = Object.entries(addons).map(([, addon]) => addon);
3067
+ const ordered = orderAddons(mapped, addonSetupResults);
3068
+ for (const addon of ordered) {
3069
+ workspace = await createWorkspace({
3070
+ ...workspace,
3071
+ options: options$6[addon.id]
3072
+ });
3073
+ const { files, pnpmBuildDependencies } = await runAddon({
3074
+ workspace,
3075
+ addon,
3076
+ multiple: ordered.length > 1
3077
+ });
3078
+ files.forEach((f) => filesToFormat.add(f));
3079
+ pnpmBuildDependencies.forEach((s) => allPnpmBuildDependencies.push(s));
3080
+ }
3081
+ return {
3082
+ filesToFormat: Array.from(filesToFormat),
3083
+ pnpmBuildDependencies: allPnpmBuildDependencies
3084
+ };
3085
+ }
3086
+ function setupAddons(addons, workspace) {
3087
+ const addonSetupResults = {};
3088
+ for (const addon of addons) {
3089
+ const setupResult = {
3090
+ unsupported: [],
3091
+ dependsOn: [],
3092
+ runsAfter: []
3093
+ };
3094
+ addon.setup?.({
3095
+ ...workspace,
3096
+ dependsOn: (name) => {
3097
+ setupResult.dependsOn.push(name);
3098
+ setupResult.runsAfter.push(name);
3099
+ },
3100
+ unsupported: (reason) => setupResult.unsupported.push(reason),
3101
+ runsAfter: (name) => setupResult.runsAfter.push(name)
3102
+ });
3103
+ addonSetupResults[addon.id] = setupResult;
3104
+ }
3105
+ return addonSetupResults;
3106
+ }
3107
+ async function runAddon({ addon, multiple, workspace }) {
3108
+ const files = /* @__PURE__ */ new Set();
3109
+ for (const [id, question] of Object.entries(addon.options)) if (question.condition?.(workspace.options) !== false) workspace.options[id] ??= question.default;
3110
+ const dependencies = [];
3111
+ const pnpmBuildDependencies = [];
3112
+ const sv = {
3113
+ file: (path$1, content) => {
3114
+ try {
3115
+ let fileContent = fileExists(workspace.cwd, path$1) ? readFile(workspace.cwd, path$1) : "";
3116
+ fileContent = content(fileContent);
3117
+ if (!fileContent) return fileContent;
3118
+ writeFile(workspace, path$1, fileContent);
3119
+ files.add(path$1);
3120
+ } catch (e) {
3121
+ if (e instanceof Error) throw new Error(`Unable to process '${path$1}'. Reason: ${e.message}`);
3122
+ throw e;
3123
+ }
3124
+ },
3125
+ execute: async (commandArgs, stdio) => {
3126
+ const { command, args } = resolveCommand(workspace.packageManager, "execute", commandArgs);
3127
+ const addonPrefix = multiple ? `${addon.id}: ` : "";
3128
+ const executedCommand = `${command} ${args.join(" ")}`;
3129
+ if (!TESTING) T.step(`${addonPrefix}Running external command ${import_picocolors.default.gray(`(${executedCommand})`)}`);
3130
+ if (workspace.packageManager === "npm") args.unshift("--yes");
3131
+ try {
3132
+ await be(command, args, {
3133
+ nodeOptions: {
3134
+ cwd: workspace.cwd,
3135
+ stdio: TESTING ? "pipe" : stdio
3136
+ },
3137
+ throwOnError: true
3138
+ });
3139
+ } catch (error) {
3140
+ const typedError = error;
3141
+ throw new Error(`Failed to execute scripts '${executedCommand}': ${typedError.message}`, { cause: typedError.output });
3142
+ }
3143
+ },
3144
+ dependency: (pkg, version) => {
3145
+ dependencies.push({
3146
+ pkg,
3147
+ version,
3148
+ dev: false
3149
+ });
3150
+ },
3151
+ devDependency: (pkg, version) => {
3152
+ dependencies.push({
3153
+ pkg,
3154
+ version,
3155
+ dev: true
3156
+ });
3157
+ },
3158
+ pnpmBuildDependency: (pkg) => {
3159
+ pnpmBuildDependencies.push(pkg);
3160
+ }
3161
+ };
3162
+ await addon.run({
3163
+ ...workspace,
3164
+ sv
3165
+ });
3166
+ const pkgPath = installPackages(dependencies, workspace);
3167
+ files.add(pkgPath);
3168
+ return {
3169
+ files: Array.from(files),
3170
+ pnpmBuildDependencies
3171
+ };
3172
+ }
3173
+ function orderAddons(addons, setupResults) {
3174
+ return addons.sort((a, b) => {
3175
+ return setupResults[a.id]?.runsAfter?.length - setupResults[b.id]?.runsAfter?.length;
3176
+ });
3177
+ }
3178
+
3179
+ //#endregion
3180
+ export { addDefault, applyAddons, communityAddonIds, create, createDefault, createWorkspace, formatFiles, getAddonDetails, getCommunityAddon, getHighlighter, installAddon, isVersionUnsupportedBelow, officialAddons, overrideProperties, setupAddons };