auth 1.7.0-beta.4 → 1.7.0-beta.6

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 (3) hide show
  1. package/dist/api.mjs +37 -8
  2. package/dist/index.mjs +305 -143
  3. package/package.json +6 -6
package/dist/api.mjs CHANGED
@@ -133,6 +133,10 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
133
133
  if (attr.type === "date" && attr.defaultValue.toString().includes("new Date()")) if (databaseType === "sqlite") type += `.default(sql\`(cast(unixepoch('subsecond') * 1000 as integer))\`)`;
134
134
  else type += `.defaultNow()`;
135
135
  } else if (typeof attr.defaultValue === "string") type += `.default("${attr.defaultValue}")`;
136
+ else if (Array.isArray(attr.defaultValue)) {
137
+ const elements = attr.defaultValue.map((value) => JSON.stringify(value)).join(", ");
138
+ type += `.default([${elements}])`;
139
+ } else if (typeof attr.defaultValue === "object" && attr.defaultValue !== null) type += `.default(${JSON.stringify(attr.defaultValue)})`;
136
140
  else type += `.default(${attr.defaultValue})`;
137
141
  if (attr.onUpdate && attr.type === "date") {
138
142
  if (typeof attr.onUpdate === "function") type += `.$onUpdate(${attr.onUpdate})`;
@@ -404,6 +408,16 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
404
408
  return "Int[]";
405
409
  }
406
410
  }
411
+ function getFieldTypeParts(type) {
412
+ const isArray = type.endsWith("[]");
413
+ const typeWithoutArray = isArray ? type.slice(0, -2) : type;
414
+ const isOptional = typeWithoutArray.endsWith("?");
415
+ return {
416
+ fieldType: isOptional ? typeWithoutArray.slice(0, -1) : typeWithoutArray,
417
+ isArray,
418
+ isOptional
419
+ };
420
+ }
407
421
  const prismaModel = builder.findByType("model", { name: modelName });
408
422
  if (!prismaModel) if (provider === "mongodb") builder.model(modelName).field("id", "String").attribute("id").attribute(`map("_id")`);
