sv 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/bin.js +788 -945
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{index-CfDBZLMZ.js → index-A89HFWzv.js} +3 -3
  4. package/dist/index-A89HFWzv.js.map +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/shared.json +5 -5
  7. package/dist/templates/demo/meta.json +2 -2
  8. package/dist/templates/demo/package.json +2 -2
  9. package/dist/templates/library/meta.json +4 -0
  10. package/dist/templates/{skeletonlib → library}/package.json +6 -6
  11. package/dist/templates/minimal/meta.json +4 -0
  12. package/dist/templates/{skeleton → minimal}/package.json +2 -3
  13. package/dist/unocss-BUQS5wKg.js +6 -0
  14. package/dist/unocss-BUQS5wKg.js.map +1 -0
  15. package/dist/unplugin-icons-BietOpsP.js +6 -0
  16. package/dist/unplugin-icons-BietOpsP.js.map +1 -0
  17. package/package.json +17 -17
  18. package/dist/index-CfDBZLMZ.js.map +0 -1
  19. package/dist/templates/skeleton/meta.json +0 -4
  20. package/dist/templates/skeletonlib/meta.json +0 -4
  21. package/dist/unocss-Dk7i15rK.js +0 -11
  22. package/dist/unocss-Dk7i15rK.js.map +0 -1
  23. package/dist/unplugin-icons-DkNLYvBs.js +0 -11
  24. package/dist/unplugin-icons-DkNLYvBs.js.map +0 -1
  25. /package/dist/templates/{skeletonlib → library}/assets/DOT-gitignore +0 -0
  26. /package/dist/templates/{skeleton → library}/assets/DOT-npmrc +0 -0
  27. /package/dist/templates/{skeletonlib → library}/assets/src/app.html +0 -0
  28. /package/dist/templates/{skeleton → library}/assets/static/favicon.png +0 -0
  29. /package/dist/templates/{skeletonlib → library}/files.types=checkjs.json +0 -0
  30. /package/dist/templates/{skeletonlib → library}/files.types=none.json +0 -0
  31. /package/dist/templates/{skeletonlib → library}/files.types=typescript.json +0 -0
  32. /package/dist/templates/{skeleton → minimal}/assets/DOT-gitignore +0 -0
  33. /package/dist/templates/{skeletonlib → minimal}/assets/DOT-npmrc +0 -0
  34. /package/dist/templates/{skeleton → minimal}/assets/src/app.html +0 -0
  35. /package/dist/templates/{skeletonlib → minimal}/assets/static/favicon.png +0 -0
  36. /package/dist/templates/{skeleton → minimal}/files.types=checkjs.json +0 -0
  37. /package/dist/templates/{skeleton → minimal}/files.types=none.json +0 -0
  38. /package/dist/templates/{skeleton → minimal}/files.types=typescript.json +0 -0
package/dist/bin.js CHANGED
@@ -22,28 +22,28 @@ import 'node:fs/promises';
22
22
  import { pipeline as pipeline$1 } from 'node:stream/promises';
23
23
  import { createGunzip } from 'node:zlib';
24
24
  import require$$0$3 from 'events';
25
- import { t as templates, c as create$2 } from './index-CfDBZLMZ.js';
25
+ import { t as templates, c as create$2 } from './index-A89HFWzv.js';
26
26
 
27
27
  var name = "sv";
28
- var version = "0.5.1";
28
+ var version = "0.5.3";
29
+ var type = "module";
29
30
  var description = "A CLI for creating and updating SvelteKit projects";
30
- var keywords = [
31
- "create",
32
- "new",
33
- "project",
34
- "starter",
35
- "svelte",
36
- "sveltekit",
37
- "template",
38
- "wizard"
39
- ];
31
+ var license = "MIT";
40
32
  var repository = {
41
33
  type: "git",
42
34
  url: "https://github.com/sveltejs/cli",
43
35
  directory: "packages/cli"
44
36
  };
45
- var license = "MIT";
46
37
  var homepage = "https://svelte.dev";
38
+ var scripts = {
39
+ check: "tsc",
40
+ format: "pnpm lint --write",
41
+ lint: "prettier --check . --config ../../prettier.config.js --ignore-path ../../.gitignore --ignore-path .gitignore --ignore-path ../../.prettierignore",
42
+ postpublish: "pnpm -F @sveltejs/create update-template-repo"
43
+ };
44
+ var files = [
45
+ "dist"
46
+ ];
47
47
  var bin = "./dist/bin.js";
48
48
  var exports$1 = {
49
49
  ".": {
@@ -65,30 +65,30 @@ var devDependencies = {
65
65
  tinyexec: "^0.3.0",
66
66
  valibot: "^0.41.0"
67
67
  };
68
- var scripts = {
69
- lint: "prettier --check . --config ../../.prettierrc --ignore-path ../../.gitignore --ignore-path .gitignore --ignore-path ../../.prettierignore",
70
- format: "pnpm lint --write",
71
- check: "tsc",
72
- postpublish: "pnpm -F @sveltejs/create update-template-repo"
73
- };
74
- var files = [
75
- "dist"
68
+ var keywords = [
69
+ "create",
70
+ "new",
71
+ "project",
72
+ "starter",
73
+ "svelte",
74
+ "sveltekit",
75
+ "template",
76
+ "wizard"
76
77
  ];
77
- var type = "module";
78
78
  var pkg = {
79
79
  name: name,
80
80
  version: version,
81
+ type: type,
81
82
  description: description,
82
- keywords: keywords,
83
- repository: repository,
84
83
  license: license,
84
+ repository: repository,
85
85
  homepage: homepage,
86
+ scripts: scripts,
87
+ files: files,
86
88
  bin: bin,
87
89
  exports: exports$1,
88
90
  devDependencies: devDependencies,
89
- scripts: scripts,
90
- files: files,
91
- type: type
91
+ keywords: keywords
92
92
  };
93
93
 
94
94
  var commonjsGlobal$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -5608,83 +5608,6 @@ class ConfirmPrompt extends Prompt {
5608
5608
  });
5609
5609
  }
5610
5610
  }
5611
- var __defProp$5 = Object.defineProperty;
5612
- var __typeError = (msg) => {
5613
- throw TypeError(msg);
5614
- };
5615
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5616
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
5617
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5618
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
5619
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
5620
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
5621
- var _selectableGroups;
5622
- class GroupMultiSelectPrompt extends Prompt {
5623
- constructor(opts) {
5624
- super(opts, false);
5625
- __publicField$5(this, "options");
5626
- __publicField$5(this, "cursor", 0);
5627
- __privateAdd(this, _selectableGroups);
5628
- const { options } = opts;
5629
- __privateSet(this, _selectableGroups, opts.selectableGroups ?? true);
5630
- this.options = Object.entries(options).flatMap(([key, option]) => [
5631
- { value: key, group: true, label: key },
5632
- ...option.map((opt) => ({ ...opt, group: key }))
5633
- ]);
5634
- this.value = [...opts.initialValues ?? []];
5635
- this.cursor = Math.max(
5636
- this.options.findIndex(({ value }) => value === opts.cursorAt),
5637
- __privateGet(this, _selectableGroups) ? 0 : 1
5638
- );
5639
- this.on("cursor", (key) => {
5640
- switch (key) {
5641
- case "left":
5642
- case "up":
5643
- this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
5644
- if (!__privateGet(this, _selectableGroups) && this.options[this.cursor].group === true) {
5645
- this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
5646
- }
5647
- break;
5648
- case "down":
5649
- case "right":
5650
- this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
5651
- if (!__privateGet(this, _selectableGroups) && this.options[this.cursor].group === true) {
5652
- this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
5653
- }
5654
- break;
5655
- case "space":
5656
- this.toggleValue();
5657
- break;
5658
- }
5659
- });
5660
- }
5661
- getGroupItems(group2) {
5662
- return this.options.filter((o) => o.group === group2);
5663
- }
5664
- isGroupSelected(group2) {
5665
- const items = this.getGroupItems(group2);
5666
- return __privateGet(this, _selectableGroups) && items.every((i) => this.value.includes(i.value));
5667
- }
5668
- toggleValue() {
5669
- const item = this.options[this.cursor];
5670
- if (item.group === true) {
5671
- const group2 = item.value;
5672
- const groupedItems = this.getGroupItems(group2);
5673
- if (this.isGroupSelected(group2)) {
5674
- this.value = this.value.filter(
5675
- (v) => groupedItems.findIndex((i) => i.value === v) === -1
5676
- );
5677
- } else {
5678
- this.value = [...this.value, ...groupedItems.map((i) => i.value)];
5679
- }
5680
- this.value = Array.from(new Set(this.value));
5681
- } else {
5682
- const selected = this.value.includes(item.value);
5683
- this.value = selected ? this.value.filter((v) => v !== item.value) : [...this.value, item.value];
5684
- }
5685
- }
5686
- }
5687
- _selectableGroups = /* @__PURE__ */ new WeakMap();
5688
5611
  var __defProp$4 = Object.defineProperty;
5689
5612
  var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5690
5613
  var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -6277,112 +6200,6 @@ ${color$2.cyan(S_BAR_END)}
6277
6200
  }
6278
6201
  }).prompt();
6279
6202
  };
6280
- const groupMultiselect = (opts) => {
6281
- const { selectableGroups = false, spacedGroups = false } = opts;
6282
- const opt = (option, state, options = []) => {
6283
- const label = option.label ?? String(option.value);
6284
- const isItem = typeof option.group === "string";
6285
- const next = isItem && (options[options.indexOf(option) + 1] ?? { group: true });
6286
- const isLast = isItem && next.group === true;
6287
- const prefix = isItem ? selectableGroups ? `${isLast ? S_BAR_END : S_BAR$1} ` : " " : "";
6288
- const spacingPrefix = spacedGroups && !isItem ? `
6289
- ${color$2.cyan(S_BAR$1)} ` : "";
6290
- if (state === "active") {
6291
- return `${spacingPrefix}${color$2.dim(prefix)}${color$2.cyan(S_CHECKBOX_ACTIVE)} ${label} ${option.hint ? color$2.dim(`(${option.hint})`) : ""}`;
6292
- } else if (state === "group-active") {
6293
- return `${spacingPrefix}${prefix}${color$2.cyan(S_CHECKBOX_ACTIVE)} ${color$2.dim(label)}`;
6294
- } else if (state === "group-active-selected") {
6295
- return `${spacingPrefix}${prefix}${color$2.green(S_CHECKBOX_SELECTED)} ${color$2.dim(label)}`;
6296
- } else if (state === "selected") {
6297
- return `${spacingPrefix}${color$2.dim(prefix)}${color$2.green(S_CHECKBOX_SELECTED)} ${color$2.dim(
6298
- label
6299
- )}`;
6300
- } else if (state === "cancelled") {
6301
- return color$2.strikethrough(color$2.dim(label));
6302
- } else if (state === "active-selected") {
6303
- return `${spacingPrefix}${color$2.dim(prefix)}${color$2.green(S_CHECKBOX_SELECTED)} ${label} ${option.hint ? color$2.dim(`(${option.hint})`) : ""}`;
6304
- } else if (state === "submitted") {
6305
- return color$2.dim(label);
6306
- }
6307
- return `${spacingPrefix}${color$2.dim(prefix)}${isItem || selectableGroups ? `${color$2.dim(S_CHECKBOX_INACTIVE)} ` : ""}${color$2.dim(label)}`;
6308
- };
6309
- return new GroupMultiSelectPrompt({
6310
- options: opts.options,
6311
- initialValues: opts.initialValues,
6312
- required: opts.required ?? true,
6313
- cursorAt: opts.cursorAt,
6314
- selectableGroups,
6315
- validate(selected) {
6316
- if (this.required && selected.length === 0)
6317
- return `Please select at least one option.
6318
- ${color$2.reset(
6319
- color$2.dim(
6320
- `Press ${color$2.gray(color$2.bgWhite(color$2.inverse(" space ")))} to select, ${color$2.gray(
6321
- color$2.bgWhite(color$2.inverse(" enter "))
6322
- )} to submit`
6323
- )
6324
- )}`;
6325
- },
6326
- render() {
6327
- const title = `${color$2.gray(S_BAR$1)}
6328
- ${symbol(this.state)} ${opts.message}
6329
- `;
6330
- switch (this.state) {
6331
- case "submit": {
6332
- return `${title}${color$2.gray(S_BAR$1)} ${this.options.filter(({ value }) => this.value.includes(value)).map((option) => opt(option, "submitted")).join(color$2.dim(", "))}`;
6333
- }
6334
- case "cancel": {
6335
- const label = this.options.filter(({ value }) => this.value.includes(value)).map((option) => opt(option, "cancelled")).join(color$2.dim(", "));
6336
- return `${title}${color$2.gray(S_BAR$1)} ${label.trim() ? `${label}
6337
- ${color$2.gray(S_BAR$1)}` : ""}`;
6338
- }
6339
- case "error": {
6340
- const footer = this.error.split("\n").map(
6341
- (ln, i) => i === 0 ? `${color$2.yellow(S_BAR_END)} ${color$2.yellow(ln)}` : ` ${ln}`
6342
- ).join("\n");
6343
- return `${title}${color$2.yellow(S_BAR$1)} ${this.options.map((option, i, options) => {
6344
- const selected = this.value.includes(option.value) || option.group === true && this.isGroupSelected(`${option.value}`);
6345
- const active = i === this.cursor;
6346
- const groupActive = !active && typeof option.group === "string" && this.options[this.cursor].value === option.group;
6347
- if (groupActive) {
6348
- return opt(option, selected ? "group-active-selected" : "group-active", options);
6349
- }
6350
- if (active && selected) {
6351
- return opt(option, "active-selected", options);
6352
- }
6353
- if (selected) {
6354
- return opt(option, "selected", options);
6355
- }
6356
- return opt(option, active ? "active" : "inactive", options);
6357
- }).join(`
6358
- ${color$2.yellow(S_BAR$1)} `)}
6359
- ${footer}
6360
- `;
6361
- }
6362
- default: {
6363
- return `${title}${color$2.cyan(S_BAR$1)} ${this.options.map((option, i, options) => {
6364
- const selected = this.value.includes(option.value) || option.group === true && this.isGroupSelected(`${option.value}`);
6365
- const active = i === this.cursor;
6366
- const groupActive = !active && typeof option.group === "string" && this.options[this.cursor].value === option.group;
6367
- if (groupActive) {
6368
- return opt(option, selected ? "group-active-selected" : "group-active", options);
6369
- }
6370
- if (active && selected) {
6371
- return opt(option, "active-selected", options);
6372
- }
6373
- if (selected) {
6374
- return opt(option, "selected", options);
6375
- }
6376
- return opt(option, active ? "active" : "inactive", options);
6377
- }).join(`
6378
- ${color$2.cyan(S_BAR$1)} `)}
6379
- ${color$2.cyan(S_BAR_END)}
6380
- `;
6381
- }
6382
- }
6383
- }
6384
- }).prompt();
6385
- };
6386
6203
  const strip$1 = (str) => str.replace(ansiRegex(), "");
