sv 0.5.1 → 0.5.2

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 +765 -915
  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.2";
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];
@@ -48310,7 +48148,7 @@ let MagicString$1 = class MagicString {
48310
48148
  };
48311
48149
  function parseScript(source) {
48312
48150
  const ast = parseScript$1(source);
48313
- const generateCode = () => serializeScript(ast);
48151
+ const generateCode = () => serializeScript(ast, source);
48314
48152
  return { ast, source, generateCode };
48315
48153
  }
48316
48154
  function parseCss(source) {
@@ -48494,10 +48332,8 @@ const options$3 = defineAdderOptions({
48494
48332
  });
48495
48333
  var drizzle = defineAdder({
48496
48334
  id: "drizzle",
48497
- name: "Drizzle",
48498
- description: "Headless ORM for NodeJS, TypeScript and JavaScript",
48499
48335
  environments: { svelte: false, kit: true },
48500
- documentation: "https://orm.drizzle.team/docs/overview",
48336
+ homepage: "https://orm.drizzle.team",
48501
48337
  options: options$3,
48502
48338
  packages: [
48503
48339
  { name: "drizzle-orm", version: "^0.33.0", dev: false },
@@ -48769,7 +48605,7 @@ var drizzle = defineAdder({
48769
48605
  if (options2.docker) {
48770
48606
  steps.push(`Run ${highlighter.command("npm run db:start")} to start the docker container`);
48771
48607
  }
48772
- steps.push(`To update your DB schema, run ${highlighter.command("npm run db:push")}`);
48608
+ steps.push(`Run ${highlighter.command("npm run db:push")} to update your database schema`);
48773
48609
  return steps;
48774
48610
  }
48775
48611
  });
@@ -48865,10 +48701,8 @@ function addEslintConfigPrettier({ content }) {
48865
48701
 
48866
48702
  var eslint = defineAdder({
48867
48703
  id: "eslint",
48868
- name: "ESLint",
48869
- description: "A configurable JavaScript linter",
48870
48704
  environments: { svelte: true, kit: true },
48871
- documentation: "https://eslint.org",
48705
+ homepage: "https://eslint.org",
48872
48706
  options: {},
48873
48707
  packages: [
48874
48708
  { name: "eslint", version: "^9.7.0", dev: true },
@@ -48986,570 +48820,6 @@ var eslint = defineAdder({
48986
48820
  ]
48987
48821
  });
48988
48822
 
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
48823
  const comma = ','.charCodeAt(0);
49554
48824
  const semicolon = ';'.charCodeAt(0);
49555
48825
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -50897,6 +50167,635 @@ class MagicString {
50897
50167
  }
50898
50168
  }
50899
50169
 
50170
+ var __freeze = Object.freeze;
50171
+ var __defProp = Object.defineProperty;
50172
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(cooked.slice()) }));
50173
+ var _a, _b;
50174
+ const TABLE_TYPE = {
50175
+ mysql: "mysqlTable",
50176
+ postgresql: "pgTable",
50177
+ sqlite: "sqliteTable"
50178
+ };
50179
+ let drizzleDialect;
50180
+ let schemaPath;
50181
+ const options$2 = defineAdderOptions({
50182
+ demo: {
50183
+ type: "boolean",
50184
+ default: true,
50185
+ question: `Do you want to include a demo? ${picocolors.dim("(includes a login/register page)")}`
50186
+ }
50187
+ });
50188
+ var lucia = defineAdder({
50189
+ id: "lucia",
50190
+ environments: { svelte: false, kit: true },
50191
+ homepage: "https://lucia-next.pages.dev",
50192
+ options: options$2,
50193
+ packages: [
50194
+ { name: "@oslojs/crypto", version: "^1.0.1", dev: false },
50195
+ { name: "@oslojs/encoding", version: "^1.1.0", dev: false },
50196
+ // password hashing for demo
50197
+ {
50198
+ name: "@node-rs/argon2",
50199
+ version: "^1.1.0",
50200
+ condition: ({ options: options2 }) => options2.demo,
50201
+ dev: false
50202
+ }
50203
+ ],
50204
+ dependsOn: ["drizzle"],
50205
+ files: [
50206
+ {
50207
+ name: ({ typescript }) => `drizzle.config.${typescript ? "ts" : "js"}`,
50208
+ content: ({ content }) => {
50209
+ const { ast, generateCode } = parseScript(content);
50210
+ const isProp = (name, node) => node.key.type === "Identifier" && node.key.name === name;
50211
+ walk$1.walk(ast, {}, {
50212
+ ObjectProperty(node) {
50213
+ if (isProp("dialect", node) && node.value.type === "StringLiteral") {
50214
+ drizzleDialect = node.value.value;
50215
+ }
50216
+ if (isProp("schema", node) && node.value.type === "StringLiteral") {
50217
+ schemaPath = node.value.value;
50218
+ }
50219
+ }
50220
+ });
50221
+ if (!drizzleDialect) {
50222
+ throw new Error("Failed to detect DB dialect in your `drizzle.config.[js|ts]` file");
50223
+ }
50224
+ if (!schemaPath) {
50225
+ throw new Error("Failed to find schema path in your `drizzle.config.[js|ts]` file");
50226
+ }
50227
+ return generateCode();
50228
+ }
50229
+ },
50230
+ {
50231
+ name: () => schemaPath,
50232
+ content: ({ content, options: options2, typescript }) => {
50233
+ const { ast, generateCode } = parseScript(content);
50234
+ const createTable = (name) => _function.call(TABLE_TYPE[drizzleDialect], [name]);
50235
+ const userDecl = variables.declaration(ast, "const", "user", createTable("user"));
50236
+ const sessionDecl = variables.declaration(ast, "const", "session", createTable("session"));
50237
+ const user = exports.namedExport(ast, "user", userDecl);
50238
+ const session = exports.namedExport(ast, "session", sessionDecl);
50239
+ const userTable = getCallExpression(user);
50240
+ const sessionTable = getCallExpression(session);
50241
+ if (!userTable || !sessionTable) {
50242
+ throw new Error("failed to find call expression of `user` or `session`");
50243
+ }
50244
+ if (userTable.arguments.length === 1) {
50245
+ userTable.arguments.push(object.createEmpty());
50246
+ }
50247
+ if (sessionTable.arguments.length === 1) {
50248
+ sessionTable.arguments.push(object.createEmpty());
50249
+ }
50250
+ const userAttributes = userTable.arguments[1];
50251
+ const sessionAttributes = sessionTable.arguments[1];
50252
+ if (userAttributes?.type !== "ObjectExpression" || sessionAttributes?.type !== "ObjectExpression") {
50253
+ throw new Error("unexpected shape of `user` or `session` table definition");
50254
+ }
50255
+ if (drizzleDialect === "sqlite") {
50256
+ imports.addNamed(ast, "drizzle-orm/sqlite-core", {
50257
+ sqliteTable: "sqliteTable",
50258
+ text: "text",
50259
+ integer: "integer"
50260
+ });
50261
+ object.overrideProperties(userAttributes, {
50262
+ id: common.expressionFromString(`text('id').primaryKey()`)
50263
+ });
50264
+ if (options2.demo) {
50265
+ object.overrideProperties(userAttributes, {
50266
+ username: common.expressionFromString(`text('username').notNull().unique()`),
50267
+ passwordHash: common.expressionFromString(`text('password_hash').notNull()`)
50268
+ });
50269
+ }
50270
+ object.overrideProperties(sessionAttributes, {
50271
+ id: common.expressionFromString(`text('id').primaryKey()`),
50272
+ userId: common.expressionFromString(
50273
+ `text('user_id').notNull().references(() => user.id)`
50274
+ ),
50275
+ expiresAt: common.expressionFromString(
50276
+ `integer('expires_at', { mode: 'timestamp' }).notNull()`
50277
+ )
50278
+ });
50279
+ }
50280
+ if (drizzleDialect === "mysql") {
50281
+ imports.addNamed(ast, "drizzle-orm/mysql-core", {
50282
+ mysqlTable: "mysqlTable",
50283
+ varchar: "varchar",
50284
+ datetime: "datetime"
50285
+ });
50286
+ object.overrideProperties(userAttributes, {
50287
+ id: common.expressionFromString(`varchar('id', { length: 255 }).primaryKey()`)
50288
+ });
50289
+ if (options2.demo) {
50290
+ object.overrideProperties(userAttributes, {
50291
+ username: common.expressionFromString(
50292
+ `varchar('username', { length: 32 }).notNull().unique()`
50293
+ ),
50294
+ passwordHash: common.expressionFromString(
50295
+ `varchar('password_hash', { length: 255 }).notNull()`
50296
+ )
50297
+ });
50298
+ }
50299
+ object.overrideProperties(sessionAttributes, {
50300
+ id: common.expressionFromString(`varchar('id', { length: 255 }).primaryKey()`),
50301
+ userId: common.expressionFromString(
50302
+ `varchar('user_id', { length: 255 }).notNull().references(() => user.id)`
50303
+ ),
50304
+ expiresAt: common.expressionFromString(`datetime('expires_at').notNull()`)
50305
+ });
50306
+ }
50307
+ if (drizzleDialect === "postgresql") {
50308
+ imports.addNamed(ast, "drizzle-orm/pg-core", {
50309
+ pgTable: "pgTable",
50310
+ text: "text",
50311
+ timestamp: "timestamp"
50312
+ });
50313
+ object.overrideProperties(userAttributes, {
50314
+ id: common.expressionFromString(`text('id').primaryKey()`)
50315
+ });
50316
+ if (options2.demo) {
50317
+ object.overrideProperties(userAttributes, {
50318
+ username: common.expressionFromString(`text('username').notNull().unique()`),
50319
+ passwordHash: common.expressionFromString(`text('password_hash').notNull()`)
50320
+ });
50321
+ }
50322
+ object.overrideProperties(sessionAttributes, {
50323
+ id: common.expressionFromString(`text('id').primaryKey()`),
50324
+ userId: common.expressionFromString(
50325
+ `text('user_id').notNull().references(() => user.id)`
50326
+ ),
50327
+ expiresAt: common.expressionFromString(
50328
+ `timestamp('expires_at', { withTimezone: true, mode: 'date' }).notNull()`
50329
+ )
50330
+ });
50331
+ }
50332
+ let code = generateCode();
50333
+ if (typescript) {
50334
+ if (!code.includes("export type Session =")) {
50335
+ code += "\n\nexport type Session = typeof session.$inferSelect;";
50336
+ }
50337
+ if (!code.includes("export type User =")) {
50338
+ code += "\n\nexport type User = typeof user.$inferSelect;";
50339
+ }
50340
+ }
50341
+ return code;
50342
+ }
50343
+ },
50344
+ {
50345
+ name: ({ kit: kit2, typescript }) => `${kit2?.libDirectory}/server/auth.${typescript ? "ts" : "js"}`,
50346
+ content: ({ content, typescript }) => {
50347
+ const { ast, generateCode } = parseScript(content);
50348
+ imports.addNamespace(ast, "$lib/server/db/schema", "table");
50349
+ imports.addNamed(ast, "$lib/server/db", { db: "db" });
50350
+ imports.addNamed(ast, "@oslojs/encoding", {
50351
+ encodeBase32LowerCaseNoPadding: "encodeBase32LowerCaseNoPadding",
50352
+ encodeHexLowerCase: "encodeHexLowerCase"
50353
+ });
50354
+ imports.addNamed(ast, "@oslojs/crypto/sha2", { sha256: "sha256" });
50355
+ imports.addNamed(ast, "drizzle-orm", { eq: "eq" });
50356
+ const ms = new MagicString(generateCode().trim());
50357
+ const [ts] = utils.createPrinter(typescript);
50358
+ if (!ms.original.includes("const DAY_IN_MS")) {
50359
+ ms.append("\n\nconst DAY_IN_MS = 1000 * 60 * 60 * 24;");
50360
+ }
50361
+ if (!ms.original.includes("export const sessionCookieName")) {
50362
+ ms.append("\n\nexport const sessionCookieName = 'auth-session';");
50363
+ }
50364
+ if (!ms.original.includes("function generateSessionToken")) {
50365
+ const generateSessionToken = dedent`
50366
+ ${ts("", "/** @returns {string} */")}
50367
+ function generateSessionToken()${ts(": string")} {
50368
+ const bytes = crypto.getRandomValues(new Uint8Array(20));
50369
+ const token = encodeBase32LowerCaseNoPadding(bytes);
50370
+ return token;
50371
+ }`;
50372
+ ms.append(`
50373
+
50374
+ ${generateSessionToken}`);
50375
+ }
50376
+ if (!ms.original.includes("async function createSession")) {
50377
+ const createSession = dedent`
50378
+ ${ts("", "/** @param {string} userId */")}
50379
+ export async function createSession(userId${ts(": string")})${ts(": Promise<table.Session>")} {
50380
+ const token = generateSessionToken();
50381
+ const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
50382
+ const session${ts(": table.Session")} = {
50383
+ id: sessionId,
50384
+ userId,
50385
+ expiresAt: new Date(Date.now() + DAY_IN_MS * 30)
50386
+ };
50387
+ await db.insert(table.session).values(session);
50388
+ return session;
50389
+ }`;
50390
+ ms.append(`
50391
+
50392
+ ${createSession}`);
50393
+ }
50394
+ if (!ms.original.includes("async function invalidateSession")) {
50395
+ const invalidateSession = dedent`
50396
+ ${ts("", "/**")}
50397
+ ${ts("", " * @param {string} sessionId")}
50398
+ ${ts("", " * @returns {Promise<void>}")}
50399
+ ${ts("", " */")}
50400
+ export async function invalidateSession(sessionId${ts(": string")})${ts(": Promise<void>")} {
50401
+ await db.delete(table.session).where(eq(table.session.id, sessionId));
50402
+ }`;
50403
+ ms.append(`
50404
+
50405
+ ${invalidateSession}`);
50406
+ }
50407
+ if (!ms.original.includes("async function validateSession")) {
50408
+ const validateSession = dedent`
50409
+ ${ts("", "/** @param {string} sessionId */")}
50410
+ export async function validateSession(sessionId${ts(": string")}) {
50411
+ const [result] = await db
50412
+ .select({
50413
+ // Adjust user table here to tweak returned data
50414
+ user: { id: table.user.id, username: table.user.username },
50415
+ session: table.session
50416
+ })
50417
+ .from(table.session)
50418
+ .innerJoin(table.user, eq(table.session.userId, table.user.id))
50419
+ .where(eq(table.session.id, sessionId));
50420
+
50421
+ if (!result) {
50422
+ return { session: null, user: null };
50423
+ }
50424
+ const { session, user } = result;
50425
+
50426
+ const sessionExpired = Date.now() >= session.expiresAt.getTime();
50427
+ if (sessionExpired) {
50428
+ await db.delete(table.session).where(eq(table.session.id, session.id));
50429
+ return { session: null, user: null };
50430
+ }
50431
+
50432
+ const renewSession = Date.now() >= session.expiresAt.getTime() - DAY_IN_MS * 15;
50433
+ if (renewSession) {
50434
+ session.expiresAt = new Date(Date.now() + DAY_IN_MS * 30);
50435
+ await db
50436
+ .update(table.session)
50437
+ .set({ expiresAt: session.expiresAt })
50438
+ .where(eq(table.session.id, session.id));
50439
+ }
50440
+
50441
+ return { session, user };
50442
+ }`;
50443
+ ms.append(`
50444
+
50445
+ ${validateSession}`);
50446
+ }
50447
+ if (typescript && !ms.original.includes("export type SessionValidationResult")) {
50448
+ const sessionType = "export type SessionValidationResult = Awaited<ReturnType<typeof validateSession>>;";
50449
+ ms.append(`
50450
+
50451
+ ${sessionType}`);
50452
+ }
50453
+ return ms.toString();
50454
+ }
50455
+ },
50456
+ {
50457
+ name: () => "src/app.d.ts",
50458
+ condition: ({ typescript }) => typescript,
50459
+ content: ({ content }) => {
50460
+ const { ast, generateCode } = parseScript(content);
50461
+ const locals = kit.addGlobalAppInterface(ast, "Locals");
50462
+ if (!locals) {
50463
+ throw new Error("Failed detecting `locals` interface in `src/app.d.ts`");
50464
+ }
50465
+ const user = locals.body.body.find((prop) => common.hasTypeProp("user", prop));
50466
+ const session = locals.body.body.find((prop) => common.hasTypeProp("session", prop));
50467
+ if (!user) {
50468
+ locals.body.body.push(createLuciaType("user"));
50469
+ }
50470
+ if (!session) {
50471
+ locals.body.body.push(createLuciaType("session"));
50472
+ }
50473
+ return generateCode();
50474
+ }
50475
+ },
50476
+ {
50477
+ name: ({ typescript }) => `src/hooks.server.${typescript ? "ts" : "js"}`,
50478
+ content: ({ content, typescript }) => {
50479
+ const { ast, generateCode } = parseScript(content);
50480
+ imports.addNamespace(ast, "$lib/server/auth.js", "auth");
50481
+ imports.addNamed(ast, "$app/environment", { dev: "dev" });
50482
+ kit.addHooksHandle(ast, typescript, "auth", getAuthHandleContent());
50483
+ return generateCode();
50484
+ }
50485
+ },
50486
+ // DEMO
50487
+ // login/register
50488
+ {
50489
+ name: ({ kit: kit2, typescript }) => `${kit2.routesDirectory}/demo/login/+page.server.${typescript ? "ts" : "js"}`,
50490
+ condition: ({ options: options2 }) => options2.demo,
50491
+ content({ content, typescript, kit: kit2 }) {
50492
+ if (content) {
50493
+ const filePath = `${kit2.routesDirectory}/demo/login/+page.server.${typescript ? "ts" : "js"}`;
50494
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50495
+ return content;
50496
+ }
50497
+ const [ts] = utils.createPrinter(typescript);
50498
+ return dedent`
50499
+ import { hash, verify } from '@node-rs/argon2';
50500
+ import { generateRandomString } from '@oslojs/crypto/random';
50501
+ import { fail, redirect } from '@sveltejs/kit';
50502
+ import { eq } from 'drizzle-orm';
50503
+ import { dev } from '$app/environment';
50504
+ import * as auth from '$lib/server/auth';
50505
+ import { db } from '$lib/server/db';
50506
+ import * as table from '$lib/server/db/schema';
50507
+ ${ts(`import type { Actions, PageServerLoad } from './$types';
50508
+ `)}
50509
+ export const load${ts(": PageServerLoad")} = async (event) => {
50510
+ if (event.locals.user) {
50511
+ return redirect(302, '/demo');
50512
+ }
50513
+ return {};
50514
+ };
50515
+
50516
+ export const actions${ts(": Actions")} = {
50517
+ login: async (event) => {
50518
+ const formData = await event.request.formData();
50519
+ const username = formData.get('username');
50520
+ const password = formData.get('password');
50521
+
50522
+ if (!validateUsername(username)) {
50523
+ return fail(400, { message: 'Invalid username' });
50524
+ }
50525
+ if (!validatePassword(password)) {
50526
+ return fail(400, { message: 'Invalid password' });
50527
+ }
50528
+
50529
+ const results = await db
50530
+ .select()
50531
+ .from(table.user)
50532
+ .where(eq(table.user.username, username));
50533
+
50534
+ const existingUser = results.at(0);
50535
+ if (!existingUser) {
50536
+ return fail(400, { message: 'Incorrect username or password' });
50537
+ }
50538
+
50539
+ const validPassword = await verify(existingUser.passwordHash, password, {
50540
+ memoryCost: 19456,
50541
+ timeCost: 2,
50542
+ outputLen: 32,
50543
+ parallelism: 1,
50544
+ });
50545
+ if (!validPassword) {
50546
+ return fail(400, { message: 'Incorrect username or password' });
50547
+ }
50548
+
50549
+ const session = await auth.createSession(existingUser.id);
50550
+ event.cookies.set(auth.sessionCookieName, session.id, {
50551
+ path: '/',
50552
+ sameSite: 'lax',
50553
+ httpOnly: true,
50554
+ expires: session.expiresAt,
50555
+ secure: !dev
50556
+ });
50557
+
50558
+ return redirect(302, '/demo');
50559
+ },
50560
+ register: async (event) => {
50561
+ const formData = await event.request.formData();
50562
+ const username = formData.get('username');
50563
+ const password = formData.get('password');
50564
+
50565
+ if (!validateUsername(username)) {
50566
+ return fail(400, { message: 'Invalid username' });
50567
+ }
50568
+ if (!validatePassword(password)) {
50569
+ return fail(400, { message: 'Invalid password' });
50570
+ }
50571
+
50572
+ const userId = generateUserId();
50573
+ const passwordHash = await hash(password, {
50574
+ // recommended minimum parameters
50575
+ memoryCost: 19456,
50576
+ timeCost: 2,
50577
+ outputLen: 32,
50578
+ parallelism: 1,
50579
+ });
50580
+
50581
+ try {
50582
+ await db.insert(table.user).values({ id: userId, username, passwordHash });
50583
+
50584
+ const session = await auth.createSession(userId);
50585
+ event.cookies.set(auth.sessionCookieName, session.id, {
50586
+ path: '/',
50587
+ sameSite: 'lax',
50588
+ httpOnly: true,
50589
+ expires: session.expiresAt,
50590
+ secure: !dev
50591
+ });
50592
+ } catch (e) {
50593
+ return fail(500, { message: 'An error has occurred' });
50594
+ }
50595
+ return redirect(302, '/demo');
50596
+ },
50597
+ };
50598
+
50599
+ const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
50600
+
50601
+ function generateUserId(length = 21)${ts(": string")} {
50602
+ return generateRandomString({ read: (bytes) => crypto.getRandomValues(bytes) }, alphabet, length);
50603
+ }
50604
+
50605
+ function validateUsername(username${ts(": unknown")})${ts(": username is string")} {
50606
+ return (
50607
+ typeof username === 'string' &&
50608
+ username.length >= 3 &&
50609
+ username.length <= 31 &&
50610
+ /^[a-z0-9_-]+$/.test(username)
50611
+ );
50612
+ }
50613
+
50614
+ function validatePassword(password${ts(": unknown")})${ts(": password is string")} {
50615
+ return (
50616
+ typeof password === 'string' &&
50617
+ password.length >= 6 &&
50618
+ password.length <= 255
50619
+ );
50620
+ }
50621
+ `;
50622
+ }
50623
+ },
50624
+ {
50625
+ name: ({ kit: kit2 }) => `${kit2.routesDirectory}/demo/login/+page.svelte`,
50626
+ condition: ({ options: options2 }) => options2.demo,
50627
+ content({ content, typescript, kit: kit2 }) {
50628
+ if (content) {
50629
+ const filePath = `${kit2.routesDirectory}/demo/login/+page.svelte`;
50630
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50631
+ return content;
50632
+ }
50633
+ const [ts] = utils.createPrinter(typescript);
50634
+ return dedent(_a || (_a = __template(["\n <script ", ">\n import { enhance } from '$app/forms';\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';
50635
+ `), ts(": ActionData"));
50636
+ }
50637
+ },
50638
+ // logout
50639
+ {
50640
+ name: ({ kit: kit2, typescript }) => `${kit2.routesDirectory}/demo/+page.server.${typescript ? "ts" : "js"}`,
50641
+ condition: ({ options: options2 }) => options2.demo,
50642
+ content({ content, typescript, kit: kit2 }) {
50643
+ if (content) {
50644
+ const filePath = `${kit2.routesDirectory}/demo/+page.server.${typescript ? "ts" : "js"}`;
50645
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50646
+ return content;
50647
+ }
50648
+ const [ts] = utils.createPrinter(typescript);
50649
+ return dedent`
50650
+ import * as auth from '$lib/server/auth';
50651
+ import { fail, redirect } from '@sveltejs/kit';
50652
+ ${ts(`import type { Actions, PageServerLoad } from './$types';
50653
+ `)}
50654
+ export const load${ts(": PageServerLoad")} = async (event) => {
50655
+ if (!event.locals.user) {
50656
+ return redirect(302, '/demo/login');
50657
+ }
50658
+ return { user: event.locals.user };
50659
+ };
50660
+
50661
+ export const actions${ts(": Actions")} = {
50662
+ logout: async (event) => {
50663
+ if (!event.locals.session) {
50664
+ return fail(401);
50665
+ }
50666
+ await auth.invalidateSession(event.locals.session.id);
50667
+ event.cookies.delete(auth.sessionCookieName, { path: '/' });
50668
+
50669
+ return redirect(302, '/demo/login');
50670
+ },
50671
+ };
50672
+ `;
50673
+ }
50674
+ },
50675
+ {
50676
+ name: ({ kit: kit2 }) => `${kit2.routesDirectory}/demo/+page.svelte`,
50677
+ condition: ({ options: options2 }) => options2.demo,
50678
+ content({ content, typescript, kit: kit2 }) {
50679
+ if (content) {
50680
+ const filePath = `${kit2.routesDirectory}/demo/+page.svelte`;
50681
+ log.warn(`Existing ${picocolors.yellow(filePath)} file. Could not update.`);
50682
+ return content;
50683
+ }
50684
+ const [ts] = utils.createPrinter(typescript);
50685
+ return dedent(_b || (_b = __template(["\n <script ", ">\n import { enhance } from '$app/forms';\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';
50686
+ `), ts(": PageServerData"));
50687
+ }
50688
+ }
50689
+ ],
50690
+ nextSteps: ({ highlighter, options: options2 }) => {
50691
+ const steps = [`Run ${highlighter.command("npm run db:push")} to update your database schema`];
50692
+ if (options2.demo) {
50693
+ steps.push(`Visit ${highlighter.route("/demo")} route to view the demo`);
50694
+ }
50695
+ return steps;
50696
+ }
50697
+ });
50698
+ function createLuciaType(name) {
50699
+ return {
50700
+ type: "TSPropertySignature",
50701
+ key: {
50702
+ type: "Identifier",
50703
+ name
50704
+ },
50705
+ typeAnnotation: {
50706
+ type: "TSTypeAnnotation",
50707
+ typeAnnotation: {
50708
+ type: "TSIndexedAccessType",
50709
+ objectType: {
50710
+ type: "TSImportType",
50711
+ argument: { type: "StringLiteral", value: "$lib/server/auth" },
50712
+ qualifier: {
50713
+ type: "Identifier",
50714
+ name: "SessionValidationResult"
50715
+ }
50716
+ },
50717
+ indexType: {
50718
+ type: "TSLiteralType",
50719
+ literal: {
50720
+ type: "StringLiteral",
50721
+ value: name
50722
+ }
50723
+ }
50724
+ }
50725
+ }
50726
+ };
50727
+ }
50728
+ function getAuthHandleContent() {
50729
+ return `
50730
+ async ({ event, resolve }) => {
50731
+ const sessionId = event.cookies.get(auth.sessionCookieName);
50732
+ if (!sessionId) {
50733
+ event.locals.user = null;
50734
+ event.locals.session = null;
50735
+ return resolve(event);
50736
+ }
50737
+
50738
+ const { session, user } = await auth.validateSession(sessionId);
50739
+ if (session) {
50740
+ event.cookies.set(auth.sessionCookieName, session.id, {
50741
+ path: '/',
50742
+ sameSite: 'lax',
50743
+ httpOnly: true,
50744
+ expires: session.expiresAt,
50745
+ secure: !dev
50746
+ });
50747
+ } else {
50748
+ event.cookies.delete(auth.sessionCookieName, { path: '/' });
50749
+ }
50750
+
50751
+ event.locals.user = user;
50752
+ event.locals.session = session;
50753
+
50754
+ return resolve(event);
50755
+ };`;
50756
+ }
50757
+ function getCallExpression(ast) {
50758
+ let callExpression;
50759
+ walk$1.walk(ast, {}, {
50760
+ CallExpression(node) {
50761
+ callExpression ?? (callExpression = node);
50762
+ }
50763
+ });
50764
+ return callExpression;
50765
+ }
50766
+
50767
+ var mdsvex = defineAdder({
50768
+ id: "mdsvex",
50769
+ environments: { svelte: true, kit: true },
50770
+ homepage: "https://mdsvex.pngwn.io",
50771
+ options: {},
50772
+ packages: [{ name: "mdsvex", version: "^0.11.2", dev: true }],
50773
+ files: [
50774
+ {
50775
+ name: () => "svelte.config.js",
50776
+ content: ({ content }) => {
50777
+ const { ast, generateCode } = parseScript(content);
50778
+ imports.addNamed(ast, "mdsvex", { mdsvex: "mdsvex" });
50779
+ const { value: exportDefault } = exports.defaultExport(ast, object.createEmpty());
50780
+ let preprocessorArray = object.property(exportDefault, "preprocess", array.createEmpty());
50781
+ const isArray = preprocessorArray.type === "ArrayExpression";
50782
+ if (!isArray) {
50783
+ const previousElement = preprocessorArray;
50784
+ preprocessorArray = array.createEmpty();
50785
+ array.push(preprocessorArray, previousElement);
50786
+ object.overrideProperty(exportDefault, "preprocess", preprocessorArray);
50787
+ }
50788
+ const mdsvexCall = _function.call("mdsvex", []);
50789
+ array.push(preprocessorArray, mdsvexCall);
50790
+ const extensionsArray = object.property(exportDefault, "extensions", array.createEmpty());
50791
+ array.push(extensionsArray, ".svelte");
50792
+ array.push(extensionsArray, ".svx");
50793
+ return generateCode();
50794
+ }
50795
+ }
50796
+ ]
50797
+ });
50798
+
50900
50799
  function element(tagName, attributes = {}) {
50901
50800
  const element2 = new Element(tagName, {}, void 0, index.Tag);
50902
50801
  element2.attribs = attributes;
@@ -50969,10 +50868,8 @@ const options$1 = defineAdderOptions({
50969
50868
  });
50970
50869
  var paraglide = defineAdder({
50971
50870
  id: "paraglide",
50972
- name: "Paraglide",
50973
- description: "Typesafe i18n with localised routing",
50974
50871
  environments: { svelte: false, kit: true },
50975
- documentation: "https://inlang.com/m/dxnzrydw/paraglide-sveltekit-i18n",
50872
+ homepage: "https://inlang.com",
50976
50873
  options: options$1,
50977
50874
  packages: [
50978
50875
  {
@@ -51205,10 +51102,8 @@ function parseLanguageTagInput(input) {
51205
51102
 
51206
51103
  var playwright = defineAdder({
51207
51104
  id: "playwright",
51208
- name: "Playwright",
51209
- description: "A testing framework for end-to-end testing",
51210
51105
  environments: { svelte: true, kit: true },
51211
- documentation: "https://playwright.dev",
51106
+ homepage: "https://playwright.dev",
51212
51107
  options: {},
51213
51108
  packages: [{ name: "@playwright/test", version: "^1.45.3", dev: true }],
51214
51109
  files: [
@@ -51277,10 +51172,8 @@ var playwright = defineAdder({
51277
51172
 
51278
51173
  var prettier = defineAdder({
51279
51174
  id: "prettier",
51280
- name: "Prettier",
51281
- description: "An opinionated code formatter",
51282
51175
  environments: { svelte: true, kit: true },
51283
- documentation: "https://prettier.io",
51176
+ homepage: "https://prettier.io",
51284
51177
  options: {},
51285
51178
  packages: [
51286
51179
  { name: "prettier", version: "^3.3.2", dev: true },
@@ -51370,10 +51263,8 @@ function hasEslint(dependencyVersion) {
51370
51263
 
51371
51264
  var routify = defineAdder({
51372
51265
  id: "routify",
51373
- name: "Routify",
51374
- description: "The Router that Grows With You",
51375
51266
  environments: { svelte: true, kit: false },
51376
- documentation: "https://routify.dev",
51267
+ homepage: "https://routify.dev",
51377
51268
  options: {},
51378
51269
  packages: [{ name: "@roxi/routify", version: "next", dev: true }],
51379
51270
  files: [
@@ -51447,10 +51338,8 @@ const routifyDemoHtml = `
51447
51338
 
51448
51339
  var storybook = defineAdder({
51449
51340
  id: "storybook",
51450
- name: "Storybook",
51451
- description: "Build UIs without the grunt work",
51452
51341
  environments: { kit: true, svelte: true },
51453
- documentation: "https://storybook.js.org/docs/get-started",
51342
+ homepage: "https://storybook.js.org",
51454
51343
  options: {},
51455
51344
  packages: [],
51456
51345
  scripts: [
@@ -51489,10 +51378,8 @@ const options = defineAdderOptions({
51489
51378
  var tailwindcss = defineAdder({
51490
51379
  id: "tailwindcss",
51491
51380
  alias: "tailwind",
51492
- name: "Tailwind CSS",
51493
- description: "Rapidly build modern websites without ever leaving your HTML",
51494
51381
  environments: { svelte: true, kit: true },
51495
- documentation: "https://tailwindcss.com/docs",
51382
+ homepage: "https://tailwindcss.com",
51496
51383
  options,
51497
51384
  packages: [
51498
51385
  { name: "tailwindcss", version: "^3.4.9", dev: true },
@@ -51607,10 +51494,8 @@ var tailwindcss = defineAdder({
51607
51494
 
51608
51495
  var vitest = defineAdder({
51609
51496
  id: "vitest",
51610
- name: "Vitest",
51611
- description: "A testing framework powered by Vite",
51612
51497
  environments: { svelte: true, kit: true },
51613
- documentation: "https://vitest.dev",
51498
+ homepage: "https://vitest.dev",
51614
51499
  options: {},
51615
51500
  packages: [{ name: "vitest", version: "^2.0.4", dev: true }],
51616
51501
  files: [
@@ -51685,45 +51570,31 @@ var vitest = defineAdder({
51685
51570
  ]
51686
51571
  });
51687
51572
 
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);
51573
+ const officialAdders = [
51574
+ prettier,
51575
+ eslint,
51576
+ vitest,
51577
+ playwright,
51578
+ tailwindcss,
51579
+ drizzle,
51580
+ lucia,
51581
+ mdsvex,
51582
+ paraglide,
51583
+ storybook,
51584
+ routify
51585
+ ];
51586
+ function getAdderDetails(id) {
51587
+ const details = officialAdders.find((a) => a.id === id);
51708
51588
  if (!details) {
51709
- throw new Error(`Invalid adder name: ${name}`);
51589
+ throw new Error(`Invalid adder: ${id}`);
51710
51590
  }
51711
51591
  return details;
51712
51592
  }
51713
51593
 
51714
- const categories = [
51715
- "Code Quality",
51716
- "Testing",
51717
- "CSS",
51718
- "Database",
51719
- "Auth",
51720
- "Additional Functionality"
51721
- ];
51722
-
51723
51594
  function __variableDynamicImportRuntime0__(path) {
51724
51595
  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');
51596
+ case '../../../community-adders/unocss.ts': return import('./unocss-BUQS5wKg.js');
51597
+ case '../../../community-adders/unplugin-icons.ts': return import('./unplugin-icons-BietOpsP.js');
51727
51598
  default: return new Promise(function(resolve, reject) {
51728
51599
  (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)(
51729
51600
  reject.bind(null, new Error("Unknown variable dynamic import: " + path))
@@ -51853,7 +51724,7 @@ function getGlobalPreconditions(cwd, projectType, adders) {
51853
51724
  return { success: true, message: void 0 };
51854
51725
  }
51855
51726
  const messages = addersForInvalidEnvironment.map(
51856
- (a) => `"${a.name}" does not support "${projectType}"`
51727
+ (a) => `"${a.id}" does not support "${projectType}"`
51857
51728
  );
51858
51729
  return { success: false, message: messages.join(" / ") };
51859
51730
  }
@@ -55301,7 +55172,7 @@ const AddersSchema = array$1(string());
55301
55172
  const AdderOptionFlagsSchema = object$1({
55302
55173
  tailwindcss: optional(array$1(string())),
55303
55174
  drizzle: optional(array$1(string())),
55304
- supabase: optional(array$1(string())),
55175
+ lucia: optional(array$1(string())),
55305
55176
  paraglide: optional(array$1(string()))
55306
55177
  });
55307
55178
  const OptionsSchema$1 = strictObject({
@@ -55311,8 +55182,7 @@ const OptionsSchema$1 = strictObject({
55311
55182
  community: optional(union([AddersSchema, boolean()])),
55312
55183
  ...AdderOptionFlagsSchema.entries
55313
55184
  });
55314
- const adderDetails = adderIds.map((id) => getAdderDetails(id));
55315
- const aliases = adderDetails.map((c) => c.alias).filter((v2) => v2 !== void 0);
55185
+ const aliases = officialAdders.map((c) => c.alias).filter((v2) => v2 !== void 0);
55316
55186
  const addersOptions = getAdderOptionFlags();
55317
55187
  const communityDetails = [];
55318
55188
  const defaultPkgPath = up();
@@ -55329,14 +55199,17 @@ const add = new Command("add").description("applies specified adders into a proj
55329
55199
  );
55330
55200
  process$1$1.exit(1);
55331
55201
  }
55332
- const adders = parse$8(AddersSchema, adderArgs);
55202
+ const specifiedAdders = parse$8(AddersSchema, adderArgs);
55333
55203
  const options = parse$8(OptionsSchema$1, opts);
55334
- const invalidAdders = adders.filter((a) => !adderIds.includes(a) && !aliases.includes(a));
55204
+ const adderIds = officialAdders.map((adder) => adder.id);
55205
+ const invalidAdders = specifiedAdders.filter(
55206
+ (a) => !adderIds.includes(a) && !aliases.includes(a)
55207
+ );
55335
55208
  if (invalidAdders.length > 0) {
55336
55209
  console.error(`Invalid adders specified: ${invalidAdders.join(", ")}`);
55337
55210
  process$1$1.exit(1);
55338
55211
  }
55339
- const selectedAdders = transformAliases(adders);
55212
+ const selectedAdders = transformAliases(specifiedAdders);
55340
55213
  runCommand(async () => {
55341
55214
  await runAddCommand(options, selectedAdders);
55342
55215
  });
@@ -55344,9 +55217,9 @@ const add = new Command("add").description("applies specified adders into a proj
55344
55217
  for (const option of addersOptions) {
55345
55218
  add.addOption(option);
55346
55219
  }
55347
- async function runAddCommand(options, adders) {
55220
+ async function runAddCommand(options, selectedAdderIds) {
55348
55221
  var _a;
55349
- const selectedAdders = adders.map((id) => ({
55222
+ const selectedAdders = selectedAdderIds.map((id) => ({
55350
55223
  type: "official",
55351
55224
  adder: getAdderDetails(id)
55352
55225
  }));
@@ -55404,23 +55277,17 @@ Available options: ${choices.join(", ")}`
55404
55277
  }
55405
55278
  }
55406
55279
  if (options.community === true) {
55407
- const promptOptions = {};
55408
55280
  const communityAdders = await Promise.all(
55409
- communityAdderIds.map(async (id) => ({ id, ...await getCommunityAdder(id) }))
55281
+ communityAdderIds.map(async (id) => await getCommunityAdder(id))
55410
55282
  );
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({
55283
+ const promptOptions = communityAdders.map((adder) => ({
55284
+ value: adder.id,
55285
+ label: adder.id,
55286
+ hint: "https://www.npmjs.com/package/" + adder.id
55287
+ }));
55288
+ const selected = await multiselect({
55420
55289
  message: "Which community tools would you like to add to your project?",
55421
55290
  options: promptOptions,
55422
- spacedGroups: true,
55423
- selectableGroups: false,
55424
55291
  required: false
55425
55292
  });
55426
55293
  if (isCancel(selected)) {
@@ -55433,7 +55300,7 @@ Available options: ${choices.join(", ")}`
55433
55300
  options.community = selected;
55434
55301
  }
55435
55302
  if (Array.isArray(options.community) && options.community.length > 0) {
55436
- const adders2 = options.community.map((id) => {
55303
+ const adders = options.community.map((id) => {
55437
55304
  const hasDirective = Object.values(Directive).some((directive) => id.startsWith(directive));
55438
55305
  if (hasDirective) return id;
55439
55306
  const validAdder = communityAdderIds.includes(id);
@@ -55449,15 +55316,8 @@ Available options: ${communityAdderIds.join(", ")}`
55449
55316
  try {
55450
55317
  start("Resolving community adder packages");
55451
55318
  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
- };
55319
+ adders.map(async (id) => {
55320
+ return await getPackageJSON({ cwd: options.cwd, packageName: id });
55461
55321
  })
55462
55322
  );
55463
55323
  stop("Resolved community adder packages");
@@ -55493,30 +55353,20 @@ Available options: ${communityAdderIds.join(", ")}`
55493
55353
  }
55494
55354
  }
55495
55355
  if (selectedAdders.length === 0) {
55496
- const adderOptions = {};
55497
55356
  const workspace2 = createWorkspace(options.cwd);
55498
55357
  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({
55358
+ const adderOptions = officialAdders.map((adder) => {
55359
+ if (projectType === "kit" && !adder.environments.kit) return;
55360
+ if (projectType === "svelte" && !adder.environments.svelte) return;
55361
+ return {
55362
+ label: adder.id,
55363
+ value: adder.id,
55364
+ hint: adder.homepage
55365
+ };
55366
+ }).filter((a) => !!a);
55367
+ const selected = await multiselect({
55516
55368
  message: "What would you like to add to your project?",
55517
55369
  options: adderOptions,
55518
- spacedGroups: true,
55519
- selectableGroups: false,
55520
55370
  required: false
55521
55371
  });
55522
55372
  if (isCancel(selected)) {
@@ -55526,12 +55376,11 @@ Available options: ${communityAdderIds.join(", ")}`
55526
55376
  selected.forEach((id) => selectedAdders.push({ type: "official", adder: getAdderDetails(id) }));
55527
55377
  }
55528
55378
  for (const { adder } of selectedAdders) {
55529
- const name = adder.name;
55530
55379
  const dependents = adder.dependsOn?.filter((dep) => !selectedAdders.some((a) => a.adder.id === dep)) ?? [];
55531
55380
  const workspace2 = createWorkspace(options.cwd);
55532
55381
  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}'`);
55382
+ const dependent = officialAdders.find((a) => a.id === depId);
55383
+ if (!dependent) throw new Error(`Adder '${adder.id}' depends on an invalid '${depId}'`);
55535
55384
  let installed = false;
55536
55385
  installed = dependent.packages.every(
55537
55386
  // we'll skip the conditions since we don't have any options to supply it
@@ -55539,7 +55388,7 @@ Available options: ${communityAdderIds.join(", ")}`
55539
55388
  );
55540
55389
  if (installed) continue;
55541
55390
  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?")}`
55391
+ message: `The ${pc.bold(pc.cyan(adder.id))} adder requires ${pc.bold(pc.cyan(depId))} to also be installed. ${pc.green("Install it?")}`
55543
55392
  });
55544
55393
  if (install !== true) {
55545
55394
  cancel("Operation cancelled.");
@@ -55548,11 +55397,11 @@ Available options: ${communityAdderIds.join(", ")}`
55548
55397
  selectedAdders.push({ type: "official", adder: dependent });
55549
55398
  }
55550
55399
  }
55551
- if (options.preconditions) {
55400
+ if (options.preconditions && selectedAdders.length > 0) {
55552
55401
  const { kit } = createWorkspace(options.cwd);
55553
55402
  const projectType = kit ? "kit" : "svelte";
55554
- const adders2 = selectedAdders.map(({ adder }) => adder);
55555
- const { preconditions } = getGlobalPreconditions(options.cwd, projectType, adders2);
55403
+ const adders = selectedAdders.map(({ adder }) => adder);
55404
+ const { preconditions } = getGlobalPreconditions(options.cwd, projectType, adders);
55556
55405
  const fails = [];
55557
55406
  for (const condition of preconditions) {
55558
55407
  const { message, success } = await condition.run();
@@ -55573,7 +55422,7 @@ Available options: ${communityAdderIds.join(", ")}`
55573
55422
  }
55574
55423
  for (const { adder, type } of selectedAdders) {
55575
55424
  const adderId = adder.id;
55576
- const questionPrefix = selectedAdders.length > 1 ? `${adder.name}: ` : "";
55425
+ const questionPrefix = selectedAdders.length > 1 ? `${adder.id}: ` : "";
55577
55426
  let values = {};
55578
55427
  if (type === "official") {
55579
55428
  official[adderId] ?? (official[adderId] = {});
@@ -55626,10 +55475,10 @@ Available options: ${communityAdderIds.join(", ")}`
55626
55475
  }
55627
55476
  let filesToFormat = [];
55628
55477
  if (Object.keys({ ...official, ...community }).length > 0) {
55629
- filesToFormat = await installAdders({ cwd: options.cwd, official, community });
55630
- log$1.success("Successfully installed adders");
55478
+ filesToFormat = await runAdders({ cwd: options.cwd, official, community });
55479
+ log$1.success("Successfully setup integrations");
55631
55480
  }
55632
- let depsStatus;
55481
+ let depsStatus = "skipped";
55633
55482
  if (options.install && selectedAdders.length > 0) {
55634
55483
  depsStatus = await suggestInstallingDependencies(options.cwd);
55635
55484
  }
@@ -55649,7 +55498,7 @@ Available options: ${communityAdderIds.join(", ")}`
55649
55498
  const nextStepsMsg = selectedAdders.filter(({ adder }) => adder.nextSteps).map(({ adder }) => {
55650
55499
  let adderMessage = "";
55651
55500
  if (selectedAdders.length > 1) {
55652
- adderMessage = `${pc.green(adder.name)}:
55501
+ adderMessage = `${pc.green(adder.id)}:
55653
55502
  `;
55654
55503
  }
55655
55504
  const adderNextSteps = adder.nextSteps({
@@ -55662,16 +55511,16 @@ Available options: ${communityAdderIds.join(", ")}`
55662
55511
  }).join("\n\n");
55663
55512
  if (nextStepsMsg) box(nextStepsMsg, "Next steps");
55664
55513
  }
55665
- async function installAdders({
55514
+ async function runAdders({
55666
55515
  cwd,
55667
55516
  official = {},
55668
55517
  community = {}
55669
55518
  }) {
55670
- const adderDetails2 = Object.keys(official).map((id) => getAdderDetails(id));
55519
+ const adderDetails = Object.keys(official).map((id) => getAdderDetails(id));
55671
55520
  const commDetails = Object.keys(community).map(
55672
55521
  (id) => communityDetails.find((a) => a.id === id)
55673
55522
  );
55674
- const details = adderDetails2.concat(commDetails);
55523
+ const details = adderDetails.concat(commDetails);
55675
55524
  details.sort((a, b) => {
55676
55525
  if (!a.dependsOn) return -1;
55677
55526
  if (!b.dependsOn) return 1;
@@ -55689,8 +55538,7 @@ async function installAdders({
55689
55538
  changedFiles.forEach((file) => filesToFormat.add(file));
55690
55539
  await config.postInstall?.(workspace);
55691
55540
  if (config.scripts && config.scripts.length > 0) {
55692
- const name = config.name;
55693
- log$1.step(`Running external command ${pc.gray(`(${name})`)}`);
55541
+ log$1.step(`Running external command ${pc.gray(`(${config.id})`)}`);
55694
55542
  for (const script of config.scripts) {
55695
55543
  if (script.condition?.(workspace) === false) continue;
55696
55544
  const { command, args } = resolveCommand(workspace.packageManager, "execute", script.args);
@@ -55704,7 +55552,7 @@ async function installAdders({
55704
55552
  );
55705
55553
  }
55706
55554
  }
55707
- log$1.success(`Finished running ${name}`);
55555
+ log$1.success(`Finished running ${config.id}`);
55708
55556
  }
55709
55557
  }
55710
55558
  return Array.from(filesToFormat);
@@ -55713,7 +55561,7 @@ function transformAliases(ids) {
55713
55561
  const set = /* @__PURE__ */ new Set();
55714
55562
  for (const id of ids) {
55715
55563
  if (aliases.includes(id)) {
55716
- const adder = adderDetails.find((a) => a.alias === id);
55564
+ const adder = officialAdders.find((a) => a.alias === id);
55717
55565
  set.add(adder.id);
55718
55566
  } else {
55719
55567
  set.add(id);
@@ -55723,7 +55571,8 @@ function transformAliases(ids) {
55723
55571
  }
55724
55572
  function getAdderOptionFlags() {
55725
55573
  const options = [];
55726
- for (const id of adderIds) {
55574
+ for (const adder of officialAdders) {
55575
+ const id = adder.id;
55727
55576
  const details = getAdderDetails(id);
55728
55577
  if (Object.values(details.options).length === 0) continue;
55729
55578
  const { defaults, groups } = getOptionChoices(details);
@@ -55838,7 +55687,7 @@ async function createProject(cwd, options) {
55838
55687
  });
55839
55688
  },
55840
55689
  force: async ({ results: { directory: directory2 } }) => {
55841
- if (fs$3.existsSync(directory2) && fs$3.readdirSync(directory2).length > 0) {
55690
+ if (fs$3.existsSync(directory2) && fs$3.readdirSync(directory2).filter((x) => !x.startsWith(".git")).length > 0) {
55842
55691
  const force = await confirm({
55843
55692
  message: "Directory not empty. Continue?",
55844
55693
  initialValue: false
@@ -55852,8 +55701,8 @@ async function createProject(cwd, options) {
55852
55701
  template: () => {
55853
55702
  if (options.template) return Promise.resolve(options.template);
55854
55703
  return select({
55855
- message: "Which Svelte app template",
55856
- initialValue: "skeleton",
55704
+ message: "Which template would you like?",
55705
+ initialValue: "minimal",
55857
55706
  options: templates.map((t) => ({ label: t.title, value: t.name, hint: t.description }))
55858
55707
  });
55859
55708
  },
@@ -55888,10 +55737,11 @@ async function createProject(cwd, options) {
55888
55737
  initSpinner.stop("Project created");
55889
55738
  if (options.adders) {
55890
55739
  await runAddCommand(
55891
- { cwd: projectPath, install: options.install, preconditions: true, community: [] },
55740
+ { cwd: projectPath, install: false, preconditions: true, community: [] },
55892
55741
  []
55893
55742
  );
55894
- } else if (options.install) {
55743
+ }
55744
+ if (options.install) {
55895
55745
  await suggestInstallingDependencies(projectPath);
55896
55746
  }
55897
55747
  return {