409
423
  else {
@@ -416,15 +430,9 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
416
430
  for (const field in fields) {
417
431
  const attr = fields[field];
418
432
  const fieldName = attr.fieldName || field;
419
- if (prismaModel) {
420
- if (builder.findByType("field", {
421
- name: fieldName,
422
- within: prismaModel.properties
423
- })) continue;
424
- }
425
433
  const useUUIDs = options.advanced?.database?.generateId === "uuid";
426
434
  const useNumberId = options.advanced?.database?.generateId === "serial";
427
- const fieldBuilder = builder.model(modelName).field(fieldName, field === "id" && useNumberId ? getType({
435
+ const fieldType = field === "id" && useNumberId ? getType({
428
436
  isBigint: false,
429
437
  isOptional: false,
430
438
  type: "number"
@@ -432,12 +440,33 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
432
440
  isBigint: attr?.bigint || false,
433
441
  isOptional: attr?.required === false,
434
442
  type: attr.references?.field === "id" ? useNumberId ? "number" : "string" : attr.type
435
- }));
443
+ });
444
+ if (prismaModel) {
445
+ const isAlreadyExist = builder.findByType("field", {
446
+ name: fieldName,
447
+ within: prismaModel.properties
448
+ });
449
+ if (isAlreadyExist) {
450
+ if (fieldType && typeof isAlreadyExist.fieldType === "string") {
451
+ const fieldTypeParts = getFieldTypeParts(fieldType);
452
+ const existingFieldTypeParts = getFieldTypeParts(isAlreadyExist.fieldType);
453
+ if ((existingFieldTypeParts.fieldType === "Int" || existingFieldTypeParts.fieldType === "BigInt") && (fieldTypeParts.fieldType === "Int" || fieldTypeParts.fieldType === "BigInt")) {
454
+ isAlreadyExist.fieldType = fieldTypeParts.fieldType;
455
+ isAlreadyExist.optional = fieldTypeParts.isOptional || void 0;
456
+ isAlreadyExist.array = fieldTypeParts.isArray || void 0;
457
+ }
458
+ }
459
+ continue;
460
+ }
461
+ }
462
+ if (!fieldType) throw new Error(`Unsupported Prisma field type for model "${modelName}", field "${fieldName}"${attr.type ? ` (source type: "${attr.type}")` : ""}.`);
463
+ const fieldBuilder = builder.model(modelName).field(fieldName, fieldType);
436
464
  if (field === "id") {
437
465
  fieldBuilder.attribute("id");
438
466
  if (provider === "mongodb") fieldBuilder.attribute(`map("_id")`);
439
467
  }
440
468
  if (attr.unique) builder.model(modelName).blockAttribute(`unique([${fieldName}])`);
469
+ if ((attr.type === "string[]" || attr.type === "number[]") && provider !== "sqlite" && provider !== "mysql" && attr.defaultValue === void 0) fieldBuilder.attribute("default([])");
441
470
  if (attr.defaultValue !== void 0) {
442
471
  if (Array.isArray(attr.defaultValue)) {
443
472
  if (attr.type === "json") {
package/dist/index.mjs CHANGED
@@ -578,7 +578,25 @@ function showNextSteps(lines) {
578
578
  }
579
579
  const ai = new Command("ai").description("Interactive setup for Agent Auth — AI agent authentication").action(aiAction);
580
580
  //#endregion
581
- //#region src/utils/add-cloudflare-modules.ts
581
+ //#region src/utils/cloudflare-virtual-modules.ts
582
+ /**
583
+ * `cloudflare:workers` is a Workers-runtime built-in module. The CLI loads
584
+ * `auth.ts` with jiti, outside that runtime, so a config importing it would
585
+ * crash. It is aliased to an inert stub whose named exports mirror the real
586
+ * module so every import links.
587
+ *
588
+ * Like the SvelteKit stubs, these are *named* exports that must exist at link
589
+ * time, so the surface is enumerated by hand. The list mirrors workerd's
590
+ * `cloudflare:workers` re-export module: the entrypoint/RPC classes are real
591
+ * classes (so `extends` works), and the value/helper exports are recursive
592
+ * proxies that absorb any access (so `env.MY_BINDING.get()` does not throw).
593
+ *
594
+ * `cloudflare:test` is intentionally NOT stubbed: it is a different module with
595
+ * a different surface, provided only by `@cloudflare/vitest-pool-workers` for
596
+ * test runs, and an auth config never imports it.
597
+ *
598
+ * @see https://github.com/cloudflare/workerd/blob/main/src/cloudflare/workers.ts
599
+ */
582
600
  const createModule = () => {
583
601
  return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
584
602
  const createStub = (label) => {
@@ -591,15 +609,14 @@ const createStub = (label) => {
591
609
  if (prop === "then") return undefined;
592
610
  return createStub(label + "." + String(prop));
593
611
  },
594
- apply(_, __, args) {
595
- return createStub(label + "()")
612
+ apply() {
613
+ return createStub(label + "()");
596
614
  },
597
615
  construct() {
598
616
  return createStub(label + "#instance");
599
617
  },
600
618
  };
601
- const fn = () => createStub(label + "()");
602
- return new Proxy(fn, handler);
619
+ return new Proxy(function () {}, handler);
603
620
  };
604
621
 
605
622
  class WorkerEntrypoint {
@@ -608,141 +625,204 @@ class WorkerEntrypoint {
608
625
  this.env = env;
609
626
  }
610
627
  }
611
-
612
628
  class DurableObject {
613
- constructor(state, env) {
614
- this.state = state;
629
+ constructor(ctx, env) {
630
+ this.ctx = ctx;
615
631
  this.env = env;
616
632
  }
617
633
  }
618
-
619
- class RpcTarget {
620
- constructor(value) {
621
- this.value = value;
634
+ class WorkflowEntrypoint {
635
+ constructor(ctx, env) {
636
+ this.ctx = ctx;
637
+ this.env = env;
622
638
  }
623
639
  }
624
-
625
- const RpcStub = RpcTarget;
640
+ class RpcTarget {}
641
+ class RpcStub {}
642
+ class RpcPromise {}
643
+ class RpcProperty {}
644
+ class ServiceStub {}
626
645
 
627
646
  const env = createStub("env");
628
- const caches = createStub("caches");
629
- const scheduler = createStub("scheduler");
630
- const executionCtx = createStub("executionCtx");
631
-
632
- export { DurableObject, RpcStub, RpcTarget, WorkerEntrypoint, caches, env, executionCtx, scheduler };
647
+ const exportsStub = createStub("exports");
648
+ const cache = createStub("cache");
649
+ const tracing = createStub("tracing");
650
+ const withEnv = createStub("withEnv");
651
+ const withExports = createStub("withExports");
652
+ const withEnvAndExports = createStub("withEnvAndExports");
653
+ const waitUntil = createStub("waitUntil");
654
+ const abortIsolate = createStub("abortIsolate");
633
655
 
634
- const defaultExport = {
656
+ export {
657
+ WorkerEntrypoint,
635
658
  DurableObject,
636
- RpcStub,
659
+ WorkflowEntrypoint,
637
660
  RpcTarget,
638
- WorkerEntrypoint,
639
- caches,
661
+ RpcStub,
662
+ RpcPromise,
663
+ RpcProperty,
664
+ ServiceStub,
640
665
  env,
641
- executionCtx,
642
- scheduler,
666
+ exportsStub as exports,
667
+ cache,
668
+ tracing,
669
+ withEnv,
670
+ withExports,
671
+ withEnvAndExports,
672
+ waitUntil,
673
+ abortIsolate,
643
674
  };
644
-
645
- export default defaultExport;
646
675
  // jiti dirty hack: .unknown
647
676
  `)}`;
648
677
  };
649
678
  const CLOUDFLARE_STUB_MODULE = createModule();
650
- function addCloudflareModules(aliases, _cwd) {
679
+ function addCloudflareVirtualModules(aliases) {
651
680
  if (!aliases["cloudflare:workers"]) aliases["cloudflare:workers"] = CLOUDFLARE_STUB_MODULE;
652
- if (!aliases["cloudflare:test"]) aliases["cloudflare:test"] = CLOUDFLARE_STUB_MODULE;
653
681
  }
654
682
  //#endregion
655
- //#region src/utils/add-svelte-kit-env-modules.ts
683
+ //#region src/utils/sveltekit-virtual-modules.ts
656
684
  /**
657
- * Adds SvelteKit environment modules and path aliases
658
- * @param aliases - The aliases object to populate
659
- * @param cwd - Current working directory (optional, defaults to process.cwd())
685
+ * SvelteKit exposes virtual runtime modules (`$env/*`, `$app/*`,
686
+ * `$service-worker`) that exist only while its Vite plugin runs. The CLI loads
687
+ * `auth.ts` with jiti, outside Vite, so a config importing them would crash the
688
+ * loader. Each is aliased to an inert stub.
689
+ *
690
+ * The stubs are injected unconditionally — a non-SvelteKit config never imports
691
+ * them, so the unused aliases are harmless, and it keeps this free of project
692
+ * detection. Real path aliases (`$lib` and any `kit.alias`) are deliberately
693
+ * NOT handled here: `svelte-kit sync` writes them into `.svelte-kit/tsconfig.json`,
694
+ * which the tsconfig `paths` matcher in `get-config.ts` resolves.
695
+ *
696
+ * Why the export surface is enumerated by hand: these are *named* exports, and
697
+ * ESM requires every imported name to exist at link time, so an opaque or
698
+ * wildcard stub is impossible. (Vite asset imports are default-export and so
699
+ * can be matched by rule in `vite-virtual-modules.ts`; a static analyzer can
700
+ * ignore these opaquely because it never runs the module — we do, so we have to
701
+ * provide runnable exports.) The shapes mirror SvelteKit's public, documented
702
+ * surface, which is the stable contract; the internal `__sveltekit/*` virtual
703
+ * modules the real files depend on are not, which is why we stub `$app/*`
704
+ * directly rather than resolving SvelteKit's on-disk files.
705
+ *
706
+ * The authoritative export surfaces this mirrors:
707
+ *
708
+ * @see https://github.com/sveltejs/kit/tree/main/packages/kit/src/runtime/app
709
+ * @see https://github.com/sveltejs/kit/blob/main/packages/kit/src/types/ambient.d.ts
660
710
  */
661
- function addSvelteKitEnvModules(aliases, cwd) {
662
- const workingDir = cwd || process.cwd();
663
- aliases["$env/dynamic/private"] = createDataUriModule(createDynamicEnvModule());
664
- aliases["$env/dynamic/public"] = createDataUriModule(createDynamicEnvModule());
665
- aliases["$env/static/private"] = createDataUriModule(createStaticEnvModule(filterPrivateEnv("PUBLIC_", "")));
666
- aliases["$env/static/public"] = createDataUriModule(createStaticEnvModule(filterPublicEnv("PUBLIC_", "")));
667
- const svelteKitAliases = getSvelteKitPathAliases(workingDir);
668
- Object.assign(aliases, svelteKitAliases);
669
- }
670
- function getSvelteKitPathAliases(cwd) {
671
- const aliases = {};
672
- const packageJsonPath = path.join(cwd, "package.json");
673
- const svelteConfigPath = path.join(cwd, "svelte.config.js");
674
- const svelteConfigTsPath = path.join(cwd, "svelte.config.ts");
675
- let isSvelteKitProject = false;
676
- if (fs.existsSync(packageJsonPath)) try {
677
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
678
- isSvelteKitProject = !!{
679
- ...packageJson.dependencies,
680
- ...packageJson.devDependencies
681
- }["@sveltejs/kit"];
682
- } catch {}
683
- if (!isSvelteKitProject) isSvelteKitProject = fs.existsSync(svelteConfigPath) || fs.existsSync(svelteConfigTsPath);
684
- if (!isSvelteKitProject) return aliases;
685
- const libPaths = [path.join(cwd, "src", "lib"), path.join(cwd, "lib")];
686
- for (const libPath of libPaths) if (fs.existsSync(libPath)) {
687
- aliases["$lib"] = libPath;
688
- for (const subPath of [
689
- "server",
690
- "utils",
691
- "components",
692
- "stores"
693
- ]) {
694
- const subDir = path.join(libPath, subPath);
695
- if (fs.existsSync(subDir)) aliases[`$lib/${subPath}`] = subDir;
696
- }
697
- break;
698
- }
699
- aliases["$app/server"] = createDataUriModule(createAppServerModule());
700
- const customAliases = getSvelteConfigAliases(cwd);
701
- Object.assign(aliases, customAliases);
702
- return aliases;
703
- }
704
- function getSvelteConfigAliases(cwd) {
705
- const aliases = {};
706
- const configPaths = [path.join(cwd, "svelte.config.js"), path.join(cwd, "svelte.config.ts")];
707
- for (const configPath of configPaths) if (fs.existsSync(configPath)) {
708
- try {
709
- const aliasMatch = fs.readFileSync(configPath, "utf-8").match(/alias\s*:\s*\{([^}]+)\}/);
710
- if (aliasMatch && aliasMatch[1]) {
711
- const aliasMatches = aliasMatch[1].matchAll(/['"`](\$[^'"`]+)['"`]\s*:\s*['"`]([^'"`]+)['"`]/g);
712
- for (const match of aliasMatches) {
713
- const [, alias, target] = match;
714
- if (alias && target) {
715
- aliases[alias + "/*"] = path.resolve(cwd, target) + "/*";
716
- aliases[alias] = path.resolve(cwd, target);
717
- }
718
- }
719
- }
720
- } catch {}
721
- break;
722
- }
723
- return aliases;
711
+ function addSvelteKitVirtualModules(aliases) {
712
+ aliases["$env/dynamic/private"] = createStubModule(createDynamicEnvModule("private"));
713
+ aliases["$env/dynamic/public"] = createStubModule(createDynamicEnvModule("public"));
714
+ aliases["$env/static/private"] = createStubModule(createStaticEnvModule(filterPrivateEnv("PUBLIC_", "")));
715
+ aliases["$env/static/public"] = createStubModule(createStaticEnvModule(filterPublicEnv("PUBLIC_", "")));
716
+ for (const [id, body] of Object.entries(appModuleStubs)) aliases[id] = createStubModule(body);
724
717
  }
725
- function createAppServerModule() {
726
- return `
727
- // $app/server stub for CLI compatibility
728
- export default {};
729
- // jiti dirty hack: .unknown
718
+ /**
719
+ * `$app/env` is SvelteKit's alias for `$app/environment` with an identical
720
+ * export surface, so both specifiers share this body.
721
+ * @see https://github.com/sveltejs/kit/pull/15934
722
+ */
723
+ const environmentStub = `
724
+ export const browser = false;
725
+ export const building = false;
726
+ export const dev = false;
727
+ export const version = "";
730
728
  `;
731
- }
732
- function createDataUriModule(module) {
733
- return `data:text/javascript;charset=utf-8,${encodeURIComponent(module)}`;
729
+ /**
730
+ * Specifier → module source for the inert `$app/*` and `$service-worker`
731
+ * stubs. The bodies do nothing (the CLI never serves a request); they exist
732
+ * only so every name a config might import resolves. Keep each entry aligned
733
+ * with SvelteKit's documented exports.
734
+ * @see https://svelte.dev/docs/kit/$app-environment
735
+ * @see https://svelte.dev/docs/kit/$app-server
736
+ * @see https://svelte.dev/docs/kit/$service-worker
737
+ */
738
+ const appModuleStubs = {
739
+ "$app/environment": environmentStub,
740
+ "$app/env": environmentStub,
741
+ "$app/server": `
742
+ export function getRequestEvent() {}
743
+ export function read() {}
744
+ export function query() {}
745
+ export function prerender() {}
746
+ export function command() {}
747
+ export function form() {}
748
+ export const requested = false;
749
+ `,
750
+ "$app/paths": `
751
+ export const base = "";
752
+ export const assets = "";
753
+ export function resolve(path) { return path; }
754
+ export function resolveRoute(path) { return path; }
755
+ export function asset(value) { return value; }
756
+ export async function match() { return null; }
757
+ `,
758
+ "$app/navigation": `
759
+ export function goto() {}
760
+ export function invalidate() {}
761
+ export function invalidateAll() {}
762
+ export function preloadData() {}
763
+ export function preloadCode() {}
764
+ export function beforeNavigate() {}
765
+ export function afterNavigate() {}
766
+ export function onNavigate() {}
767
+ export function disableScrollHandling() {}
768
+ export function pushState() {}
769
+ export function replaceState() {}
770
+ export function refreshAll() {}
771
+ `,
772
+ "$app/state": `
773
+ export const page = {};
774
+ export const navigating = {};
775
+ export const updated = { check() { return Promise.resolve(false); } };
776
+ `,
777
+ "$app/stores": `
778
+ export const page = { subscribe() { return () => {}; } };
779
+ export const navigating = { subscribe() { return () => {}; } };
780
+ export const updated = { subscribe() { return () => {}; }, check() { return Promise.resolve(false); } };
781
+ export function getStores() { return { page, navigating, updated }; }
782
+ `,
783
+ "$app/forms": `
784
+ export function applyAction() {}
785
+ export function deserialize() {}
786
+ export function enhance() {}
787
+ `,
788
+ "$service-worker": `
789
+ export const base = "";
790
+ export const build = [];
791
+ export const files = [];
792
+ export const prerendered = [];
793
+ export const version = "";
794
+ `
795
+ };
796
+ /**
797
+ * Wraps a module body as a `data:` URI for use as a jiti alias target. The
798
+ * trailing marker is load-bearing: without an "extension", jiti resolves the
799
+ * alias value as a file path and fails with ENOENT, so the comment gives it an
800
+ * unknown extension and forces a native import instead. (Stubs injected by the
801
+ * Babel plugin in `vite-virtual-modules.ts` set the specifier directly and do
802
+ * not go through alias resolution, so they need no marker.)
803
+ */
804
+ function createStubModule(body) {
805
+ const source = `${body}\n// jiti dirty hack: .unknown\n`;
806
+ return `data:text/javascript;charset=utf-8,${encodeURIComponent(source)}`;
734
807
  }
735
808
  function createStaticEnvModule(env) {
736
- return `
737
- ${Object.keys(env).filter((k) => validIdentifier.test(k) && !reserved.has(k)).map((k) => `export const ${k} = ${JSON.stringify(env[k])};`).join("\n")}
738
- // jiti dirty hack: .unknown
739
- `;
809
+ return Object.keys(env).filter((k) => validIdentifier.test(k) && !reserved.has(k)).map((k) => `export const ${k} = ${JSON.stringify(env[k])};`).join("\n");
740
810
  }
741
- function createDynamicEnvModule() {
811
+ function createDynamicEnvModule(visibility) {
742
812
  return `
743
- export const env = process.env;
744
- // jiti dirty hack: .unknown
745
- `;
813
+ const keep = (key) => typeof key === "string" && ${visibility === "public" ? `key.startsWith("PUBLIC_")` : `!key.startsWith("PUBLIC_")`};
814
+ export const env = new Proxy(
815
+ {},
816
+ {
817
+ get: (_, key) => (keep(key) ? process.env[key] : undefined),
818
+ has: (_, key) => keep(key) && key in process.env,
819
+ ownKeys: () => Object.keys(process.env).filter(keep),
820
+ getOwnPropertyDescriptor: (_, key) =>
821
+ keep(key) && key in process.env
822
+ ? { value: process.env[key], enumerable: true, configurable: true }
823
+ : undefined,
824
+ },
825
+ );`;
746
826
  }
747
827
  function filterPrivateEnv(publicPrefix, privatePrefix) {
748
828
  return Object.fromEntries(Object.entries(process.env).filter(([k]) => k.startsWith(privatePrefix) && (publicPrefix === "" || !k.startsWith(publicPrefix))));
@@ -802,6 +882,50 @@ const reserved = new Set([
802
882
  "instanceof"
803
883
  ]);
804
884
  //#endregion
885
+ //#region src/utils/vite-virtual-modules.ts
886
+ /**
887
+ * Stub modules for Vite's "special" imports (asset and query-suffixed
888
+ * modules). Vite resolves these through its plugin pipeline at build time; the
889
+ * CLI loads auth configs with jiti, where no such pipeline exists and there is
890
+ * no file on disk to read. Without a substitute, a config that transitively
891
+ * imports e.g. `./logo.svg`, `./app.css?inline`, or `./worker.ts?worker`
892
+ * crashes the loader.
893
+ *
894
+ * Detection mirrors Vite's own classification. The query-suffix patterns are
895
+ * tested against the full specifier, the extension membership against the
896
+ * specifier with its query stripped, and query patterns take precedence over
897
+ * extension membership (so `./a.css?raw` is raw text, not a stylesheet). The
898
+ * regexes are not part of Vite's public API, so they are copied here.
899
+ *
900
+ * @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts
901
+ * @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/asset.ts
902
+ */
903
+ const WORKER_RE = /[?&](?:worker|sharedworker)(?:&|$)/;
904
+ const URL_RE = /[?&]url(?:&|$)/;
905
+ const RAW_RE = /[?&]raw(?:&|$)/;
906
+ const INLINE_RE = /[?&]inline(?:&|$)/;
907
+ const WASM_INIT_RE = /\.wasm\?init\b/;
908
+ const CSS_MODULE_RE = /\.module\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
909
+ const CSS_LANGS_RE = /\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
910
+ const KNOWN_ASSET_RE = /\.(?:apng|bmp|png|jpe?g|jfif|pjpeg|pjp|gif|svg|ico|webp|avif|cur|jxl|mp4|webm|ogg|mp3|wav|flac|aac|opus|mov|m4a|vtt|woff2?|eot|ttf|otf|webmanifest|pdf|txt)(?:\?.*)?$/i;
911
+ function createDataUriModule(body) {
912
+ return `data:text/javascript;charset=utf-8,${encodeURIComponent(body)}`;
913
+ }
914
+ /**
915
+ * Returns a data-URI stub module for a Vite special import, or `undefined`
916
+ * when the specifier is an ordinary module that should resolve normally. The
917
+ * stub's runtime shape matches what Vite would emit (a string for raw/url, a
918
+ * worker constructor, a class-name proxy for CSS Modules, and so on).
919
+ */
920
+ function getViteAssetStub(specifier) {
921
+ if (WORKER_RE.test(specifier)) return createDataUriModule(URL_RE.test(specifier) ? `export default "";` : `export default function () {};`);
922
+ if (WASM_INIT_RE.test(specifier)) return createDataUriModule(`export default async () => ({ exports: {} });`);
923
+ if (RAW_RE.test(specifier) || INLINE_RE.test(specifier) || URL_RE.test(specifier)) return createDataUriModule(`export default "";`);
924
+ if (CSS_MODULE_RE.test(specifier)) return createDataUriModule(`export default new Proxy({}, { get: (_, key) => String(key) });`);
925
+ if (CSS_LANGS_RE.test(specifier)) return createDataUriModule(`export default undefined;`);
926
+ if (KNOWN_ASSET_RE.test(specifier)) return createDataUriModule(`export default "";`);
927
+ }
928
+ //#endregion
805
929
  //#region src/utils/get-config.ts
806
930
  let possiblePaths$1 = [
807
931
  "auth.ts",
@@ -943,6 +1067,11 @@ function createRewriteImportPathsPlugin(matchers) {
943
1067
  return ({ types: t }) => {
944
1068
  const rewrite = (source) => {
945
1069
  if (!source) return;
1070
+ const stub = getViteAssetStub(source.value);
1071
+ if (stub) {
1072
+ source.value = stub;
1073
+ return;
1074
+ }
946
1075
  const resolved = resolveWithMatchers(source.value, matchers);
947
1076
  if (resolved) source.value = resolved;
948
1077
  };
@@ -972,16 +1101,15 @@ function createRewriteImportPathsPlugin(matchers) {
972
1101
  /** Virtual module aliases; real tsconfig paths go through the babel plugin. */
973
1102
  function getVirtualModuleAliases() {
974
1103
  const result = {};
975
- addSvelteKitEnvModules(result);
976
- addCloudflareModules(result);
1104
+ addSvelteKitVirtualModules(result);
1105
+ addCloudflareVirtualModules(result);
977
1106
  return result;
978
1107
  }
979
1108
  /**
980
1109
  * .tsx files are not supported by Jiti.
981
1110
  */
982
1111
  const jitiOptions = (cwd) => {
983
- const matchers = collectPathsMatchers(cwd);
984
- const plugins = matchers.length > 0 ? [createRewriteImportPathsPlugin(matchers)] : [];
1112
+ const plugins = [createRewriteImportPathsPlugin(collectPathsMatchers(cwd))];
985
1113
  return {
986
1114
  transformOptions: { babel: {
987
1115
  presets: [[babelPresetTypeScript, {
@@ -1282,6 +1410,10 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
1282
1410
  if (attr.type === "date" && attr.defaultValue.toString().includes("new Date()")) if (databaseType === "sqlite") type += `.default(sql\`(cast(unixepoch('subsecond') * 1000 as integer))\`)`;
1283
1411
  else type += `.defaultNow()`;
1284
1412
  } else if (typeof attr.defaultValue === "string") type += `.default("${attr.defaultValue}")`;
1413
+ else if (Array.isArray(attr.defaultValue)) {
1414
+ const elements = attr.defaultValue.map((value) => JSON.stringify(value)).join(", ");
1415
+ type += `.default([${elements}])`;
1416
+ } else if (typeof attr.defaultValue === "object" && attr.defaultValue !== null) type += `.default(${JSON.stringify(attr.defaultValue)})`;
1285
1417
  else type += `.default(${attr.defaultValue})`;
1286
1418
  if (attr.onUpdate && attr.type === "date") {
1287
1419
  if (typeof attr.onUpdate === "function") type += `.$onUpdate(${attr.onUpdate})`;
@@ -1638,6 +1770,16 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
1638
1770
  return "Int[]";
1639
1771
  }
1640
1772
  }
1773
+ function getFieldTypeParts(type) {
1774
+ const isArray = type.endsWith("[]");
1775
+ const typeWithoutArray = isArray ? type.slice(0, -2) : type;
1776
+ const isOptional = typeWithoutArray.endsWith("?");
1777
+ return {
1778
+ fieldType: isOptional ? typeWithoutArray.slice(0, -1) : typeWithoutArray,
1779
+ isArray,
1780
+ isOptional
1781
+ };
1782
+ }
1641
1783
  const prismaModel = builder.findByType("model", { name: modelName });
1642
1784
  if (!prismaModel) if (provider === "mongodb") builder.model(modelName).field("id", "String").attribute("id").attribute(`map("_id")`);
1643
1785
  else {
@@ -1650,15 +1792,9 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
1650
1792
  for (const field in fields) {
1651
1793
  const attr = fields[field];
1652
1794
  const fieldName = attr.fieldName || field;
1653
- if (prismaModel) {
1654
- if (builder.findByType("field", {
1655
- name: fieldName,
1656
- within: prismaModel.properties
1657
- })) continue;
1658
- }
1659
1795
  const useUUIDs = options.advanced?.database?.generateId === "uuid";
1660
1796
  const useNumberId = options.advanced?.database?.generateId === "serial";
1661
- const fieldBuilder = builder.model(modelName).field(fieldName, field === "id" && useNumberId ? getType({
1797
+ const fieldType = field === "id" && useNumberId ? getType({
1662
1798
  isBigint: false,
1663
1799
  isOptional: false,
1664
1800
  type: "number"
@@ -1666,12 +1802,33 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
1666
1802
  isBigint: attr?.bigint || false,
1667
1803
  isOptional: attr?.required === false,
1668
1804
  type: attr.references?.field === "id" ? useNumberId ? "number" : "string" : attr.type
1669
- }));
1805
+ });
1806
+ if (prismaModel) {
1807
+ const isAlreadyExist = builder.findByType("field", {
1808
+ name: fieldName,
1809
+ within: prismaModel.properties
1810
+ });
1811
+ if (isAlreadyExist) {
1812
+ if (fieldType && typeof isAlreadyExist.fieldType === "string") {
1813
+ const fieldTypeParts = getFieldTypeParts(fieldType);
1814
+ const existingFieldTypeParts = getFieldTypeParts(isAlreadyExist.fieldType);
1815
+ if ((existingFieldTypeParts.fieldType === "Int" || existingFieldTypeParts.fieldType === "BigInt") && (fieldTypeParts.fieldType === "Int" || fieldTypeParts.fieldType === "BigInt")) {
1816
+ isAlreadyExist.fieldType = fieldTypeParts.fieldType;
1817
+ isAlreadyExist.optional = fieldTypeParts.isOptional || void 0;
1818
+ isAlreadyExist.array = fieldTypeParts.isArray || void 0;
1819
+ }
1820
+ }
1821
+ continue;
1822
+ }
1823
+ }
1824
+ if (!fieldType) throw new Error(`Unsupported Prisma field type for model "${modelName}", field "${fieldName}"${attr.type ? ` (source type: "${attr.type}")` : ""}.`);
1825
+ const fieldBuilder = builder.model(modelName).field(fieldName, fieldType);
1670
1826
  if (field === "id") {
1671
1827
  fieldBuilder.attribute("id");
1672
1828
  if (provider === "mongodb") fieldBuilder.attribute(`map("_id")`);
1673
1829
  }
1674
1830
  if (attr.unique) builder.model(modelName).blockAttribute(`unique([${fieldName}])`);
1831
+ if ((attr.type === "string[]" || attr.type === "number[]") && provider !== "sqlite" && provider !== "mysql" && attr.defaultValue === void 0) fieldBuilder.attribute("default([])");
1675
1832
  if (attr.defaultValue !== void 0) {
1676
1833
  if (Array.isArray(attr.defaultValue)) {
1677
1834
  if (attr.type === "json") {
@@ -1848,6 +2005,9 @@ function createMockAdapter$1(adapterId, dialect) {
1848
2005
  consumeOne: async () => {
1849
2006
  throw new Error("Mock adapter methods should not be called");
1850
2007
  },
2008
+ incrementOne: async () => {
2009
+ throw new Error("Mock adapter methods should not be called");
2010
+ },
1851
2011
  transaction: async (callback) => {
1852
2012
  throw new Error("Mock adapter methods should not be called");
1853
2013
  },
@@ -1857,6 +2017,19 @@ function createMockAdapter$1(adapterId, dialect) {
1857
2017
  }
1858
2018
  };
1859
2019
  }
2020
+ function getDefaultSchemaOutputFileName(adapterId, now = /* @__PURE__ */ new Date()) {
2021
+ if (adapterId === "prisma") return "schema.prisma";
2022
+ if (adapterId === "kysely") return `${now.toISOString().replace(/:/g, "-")}.sql`;
2023
+ return "auth-schema.ts";
2024
+ }
2025
+ async function resolveSchemaOutputPath({ cwd, output, adapterId, now = /* @__PURE__ */ new Date() }) {
2026
+ if (!output) return output;
2027
+ const resolvedOutput = path.resolve(cwd, output);
2028
+ try {
2029
+ if ((await fs$1.stat(resolvedOutput)).isDirectory()) return path.join(output, getDefaultSchemaOutputFileName(adapterId, now));
2030
+ } catch {}
2031
+ return output;
2032
+ }
1860
2033
  async function generateAction(opts) {
1861
2034
  const options = z.object({
1862
2035
  cwd: z.string(),
@@ -1886,6 +2059,11 @@ async function generateAction(opts) {
1886
2059
  console.error(e.message);
1887
2060
  process.exit(1);
1888
2061
  });
2062
+ options.output = await resolveSchemaOutputPath({
2063
+ cwd,
2064
+ output: options.output,
2065
+ adapterId: adapter.id
2066
+ });
1889
2067
  const spinner = yoctoSpinner({ text: "preparing schema..." }).start();
1890
2068
  const schema = await generateSchema({
1891
2069
  adapter,
@@ -2109,6 +2287,8 @@ function sanitizeBetterAuthConfig(config) {
2109
2287
  const sanitized = JSON.parse(JSON.stringify(config));
2110
2288
  const sensitiveKeys = [
2111
2289
  "secret",
2290
+ "secrets",
2291
+ "secretKey",
2112
2292
  "clientSecret",
2113
2293
  "clientId",
2114
2294
  "authToken",
@@ -2162,6 +2342,7 @@ function sanitizeBetterAuthConfig(config) {
2162
2342
  const lowerSensitiveKey = sensitiveKey.toLowerCase();
2163
2343
  return lowerKey === lowerSensitiveKey || lowerKey.endsWith(lowerSensitiveKey);
2164
2344
  })) if (typeof value === "string" && value.length > 0) result[key] = "[REDACTED]";
2345
+ else if (Array.isArray(value)) result[key] = "[REDACTED]";
2165
2346
  else if (typeof value === "object" && value !== null) result[key] = redactSensitive(value, key);
2166
2347
  else result[key] = value;
2167
2348
  else result[key] = redactSensitive(value, key);
@@ -3689,25 +3870,6 @@ const tempPluginsConfig = {
3689
3870
  }]
3690
3871
  }
3691
3872
  },
3692
- oidc: {
3693
- displayName: "OIDC",
3694
- auth: {
3695
- function: "oidc",
3696
- imports: [{
3697
- path: "better-auth/plugins",
3698
- imports: [createImport({ name: "oidc" })],
3699
- isNamedImport: false
3700
- }]
3701
- },
3702
- authClient: {
3703
- function: "oidcClient",
3704
- imports: [{
3705
- path: "better-auth/client/plugins",
3706
- imports: [createImport({ name: "oidcClient" })],
3707
- isNamedImport: false
3708
- }]
3709
- }
3710
- },
3711
3873
  admin: {
3712
3874
  displayName: "Admin",
3713
3875
  auth: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth",
3
- "version": "1.7.0-beta.4",
3
+ "version": "1.7.0-beta.6",
4
4
  "description": "The CLI for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  "@babel/core": "^7.29.0",
47
47
  "@babel/preset-react": "^7.28.5",
48
48
  "@babel/preset-typescript": "^7.28.5",
49
- "@better-auth/utils": "0.4.1",
49
+ "@better-auth/utils": "0.4.2",
50
50
  "@clack/prompts": "^0.11.0",
51
51
  "@mrleebo/prisma-ast": "^0.13.1",
52
52
  "c12": "^4.0.0-beta.5",
@@ -61,9 +61,9 @@
61
61
  "semver": "^7.7.4",
62
62
  "yocto-spinner": "^0.2.3",
63
63
  "zod": "^4.3.6",
64
- "@better-auth/core": "1.7.0-beta.4",
65
- "@better-auth/telemetry": "1.7.0-beta.4",
66
- "better-auth": "1.7.0-beta.4"
64
+ "@better-auth/core": "1.7.0-beta.6",
65
+ "@better-auth/telemetry": "1.7.0-beta.6",
66
+ "better-auth": "1.7.0-beta.6"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@types/better-sqlite3": "^7.6.13",
@@ -75,7 +75,7 @@
75
75
  "tsx": "^4.21.0",
76
76
  "type-fest": "^5.4.4",
77
77
  "typescript": "^5.9.3",
78
- "@better-auth/passkey": "1.7.0-beta.4"
78
+ "@better-auth/passkey": "1.7.0-beta.6"
79
79
  },
80
80
  "scripts": {
81
81
  "build": "tsdown",