auth 1.7.0-beta.5 → 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.
- package/dist/api.mjs +36 -8
- package/dist/index.mjs +301 -143
- 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
|
|
435
|
+
const fieldType = field === "id" && useNumberId ? getType({
|
|
428
436
|
isBigint: false,
|
|
429
437
|
isOptional: false,
|
|
430
438
|
type: "number"
|
|
@@ -432,7 +440,27 @@ 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")`);
|
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/
|
|
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(
|
|
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
|
-
|
|
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(
|
|
614
|
-
this.
|
|
629
|
+
constructor(ctx, env) {
|
|
630
|
+
this.ctx = ctx;
|
|
615
631
|
this.env = env;
|
|
616
632
|
}
|
|
617
633
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
this.
|
|
634
|
+
class WorkflowEntrypoint {
|
|
635
|
+
constructor(ctx, env) {
|
|
636
|
+
this.ctx = ctx;
|
|
637
|
+
this.env = env;
|
|
622
638
|
}
|
|
623
639
|
}
|
|
624
|
-
|
|
625
|
-
|
|
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
|
|
629
|
-
const
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
|
|
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
|
-
|
|
656
|
+
export {
|
|
657
|
+
WorkerEntrypoint,
|
|
635
658
|
DurableObject,
|
|
636
|
-
|
|
659
|
+
WorkflowEntrypoint,
|
|
637
660
|
RpcTarget,
|
|
638
|
-
|
|
639
|
-
|
|
661
|
+
RpcStub,
|
|
662
|
+
RpcPromise,
|
|
663
|
+
RpcProperty,
|
|
664
|
+
ServiceStub,
|
|
640
665
|
env,
|
|
641
|
-
|
|
642
|
-
|
|
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
|
|
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/
|
|
683
|
+
//#region src/utils/sveltekit-virtual-modules.ts
|
|
656
684
|
/**
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
*
|
|
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
|
|
662
|
-
|
|
663
|
-
aliases["$env/dynamic/
|
|
664
|
-
aliases["$env/
|
|
665
|
-
aliases["$env/static/
|
|
666
|
-
aliases[
|
|
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
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
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
|
-
|
|
733
|
-
|
|
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
|
-
|
|
744
|
-
|
|
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
|
-
|
|
976
|
-
|
|
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
|
|
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
|
|
1797
|
+
const fieldType = field === "id" && useNumberId ? getType({
|
|
1662
1798
|
isBigint: false,
|
|
1663
1799
|
isOptional: false,
|
|
1664
1800
|
type: "number"
|
|
@@ -1666,7 +1802,27 @@ 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")`);
|
|
@@ -1849,6 +2005,9 @@ function createMockAdapter$1(adapterId, dialect) {
|
|
|
1849
2005
|
consumeOne: async () => {
|
|
1850
2006
|
throw new Error("Mock adapter methods should not be called");
|
|
1851
2007
|
},
|
|
2008
|
+
incrementOne: async () => {
|
|
2009
|
+
throw new Error("Mock adapter methods should not be called");
|
|
2010
|
+
},
|
|
1852
2011
|
transaction: async (callback) => {
|
|
1853
2012
|
throw new Error("Mock adapter methods should not be called");
|
|
1854
2013
|
},
|
|
@@ -1858,6 +2017,19 @@ function createMockAdapter$1(adapterId, dialect) {
|
|
|
1858
2017
|
}
|
|
1859
2018
|
};
|
|
1860
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
|
+
}
|
|
1861
2033
|
async function generateAction(opts) {
|
|
1862
2034
|
const options = z.object({
|
|
1863
2035
|
cwd: z.string(),
|
|
@@ -1887,6 +2059,11 @@ async function generateAction(opts) {
|
|
|
1887
2059
|
console.error(e.message);
|
|
1888
2060
|
process.exit(1);
|
|
1889
2061
|
});
|
|
2062
|
+
options.output = await resolveSchemaOutputPath({
|
|
2063
|
+
cwd,
|
|
2064
|
+
output: options.output,
|
|
2065
|
+
adapterId: adapter.id
|
|
2066
|
+
});
|
|
1890
2067
|
const spinner = yoctoSpinner({ text: "preparing schema..." }).start();
|
|
1891
2068
|
const schema = await generateSchema({
|
|
1892
2069
|
adapter,
|
|
@@ -3693,25 +3870,6 @@ const tempPluginsConfig = {
|
|
|
3693
3870
|
}]
|
|
3694
3871
|
}
|
|
3695
3872
|
},
|
|
3696
|
-
oidc: {
|
|
3697
|
-
displayName: "OIDC",
|
|
3698
|
-
auth: {
|
|
3699
|
-
function: "oidc",
|
|
3700
|
-
imports: [{
|
|
3701
|
-
path: "better-auth/plugins",
|
|
3702
|
-
imports: [createImport({ name: "oidc" })],
|
|
3703
|
-
isNamedImport: false
|
|
3704
|
-
}]
|
|
3705
|
-
},
|
|
3706
|
-
authClient: {
|
|
3707
|
-
function: "oidcClient",
|
|
3708
|
-
imports: [{
|
|
3709
|
-
path: "better-auth/client/plugins",
|
|
3710
|
-
imports: [createImport({ name: "oidcClient" })],
|
|
3711
|
-
isNamedImport: false
|
|
3712
|
-
}]
|
|
3713
|
-
}
|
|
3714
|
-
},
|
|
3715
3873
|
admin: {
|
|
3716
3874
|
displayName: "Admin",
|
|
3717
3875
|
auth: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auth",
|
|
3
|
-
"version": "1.7.0-beta.
|
|
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.
|
|
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.
|
|
65
|
-
"@better-auth/telemetry": "1.7.0-beta.
|
|
66
|
-
"better-auth": "1.7.0-beta.
|
|
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.
|
|
78
|
+
"@better-auth/passkey": "1.7.0-beta.6"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"build": "tsdown",
|