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.
- package/dist/api.mjs +37 -8
- package/dist/index.mjs +305 -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,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/
|
|
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,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.
|
|
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",
|