6387
6204
  function buildBox(message = "", title = "", dimmed = true) {
6388
6205
  const lines = `
@@ -45856,8 +45673,15 @@ function parseScript$1(content) {
45856
45673
  });
45857
45674
  return recastOutput.program;
45858
45675
  }
45859
- function serializeScript(ast) {
45860
- return main.print(ast).code;
45676
+ function serializeScript(ast, previousContent) {
45677
+ let options2;
45678
+ if (!previousContent) {
45679
+ options2 = {
45680
+ quote: "single",
45681
+ useTabs: true
45682
+ };
45683
+ }
45684
+ return main.print(ast, options2).code;
45861
45685
  }
45862
45686
  function parseCss$1(content) {
45863
45687
  return parse$1(content);
@@ -46345,6 +46169,19 @@ function addEmpty(ast, importFrom) {
46345
46169
  };
46346
46170
  addImportIfNecessary(ast, expectedImportDeclaration);
46347
46171
  }
46172
+ function addNamespace(ast, importFrom, importAs) {
46173
+ const expectedImportDeclaration = {
46174
+ type: "ImportDeclaration",
46175
+ source: { type: "Literal", value: importFrom },
46176
+ specifiers: [
46177
+ {
46178
+ type: "ImportNamespaceSpecifier",
46179
+ local: { type: "Identifier", name: importAs }
46180
+ }
46181
+ ]
46182
+ };
46183
+ addImportIfNecessary(ast, expectedImportDeclaration);
46184
+ }
46348
46185
  function addDefault(ast, importFrom, importAs) {
46349
46186
  const expectedImportDeclaration = {
46350
46187
  type: "ImportDeclaration",
@@ -46421,7 +46258,8 @@ var imports = /* @__PURE__ */ Object.freeze({
46421
46258
  __proto__: null,
46422
46259
  addDefault,
46423
46260
  addEmpty,
46424
- addNamed
46261
+ addNamed,
46262
+ addNamespace
46425
46263
  });
46426
46264
  function declaration(ast, kind, name, value) {
46427
46265
  const declarations = ast.type == "Program" ? ast.body.filter((x) => x.type == "VariableDeclaration") : [ast];
@@ -46568,7 +46406,7 @@ function addGlobalAppInterface(ast, name) {
46568
46406
  }
46569
46407
  return interfaceNode;
46570
46408
  }
46571
- function addHooksHandle(ast, typescript, newHandleName, handleContent, forceSeparateHandle = false) {
46409
+ function addHooksHandle(ast, typescript, newHandleName, handleContent) {
46572
46410
  if (typescript) {
46573
46411
  addNamed(ast, "@sveltejs/kit", { Handle: "Handle" }, true);
46574
46412
  }
@@ -46601,31 +46439,23 @@ function addHooksHandle(ast, typescript, newHandleName, handleContent, forceSepa
46601
46439
  const newHandle = expressionFromString(handleContent);
46602
46440
  if (hasNode(ast, newHandle)) return;
46603
46441
  if (!originalHandleDecl || !exportDecl) {
46604
- const newDecl2 = declaration(ast, "const", handleName, newHandle);
46442
+ const newDecl2 = declaration(ast, "const", newHandleName, newHandle);
46605
46443
  if (typescript) {
46606
46444
  const declarator = newDecl2.declarations[0];
46607
46445
  typeAnnotateDeclarator(declarator, "Handle");
46608
46446
  }
46609
- if (!forceSeparateHandle) namedExport(ast, handleName, newDecl2);
46610
- else {
46611
- const newDecl3 = declaration(ast, "const", newHandleName, newHandle);
46612
- if (typescript) {
46613
- const declarator = newDecl3.declarations[0];
46614
- typeAnnotateDeclarator(declarator, "Handle");
46615
- }
46616
- ast.body.push(newDecl3);
46617
- const handleDecl = declaration(
46618
- ast,
46619
- "const",
46620
- handleName,
46621
- expressionFromString(newHandleName)
46622
- );
46623
- if (typescript) {
46624
- const declarator = handleDecl.declarations[0];
46625
- typeAnnotateDeclarator(declarator, "Handle");
46626
- }
46627
- namedExport(ast, handleName, handleDecl);
46447
+ ast.body.push(newDecl2);
46448
+ const handleDecl = declaration(
46449
+ ast,
46450
+ "const",
46451
+ handleName,
46452
+ expressionFromString(newHandleName)
46453
+ );
46454
+ if (typescript) {
46455
+ const declarator = handleDecl.declarations[0];
46456
+ typeAnnotateDeclarator(declarator, "Handle");
46628
46457
  }
46458
+ namedExport(ast, handleName, handleDecl);
46629
46459
  return;
46630
46460
  }
46631
46461
  const newDecl = declaration(ast, "const", newHandleName, newHandle);
@@ -48310,7 +48140,7 @@ let MagicString$1 = class MagicString {
48310
48140
  };
48311
48141
  function parseScript(source) {
48312
48142
  const ast = parseScript$1(source);
48313
- const generateCode = () => serializeScript(ast);
48143
+ const generateCode = () => serializeScript(ast, source);
48314
48144
  return { ast, source, generateCode };
48315
48145
  }
48316
48146
  function parseCss(source) {
@@ -48494,10 +48324,8 @@ const options$3 = defineAdderOptions({
48494
48324
  });
48495
48325
  var drizzle = defineAdder({
48496
48326
  id: "drizzle",
48497
- name: "Drizzle",
48498
- description: "Headless ORM for NodeJS, TypeScript and JavaScript",
48499
48327
  environments: { svelte: false, kit: true },
48500
- documentation: "https://orm.drizzle.team/docs/overview",
48328
+ homepage: "https://orm.drizzle.team",
48501
48329
  options: options$3,
48502
48330
  packages: [
48503
48331
  { name: "drizzle-orm", version: "^0.33.0", dev: false },
@@ -48769,7 +48597,7 @@ var drizzle = defineAdder({
48769
48597
  if (options2.docker) {
48770
48598
  steps.push(`Run ${highlighter.command("npm run db:start")} to start the docker container`);
48771
48599
  }
48772
- steps.push(`To update your DB schema, run ${highlighter.command("npm run db:push")}`);
48600
+ steps.push(`Run ${highlighter.command("npm run db:push")} to update your database schema`);
48773
48601
  return steps;
48774
48602
  }
48775
48603
  });
@@ -48865,10 +48693,8 @@ function addEslintConfigPrettier({ content }) {
48865
48693
 
48866
48694
  var eslint = defineAdder({
48867
48695
  id: "eslint",
48868
- name: "ESLint",
48869
- description: "A configurable JavaScript linter",
48870
48696
  environments: { svelte: true, kit: true },
48871
- documentation: "https://eslint.org",
48697
+ homepage: "https://eslint.org",
48872
48698
  options: {},
48873
48699
  packages: [
48874
48700
  { name: "eslint", version: "^9.7.0", dev: true },
@@ -48986,570 +48812,6 @@ var eslint = defineAdder({
48986
48812
  ]
48987
48813
  });
48988
48814
 
48989
- var __freeze = Object.freeze;
48990
- var __defProp = Object.defineProperty;
48991
- var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(cooked.slice()) }));
48992
- var _a, _b;
48993
- const LUCIA_ADAPTER = {
48994
- mysql: "DrizzleMySQLAdapter",
48995
- postgresql: "DrizzlePostgreSQLAdapter",
48996
- sqlite: "DrizzleSQLiteAdapter"
48997
- };
48998
- const TABLE_TYPE = {
48999
- mysql: "mysqlTable",
49000
- postgresql: "pgTable",
49001
- sqlite: "sqliteTable"
49002
- };
49003
- let drizzleDialect;
49004
- let schemaPath;
49005
- const options$2 = defineAdderOptions({
49006
- demo: {
49007
- type: "boolean",
49008
- default: false,
49009
- question: `Do you want to include a demo? ${picocolors.dim("(includes a login/register page)")}`
49010
- }
49011
- });
49012
- var lucia = defineAdder({
49013
- id: "lucia",
49014
- name: "Lucia",
49015
- description: "An auth library that abstracts away the complexity of handling sessions",
49016
- environments: { svelte: false, kit: true },
49017
- documentation: "https://lucia-auth.com",
49018
- options: options$2,
49019
- packages: [
49020
- { name: "lucia", version: "^3.2.0", dev: false },
49021
- { name: "@lucia-auth/adapter-drizzle", version: "^1.1.0", dev: false },
49022
- // password hashing for demo
49023
- {
49024
- name: "@node-rs/argon2",
49025
- version: "^1.1.0",
49026
- condition: ({ options: options2 }) => options2.demo,
49027
- dev: false
49028
- }
49029
- ],
49030
- dependsOn: ["drizzle"],
49031
- files: [
49032
- {
49033
- name: ({ typescript }) => `drizzle.config.${typescript ? "ts" : "js"}`,
49034
- content: ({ content }) => {
49035
- const { ast, generateCode } = parseScript(content);
49036
- const isProp = (name, node) => node.key.type === "Identifier" && node.key.name === name;
49037
- walk$1.walk(ast, {}, {
49038
- ObjectProperty(node) {
49039
- if (isProp("dialect", node) && node.value.type === "StringLiteral") {
49040
- drizzleDialect = node.value.value;
49041
- }
49042
- if (isProp("schema", node) && node.value.type === "StringLiteral") {
49043
- schemaPath = node.value.value;
49044
- }
49045
- }
49046
- });
49047
- if (!drizzleDialect) {
49048
- throw new Error("Failed to detect DB dialect in your `drizzle.config.[js|ts]` file");
49049
- }
49050
- if (!schemaPath) {
49051
- throw new Error("Failed to find schema path in your `drizzle.config.[js|ts]` file");
49052
- }
49053
- return generateCode();
49054
- }
49055
- },
49056
- {
49057
- name: () => schemaPath,
49058
- content: ({ content, options: options2 }) => {
49059
- const { ast, generateCode } = parseScript(content);
49060
- const createTable = (name) => _function.call(TABLE_TYPE[drizzleDialect], [name]);
49061
- const userDecl = variables.declaration(ast, "const", "user", createTable("user"));
49062
- const sessionDecl = variables.declaration(ast, "const", "session", createTable("session"));
49063
- const user = exports.namedExport(ast, "user", userDecl);
49064
- const session = exports.namedExport(ast, "session", sessionDecl);
49065
- const userTable = getCallExpression(user);
49066
- const sessionTable = getCallExpression(session);
49067
- if (!userTable || !sessionTable) {
49068
- throw new Error("failed to find call expression of `user` or `session`");
49069
- }
49070
- if (userTable.arguments.length === 1) {
49071
- userTable.arguments.push(object.createEmpty());
49072
- }
49073
- if (sessionTable.arguments.length === 1) {
49074
- sessionTable.arguments.push(object.createEmpty());
49075
- }
49076
- const userAttributes = userTable.arguments[1];
49077
- const sessionAttributes = sessionTable.arguments[1];
49078
- if (userAttributes?.type !== "ObjectExpression" || sessionAttributes?.type !== "ObjectExpression") {
49079
- throw new Error("unexpected shape of `user` or `session` table definition");
49080
- }
49081
- if (drizzleDialect === "sqlite") {
49082
- imports.addNamed(ast, "drizzle-orm/sqlite-core", {
49083
- sqliteTable: "sqliteTable",
49084
- text: "text",
49085
- integer: "integer"
49086
- });
49087
- object.overrideProperties(userAttributes, {
49088
- id: common.expressionFromString(`text('id').primaryKey()`)
49089
- });
49090
- if (options2.demo) {
49091
- object.overrideProperties(userAttributes, {
49092
- username: common.expressionFromString(`text('username').notNull().unique()`),
49093
- passwordHash: common.expressionFromString(`text('password_hash').notNull()`)
49094
- });
49095
- }
49096
- object.overrideProperties(sessionAttributes, {
49097
- id: common.expressionFromString(`text('id').primaryKey()`),
49098
- userId: common.expressionFromString(
49099
- `text('user_id').notNull().references(() => user.id)`
49100
- ),
49101
- expiresAt: common.expressionFromString(`integer('expires_at').notNull()`)
49102
- });
49103
- }
49104
- if (drizzleDialect === "mysql") {
49105
- imports.addNamed(ast, "drizzle-orm/mysql-core", {
49106
- mysqlTable: "mysqlTable",
49107
- varchar: "varchar",
49108
- datetime: "datetime"
49109
- });
49110
- object.overrideProperties(userAttributes, {
49111
- id: common.expressionFromString(`varchar('id', { length: 255 }).primaryKey()`)
49112
- });
49113
- if (options2.demo) {
49114
- object.overrideProperties(userAttributes, {
49115
- username: common.expressionFromString(
49116
- `varchar('username', { length: 32 }).notNull().unique()`
49117
- ),
49118
- passwordHash: common.expressionFromString(
49119
- `varchar('password_hash', { length: 255 }).notNull()`
49120
- )
49121
- });
49122
- }
49123
- object.overrideProperties(sessionAttributes, {
49124
- id: common.expressionFromString(`varchar('id', { length: 255 }).primaryKey()`),
49125
- userId: common.expressionFromString(
49126
- `varchar('user_id', { length: 255 }).notNull().references(() => user.id)`
49127
- ),
49128
- expiresAt: common.expressionFromString(`datetime('expires_at').notNull()`)
49129
- });
49130
- }
49131
- if (drizzleDialect === "postgresql") {
49132
- imports.addNamed(ast, "drizzle-orm/pg-core", {
49133
- pgTable: "pgTable",
49134
- text: "text",
49135
- timestamp: "timestamp"
49136
- });
49137
- object.overrideProperties(userAttributes, {
49138
- id: common.expressionFromString(`text('id').primaryKey()`)
49139
- });
49140
- if (options2.demo) {
49141
- object.overrideProperties(userAttributes, {
49142
- username: common.expressionFromString(`text('username').notNull().unique()`),
49143
- passwordHash: common.expressionFromString(`text('password_hash').notNull()`)
49144
- });
49145
- }
49146
- object.overrideProperties(sessionAttributes, {
49147
- id: common.expressionFromString(`text('id').primaryKey()`),
49148
- userId: common.expressionFromString(
49149
- `text('user_id').notNull().references(() => user.id)`
49150
- ),
49151
- expiresAt: common.expressionFromString(
49152
- `timestamp('expires_at', { withTimezone: true, mode: 'date' }).notNull()`
49153
- )
49154
- });
49155
- }
49156
- return generateCode();
49157
- }
49158
- },
49159
- {
49160
- name: ({ kit: kit2, typescript }) => `${kit2?.libDirectory}/server/auth.${typescript ? "ts" : "js"}`,
49161
- content: ({ content, typescript, options: options2 }) => {
49162
- const { ast, generateCode } = parseScript(content);
49163
- const adapter = LUCIA_ADAPTER[drizzleDialect];
49164
- imports.addNamed(ast, "$lib/server/db/schema.js", { user: "user", session: "session" });
49165
- imports.addNamed(ast, "$lib/server/db", { db: "db" });
49166
- imports.addNamed(ast, "lucia", { Lucia: "Lucia" });
49167
- imports.addNamed(ast, "@lucia-auth/adapter-drizzle", { [adapter]: adapter });
49168
- imports.addNamed(ast, "$app/environment", { dev: "dev" });
49169
- const adapterDecl = common.statementFromString(
49170
- `const adapter = new ${adapter}(db, session, user);`
49171
- );
49172
- common.addStatement(ast, adapterDecl);
49173
- const luciaInit = common.expressionFromString(`
49174
- new Lucia(adapter, {
49175
- sessionCookie: {
49176
- attributes: {
49177
- secure: !dev
49178
- }
49179
- },
49180
- ${options2.demo ? "getUserAttributes: (attributes) => ({ username: attributes.username })" : ""}
49181
- })`);
49182
- const luciaDecl = variables.declaration(ast, "const", "lucia", luciaInit);
49183
- exports.namedExport(ast, "lucia", luciaDecl);
49184
- if (typescript && !/declare module ["']lucia["']/.test(content)) {
49185
- const moduleDecl = common.statementFromString(`
49186
- declare module 'lucia' {
49187
- interface Register {
49188
- Lucia: typeof lucia;
49189
- // attributes that are already included are omitted
49190
- DatabaseUserAttributes: Omit<typeof user.$inferSelect, 'id'>;
49191
- DatabaseSessionAttributes: Omit<typeof session.$inferSelect, 'id' | 'userId' | 'expiresAt'>;
49192
- }
49193
- }`);
49194
- common.addStatement(ast, moduleDecl);
49195
- }
49196
- return generateCode();
49197
- }
49198
- },
49199
- {
49200
- name: () => "src/app.d.ts",
49201
- condition: ({ typescript }) => typescript,
49202
- content: ({ content }) => {
49203
- const { ast, generateCode } = parseScript(content);
49204
- const locals = kit.addGlobalAppInterface(ast, "Locals");
49205
- if (!locals) {
49206
- throw new Error("Failed detecting `locals` interface in `src/app.d.ts`");
49207
- }
49208
- const user = locals.body.body.find((prop) => common.hasTypeProp("user", prop));
49209
- const session = locals.body.body.find((prop) => common.hasTypeProp("session", prop));
49210
- if (!user) {
49211
- locals.body.body.push(createLuciaType("user"));
49212
- }
49213
- if (!session) {
49214
- locals.body.body.push(createLuciaType("session"));
49215
- }
49216
- return generateCode();
49217
- }
49218
- },
49219
- {
49220
- name: ({ typescript }) => `src/hooks.server.${typescript ? "ts" : "js"}`,
49221
- content: ({ content, typescript }) => {
49222
- const { ast, generateCode } = parseScript(content);
49223
- imports.addNamed(ast, "$lib/server/auth.js", { lucia: "lucia" });
49224
- kit.addHooksHandle(ast, typescript, "auth", getAuthHandleContent());
49225
- return generateCode();
49226
- }
49227
- },
49228
- // DEMO
49229
- // login/register
49230
- {
49231
- name: ({ kit: kit2, typescript }) => `${kit2.routesDirectory}/demo/login/+page.server.${typescript ? "ts" : "js"}`,
49232
- condition: ({ options: options2 }) => options2.demo,
49233
- content({ content, typescript }) {
49234
- if (content) {
49235
- log.warn(
49236
- `Existing ${picocolors.yellow("/demo/login/+page.server.[js|ts]")} file. Could not update.`
49237
- );
49238
- return content;
49239
- }
49240
- const [ts] = utils.createPrinter(typescript);
49241
- return dedent`
49242
- import { fail, redirect } from '@sveltejs/kit';
49243
- import { hash, verify } from '@node-rs/argon2';
49244
- import { eq } from 'drizzle-orm';
49245
- import { generateId } from 'lucia';
49246
- import { lucia } from '$lib/server/auth';
49247
- import { db } from '$lib/server/db';
49248
- import { user } from '$lib/server/db/schema.js';
49249
- ${ts(`import type { Actions, PageServerLoad } from './$types';`)}
49250
-
49251
- export const load${ts(": PageServerLoad")} = async (event) => {
49252
- if (event.locals.user) {
49253
- return redirect(302, '/demo');
49254
- }
49255
- return {};
49256
- };
49257
-
49258
- export const actions${ts(": Actions")} = {
49259
- login: async (event) => {
49260
- const formData = await event.request.formData();
49261
- const username = formData.get('username');
49262
- const password = formData.get('password');
49263
-
49264
- if (!validateUsername(username)) {
49265
- return fail(400, {
49266
- message: 'Invalid username',
49267
- });
49268
- }
49269
- if (!validatePassword(password)) {
49270
- return fail(400, {
49271
- message: 'Invalid password',
49272
- });
49273
- }
49274
-
49275
- const results = await db
49276
- .select()
49277
- .from(user)
49278
- .where(eq(user.username, username));
49279
-
49280
- const existingUser = results.at(0);
49281
- if (!existingUser) {
49282
- return fail(400, {
49283
- message: 'Incorrect username or password',
49284
- });
49285
- }
49286
-
49287
- const validPassword = await verify(existingUser.passwordHash, password, {
49288
- memoryCost: 19456,
49289
- timeCost: 2,
49290
- outputLen: 32,
49291
- parallelism: 1,
49292
- });
49293
- if (!validPassword) {
49294
- return fail(400, {
49295
- message: 'Incorrect username or password',
49296
- });
49297
- }
49298
-
49299
- const session = await lucia.createSession(existingUser.id, {});
49300
- const sessionCookie = lucia.createSessionCookie(session.id);
49301
- event.cookies.set(sessionCookie.name, sessionCookie.value, {
49302
- path: '/',
49303
- ...sessionCookie.attributes,
49304
- });
49305
-
49306
- return redirect(302, '/demo');
49307
- },
49308
- register: async (event) => {
49309
- const formData = await event.request.formData();
49310
- const username = formData.get('username');
49311
- const password = formData.get('password');
49312
-
49313
- if (!validateUsername(username)) {
49314
- return fail(400, {
49315
- message: 'Invalid username',
49316
- });
49317
- }
49318
- if (!validatePassword(password)) {
49319
- return fail(400, {
49320
- message: 'Invalid password',
49321
- });
49322
- }
49323
-
49324
- const passwordHash = await hash(password, {
49325
- // recommended minimum parameters
49326
- memoryCost: 19456,
49327
- timeCost: 2,
49328
- outputLen: 32,
49329
- parallelism: 1,
49330
- });
49331
- const userId = generateId(15);
49332
-
49333
- try {
49334
- await db.insert(user).values({
49335
- id: userId,
49336
- username,
49337
- passwordHash,
49338
- });
49339
-
49340
- const session = await lucia.createSession(userId, {});
49341
- const sessionCookie = lucia.createSessionCookie(session.id);
49342
- event.cookies.set(sessionCookie.name, sessionCookie.value, {
49343
- path: '/',
49344
- ...sessionCookie.attributes,
49345
- });
49346
- } catch (e) {
49347
- return fail(500, {
49348
- message: 'An error has occurred',
49349
- });
49350
- }
49351
- return redirect(302, '/demo');
49352
- },
49353
- };
49354
-
49355
- function validateUsername(username${ts(": unknown): username is string", ")")} {
49356
- return (
49357
- typeof username === 'string' &&
49358
- username.length >= 3 &&
49359
- username.length <= 31 &&
49360
- /^[a-z0-9_-]+$/.test(username)
49361
- );
49362
- }
49363
-
49364
- function validatePassword(password${ts(": unknown): password is string", ")")} {
49365
- return (
49366
- typeof password === 'string' &&
49367
- password.length >= 6 &&
49368
- password.length <= 255
49369
- );
49370
- }
49371
- `;
49372
- }
49373
- },
49374
- {
49375
- name: ({ kit: kit2 }) => `${kit2.routesDirectory}/demo/login/+page.svelte`,
49376
- condition: ({ options: options2 }) => options2.demo,
49377
- content({ content, typescript }) {
49378
- if (content) {
49379
- log.warn(`Existing ${picocolors.yellow("/demo/login/+page.svelte")} file. Could not update.`);
49380
- return content;
49381
- }
49382
- const [ts] = utils.createPrinter(typescript);
49383
- return dedent(_a || (_a = __template(["\n <script ", ">\n import { enhance } from '$app/forms';\n ", "\n\n export let form", ";\n <\/script>\n\n <h1>Login/Register</h1>\n <form method='post' action='?/login' use:enhance>\n <label>\n Username\n <input name='username' />\n </label>\n <label>\n Password\n <input type='password' name='password' />\n </label>\n <button>Login</button>\n <button formaction='?/register'>Register</button>\n </form>\n <p style='color: red'>{form?.message ?? ''}</p>\n "])), ts(`lang='ts'`), ts(`import type { ActionData } from './$types';`), ts(": ActionData"));
49384
- }
49385
- },
49386
- // logout
49387
- {
49388
- name: ({ kit: kit2, typescript }) => `${kit2.routesDirectory}/demo/+page.server.${typescript ? "ts" : "js"}`,
49389
- condition: ({ options: options2 }) => options2.demo,
49390
- content({ content, typescript }) {
49391
- if (content) {
49392
- log.warn(
49393
- `Existing ${picocolors.yellow("/demo/+page.server.[js|ts]")} file. Could not update.`
49394
- );
49395
- return content;
49396
- }
49397
- const [ts] = utils.createPrinter(typescript);
49398
- return dedent`
49399
- import { lucia } from '$lib/server/auth';
49400
- import { fail, redirect } from '@sveltejs/kit';
49401
- ${ts(`import type { Actions, PageServerLoad } from './$types';`)}
49402
-
49403
- export const load${ts(": PageServerLoad")} = async (event) => {
49404
- if (!event.locals.user) {
49405
- return redirect(302, '/demo/login');
49406
- }
49407
- return {
49408
- user: event.locals.user,
49409
- };
49410
- };
49411
-
49412
- export const actions${ts(": Actions")} = {
49413
- logout: async (event) => {
49414
- if (!event.locals.session) {
49415
- return fail(401);
49416
- }
49417
- await lucia.invalidateSession(event.locals.session.id);
49418
- const sessionCookie = lucia.createBlankSessionCookie();
49419
- event.cookies.set(sessionCookie.name, sessionCookie.value, {
49420
- path: '/',
49421
- ...sessionCookie.attributes,
49422
- });
49423
- return redirect(302, '/demo/login');
49424
- },
49425
- };
49426
- `;
49427
- }
49428
- },
49429
- {
49430
- name: ({ kit: kit2 }) => `${kit2.routesDirectory}/demo/+page.svelte`,
49431
- condition: ({ options: options2 }) => options2.demo,
49432
- content({ content, typescript }) {
49433
- if (content) {
49434
- log.warn(`Existing ${picocolors.yellow("/demo/+page.svelte")} file. Could not update.`);
49435
- return content;
49436
- }
49437
- const [ts] = utils.createPrinter(typescript);
49438
- return dedent(_b || (_b = __template(["\n <script ", ">\n import { enhance } from '$app/forms';\n ", "\n\n export let data", ";\n <\/script>\n\n <h1>Hi, {data.user.username}!</h1>\n <p>Your user ID is {data.user.id}.</p>\n <form method='post' action='?/logout' use:enhance>\n <button>Sign out</button>\n </form>\n "])), ts(`lang='ts'`), ts(`import type { PageServerData } from './$types';`), ts(": PageServerData"));
49439
- }
49440
- }
49441
- ],
49442
- nextSteps: ({ highlighter, options: options2 }) => {
49443
- const steps = [`Run ${highlighter.command("npm run db:push")} to update your database`];
49444
- if (options2.demo) {
49445
- steps.push(`Visit ${highlighter.route("/demo")} route to view the demo`);
49446
- }
49447
- return steps;
49448
- }
49449
- });
49450
- function createLuciaType(name) {
49451
- return {
49452
- type: "TSPropertySignature",
49453
- key: {
49454
- type: "Identifier",
49455
- name
49456
- },
49457
- typeAnnotation: {
49458
- type: "TSTypeAnnotation",
49459
- typeAnnotation: {
49460
- type: "TSUnionType",
49461
- types: [
49462
- {
49463
- type: "TSImportType",
49464
- argument: { type: "StringLiteral", value: "lucia" },
49465
- qualifier: {
49466
- type: "Identifier",
49467
- // capitalize first letter
49468
- name: `${name[0].toUpperCase()}${name.slice(1)}`
49469
- }
49470
- },
49471
- {
49472
- type: "TSNullKeyword"
49473
- }
49474
- ]
49475
- }
49476
- }
49477
- };
49478
- }
49479
- function getAuthHandleContent() {
49480
- return `
49481
- async ({ event, resolve }) => {
49482
- const sessionId = event.cookies.get(lucia.sessionCookieName);
49483
- if (!sessionId) {
49484
- event.locals.user = null;
49485
- event.locals.session = null;
49486
- return resolve(event);
49487
- }
49488
-
49489
- const { session, user } = await lucia.validateSession(sessionId);
49490
- if (!session) {
49491
- event.cookies.delete(lucia.sessionCookieName, { path: '/' });
49492
- }
49493
-
49494
- if (session?.fresh) {
49495
- const sessionCookie = lucia.createSessionCookie(session.id);
49496
-
49497
- event.cookies.set(sessionCookie.name, sessionCookie.value, {
49498
- path: '/',
49499
- ...sessionCookie.attributes,
49500
- });
49501
- }
49502
-
49503
- event.locals.user = user;
49504
- event.locals.session = session;
49505
-
49506
- return resolve(event);
49507
- };`;
49508
- }
49509
- function getCallExpression(ast) {
49510
- let callExpression;
49511
- walk$1.walk(ast, {}, {
49512
- CallExpression(node) {
49513
- callExpression ?? (callExpression = node);
49514
- }
49515
- });
49516
- return callExpression;
49517
- }
49518
-
49519
- var mdsvex = defineAdder({
49520
- id: "mdsvex",
49521
- name: "mdsvex",
49522
- description: "svelte in markdown",
49523
- environments: { svelte: true, kit: true },
49524
- documentation: "https://mdsvex.pngwn.io/docs",
49525
- options: {},
49526
- packages: [{ name: "mdsvex", version: "^0.11.2", dev: true }],
49527
- files: [
49528
- {
49529
- name: () => "svelte.config.js",
49530
- content: ({ content }) => {
49531
- const { ast, generateCode } = parseScript(content);
49532
- imports.addNamed(ast, "mdsvex", { mdsvex: "mdsvex" });
49533
- const { value: exportDefault } = exports.defaultExport(ast, object.createEmpty());
49534
- let preprocessorArray = object.property(exportDefault, "preprocess", array.createEmpty());
49535
- const isArray = preprocessorArray.type === "ArrayExpression";
49536
- if (!isArray) {
49537
- const previousElement = preprocessorArray;
49538
- preprocessorArray = array.createEmpty();
49539
- array.push(preprocessorArray, previousElement);
49540
- object.overrideProperty(exportDefault, "preprocess", preprocessorArray);
49541
- }
49542
- const mdsvexCall = _function.call("mdsvex", []);
49543
- array.push(preprocessorArray, mdsvexCall);
49544
- const extensionsArray = object.property(exportDefault, "extensions", array.createEmpty());
49545
- array.push(extensionsArray, ".svelte");
49546
- array.push(extensionsArray, ".svx");
49547
- return generateCode();
49548
- }
49549
- }
49550
- ]
49551
- });
49552
-
49553
48815
  const comma = ','.charCodeAt(0);
49554
48816
  const semicolon = ';'.charCodeAt(0);
49555
48817
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -50897,6 +50159,637 @@ class MagicString {
50897
50159
  }
50898
50160
  }
50899
50161
 
50162
+ var __freeze = Object.freeze;
50163
+ var __defProp = Object.defineProperty;
50164
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(cooked.slice()) }));
50165
+ var _a, _b;
50166
+ const TABLE_TYPE = {
50167
+ mysql: "mysqlTable",
50168
+ postgresql: "pgTable",
50169
+ sqlite: "sqliteTable"
50170
+ };
50171
+ let drizzleDialect;
50172
+ let schemaPath;
50173
+ const options$2 = defineAdderOptions({
50174
+ demo: {
50175
+ type: "boolean",
50176
+ default: true,
50177
+ question: `Do you want to include a demo? ${picocolors.dim("(includes a login/register page)")}`
50178
+ }
50179
+ });
50180
+ var lucia = defineAdder({
50181
+ id: "lucia",
50182
+ environments: { svelte: false, kit: true },
50183
+ homepage: "https://lucia-next.pages.dev",
50184
+ options: options$2,
50185
+ packages: [
50186
+ { name: "@oslojs/crypto", version: "^1.0.1", dev: false },
50187
+ { name: "@oslojs/encoding", version: "^1.1.0", dev: false },
50188
+ // password hashing for demo
50189
+ {
50190
+ name: "@node-rs/argon2",
50191
+ version: "^1.1.0",
50192
+ condition: ({ options: options2 }) => options2.demo,
50193
+ dev: false
50194
+ }
50195
+ ],
50196
+ dependsOn: ["drizzle"],
50197
+ files: [
50198
+ {
50199
+ name: ({ typescript }) => `drizzle.config.${typescript ? "ts" : "js"}`,
50200
+ content: ({ content }) => {
50201
+ const { ast, generateCode } = parseScript(content);
50202
+ const isProp = (name, node) => node.key.type === "Identifier" && node.key.name === name;
50203
+ walk$1.walk(ast, {}, {
50204
+ ObjectProperty(node) {
50205
+ if (isProp("dialect", node) && node.value.type === "StringLiteral") {
50206
+ drizzleDialect = node.value.value;
50207
+ }
50208
+ if (isProp("schema", node) && node.value.type === "StringLiteral") {
50209
+ schemaPath = node.value.value;
50210
+ }
50211
+ }
50212
+ });
50213
+ if (!drizzleDialect) {
50214
+ throw new Error("Failed to detect DB dialect in your `drizzle.config.[js|ts]` file");
50215
+ }
50216
+ if (!schemaPath) {
50217
+ throw new Error("Failed to find schema path in your `drizzle.config.[js|ts]` file");
50218
+ }
50219
+ return generateCode();
50220
+ }
50221
+ },
50222
+ {
50223
+ name: () => schemaPath,
50224
+ content: ({ content, options: options2, typescript }) => {
50225
+ const { ast, generateCode } = parseScript(content);
50226
+ const createTable = (name) => _function.call(TABLE_TYPE[drizzleDialect], [name]);
50227
+ const userDecl = variables.declaration(ast, "const", "user", createTable("user"));
50228
+ const sessionDecl = variables.declaration(ast, "const", "session", createTable("session"));
50229
+ const user = exports.namedExport(ast, "user", userDecl);
50230
+ const session = exports.namedExport(ast, "session", sessionDecl);
50231
+ const userTable = getCallExpression(user);
50232
+ const sessionTable = getCallExpression(session);
50233
+ if (!userTable || !sessionTable) {
50234
+ throw new Error("failed to find call expression of `user` or `session`");
50235
+ }
50236
+ if (userTable.arguments.length === 1) {
50237
+ userTable.arguments.push(object.createEmpty());
50238
+ }
50239
+ if (sessionTable.arguments.length === 1) {
50240
+ sessionTable.arguments.push(object.createEmpty());
50241
+ }
50242
+ const userAttributes = userTable.arguments[1];
50243
+ const sessionAttributes = sessionTable.arguments[1];
50244
+ if (userAttributes?.type !== "ObjectExpression" || sessionAttributes?.type !== "ObjectExpression") {
50245
+ throw new Error("unexpected shape of `user` or `session` table definition");
50246
+ }
50247
+ if (drizzleDialect === "sqlite") {
50248
+ imports.addNamed(ast, "drizzle-orm/sqlite-core", {
50249
+ sqliteTable: "sqliteTable",
50250
+ text: "text",
50251
+ integer: "integer"
50252
+ });
50253
+ object.overrideProperties(userAttributes, {
50254
+ id: common.expressionFromString(`text('id').primaryKey()`)
50255
+ });
50256
+ if (options2.demo) {
50257
+ object.overrideProperties(userAttributes, {
50258
+ username: common.expressionFromString(`text('username').notNull().unique()`),
50259
+ passwordHash: common.expressionFromString(`text('password_hash').notNull()`)
50260
+ });
50261
+ }
50262
+ object.overrideProperties(sessionAttributes, {
50263
+ id: common.expressionFromString(`text('id').primaryKey()`),
50264
+ userId: common.expressionFromString(
50265
+ `text('user_id').notNull().references(() => user.id)`
50266
+ ),
50267
+ expiresAt: common.expressionFromString(
50268
+ `integer('expires_at', { mode: 'timestamp' }).notNull()`
50269
+ )
50270
+ });
50271
+ }
50272
+ if (drizzleDialect === "mysql") {
50273
+ imports.addNamed(ast, "drizzle-orm/mysql-core", {
50274
+ mysqlTable: "mysqlTable",
50275
+ varchar: "varchar",
50276
+ datetime: "datetime"
50277
+ });
50278
+ object.overrideProperties(userAttributes, {
50279
+ id: common.expressionFromString(`varchar('id', { length: 255 }).primaryKey()`)
50280
+ });
50281
+ if (options2.demo) {
50282
+ object.overrideProperties(userAttributes, {
50283
+ username: common.expressionFromString(
50284
+ `varchar('username', { length: 32 }).notNull().unique()`
50285
+ ),
50286
+ passwordHash: common.expressionFromString(
50287
+ `varchar('password_hash', { length: 255 }).notNull()`
50288
+ )
50289
+ });
50290
+ }
50291
+ object.overrideProperties(sessionAttributes, {
50292
+ id: common.expressionFromString(`varchar('id', { length: 255 }).primaryKey()`),
50293
+ userId: common.expressionFromString(
50294
+ `varchar('user_id', { length: 255 }).notNull().references(() => user.id)`
50295
+ ),
50296
+ expiresAt: common.expressionFromString(`datetime('expires_at').notNull()`)
50297
+ });
50298
+ }
50299
+ if (drizzleDialect === "postgresql") {
50300
+ imports.addNamed(ast, "drizzle-orm/pg-core", {
50301
+ pgTable: "pgTable",
50302
+ text: "text",
50303
+ timestamp: "timestamp"
50304
+ });
50305
+ object.overrideProperties(userAttributes, {
50306
+ id: common.expressionFromString(`text('id').primaryKey()`)
50307
+ });
50308
+ if (options2.demo) {
50309
+ object.overrideProperties(userAttributes, {
50310
+ username: common.expressionFromString(`text('username').notNull().unique()`),
50311
+ passwordHash: common.expressionFromString(`text('password_hash').notNull()`)
50312
+ });
50313
+ }
50314
+ object.overrideProperties(sessionAttributes, {
50315
+ id: common.expressionFromString(`text('id').primaryKey()`),
50316
+ userId: common.expressionFromString(
50317
+ `text('user_id').notNull().references(() => user.id)`
50318
+ ),
50319
+ expiresAt: common.expressionFromString(
50320
+ `timestamp('expires_at', { withTimezone: true, mode: 'date' }).notNull()`
50321
+ )
50322
+ });
50323
+ }
50324
+ let code = generateCode();
50325
+ if (typescript) {
50326
+ if (!code.includes("export type Session =")) {
50327
+ code += "\n\nexport type Session = typeof session.$inferSelect;";
50328
+ }
50329
+ if (!code.includes("export type User =")) {
50330
+ code += "\n\nexport type User = typeof user.$inferSelect;";
50331
+ }
50332
+ }
50333
+ return code;
50334
+ }
50335
+ },
50336
+ {
50337
+ name: ({ kit: kit2, typescript }) => `${kit2?.libDirectory}/server/auth.${typescript ? "ts" : "js"}`,
50338
+ content: ({ content, typescript }) => {
50339
+ const { ast, generateCode } = parseScript(content);
50340
+ imports.addNamespace(ast, "$lib/server/db/schema", "table");
50341
+ imports.addNamed(ast, "$lib/server/db", { db: "db" });
50342
+ imports.addNamed(ast, "@oslojs/encoding", {
50343
+ encodeBase32LowerCaseNoPadding: "encodeBase32LowerCaseNoPadding",
50344
+ encodeHexLowerCase: "encodeHexLowerCase"
50345
+ });
50346
+ imports.addNamed(ast, "@oslojs/crypto/sha2", { sha256: "sha256" });
50347
+ imports.addNamed(ast, "drizzle-orm", { eq: "eq" });
50348
+ const ms = new MagicString(generateCode().trim());
50349
+ const [ts] = utils.createPrinter(typescript);
50350
+ if (!ms.original.includes("const DAY_IN_MS")) {
50351
+ ms.append("\n\nconst DAY_IN_MS = 1000 * 60 * 60 * 24;");
50352
+ }
50353
+ if (!ms.original.includes("export const sessionCookieName")) {
50354
+ ms.append("\n\nexport const sessionCookieName = 'auth-session';");
50355
+ }
50356
+ if (!ms.original.includes("function generateSessionToken")) {
50357
+ const generateSessionToken = dedent`
50358
+ ${ts("", "/** @returns {string} */")}
50359
+ function generateSessionToken()${ts(": string")} {
50360
+ const bytes = crypto.getRandomValues(new Uint8Array(20));
50361
+ const token = encodeBase32LowerCaseNoPadding(bytes);
50362
+ return token;
50363
+ }`;
50364
+ ms.append(`
50365
+
50366
+ ${generateSessionToken}`);
50367
+ }
50368
+ if (!ms.original.includes("async function createSession")) {
50369
+ const createSession = dedent`
50370
+ ${ts("", "/** @param {string} userId */")}
50371
+ export async function createSession(userId${ts(": string")})${ts(": Promise<table.Session>")} {
50372
+ const token = generateSessionToken();
50373
+ const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
50374
+ const session${ts(": table.Session")} = {
50375
+ id: sessionId,
50376
+ userId,
50377
+ expiresAt: new Date(Date.now() + DAY_IN_MS * 30)
50378
+ };
50379
+ await db.insert(table.session).values(session);
50380
+ return session;
50381
+ }`;
50382
+ ms.append(`
50383
+
50384
+ ${createSession}`);
50385
+ }
50386
+ if (!ms.original.includes("async function invalidateSession")) {
50387
+ const invalidateSession = dedent`
50388
+ ${ts("", "/**")}
50389
+ ${ts("", " * @param {string} sessionId")}
50390
+ ${ts("", " * @returns {Promise<void>}")}
50391
+ ${ts("", " */")}
50392
+ export async function invalidateSession(sessionId${ts(": string")})${ts(": Promise<void>")} {
50393
+ await db.delete(table.session).where(eq(table.session.id, sessionId));
50394
+ }`;
50395
+ ms.append(`
50396
+
50397
+ ${invalidateSession}`);
50398
+ }
50399
+ if (!ms.original.includes("async function validateSession")) {
50400
+ const validateSession = dedent`
50401
+ ${ts("", "/** @param {string} sessionId */")}
50402
+ export async function validateSession(sessionId${ts(": string")}) {
50403
+ const [result] = await db
50404
+ .select({
50405
+ // Adjust user table here to tweak returned data
50406
+ user: { id: table.user.id, username: table.user.username },
50407
+ session: table.session
50408
+ })
50409
+ .from(table.session)
50410
+ .innerJoin(table.user, eq(table.session.userId, table.user.id))
50411
+ .where(eq(table.session.id, sessionId));
50412
+
50413
+ if (!result) {
50414
+ return { session: null, user: null };
50415
+ }
50416
+ const { session, user } = result;
50417
+
50418
+ const sessionExpired = Date.now() >= session.expiresAt.getTime();
50419
+ if (sessionExpired) {
50420
+ await db.delete(table.session).where(eq(table.session.id, session.id));
50421
+ return { session: null, user: null };
50422
+ }
50423
+
50424
+ const renewSession = Date.now() >= session.expiresAt.getTime() - DAY_IN_MS * 15;
50425
+ if (renewSession) {
50426
+ session.expiresAt = new Date(Date.now() + DAY_IN_MS * 30);
50427
+ await db
50428
+ .update(table.session)
50429
+ .set({ expiresAt: session.expiresAt })
50430
+ .where(eq(table.session.id, session.id));
50431
+ }
50432
+
50433
+ return { session, user };
50434
+ }`;
50435
+ ms.append(`
50436
+
50437
+ ${validateSession}`);
50438
+ }
50439
+ if (typescript && !ms.original.includes("export type SessionValidationResult")) {
50440
+ const sessionType = "export type SessionValidationResult = Awaited<ReturnType<typeof validateSession>>;";
50441
+ ms.append(`
50442
+
50443
+ ${sessionType}`);
50444
+ }
50445
+ return ms.toString();
50446
+ }
50447
+ },
50448
+ {
50449
+ name: () => "src/app.d.ts",
50450
+ condition: ({ typescript }) => typescript,
50451
+ content: ({ content }) => {
50452
+ const { ast, generateCode } = parseScript(content);
50453
+ const locals = kit.addGlobalAppInterface(ast, "Locals");
50454
+ if (!locals) {
50455
+ throw new Error("Failed detecting `locals` interface in `src/app.d.ts`");
50456
+ }
50457
+ const user = locals.body.body.find((prop) => common.hasTypeProp("user", prop));
50458
+ const session = locals.body.body.find((prop) => common.hasTypeProp("session", prop));
50459
+ if (!user) {
50460
+ locals.body.body.push(createLuciaType("user"));
50461
+ }
50462
+ if (!session) {
50463
+ locals.body.body.push(createLuciaType("session"));
50464
+ }
50465
+ return generateCode();
50466
+ }
50467
+ },
50468
+ {
50469
+ name: ({ typescript }) => `src/hooks.server.${typescript ? "ts" : "js"}`,
50470
+ content: ({ content, typescript }) => {
50471
+ const { ast, generateCode } = parseScript(content);
50472
+ imports.addNamespace(ast, "$lib/server/auth.js", "auth");
50473
+ imports.addNamed(ast, "$app/environment", { dev: "dev" });
50474
+ kit.addHooksHandle(ast, typescript, "handleAuth", getAuthHandleContent());
50475
+ return generateCode();
50476
+ }
50477
+ },
50478
+ // DEMO
50479
+ // login/register
50480
+ {
50481
+ name: ({ kit: kit2, typescript }) => `${kit2.routesDirectory}/demo/login/+page.server.${typescript ? "ts" : "js"}`,
50482
+ condition: ({ options: options2 }) => options2.demo,
50483
+ content({ content, typescript, kit: kit2 }) {
50484
+ if (content) {
50485
+ const filePath = `${kit2.routesDirectory}/demo/login/+page.server.${typescript ? "ts" : "js"}`;
50486
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50487
+ return content;
50488
+ }
50489
+ const [ts] = utils.createPrinter(typescript);
50490
+ return dedent`
50491
+ import { hash, verify } from '@node-rs/argon2';
50492
+ import { generateRandomString } from '@oslojs/crypto/random';
50493
+ import { fail, redirect } from '@sveltejs/kit';
50494
+ import { eq } from 'drizzle-orm';
50495
+ import { dev } from '$app/environment';
50496
+ import * as auth from '$lib/server/auth';
50497
+ import { db } from '$lib/server/db';
50498
+ import * as table from '$lib/server/db/schema';
50499
+ ${ts(`import type { Actions, PageServerLoad } from './$types';
50500
+ `)}
50501
+ export const load${ts(": PageServerLoad")} = async (event) => {
50502
+ if (event.locals.user) {
50503
+ return redirect(302, '/demo');
50504
+ }
50505
+ return {};
50506
+ };
50507
+
50508
+ export const actions${ts(": Actions")} = {
50509
+ login: async (event) => {
50510
+ const formData = await event.request.formData();
50511
+ const username = formData.get('username');
50512
+ const password = formData.get('password');
50513
+
50514
+ if (!validateUsername(username)) {
50515
+ return fail(400, { message: 'Invalid username' });
50516
+ }
50517
+ if (!validatePassword(password)) {
50518
+ return fail(400, { message: 'Invalid password' });
50519
+ }
50520
+
50521
+ const results = await db
50522
+ .select()
50523
+ .from(table.user)
50524
+ .where(eq(table.user.username, username));
50525
+
50526
+ const existingUser = results.at(0);
50527
+ if (!existingUser) {
50528
+ return fail(400, { message: 'Incorrect username or password' });
50529
+ }
50530
+
50531
+ const validPassword = await verify(existingUser.passwordHash, password, {
50532
+ memoryCost: 19456,
50533
+ timeCost: 2,
50534
+ outputLen: 32,
50535
+ parallelism: 1,
50536
+ });
50537
+ if (!validPassword) {
50538
+ return fail(400, { message: 'Incorrect username or password' });
50539
+ }
50540
+
50541
+ const session = await auth.createSession(existingUser.id);
50542
+ event.cookies.set(auth.sessionCookieName, session.id, {
50543
+ path: '/',
50544
+ sameSite: 'lax',
50545
+ httpOnly: true,
50546
+ expires: session.expiresAt,
50547
+ secure: !dev
50548
+ });
50549
+
50550
+ return redirect(302, '/demo');
50551
+ },
50552
+ register: async (event) => {
50553
+ const formData = await event.request.formData();
50554
+ const username = formData.get('username');
50555
+ const password = formData.get('password');
50556
+
50557
+ if (!validateUsername(username)) {
50558
+ return fail(400, { message: 'Invalid username' });
50559
+ }
50560
+ if (!validatePassword(password)) {
50561
+ return fail(400, { message: 'Invalid password' });
50562
+ }
50563
+
50564
+ const userId = generateUserId();
50565
+ const passwordHash = await hash(password, {
50566
+ // recommended minimum parameters
50567
+ memoryCost: 19456,
50568
+ timeCost: 2,
50569
+ outputLen: 32,
50570
+ parallelism: 1,
50571
+ });
50572
+
50573
+ try {
50574
+ await db.insert(table.user).values({ id: userId, username, passwordHash });
50575
+
50576
+ const session = await auth.createSession(userId);
50577
+ event.cookies.set(auth.sessionCookieName, session.id, {
50578
+ path: '/',
50579
+ sameSite: 'lax',
50580
+ httpOnly: true,
50581
+ expires: session.expiresAt,
50582
+ secure: !dev
50583
+ });
50584
+ } catch (e) {
50585
+ return fail(500, { message: 'An error has occurred' });
50586
+ }
50587
+ return redirect(302, '/demo');
50588
+ },
50589
+ };
50590
+
50591
+ const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
50592
+
50593
+ function generateUserId(length = 21)${ts(": string")} {
50594
+ return generateRandomString({ read: (bytes) => crypto.getRandomValues(bytes) }, alphabet, length);
50595
+ }
50596
+
50597
+ function validateUsername(username${ts(": unknown")})${ts(": username is string")} {
50598
+ return (
50599
+ typeof username === 'string' &&
50600
+ username.length >= 3 &&
50601
+ username.length <= 31 &&
50602
+ /^[a-z0-9_-]+$/.test(username)
50603
+ );
50604
+ }
50605
+
50606
+ function validatePassword(password${ts(": unknown")})${ts(": password is string")} {
50607
+ return (
50608
+ typeof password === 'string' &&
50609
+ password.length >= 6 &&
50610
+ password.length <= 255
50611
+ );
50612
+ }
50613
+ `;
50614
+ }
50615
+ },
50616
+ {
50617
+ name: ({ kit: kit2 }) => `${kit2.routesDirectory}/demo/login/+page.svelte`,
50618
+ condition: ({ options: options2 }) => options2.demo,
50619
+ content({ content, dependencyVersion, typescript, kit: kit2 }) {
50620
+ if (content) {
50621
+ const filePath = `${kit2.routesDirectory}/demo/login/+page.svelte`;
50622
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50623
+ return content;
50624
+ }
50625
+ const svelte5 = !!dependencyVersion("svelte")?.startsWith("5");
50626
+ const [ts, s5] = utils.createPrinter(typescript, svelte5);
50627
+ return dedent(_a || (_a = __template(["\n <script ", ">\n import { enhance } from '$app/forms';\n ", "\n ", "\n <\/script>\n\n <h1>Login/Register</h1>\n <form method='post' action='?/login' use:enhance>\n <label>\n Username\n <input name='username' />\n </label>\n <label>\n Password\n <input type='password' name='password' />\n </label>\n <button>Login</button>\n <button formaction='?/register'>Register</button>\n </form>\n <p style='color: red'>{form?.message ?? ''}</p>\n "])), ts(`lang='ts'`), ts(`import type { ActionData } from './$types';
50628
+ `), s5(`let { form }${ts(": { form: ActionData }")} = $props();`, `export let form${ts(": ActionData")};`));
50629
+ }
50630
+ },
50631
+ // logout
50632
+ {
50633
+ name: ({ kit: kit2, typescript }) => `${kit2.routesDirectory}/demo/+page.server.${typescript ? "ts" : "js"}`,
50634
+ condition: ({ options: options2 }) => options2.demo,
50635
+ content({ content, typescript, kit: kit2 }) {
50636
+ if (content) {
50637
+ const filePath = `${kit2.routesDirectory}/demo/+page.server.${typescript ? "ts" : "js"}`;
50638
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50639
+ return content;
50640
+ }
50641
+ const [ts] = utils.createPrinter(typescript);
50642
+ return dedent`
50643
+ import * as auth from '$lib/server/auth';
50644
+ import { fail, redirect } from '@sveltejs/kit';
50645
+ ${ts(`import type { Actions, PageServerLoad } from './$types';
50646
+ `)}
50647
+ export const load${ts(": PageServerLoad")} = async (event) => {
50648
+ if (!event.locals.user) {
50649
+ return redirect(302, '/demo/login');
50650
+ }
50651
+ return { user: event.locals.user };
50652
+ };
50653
+
50654
+ export const actions${ts(": Actions")} = {
50655
+ logout: async (event) => {
50656
+ if (!event.locals.session) {
50657
+ return fail(401);
50658
+ }
50659
+ await auth.invalidateSession(event.locals.session.id);
50660
+ event.cookies.delete(auth.sessionCookieName, { path: '/' });
50661
+
50662
+ return redirect(302, '/demo/login');
50663
+ },
50664
+ };
50665
+ `;
50666
+ }
50667
+ },
50668
+ {
50669
+ name: ({ kit: kit2 }) => `${kit2.routesDirectory}/demo/+page.svelte`,
50670
+ condition: ({ options: options2 }) => options2.demo,
50671
+ content({ content, dependencyVersion, typescript, kit: kit2 }) {
50672
+ if (content) {
50673
+ const filePath = `${kit2.routesDirectory}/demo/+page.svelte`;
50674
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50675
+ return content;
50676
+ }
50677
+ const svelte5 = !!dependencyVersion("svelte")?.startsWith("5");
50678
+ const [ts, s5] = utils.createPrinter(typescript, svelte5);
50679
+ return dedent(_b || (_b = __template(["\n <script ", ">\n import { enhance } from '$app/forms';\n ", "\n ", "\n <\/script>\n\n <h1>Hi, {data.user.username}!</h1>\n <p>Your user ID is {data.user.id}.</p>\n <form method='post' action='?/logout' use:enhance>\n <button>Sign out</button>\n </form>\n "])), ts(`lang='ts'`), ts(`import type { PageServerData } from './$types';
50680
+ `), s5(`let { data }${ts(": { data: PageServerData }")} = $props();`, `export let data${ts(": PageServerData")};`));
50681
+ }
50682
+ }
50683
+ ],
50684
+ nextSteps: ({ highlighter, options: options2 }) => {
50685
+ const steps = [`Run ${highlighter.command("npm run db:push")} to update your database schema`];
50686
+ if (options2.demo) {
50687
+ steps.push(`Visit ${highlighter.route("/demo")} route to view the demo`);
50688
+ }
50689
+ return steps;
50690
+ }
50691
+ });
50692
+ function createLuciaType(name) {
50693
+ return {
50694
+ type: "TSPropertySignature",
50695
+ key: {
50696
+ type: "Identifier",
50697
+ name
50698
+ },
50699
+ typeAnnotation: {
50700
+ type: "TSTypeAnnotation",
50701
+ typeAnnotation: {
50702
+ type: "TSIndexedAccessType",
50703
+ objectType: {
50704
+ type: "TSImportType",
50705
+ argument: { type: "StringLiteral", value: "$lib/server/auth" },
50706
+ qualifier: {
50707
+ type: "Identifier",
50708
+ name: "SessionValidationResult"
50709
+ }
50710
+ },
50711
+ indexType: {
50712
+ type: "TSLiteralType",
50713
+ literal: {
50714
+ type: "StringLiteral",
50715
+ value: name
50716
+ }
50717
+ }
50718
+ }
50719
+ }
50720
+ };
50721
+ }
50722
+ function getAuthHandleContent() {
50723
+ return `
50724
+ async ({ event, resolve }) => {
50725
+ const sessionId = event.cookies.get(auth.sessionCookieName);
50726
+ if (!sessionId) {
50727
+ event.locals.user = null;
50728
+ event.locals.session = null;
50729
+ return resolve(event);
50730
+ }
50731
+
50732
+ const { session, user } = await auth.validateSession(sessionId);
50733
+ if (session) {
50734
+ event.cookies.set(auth.sessionCookieName, session.id, {
50735
+ path: '/',
50736
+ sameSite: 'lax',
50737
+ httpOnly: true,
50738
+ expires: session.expiresAt,
50739
+ secure: !dev
50740
+ });
50741
+ } else {
50742
+ event.cookies.delete(auth.sessionCookieName, { path: '/' });
50743
+ }
50744
+
50745
+ event.locals.user = user;
50746
+ event.locals.session = session;
50747
+
50748
+ return resolve(event);
50749
+ };`;
50750
+ }
50751
+ function getCallExpression(ast) {
50752
+ let callExpression;
50753
+ walk$1.walk(ast, {}, {
50754
+ CallExpression(node) {
50755
+ callExpression ?? (callExpression = node);
50756
+ }
50757
+ });
50758
+ return callExpression;
50759
+ }
50760
+
50761
+ var mdsvex = defineAdder({
50762
+ id: "mdsvex",
50763
+ environments: { svelte: true, kit: true },
50764
+ homepage: "https://mdsvex.pngwn.io",
50765
+ options: {},
50766
+ packages: [{ name: "mdsvex", version: "^0.11.2", dev: true }],
50767
+ files: [
50768
+ {
50769
+ name: () => "svelte.config.js",
50770
+ content: ({ content }) => {
50771
+ const { ast, generateCode } = parseScript(content);
50772
+ imports.addNamed(ast, "mdsvex", { mdsvex: "mdsvex" });
50773
+ const { value: exportDefault } = exports.defaultExport(ast, object.createEmpty());
50774
+ let preprocessorArray = object.property(exportDefault, "preprocess", array.createEmpty());
50775
+ const isArray = preprocessorArray.type === "ArrayExpression";
50776
+ if (!isArray) {
50777
+ const previousElement = preprocessorArray;
50778
+ preprocessorArray = array.createEmpty();
50779
+ array.push(preprocessorArray, previousElement);
50780
+ object.overrideProperty(exportDefault, "preprocess", preprocessorArray);
50781
+ }
50782
+ const mdsvexCall = _function.call("mdsvex", []);
50783
+ array.push(preprocessorArray, mdsvexCall);
50784
+ const extensionsArray = object.property(exportDefault, "extensions", array.createEmpty());
50785
+ array.push(extensionsArray, ".svelte");
50786
+ array.push(extensionsArray, ".svx");
50787
+ return generateCode();
50788
+ }
50789
+ }
50790
+ ]
50791
+ });
50792
+
50900
50793
  function element(tagName, attributes = {}) {
50901
50794
  const element2 = new Element(tagName, {}, void 0, index.Tag);
50902
50795
  element2.attribs = attributes;
@@ -50942,15 +50835,14 @@ const DEFAULT_INLANG_PROJECT = {
50942
50835
  };
50943
50836
  const options$1 = defineAdderOptions({
50944
50837
  availableLanguageTags: {
50945
- question: "Which language tags would you like to support?",
50838
+ question: `Which language tags would you like to support? ${picocolors.gray("(e.g. en,de-ch)")}`,
50946
50839
  type: "string",
50947
- default: "",
50948
- placeholder: "en,de-ch",
50840
+ default: "en",
50949
50841
  validate(input) {
50950
50842
  const { invalidLanguageTags, validLanguageTags } = parseLanguageTagInput(input);
50951
50843
  if (invalidLanguageTags.length > 0) {
50952
50844
  if (invalidLanguageTags.length === 1) {
50953
- return `The input "${invalidLanguageTags[0]}" is not a valid BCP47 language tag`;
50845
+ return `The input "${invalidLanguageTags[0]}" is not a valid IETF BCP 47 language tag`;
50954
50846
  } else {
50955
50847
  const listFormat = new Intl.ListFormat("en", { style: "long", type: "conjunction" });
50956
50848
  return `The inputs ${listFormat.format(invalidLanguageTags.map((x) => `"${x}"`))} are not valid BCP47 language tags`;
@@ -50969,10 +50861,8 @@ const options$1 = defineAdderOptions({
50969
50861
  });
50970
50862
  var paraglide = defineAdder({
50971
50863
  id: "paraglide",
50972
- name: "Paraglide",
50973
- description: "Typesafe i18n with localised routing",
50974
50864
  environments: { svelte: false, kit: true },
50975
- documentation: "https://inlang.com/m/dxnzrydw/paraglide-sveltekit-i18n",
50865
+ homepage: "https://inlang.com",
50976
50866
  options: options$1,
50977
50867
  packages: [
50978
50868
  {
@@ -51004,9 +50894,7 @@ var paraglide = defineAdder({
51004
50894
  content: ({ content }) => {
51005
50895
  const { ast, generateCode } = parseScript(content);
51006
50896
  const vitePluginName = "paraglide";
51007
- imports.addNamed(ast, "@inlang/paraglide-sveltekit/vite", {
51008
- paraglide: vitePluginName
51009
- });
50897
+ imports.addNamed(ast, "@inlang/paraglide-sveltekit/vite", { paraglide: vitePluginName });
51010
50898
  const { value: rootObject } = exports.defaultExport(
51011
50899
  ast,
51012
50900
  _function.call("defineConfig", [])
@@ -51065,7 +50953,7 @@ var paraglide = defineAdder({
51065
50953
  i18n: "i18n"
51066
50954
  });
51067
50955
  const hookHandleContent = "i18n.handle()";
51068
- kit.addHooksHandle(ast, typescript, "paraglide", hookHandleContent);
50956
+ kit.addHooksHandle(ast, typescript, "handleParaglide", hookHandleContent);
51069
50957
  return generateCode();
51070
50958
  }
51071
50959
  },
@@ -51122,7 +51010,7 @@ var paraglide = defineAdder({
51122
51010
  name: ({ kit: kit2 }) => `${kit2?.routesDirectory}/+page.svelte`,
51123
51011
  condition: ({ options: options2 }) => options2.demo,
51124
51012
  content({ content, options: options2, typescript }) {
51125
- const { script, template, generateCode } = parseSvelte(content);
51013
+ const { script, template, generateCode } = parseSvelte(content, { typescript });
51126
51014
  imports.addDefault(script.ast, "$lib/paraglide/messages.js", "* as m");
51127
51015
  imports.addNamed(script.ast, "$app/navigation", { goto: "goto" });
51128
51016
  imports.addNamed(script.ast, "$app/stores", { page: "page" });
@@ -51205,10 +51093,8 @@ function parseLanguageTagInput(input) {
51205
51093
 
51206
51094
  var playwright = defineAdder({
51207
51095
  id: "playwright",
51208
- name: "Playwright",
51209
- description: "A testing framework for end-to-end testing",
51210
51096
  environments: { svelte: true, kit: true },
51211
- documentation: "https://playwright.dev",
51097
+ homepage: "https://playwright.dev",
51212
51098
  options: {},
51213
51099
  packages: [{ name: "@playwright/test", version: "^1.45.3", dev: true }],
51214
51100
  files: [
@@ -51277,10 +51163,8 @@ var playwright = defineAdder({
51277
51163
 
51278
51164
  var prettier = defineAdder({
51279
51165
  id: "prettier",
51280
- name: "Prettier",
51281
- description: "An opinionated code formatter",
51282
51166
  environments: { svelte: true, kit: true },
51283
- documentation: "https://prettier.io",
51167
+ homepage: "https://prettier.io",
51284
51168
  options: {},
51285
51169
  packages: [
51286
51170
  { name: "prettier", version: "^3.3.2", dev: true },
@@ -51370,10 +51254,8 @@ function hasEslint(dependencyVersion) {
51370
51254
 
51371
51255
  var routify = defineAdder({
51372
51256
  id: "routify",
51373
- name: "Routify",
51374
- description: "The Router that Grows With You",
51375
51257
  environments: { svelte: true, kit: false },
51376
- documentation: "https://routify.dev",
51258
+ homepage: "https://routify.dev",
51377
51259
  options: {},
51378
51260
  packages: [{ name: "@roxi/routify", version: "next", dev: true }],
51379
51261
  files: [
@@ -51447,10 +51329,8 @@ const routifyDemoHtml = `
51447
51329
 
51448
51330
  var storybook = defineAdder({
51449
51331
  id: "storybook",
51450
- name: "Storybook",
51451
- description: "Build UIs without the grunt work",
51452
51332
  environments: { kit: true, svelte: true },
51453
- documentation: "https://storybook.js.org/docs/get-started",
51333
+ homepage: "https://storybook.js.org",
51454
51334
  options: {},
51455
51335
  packages: [],
51456
51336
  scripts: [
@@ -51489,10 +51369,8 @@ const options = defineAdderOptions({
51489
51369
  var tailwindcss = defineAdder({
51490
51370
  id: "tailwindcss",
51491
51371
  alias: "tailwind",
51492
- name: "Tailwind CSS",
51493
- description: "Rapidly build modern websites without ever leaving your HTML",
51494
51372
  environments: { svelte: true, kit: true },
51495
- documentation: "https://tailwindcss.com/docs",
51373
+ homepage: "https://tailwindcss.com",
51496
51374
  options,
51497
51375
  packages: [
51498
51376
  { name: "tailwindcss", version: "^3.4.9", dev: true },
@@ -51607,10 +51485,8 @@ var tailwindcss = defineAdder({
51607
51485
 
51608
51486
  var vitest = defineAdder({
51609
51487
  id: "vitest",
51610
- name: "Vitest",
51611
- description: "A testing framework powered by Vite",
51612
51488
  environments: { svelte: true, kit: true },
51613
- documentation: "https://vitest.dev",
51489
+ homepage: "https://vitest.dev",
51614
51490
  options: {},
51615
51491
  packages: [{ name: "vitest", version: "^2.0.4", dev: true }],
51616
51492
  files: [
@@ -51685,45 +51561,31 @@ var vitest = defineAdder({
51685
51561
  ]
51686
51562
  });
51687
51563
 
51688
- const categories$1 = {
51689
- "Code Quality": [prettier, eslint],
51690
- Testing: [vitest, playwright],
51691
- CSS: [tailwindcss],
51692
- Database: [drizzle],
51693
- Auth: [lucia],
51694
- "Additional Functionality": [storybook, paraglide, mdsvex, routify]
51695
- };
51696
- const adderCategories = getCategoriesById();
51697
- function getCategoriesById() {
51698
- const adderCategories2 = {};
51699
- for (const [key, adders] of Object.entries(categories$1)) {
51700
- adderCategories2[key] = adders.map((a) => a.id);
51701
- }
51702
- return adderCategories2;
51703
- }
51704
- const adderIds = Object.values(adderCategories).flatMap((x) => x);
51705
- const adderDetails$1 = Object.values(categories$1).flat();
51706
- function getAdderDetails(name) {
51707
- const details = adderDetails$1.find((a) => a.id === name);
51564
+ const officialAdders = [
51565
+ prettier,
51566
+ eslint,
51567
+ vitest,
51568
+ playwright,
51569
+ tailwindcss,
51570
+ drizzle,
51571
+ lucia,
51572
+ mdsvex,
51573
+ paraglide,
51574
+ storybook,
51575
+ routify
51576
+ ];
51577
+ function getAdderDetails(id) {
51578
+ const details = officialAdders.find((a) => a.id === id);
51708
51579
  if (!details) {
51709
- throw new Error(`Invalid adder name: ${name}`);
51580
+ throw new Error(`Invalid adder: ${id}`);
51710
51581
  }
51711
51582
  return details;
51712
51583
  }
51713
51584
 
51714
- const categories = [
51715
- "Code Quality",
51716
- "Testing",
51717
- "CSS",
51718
- "Database",
51719
- "Auth",
51720
- "Additional Functionality"
51721
- ];
51722
-
51723
51585
  function __variableDynamicImportRuntime0__(path) {
51724
51586
  switch (path) {
51725
- case '../../../community-adders/unocss.ts': return import('./unocss-Dk7i15rK.js');
51726
- case '../../../community-adders/unplugin-icons.ts': return import('./unplugin-icons-DkNLYvBs.js');
51587
+ case '../../../community-adders/unocss.ts': return import('./unocss-BUQS5wKg.js');
51588
+ case '../../../community-adders/unplugin-icons.ts': return import('./unplugin-icons-BietOpsP.js');
51727
51589
  default: return new Promise(function(resolve, reject) {
51728
51590
  (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)(
51729
51591
  reject.bind(null, new Error("Unknown variable dynamic import: " + path))
@@ -51853,7 +51715,7 @@ function getGlobalPreconditions(cwd, projectType, adders) {
51853
51715
  return { success: true, message: void 0 };
51854
51716
  }
51855
51717
  const messages = addersForInvalidEnvironment.map(
51856
- (a) => `"${a.name}" does not support "${projectType}"`
51718
+ (a) => `"${a.id}" does not support "${projectType}"`
51857
51719
  );
51858
51720
  return { success: false, message: messages.join(" / ") };
51859
51721
  }
@@ -55301,7 +55163,7 @@ const AddersSchema = array$1(string());
55301
55163
  const AdderOptionFlagsSchema = object$1({
55302
55164
  tailwindcss: optional(array$1(string())),
55303
55165
  drizzle: optional(array$1(string())),
55304
- supabase: optional(array$1(string())),
55166
+ lucia: optional(array$1(string())),
55305
55167
  paraglide: optional(array$1(string()))
55306
55168
  });
55307
55169
  const OptionsSchema$1 = strictObject({
@@ -55311,8 +55173,7 @@ const OptionsSchema$1 = strictObject({
55311
55173
  community: optional(union([AddersSchema, boolean()])),
55312
55174
  ...AdderOptionFlagsSchema.entries
55313
55175
  });
55314
- const adderDetails = adderIds.map((id) => getAdderDetails(id));
55315
- const aliases = adderDetails.map((c) => c.alias).filter((v2) => v2 !== void 0);
55176
+ const aliases = officialAdders.map((c) => c.alias).filter((v2) => v2 !== void 0);
55316
55177
  const addersOptions = getAdderOptionFlags();
55317
55178
  const communityDetails = [];
55318
55179
  const defaultPkgPath = up();
@@ -55329,14 +55190,17 @@ const add = new Command("add").description("applies specified adders into a proj
55329
55190
  );
55330
55191
  process$1$1.exit(1);
55331
55192
  }
55332
- const adders = parse$8(AddersSchema, adderArgs);
55193
+ const specifiedAdders = parse$8(AddersSchema, adderArgs);
55333
55194
  const options = parse$8(OptionsSchema$1, opts);
55334
- const invalidAdders = adders.filter((a) => !adderIds.includes(a) && !aliases.includes(a));
55195
+ const adderIds = officialAdders.map((adder) => adder.id);
55196
+ const invalidAdders = specifiedAdders.filter(
55197
+ (a) => !adderIds.includes(a) && !aliases.includes(a)
55198
+ );
55335
55199
  if (invalidAdders.length > 0) {
55336
55200
  console.error(`Invalid adders specified: ${invalidAdders.join(", ")}`);
55337
55201
  process$1$1.exit(1);
55338
55202
  }
55339
- const selectedAdders = transformAliases(adders);
55203
+ const selectedAdders = transformAliases(specifiedAdders);
55340
55204
  runCommand(async () => {
55341
55205
  await runAddCommand(options, selectedAdders);
55342
55206
  });
@@ -55344,9 +55208,9 @@ const add = new Command("add").description("applies specified adders into a proj
55344
55208
  for (const option of addersOptions) {
55345
55209
  add.addOption(option);
55346
55210
  }
55347
- async function runAddCommand(options, adders) {
55211
+ async function runAddCommand(options, selectedAdderIds) {
55348
55212
  var _a;
55349
- const selectedAdders = adders.map((id) => ({
55213
+ const selectedAdders = selectedAdderIds.map((id) => ({
55350
55214
  type: "official",
55351
55215
  adder: getAdderDetails(id)
55352
55216
  }));
@@ -55404,23 +55268,17 @@ Available options: ${choices.join(", ")}`
55404
55268
  }
55405
55269
  }
55406
55270
  if (options.community === true) {
55407
- const promptOptions = {};
55408
55271
  const communityAdders = await Promise.all(
55409
- communityAdderIds.map(async (id) => ({ id, ...await getCommunityAdder(id) }))
55272
+ communityAdderIds.map(async (id) => await getCommunityAdder(id))
55410
55273
  );
55411
- const categories2 = new Set(communityAdders.map((adder) => adder.category));
55412
- for (const category of categories2) {
55413
- promptOptions[category] = communityAdders.filter((adder) => adder.category === category).map((adder) => ({
55414
- value: adder.id,
55415
- label: adder.name,
55416
- hint: adder.repo
55417
- }));
55418
- }
55419
- const selected = await groupMultiselect({
55274
+ const promptOptions = communityAdders.map((adder) => ({
55275
+ value: adder.id,
55276
+ label: adder.id,
55277
+ hint: "https://www.npmjs.com/package/" + adder.id
55278
+ }));
55279
+ const selected = await multiselect({
55420
55280
  message: "Which community tools would you like to add to your project?",
55421
55281
  options: promptOptions,
55422
- spacedGroups: true,
55423
- selectableGroups: false,
55424
55282
  required: false
55425
55283
  });
55426
55284
  if (isCancel(selected)) {
@@ -55433,7 +55291,7 @@ Available options: ${choices.join(", ")}`
55433
55291
  options.community = selected;
55434
55292
  }
55435
55293
  if (Array.isArray(options.community) && options.community.length > 0) {
55436
- const adders2 = options.community.map((id) => {
55294
+ const adders = options.community.map((id) => {
55437
55295
  const hasDirective = Object.values(Directive).some((directive) => id.startsWith(directive));
55438
55296
  if (hasDirective) return id;
55439
55297
  const validAdder = communityAdderIds.includes(id);
@@ -55449,15 +55307,8 @@ Available options: ${communityAdderIds.join(", ")}`
55449
55307
  try {
55450
55308
  start("Resolving community adder packages");
55451
55309
  const pkgs = await Promise.all(
55452
- adders2.map(async (id) => {
55453
- const adder = await getCommunityAdder(id).catch(() => void 0);
55454
- const packageName = adder?.npm ?? id;
55455
- const details2 = await getPackageJSON({ cwd: options.cwd, packageName });
55456
- return {
55457
- ...details2,
55458
- // prioritize community adder defined repo urls
55459
- repo: adder?.repo ?? details2.repo
55460
- };
55310
+ adders.map(async (id) => {
55311
+ return await getPackageJSON({ cwd: options.cwd, packageName: id });
55461
55312
  })
55462
55313
  );
55463
55314
  stop("Resolved community adder packages");
@@ -55493,30 +55344,20 @@ Available options: ${communityAdderIds.join(", ")}`
55493
55344
  }
55494
55345
  }
55495
55346
  if (selectedAdders.length === 0) {
55496
- const adderOptions = {};
55497
55347
  const workspace2 = createWorkspace(options.cwd);
55498
55348
  const projectType = workspace2.kit ? "kit" : "svelte";
55499
- for (const category of categories) {
55500
- const adderIds2 = adderCategories[category];
55501
- const categoryOptions = adderIds2.map((id) => {
55502
- const config = getAdderDetails(id);
55503
- if (projectType === "kit" && !config.environments.kit) return;
55504
- if (projectType === "svelte" && !config.environments.svelte) return;
55505
- return {
55506
- label: config.name,
55507
- value: config.id,
55508
- hint: config.documentation
55509
- };
55510
- }).filter((c) => !!c);
55511
- if (categoryOptions.length > 0) {
55512
- adderOptions[category] = categoryOptions;
55513
- }
55514
- }
55515
- const selected = await groupMultiselect({
55349
+ const adderOptions = officialAdders.map((adder) => {
55350
+ if (projectType === "kit" && !adder.environments.kit) return;
55351
+ if (projectType === "svelte" && !adder.environments.svelte) return;
55352
+ return {
55353
+ label: adder.id,
55354
+ value: adder.id,
55355
+ hint: adder.homepage
55356
+ };
55357
+ }).filter((a) => !!a);
55358
+ const selected = await multiselect({
55516
55359
  message: "What would you like to add to your project?",
55517
55360
  options: adderOptions,
55518
- spacedGroups: true,
55519
- selectableGroups: false,
55520
55361
  required: false
55521
55362
  });
55522
55363
  if (isCancel(selected)) {
@@ -55526,12 +55367,11 @@ Available options: ${communityAdderIds.join(", ")}`
55526
55367
  selected.forEach((id) => selectedAdders.push({ type: "official", adder: getAdderDetails(id) }));
55527
55368
  }
55528
55369
  for (const { adder } of selectedAdders) {
55529
- const name = adder.name;
55530
55370
  const dependents = adder.dependsOn?.filter((dep) => !selectedAdders.some((a) => a.adder.id === dep)) ?? [];
55531
55371
  const workspace2 = createWorkspace(options.cwd);
55532
55372
  for (const depId of dependents) {
55533
- const dependent = adderDetails.find((a) => a.id === depId);
55534
- if (!dependent) throw new Error(`Adder '${name}' depends on an invalid '${depId}'`);
55373
+ const dependent = officialAdders.find((a) => a.id === depId);
55374
+ if (!dependent) throw new Error(`Adder '${adder.id}' depends on an invalid '${depId}'`);
55535
55375
  let installed = false;
55536
55376
  installed = dependent.packages.every(
55537
55377
  // we'll skip the conditions since we don't have any options to supply it
@@ -55539,7 +55379,7 @@ Available options: ${communityAdderIds.join(", ")}`
55539
55379
  );
55540
55380
  if (installed) continue;
55541
55381
  const install = await confirm({
55542
- message: `The ${pc.bold(pc.cyan(name))} adder requires ${pc.bold(pc.cyan(depId))} to also be installed. ${pc.green("Install it?")}`
55382
+ message: `The ${pc.bold(pc.cyan(adder.id))} adder requires ${pc.bold(pc.cyan(depId))} to also be installed. ${pc.green("Install it?")}`
55543
55383
  });
55544
55384
  if (install !== true) {
55545
55385
  cancel("Operation cancelled.");
@@ -55548,11 +55388,11 @@ Available options: ${communityAdderIds.join(", ")}`
55548
55388
  selectedAdders.push({ type: "official", adder: dependent });
55549
55389
  }
55550
55390
  }
55551
- if (options.preconditions) {
55391
+ if (options.preconditions && selectedAdders.length > 0) {
55552
55392
  const { kit } = createWorkspace(options.cwd);
55553
55393
  const projectType = kit ? "kit" : "svelte";
55554
- const adders2 = selectedAdders.map(({ adder }) => adder);
55555
- const { preconditions } = getGlobalPreconditions(options.cwd, projectType, adders2);
55394
+ const adders = selectedAdders.map(({ adder }) => adder);
55395
+ const { preconditions } = getGlobalPreconditions(options.cwd, projectType, adders);
55556
55396
  const fails = [];
55557
55397
  for (const condition of preconditions) {
55558
55398
  const { message, success } = await condition.run();
@@ -55573,7 +55413,7 @@ Available options: ${communityAdderIds.join(", ")}`
55573
55413
  }
55574
55414
  for (const { adder, type } of selectedAdders) {
55575
55415
  const adderId = adder.id;
55576
- const questionPrefix = selectedAdders.length > 1 ? `${adder.name}: ` : "";
55416
+ const questionPrefix = selectedAdders.length > 1 ? `${adder.id}: ` : "";
55577
55417
  let values = {};
55578
55418
  if (type === "official") {
55579
55419
  official[adderId] ?? (official[adderId] = {});
@@ -55626,10 +55466,10 @@ Available options: ${communityAdderIds.join(", ")}`
55626
55466
  }
55627
55467
  let filesToFormat = [];
55628
55468
  if (Object.keys({ ...official, ...community }).length > 0) {
55629
- filesToFormat = await installAdders({ cwd: options.cwd, official, community });
55630
- log$1.success("Successfully installed adders");
55469
+ filesToFormat = await runAdders({ cwd: options.cwd, official, community });
55470
+ log$1.success("Successfully setup integrations");
55631
55471
  }
55632
- let depsStatus;
55472
+ let depsStatus = "skipped";
55633
55473
  if (options.install && selectedAdders.length > 0) {
55634
55474
  depsStatus = await suggestInstallingDependencies(options.cwd);
55635
55475
  }
@@ -55649,7 +55489,7 @@ Available options: ${communityAdderIds.join(", ")}`
55649
55489
  const nextStepsMsg = selectedAdders.filter(({ adder }) => adder.nextSteps).map(({ adder }) => {
55650
55490
  let adderMessage = "";
55651
55491
  if (selectedAdders.length > 1) {
55652
- adderMessage = `${pc.green(adder.name)}:
55492
+ adderMessage = `${pc.green(adder.id)}:
55653
55493
  `;
55654
55494
  }
55655
55495
  const adderNextSteps = adder.nextSteps({
@@ -55662,16 +55502,16 @@ Available options: ${communityAdderIds.join(", ")}`
55662
55502
  }).join("\n\n");
55663
55503
  if (nextStepsMsg) box(nextStepsMsg, "Next steps");
55664
55504
  }
55665
- async function installAdders({
55505
+ async function runAdders({
55666
55506
  cwd,
55667
55507
  official = {},
55668
55508
  community = {}
55669
55509
  }) {
55670
- const adderDetails2 = Object.keys(official).map((id) => getAdderDetails(id));
55510
+ const adderDetails = Object.keys(official).map((id) => getAdderDetails(id));
55671
55511
  const commDetails = Object.keys(community).map(
55672
55512
  (id) => communityDetails.find((a) => a.id === id)
55673
55513
  );
55674
- const details = adderDetails2.concat(commDetails);
55514
+ const details = adderDetails.concat(commDetails);
55675
55515
  details.sort((a, b) => {
55676
55516
  if (!a.dependsOn) return -1;
55677
55517
  if (!b.dependsOn) return 1;
@@ -55689,11 +55529,13 @@ async function installAdders({
55689
55529
  changedFiles.forEach((file) => filesToFormat.add(file));
55690
55530
  await config.postInstall?.(workspace);
55691
55531
  if (config.scripts && config.scripts.length > 0) {
55692
- const name = config.name;
55693
- log$1.step(`Running external command ${pc.gray(`(${name})`)}`);
55694
55532
  for (const script of config.scripts) {
55695
55533
  if (script.condition?.(workspace) === false) continue;
55696
55534
  const { command, args } = resolveCommand(workspace.packageManager, "execute", script.args);
55535
+ const adderPrefix = details.length > 1 ? `${config.id}: ` : "";
55536
+ log$1.step(
55537
+ `${adderPrefix}Running external command ${pc.gray(`(${command} ${args.join(" ")})`)}`
55538
+ );
55697
55539
  if (workspace.packageManager === "npm") args.unshift("--yes");
55698
55540
  try {
55699
55541
  await be(command, args, { nodeOptions: { cwd: workspace.cwd, stdio: script.stdio } });
@@ -55704,7 +55546,6 @@ async function installAdders({
55704
55546
  );
55705
55547
  }
55706
55548
  }
55707
- log$1.success(`Finished running ${name}`);
55708
55549
  }
55709
55550
  }
55710
55551
  return Array.from(filesToFormat);
@@ -55713,7 +55554,7 @@ function transformAliases(ids) {
55713
55554
  const set = /* @__PURE__ */ new Set();
55714
55555
  for (const id of ids) {
55715
55556
  if (aliases.includes(id)) {
55716
- const adder = adderDetails.find((a) => a.alias === id);
55557
+ const adder = officialAdders.find((a) => a.alias === id);
55717
55558
  set.add(adder.id);
55718
55559
  } else {
55719
55560
  set.add(id);
@@ -55723,7 +55564,8 @@ function transformAliases(ids) {
55723
55564
  }
55724
55565
  function getAdderOptionFlags() {
55725
55566
  const options = [];
55726
- for (const id of adderIds) {
55567
+ for (const adder of officialAdders) {
55568
+ const id = adder.id;
55727
55569
  const details = getAdderDetails(id);
55728
55570
  if (Object.values(details.options).length === 0) continue;
55729
55571
  const { defaults, groups } = getOptionChoices(details);
@@ -55838,7 +55680,7 @@ async function createProject(cwd, options) {
55838
55680
  });
55839
55681
  },
55840
55682
  force: async ({ results: { directory: directory2 } }) => {
55841
- if (fs$3.existsSync(directory2) && fs$3.readdirSync(directory2).length > 0) {
55683
+ if (fs$3.existsSync(directory2) && fs$3.readdirSync(directory2).filter((x) => !x.startsWith(".git")).length > 0) {
55842
55684
  const force = await confirm({
55843
55685
  message: "Directory not empty. Continue?",
55844
55686
  initialValue: false
@@ -55852,8 +55694,8 @@ async function createProject(cwd, options) {
55852
55694
  template: () => {
55853
55695
  if (options.template) return Promise.resolve(options.template);
55854
55696
  return select({
55855
- message: "Which Svelte app template",
55856
- initialValue: "skeleton",
55697
+ message: "Which template would you like?",
55698
+ initialValue: "minimal",
55857
55699
  options: templates.map((t) => ({ label: t.title, value: t.name, hint: t.description }))
55858
55700
  });
55859
55701
  },
@@ -55888,10 +55730,11 @@ async function createProject(cwd, options) {
55888
55730
  initSpinner.stop("Project created");
55889
55731
  if (options.adders) {
55890
55732
  await runAddCommand(
55891
- { cwd: projectPath, install: options.install, preconditions: true, community: [] },
55733
+ { cwd: projectPath, install: false, preconditions: true, community: [] },
55892
55734
  []
55893
55735
  );
55894
- } else if (options.install) {
55736
+ }
55737
+ if (options.install) {
55895
55738
  await suggestInstallingDependencies(projectPath);
55896
55739
  }
55897
55740
  return {