@proofkit/better-auth 0.1.0
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/LICENSE.md +21 -0
- package/README.md +11 -0
- package/dist/esm/adapter.d.ts +13 -0
- package/dist/esm/adapter.js +178 -0
- package/dist/esm/adapter.js.map +1 -0
- package/dist/esm/better-auth-cli/utils/add-svelte-kit-env-modules.d.ts +3 -0
- package/dist/esm/better-auth-cli/utils/add-svelte-kit-env-modules.js +101 -0
- package/dist/esm/better-auth-cli/utils/add-svelte-kit-env-modules.js.map +1 -0
- package/dist/esm/better-auth-cli/utils/get-config.d.ts +8 -0
- package/dist/esm/better-auth-cli/utils/get-config.js +177 -0
- package/dist/esm/better-auth-cli/utils/get-config.js.map +1 -0
- package/dist/esm/better-auth-cli/utils/get-tsconfig-info.d.ts +2 -0
- package/dist/esm/better-auth-cli/utils/get-tsconfig-info.js +25 -0
- package/dist/esm/better-auth-cli/utils/get-tsconfig-info.js.map +1 -0
- package/dist/esm/cli/index.d.ts +2 -0
- package/dist/esm/cli/index.js +86 -0
- package/dist/esm/cli/index.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/migrate.d.ts +82 -0
- package/dist/esm/migrate.js +181 -0
- package/dist/esm/migrate.js.map +1 -0
- package/dist/esm/odata/index.d.ts +21 -0
- package/dist/esm/odata/index.js +27 -0
- package/dist/esm/odata/index.js.map +1 -0
- package/package.json +70 -0
- package/src/adapter.ts +221 -0
- package/src/better-auth-cli/README.md +1 -0
- package/src/better-auth-cli/utils/add-svelte-kit-env-modules.ts +108 -0
- package/src/better-auth-cli/utils/get-config.ts +220 -0
- package/src/better-auth-cli/utils/get-tsconfig-info.ts +26 -0
- package/src/cli/index.ts +116 -0
- package/src/index.ts +1 -0
- package/src/migrate.ts +236 -0
- package/src/odata/index.ts +45 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node --no-warnings
|
|
2
|
+
import { Command } from "@commander-js/extra-typings";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import { planMigration, prettyPrintMigrationPlan, executeMigration } from "../migrate.js";
|
|
5
|
+
import { getAdapter, getAuthTables } from "better-auth/db";
|
|
6
|
+
import { getConfig } from "../better-auth-cli/utils/get-config.js";
|
|
7
|
+
import { logger } from "better-auth";
|
|
8
|
+
import prompts from "prompts";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import { FmOdata } from "../odata/index.js";
|
|
11
|
+
async function main() {
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program.command("migrate", { isDefault: true }).option(
|
|
14
|
+
"--cwd <path>",
|
|
15
|
+
"Path to the current working directory",
|
|
16
|
+
process.cwd()
|
|
17
|
+
).option("--config <path>", "Path to the config file").option("-u, --username <username>", "Full Access Username").option("-p, --password <password>", "Full Access Password").option("-y, --yes", "Skip confirmation", false).action(async (options) => {
|
|
18
|
+
const cwd = options.cwd;
|
|
19
|
+
if (!fs.existsSync(cwd)) {
|
|
20
|
+
logger.error(`The directory "${cwd}" does not exist.`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const config = await getConfig({
|
|
24
|
+
cwd,
|
|
25
|
+
configPath: options.config
|
|
26
|
+
});
|
|
27
|
+
if (!config) {
|
|
28
|
+
logger.error(
|
|
29
|
+
"No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag."
|
|
30
|
+
);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const adapter = await getAdapter(config).catch((e) => {
|
|
34
|
+
logger.error(e.message);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
if (adapter.id !== "filemaker") {
|
|
38
|
+
logger.error(
|
|
39
|
+
"This generator is only compatible with the FileMaker adapter."
|
|
40
|
+
);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const betterAuthSchema = getAuthTables(config);
|
|
44
|
+
const adapterConfig = adapter.options.config;
|
|
45
|
+
const db = new FmOdata({
|
|
46
|
+
...adapterConfig.odata,
|
|
47
|
+
auth: (
|
|
48
|
+
// If the username and password are provided in the CLI, use them to authenticate instead of what's in the config file.
|
|
49
|
+
options.username && options.password ? {
|
|
50
|
+
username: options.username,
|
|
51
|
+
password: options.password
|
|
52
|
+
} : adapterConfig.odata.auth
|
|
53
|
+
)
|
|
54
|
+
}).database;
|
|
55
|
+
const migrationPlan = await planMigration(db, betterAuthSchema);
|
|
56
|
+
if (migrationPlan.length === 0) {
|
|
57
|
+
logger.info("No changes to apply. Database is up to date.");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!options.yes) {
|
|
61
|
+
prettyPrintMigrationPlan(migrationPlan);
|
|
62
|
+
if (migrationPlan.length > 0) {
|
|
63
|
+
console.log(
|
|
64
|
+
chalk.gray(
|
|
65
|
+
"💡 Tip: You can use the --yes flag to skip this confirmation."
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const { confirm } = await prompts({
|
|
70
|
+
type: "confirm",
|
|
71
|
+
name: "confirm",
|
|
72
|
+
message: "Apply the above changes to your database?"
|
|
73
|
+
});
|
|
74
|
+
if (!confirm) {
|
|
75
|
+
logger.error("Schema changes not applied.");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
await executeMigration(db, migrationPlan);
|
|
80
|
+
logger.info("Migration applied successfully.");
|
|
81
|
+
});
|
|
82
|
+
await program.parseAsync(process.argv);
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
main().catch(console.error);
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node --no-warnings\nimport { Command } from \"@commander-js/extra-typings\";\nimport fs from \"fs-extra\";\n\nimport {\n executeMigration,\n planMigration,\n prettyPrintMigrationPlan,\n} from \"../migrate\";\nimport { getAdapter, getAuthTables } from \"better-auth/db\";\nimport { getConfig } from \"../better-auth-cli/utils/get-config\";\nimport { logger } from \"better-auth\";\nimport { BasicAuth, Connection, Database } from \"fm-odata-client\";\nimport prompts from \"prompts\";\nimport chalk from \"chalk\";\nimport { AdapterOptions } from \"../adapter\";\nimport { FmOdata } from \"../odata\";\n\nasync function main() {\n const program = new Command();\n\n program\n .command(\"migrate\", { isDefault: true })\n .option(\n \"--cwd <path>\",\n \"Path to the current working directory\",\n process.cwd(),\n )\n .option(\"--config <path>\", \"Path to the config file\")\n .option(\"-u, --username <username>\", \"Full Access Username\")\n .option(\"-p, --password <password>\", \"Full Access Password\")\n .option(\"-y, --yes\", \"Skip confirmation\", false)\n\n .action(async (options) => {\n const cwd = options.cwd;\n if (!fs.existsSync(cwd)) {\n logger.error(`The directory \"${cwd}\" does not exist.`);\n process.exit(1);\n }\n\n const config = await getConfig({\n cwd,\n configPath: options.config,\n });\n if (!config) {\n logger.error(\n \"No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag.\",\n );\n return;\n }\n\n const adapter = await getAdapter(config).catch((e) => {\n logger.error(e.message);\n process.exit(1);\n });\n\n if (adapter.id !== \"filemaker\") {\n logger.error(\n \"This generator is only compatible with the FileMaker adapter.\",\n );\n return;\n }\n\n const betterAuthSchema = getAuthTables(config);\n\n const adapterConfig = (adapter.options as AdapterOptions).config;\n const db = new FmOdata({\n ...adapterConfig.odata,\n auth:\n // If the username and password are provided in the CLI, use them to authenticate instead of what's in the config file.\n options.username && options.password\n ? {\n username: options.username,\n password: options.password,\n }\n : adapterConfig.odata.auth,\n }).database;\n\n const migrationPlan = await planMigration(db, betterAuthSchema);\n\n if (migrationPlan.length === 0) {\n logger.info(\"No changes to apply. Database is up to date.\");\n return;\n }\n\n if (!options.yes) {\n prettyPrintMigrationPlan(migrationPlan);\n\n if (migrationPlan.length > 0) {\n console.log(\n chalk.gray(\n \"💡 Tip: You can use the --yes flag to skip this confirmation.\",\n ),\n );\n }\n\n const { confirm } = await prompts({\n type: \"confirm\",\n name: \"confirm\",\n message: \"Apply the above changes to your database?\",\n });\n if (!confirm) {\n logger.error(\"Schema changes not applied.\");\n return;\n }\n }\n\n await executeMigration(db, migrationPlan);\n\n logger.info(\"Migration applied successfully.\");\n });\n await program.parseAsync(process.argv);\n process.exit(0);\n}\n\nmain().catch(console.error);\n"],"names":[],"mappings":";;;;;;;;;;AAkBA,eAAe,OAAO;AACd,QAAA,UAAU,IAAI,QAAQ;AAE5B,UACG,QAAQ,WAAW,EAAE,WAAW,KAAM,CAAA,EACtC;AAAA,IACC;AAAA,IACA;AAAA,IACA,QAAQ,IAAI;AAAA,EAAA,EAEb,OAAO,mBAAmB,yBAAyB,EACnD,OAAO,6BAA6B,sBAAsB,EAC1D,OAAO,6BAA6B,sBAAsB,EAC1D,OAAO,aAAa,qBAAqB,KAAK,EAE9C,OAAO,OAAO,YAAY;AACzB,UAAM,MAAM,QAAQ;AACpB,QAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AAChB,aAAA,MAAM,kBAAkB,GAAG,mBAAmB;AACrD,cAAQ,KAAK,CAAC;AAAA,IAAA;AAGV,UAAA,SAAS,MAAM,UAAU;AAAA,MAC7B;AAAA,MACA,YAAY,QAAQ;AAAA,IAAA,CACrB;AACD,QAAI,CAAC,QAAQ;AACJ,aAAA;AAAA,QACL;AAAA,MACF;AACA;AAAA,IAAA;AAGF,UAAM,UAAU,MAAM,WAAW,MAAM,EAAE,MAAM,CAAC,MAAM;AAC7C,aAAA,MAAM,EAAE,OAAO;AACtB,cAAQ,KAAK,CAAC;AAAA,IAAA,CACf;AAEG,QAAA,QAAQ,OAAO,aAAa;AACvB,aAAA;AAAA,QACL;AAAA,MACF;AACA;AAAA,IAAA;AAGI,UAAA,mBAAmB,cAAc,MAAM;AAEvC,UAAA,gBAAiB,QAAQ,QAA2B;AACpD,UAAA,KAAK,IAAI,QAAQ;AAAA,MACrB,GAAG,cAAc;AAAA,MACjB;AAAA;AAAA,QAEE,QAAQ,YAAY,QAAQ,WACxB;AAAA,UACE,UAAU,QAAQ;AAAA,UAClB,UAAU,QAAQ;AAAA,QAAA,IAEpB,cAAc,MAAM;AAAA;AAAA,IAC3B,CAAA,EAAE;AAEH,UAAM,gBAAgB,MAAM,cAAc,IAAI,gBAAgB;AAE1D,QAAA,cAAc,WAAW,GAAG;AAC9B,aAAO,KAAK,8CAA8C;AAC1D;AAAA,IAAA;AAGE,QAAA,CAAC,QAAQ,KAAK;AAChB,+BAAyB,aAAa;AAElC,UAAA,cAAc,SAAS,GAAG;AACpB,gBAAA;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,UAAA;AAAA,QAEJ;AAAA,MAAA;AAGF,YAAM,EAAE,YAAY,MAAM,QAAQ;AAAA,QAChC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,MAAA,CACV;AACD,UAAI,CAAC,SAAS;AACZ,eAAO,MAAM,6BAA6B;AAC1C;AAAA,MAAA;AAAA,IACF;AAGI,UAAA,iBAAiB,IAAI,aAAa;AAExC,WAAO,KAAK,iCAAiC;AAAA,EAAA,CAC9C;AACG,QAAA,QAAQ,WAAW,QAAQ,IAAI;AACrC,UAAQ,KAAK,CAAC;AAChB;AAEA,OAAO,MAAM,QAAQ,KAAK;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FileMakerAdapter } from './adapter.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BetterAuthDbSchema } from 'better-auth/db';
|
|
2
|
+
import { Database } from 'fm-odata-client';
|
|
3
|
+
import { default as z } from 'zod/v4';
|
|
4
|
+
export declare function planMigration(db: Database, betterAuthSchema: BetterAuthDbSchema): Promise<MigrationPlan>;
|
|
5
|
+
export declare function executeMigration(db: Database, migrationPlan: MigrationPlan): Promise<void>;
|
|
6
|
+
export declare const migrationPlanSchema: z.ZodArray<z.ZodObject<{
|
|
7
|
+
tableName: z.ZodString;
|
|
8
|
+
operation: z.ZodEnum<{
|
|
9
|
+
create: "create";
|
|
10
|
+
update: "update";
|
|
11
|
+
}>;
|
|
12
|
+
fields: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13
|
+
name: z.ZodString;
|
|
14
|
+
nullable: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
16
|
+
unique: z.ZodOptional<z.ZodBoolean>;
|
|
17
|
+
global: z.ZodOptional<z.ZodBoolean>;
|
|
18
|
+
repetitions: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
type: z.ZodLiteral<"string">;
|
|
20
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
USER: "USER";
|
|
23
|
+
USERNAME: "USERNAME";
|
|
24
|
+
CURRENT_USER: "CURRENT_USER";
|
|
25
|
+
}>>;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
name: z.ZodString;
|
|
28
|
+
nullable: z.ZodOptional<z.ZodBoolean>;
|
|
29
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
unique: z.ZodOptional<z.ZodBoolean>;
|
|
31
|
+
global: z.ZodOptional<z.ZodBoolean>;
|
|
32
|
+
repetitions: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
type: z.ZodLiteral<"numeric">;
|
|
34
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
35
|
+
name: z.ZodString;
|
|
36
|
+
nullable: z.ZodOptional<z.ZodBoolean>;
|
|
37
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
38
|
+
unique: z.ZodOptional<z.ZodBoolean>;
|
|
39
|
+
global: z.ZodOptional<z.ZodBoolean>;
|
|
40
|
+
repetitions: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
type: z.ZodLiteral<"date">;
|
|
42
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
43
|
+
CURRENT_DATE: "CURRENT_DATE";
|
|
44
|
+
CURDATE: "CURDATE";
|
|
45
|
+
}>>;
|
|
46
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
47
|
+
name: z.ZodString;
|
|
48
|
+
nullable: z.ZodOptional<z.ZodBoolean>;
|
|
49
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
50
|
+
unique: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
+
global: z.ZodOptional<z.ZodBoolean>;
|
|
52
|
+
repetitions: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
type: z.ZodLiteral<"time">;
|
|
54
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
55
|
+
CURRENT_TIME: "CURRENT_TIME";
|
|
56
|
+
CURTIME: "CURTIME";
|
|
57
|
+
}>>;
|
|
58
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
59
|
+
name: z.ZodString;
|
|
60
|
+
nullable: z.ZodOptional<z.ZodBoolean>;
|
|
61
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
62
|
+
unique: z.ZodOptional<z.ZodBoolean>;
|
|
63
|
+
global: z.ZodOptional<z.ZodBoolean>;
|
|
64
|
+
repetitions: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
type: z.ZodLiteral<"timestamp">;
|
|
66
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
67
|
+
CURRENT_TIMESTAMP: "CURRENT_TIMESTAMP";
|
|
68
|
+
CURTIMESTAMP: "CURTIMESTAMP";
|
|
69
|
+
}>>;
|
|
70
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
71
|
+
name: z.ZodString;
|
|
72
|
+
nullable: z.ZodOptional<z.ZodBoolean>;
|
|
73
|
+
primary: z.ZodOptional<z.ZodBoolean>;
|
|
74
|
+
unique: z.ZodOptional<z.ZodBoolean>;
|
|
75
|
+
global: z.ZodOptional<z.ZodBoolean>;
|
|
76
|
+
repetitions: z.ZodOptional<z.ZodNumber>;
|
|
77
|
+
type: z.ZodLiteral<"container">;
|
|
78
|
+
externalSecurePath: z.ZodOptional<z.ZodString>;
|
|
79
|
+
}, z.core.$strip>]>>;
|
|
80
|
+
}, z.core.$strip>>;
|
|
81
|
+
export type MigrationPlan = z.infer<typeof migrationPlanSchema>;
|
|
82
|
+
export declare function prettyPrintMigrationPlan(migrationPlan: MigrationPlan): void;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import z from "zod/v4";
|
|
3
|
+
async function planMigration(db, betterAuthSchema) {
|
|
4
|
+
const metadata = await db.getMetadata().catch((error) => {
|
|
5
|
+
console.error("Failed to get metadata from database", error);
|
|
6
|
+
return null;
|
|
7
|
+
});
|
|
8
|
+
let entitySetToType = {};
|
|
9
|
+
if (metadata) {
|
|
10
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
11
|
+
if (value.$Kind === "EntitySet" && value.$Type) {
|
|
12
|
+
const typeKey = value.$Type.split(".").pop();
|
|
13
|
+
entitySetToType[key] = typeKey || key;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const existingTables = metadata ? Object.entries(entitySetToType).reduce(
|
|
18
|
+
(acc, [entitySetName, entityTypeKey]) => {
|
|
19
|
+
const entityType = metadata[entityTypeKey];
|
|
20
|
+
if (!entityType) return acc;
|
|
21
|
+
const fields = Object.entries(entityType).filter(
|
|
22
|
+
([fieldKey, fieldValue]) => typeof fieldValue === "object" && fieldValue !== null && "$Type" in fieldValue
|
|
23
|
+
).map(([fieldKey, fieldValue]) => ({
|
|
24
|
+
name: fieldKey,
|
|
25
|
+
type: fieldValue.$Type === "Edm.String" ? "string" : fieldValue.$Type === "Edm.DateTimeOffset" ? "timestamp" : fieldValue.$Type === "Edm.Decimal" || fieldValue.$Type === "Edm.Int32" || fieldValue.$Type === "Edm.Int64" ? "numeric" : "string"
|
|
26
|
+
}));
|
|
27
|
+
acc[entitySetName] = fields;
|
|
28
|
+
return acc;
|
|
29
|
+
},
|
|
30
|
+
{}
|
|
31
|
+
) : {};
|
|
32
|
+
const baTables = Object.entries(betterAuthSchema).sort((a, b) => (a[1].order ?? 0) - (b[1].order ?? 0)).map(([key, value]) => ({
|
|
33
|
+
...value,
|
|
34
|
+
keyName: key
|
|
35
|
+
}));
|
|
36
|
+
const migrationPlan = [];
|
|
37
|
+
for (const baTable of baTables) {
|
|
38
|
+
const fields = Object.entries(baTable.fields).map(
|
|
39
|
+
([key, field]) => ({
|
|
40
|
+
name: field.fieldName ?? key,
|
|
41
|
+
type: field.type === "boolean" || field.type.includes("number") ? "numeric" : field.type === "date" ? "timestamp" : "string"
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
const tableExists = Object.prototype.hasOwnProperty.call(
|
|
45
|
+
existingTables,
|
|
46
|
+
baTable.modelName
|
|
47
|
+
);
|
|
48
|
+
if (!tableExists) {
|
|
49
|
+
migrationPlan.push({
|
|
50
|
+
tableName: baTable.modelName,
|
|
51
|
+
operation: "create",
|
|
52
|
+
fields: [
|
|
53
|
+
{
|
|
54
|
+
name: "id",
|
|
55
|
+
type: "string",
|
|
56
|
+
primary: true,
|
|
57
|
+
unique: true
|
|
58
|
+
},
|
|
59
|
+
...fields
|
|
60
|
+
]
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
const existingFields = (existingTables[baTable.modelName] || []).map(
|
|
64
|
+
(f) => f.name
|
|
65
|
+
);
|
|
66
|
+
const existingFieldMap = (existingTables[baTable.modelName] || []).reduce(
|
|
67
|
+
(acc, f) => {
|
|
68
|
+
acc[f.name] = f.type;
|
|
69
|
+
return acc;
|
|
70
|
+
},
|
|
71
|
+
{}
|
|
72
|
+
);
|
|
73
|
+
fields.forEach((field) => {
|
|
74
|
+
if (existingFields.includes(field.name) && existingFieldMap[field.name] !== field.type) {
|
|
75
|
+
console.warn(
|
|
76
|
+
`⚠️ WARNING: Field '${field.name}' in table '${baTable.modelName}' exists but has type '${existingFieldMap[field.name]}' (expected '${field.type}'). Change the field type in FileMaker to avoid potential errors.`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
const fieldsToAdd = fields.filter(
|
|
81
|
+
(f) => !existingFields.includes(f.name)
|
|
82
|
+
);
|
|
83
|
+
if (fieldsToAdd.length > 0) {
|
|
84
|
+
migrationPlan.push({
|
|
85
|
+
tableName: baTable.modelName,
|
|
86
|
+
operation: "update",
|
|
87
|
+
fields: fieldsToAdd
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return migrationPlan;
|
|
93
|
+
}
|
|
94
|
+
async function executeMigration(db, migrationPlan) {
|
|
95
|
+
for (const step of migrationPlan) {
|
|
96
|
+
if (step.operation === "create") {
|
|
97
|
+
console.log("Creating table:", step.tableName);
|
|
98
|
+
await db.schemaManager().createTable(step.tableName, step.fields);
|
|
99
|
+
} else if (step.operation === "update") {
|
|
100
|
+
console.log("Adding fields to table:", step.tableName);
|
|
101
|
+
await db.schemaManager().addFields(step.tableName, step.fields);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const genericFieldSchema = z.object({
|
|
106
|
+
name: z.string(),
|
|
107
|
+
nullable: z.boolean().optional(),
|
|
108
|
+
primary: z.boolean().optional(),
|
|
109
|
+
unique: z.boolean().optional(),
|
|
110
|
+
global: z.boolean().optional(),
|
|
111
|
+
repetitions: z.number().optional()
|
|
112
|
+
});
|
|
113
|
+
const stringFieldSchema = genericFieldSchema.extend({
|
|
114
|
+
type: z.literal("string"),
|
|
115
|
+
maxLength: z.number().optional(),
|
|
116
|
+
default: z.enum(["USER", "USERNAME", "CURRENT_USER"]).optional()
|
|
117
|
+
});
|
|
118
|
+
const numericFieldSchema = genericFieldSchema.extend({
|
|
119
|
+
type: z.literal("numeric")
|
|
120
|
+
});
|
|
121
|
+
const dateFieldSchema = genericFieldSchema.extend({
|
|
122
|
+
type: z.literal("date"),
|
|
123
|
+
default: z.enum(["CURRENT_DATE", "CURDATE"]).optional()
|
|
124
|
+
});
|
|
125
|
+
const timeFieldSchema = genericFieldSchema.extend({
|
|
126
|
+
type: z.literal("time"),
|
|
127
|
+
default: z.enum(["CURRENT_TIME", "CURTIME"]).optional()
|
|
128
|
+
});
|
|
129
|
+
const timestampFieldSchema = genericFieldSchema.extend({
|
|
130
|
+
type: z.literal("timestamp"),
|
|
131
|
+
default: z.enum(["CURRENT_TIMESTAMP", "CURTIMESTAMP"]).optional()
|
|
132
|
+
});
|
|
133
|
+
const containerFieldSchema = genericFieldSchema.extend({
|
|
134
|
+
type: z.literal("container"),
|
|
135
|
+
externalSecurePath: z.string().optional()
|
|
136
|
+
});
|
|
137
|
+
const fieldSchema = z.discriminatedUnion("type", [
|
|
138
|
+
stringFieldSchema,
|
|
139
|
+
numericFieldSchema,
|
|
140
|
+
dateFieldSchema,
|
|
141
|
+
timeFieldSchema,
|
|
142
|
+
timestampFieldSchema,
|
|
143
|
+
containerFieldSchema
|
|
144
|
+
]);
|
|
145
|
+
z.object({
|
|
146
|
+
tableName: z.string(),
|
|
147
|
+
operation: z.enum(["create", "update"]),
|
|
148
|
+
fields: z.array(fieldSchema)
|
|
149
|
+
}).array();
|
|
150
|
+
function prettyPrintMigrationPlan(migrationPlan) {
|
|
151
|
+
if (!migrationPlan.length) {
|
|
152
|
+
console.log("No changes to apply. Database is up to date.");
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
console.log(chalk.bold.green("Migration plan:"));
|
|
156
|
+
for (const step of migrationPlan) {
|
|
157
|
+
const emoji = step.operation === "create" ? "✅" : "✏️";
|
|
158
|
+
console.log(
|
|
159
|
+
`
|
|
160
|
+
${emoji} ${step.operation === "create" ? chalk.bold.green("Create table") : chalk.bold.yellow("Update table")}: ${step.tableName}`
|
|
161
|
+
);
|
|
162
|
+
if (step.fields.length) {
|
|
163
|
+
for (const field of step.fields) {
|
|
164
|
+
let fieldDesc = ` - ${field.name} (${field.type}`;
|
|
165
|
+
if (field.primary) fieldDesc += ", primary";
|
|
166
|
+
if (field.unique) fieldDesc += ", unique";
|
|
167
|
+
fieldDesc += ")";
|
|
168
|
+
console.log(fieldDesc);
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
console.log(" (No fields to add)");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
console.log("");
|
|
175
|
+
}
|
|
176
|
+
export {
|
|
177
|
+
executeMigration,
|
|
178
|
+
planMigration,
|
|
179
|
+
prettyPrintMigrationPlan
|
|
180
|
+
};
|
|
181
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sources":["../../src/migrate.ts"],"sourcesContent":["import { type BetterAuthDbSchema } from \"better-auth/db\";\nimport { Database, type Field as FmField } from \"fm-odata-client\";\nimport chalk from \"chalk\";\nimport z from \"zod/v4\";\n\nexport async function planMigration(\n db: Database,\n betterAuthSchema: BetterAuthDbSchema,\n): Promise<MigrationPlan> {\n const metadata = await db.getMetadata().catch((error) => {\n console.error(\"Failed to get metadata from database\", error);\n return null;\n });\n\n // Build a map from entity set name to entity type key\n let entitySetToType: Record<string, string> = {};\n if (metadata) {\n for (const [key, value] of Object.entries(metadata)) {\n if (value.$Kind === \"EntitySet\" && value.$Type) {\n // $Type is like 'betterauth_test.fmp12.proofkit_user_'\n const typeKey = value.$Type.split(\".\").pop(); // e.g., 'proofkit_user_'\n entitySetToType[key] = typeKey || key;\n }\n }\n }\n\n const existingTables = metadata\n ? Object.entries(entitySetToType).reduce(\n (acc, [entitySetName, entityTypeKey]) => {\n const entityType = metadata[entityTypeKey];\n if (!entityType) return acc;\n const fields = Object.entries(entityType)\n .filter(\n ([fieldKey, fieldValue]) =>\n typeof fieldValue === \"object\" &&\n fieldValue !== null &&\n \"$Type\" in fieldValue,\n )\n .map(([fieldKey, fieldValue]) => ({\n name: fieldKey,\n type:\n fieldValue.$Type === \"Edm.String\"\n ? \"string\"\n : fieldValue.$Type === \"Edm.DateTimeOffset\"\n ? \"timestamp\"\n : fieldValue.$Type === \"Edm.Decimal\" ||\n fieldValue.$Type === \"Edm.Int32\" ||\n fieldValue.$Type === \"Edm.Int64\"\n ? \"numeric\"\n : \"string\",\n }));\n acc[entitySetName] = fields;\n return acc;\n },\n {} as Record<string, { name: string; type: string }[]>,\n )\n : {};\n\n const baTables = Object.entries(betterAuthSchema)\n .sort((a, b) => (a[1].order ?? 0) - (b[1].order ?? 0))\n .map(([key, value]) => ({\n ...value,\n keyName: key,\n }));\n\n const migrationPlan: MigrationPlan = [];\n\n for (const baTable of baTables) {\n const fields: FmField[] = Object.entries(baTable.fields).map(\n ([key, field]) => ({\n name: field.fieldName ?? key,\n type:\n field.type === \"boolean\" || field.type.includes(\"number\")\n ? \"numeric\"\n : field.type === \"date\"\n ? \"timestamp\"\n : \"string\",\n }),\n );\n\n // get existing table or create it\n const tableExists = Object.prototype.hasOwnProperty.call(\n existingTables,\n baTable.modelName,\n );\n\n if (!tableExists) {\n migrationPlan.push({\n tableName: baTable.modelName,\n operation: \"create\",\n fields: [\n {\n name: \"id\",\n type: \"string\",\n primary: true,\n unique: true,\n },\n ...fields,\n ],\n });\n } else {\n const existingFields = (existingTables[baTable.modelName] || []).map(\n (f) => f.name,\n );\n const existingFieldMap = (existingTables[baTable.modelName] || []).reduce(\n (acc, f) => {\n acc[f.name] = f.type;\n return acc;\n },\n {} as Record<string, string>,\n );\n // Warn about type mismatches (optional, not in plan)\n fields.forEach((field) => {\n if (\n existingFields.includes(field.name) &&\n existingFieldMap[field.name] !== field.type\n ) {\n console.warn(\n `⚠️ WARNING: Field '${field.name}' in table '${baTable.modelName}' exists but has type '${existingFieldMap[field.name]}' (expected '${field.type}'). Change the field type in FileMaker to avoid potential errors.`,\n );\n }\n });\n const fieldsToAdd = fields.filter(\n (f) => !existingFields.includes(f.name),\n );\n if (fieldsToAdd.length > 0) {\n migrationPlan.push({\n tableName: baTable.modelName,\n operation: \"update\",\n fields: fieldsToAdd,\n });\n }\n }\n }\n\n return migrationPlan;\n}\n\nexport async function executeMigration(\n db: Database,\n migrationPlan: MigrationPlan,\n) {\n for (const step of migrationPlan) {\n if (step.operation === \"create\") {\n console.log(\"Creating table:\", step.tableName);\n await db.schemaManager().createTable(step.tableName, step.fields);\n } else if (step.operation === \"update\") {\n console.log(\"Adding fields to table:\", step.tableName);\n await db.schemaManager().addFields(step.tableName, step.fields);\n }\n }\n}\n\nconst genericFieldSchema = z.object({\n name: z.string(),\n nullable: z.boolean().optional(),\n primary: z.boolean().optional(),\n unique: z.boolean().optional(),\n global: z.boolean().optional(),\n repetitions: z.number().optional(),\n});\n\nconst stringFieldSchema = genericFieldSchema.extend({\n type: z.literal(\"string\"),\n maxLength: z.number().optional(),\n default: z.enum([\"USER\", \"USERNAME\", \"CURRENT_USER\"]).optional(),\n});\n\nconst numericFieldSchema = genericFieldSchema.extend({\n type: z.literal(\"numeric\"),\n});\n\nconst dateFieldSchema = genericFieldSchema.extend({\n type: z.literal(\"date\"),\n default: z.enum([\"CURRENT_DATE\", \"CURDATE\"]).optional(),\n});\n\nconst timeFieldSchema = genericFieldSchema.extend({\n type: z.literal(\"time\"),\n default: z.enum([\"CURRENT_TIME\", \"CURTIME\"]).optional(),\n});\n\nconst timestampFieldSchema = genericFieldSchema.extend({\n type: z.literal(\"timestamp\"),\n default: z.enum([\"CURRENT_TIMESTAMP\", \"CURTIMESTAMP\"]).optional(),\n});\n\nconst containerFieldSchema = genericFieldSchema.extend({\n type: z.literal(\"container\"),\n externalSecurePath: z.string().optional(),\n});\n\nconst fieldSchema = z.discriminatedUnion(\"type\", [\n stringFieldSchema,\n numericFieldSchema,\n dateFieldSchema,\n timeFieldSchema,\n timestampFieldSchema,\n containerFieldSchema,\n]);\n\nexport const migrationPlanSchema = z\n .object({\n tableName: z.string(),\n operation: z.enum([\"create\", \"update\"]),\n fields: z.array(fieldSchema),\n })\n .array();\n\nexport type MigrationPlan = z.infer<typeof migrationPlanSchema>;\n\nexport function prettyPrintMigrationPlan(migrationPlan: MigrationPlan) {\n if (!migrationPlan.length) {\n console.log(\"No changes to apply. Database is up to date.\");\n return;\n }\n console.log(chalk.bold.green(\"Migration plan:\"));\n for (const step of migrationPlan) {\n const emoji = step.operation === \"create\" ? \"✅\" : \"✏️\";\n console.log(\n `\\n${emoji} ${step.operation === \"create\" ? chalk.bold.green(\"Create table\") : chalk.bold.yellow(\"Update table\")}: ${step.tableName}`,\n );\n if (step.fields.length) {\n for (const field of step.fields) {\n let fieldDesc = ` - ${field.name} (${field.type}`;\n if (field.primary) fieldDesc += \", primary\";\n if (field.unique) fieldDesc += \", unique\";\n fieldDesc += \")\";\n console.log(fieldDesc);\n }\n } else {\n console.log(\" (No fields to add)\");\n }\n }\n console.log(\"\");\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Connection, Database } from 'fm-odata-client';
|
|
2
|
+
export type BasicAuthCredentials = {
|
|
3
|
+
username: string;
|
|
4
|
+
password: string;
|
|
5
|
+
};
|
|
6
|
+
export type OttoAPIKeyAuth = {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
};
|
|
9
|
+
export type ODataAuth = BasicAuthCredentials | OttoAPIKeyAuth;
|
|
10
|
+
export declare function isBasicAuth(auth: ODataAuth): auth is BasicAuthCredentials;
|
|
11
|
+
export declare function isOttoAPIKeyAuth(auth: ODataAuth): auth is OttoAPIKeyAuth;
|
|
12
|
+
export type FmOdataConfig = {
|
|
13
|
+
hostname: string;
|
|
14
|
+
auth: ODataAuth;
|
|
15
|
+
database: string;
|
|
16
|
+
};
|
|
17
|
+
export declare class FmOdata {
|
|
18
|
+
connection: Connection;
|
|
19
|
+
database: Database;
|
|
20
|
+
constructor(args: FmOdataConfig);
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { Connection, BasicAuth, Database } from "fm-odata-client";
|
|
5
|
+
function isOttoAPIKeyAuth(auth) {
|
|
6
|
+
return typeof auth.apiKey === "string";
|
|
7
|
+
}
|
|
8
|
+
class FmOdata {
|
|
9
|
+
constructor(args) {
|
|
10
|
+
__publicField(this, "connection");
|
|
11
|
+
__publicField(this, "database");
|
|
12
|
+
if (isOttoAPIKeyAuth(args.auth)) {
|
|
13
|
+
throw new Error("Otto API key auth is yet not supported");
|
|
14
|
+
} else {
|
|
15
|
+
this.connection = new Connection(
|
|
16
|
+
args.hostname.replace(/^https?:\/\//, "").replace(/\/$/, ""),
|
|
17
|
+
new BasicAuth(args.auth.username, args.auth.password)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
this.database = new Database(this.connection, args.database);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
FmOdata,
|
|
25
|
+
isOttoAPIKeyAuth
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/odata/index.ts"],"sourcesContent":["import { BasicAuth, Connection, Database } from \"fm-odata-client\";\n\nexport type BasicAuthCredentials = {\n username: string;\n password: string;\n};\nexport type OttoAPIKeyAuth = {\n apiKey: string;\n};\nexport type ODataAuth = BasicAuthCredentials | OttoAPIKeyAuth;\n\nexport function isBasicAuth(auth: ODataAuth): auth is BasicAuthCredentials {\n return (\n typeof (auth as BasicAuthCredentials).username === \"string\" &&\n typeof (auth as BasicAuthCredentials).password === \"string\"\n );\n}\n\nexport function isOttoAPIKeyAuth(auth: ODataAuth): auth is OttoAPIKeyAuth {\n return typeof (auth as OttoAPIKeyAuth).apiKey === \"string\";\n}\n\nexport type FmOdataConfig = {\n hostname: string;\n auth: ODataAuth;\n database: string;\n};\n\nexport class FmOdata {\n public connection: Connection;\n public database: Database;\n\n constructor(args: FmOdataConfig) {\n if (isOttoAPIKeyAuth(args.auth)) {\n throw new Error(\"Otto API key auth is yet not supported\");\n } else {\n this.connection = new Connection(\n args.hostname.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\"),\n new BasicAuth(args.auth.username, args.auth.password),\n );\n }\n\n this.database = new Database(this.connection, args.database);\n }\n}\n"],"names":[],"mappings":";;;;AAkBO,SAAS,iBAAiB,MAAyC;AACjE,SAAA,OAAQ,KAAwB,WAAW;AACpD;AAQO,MAAM,QAAQ;AAAA,EAInB,YAAY,MAAqB;AAH1B;AACA;AAGD,QAAA,iBAAiB,KAAK,IAAI,GAAG;AACzB,YAAA,IAAI,MAAM,wCAAwC;AAAA,IAAA,OACnD;AACL,WAAK,aAAa,IAAI;AAAA,QACpB,KAAK,SAAS,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,OAAO,EAAE;AAAA,QAC3D,IAAI,UAAU,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;AAAA,MACtD;AAAA,IAAA;AAGF,SAAK,WAAW,IAAI,SAAS,KAAK,YAAY,KAAK,QAAQ;AAAA,EAAA;AAE/D;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proofkit/better-auth",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "FileMaker adapter for Better Auth",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/esm/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"better-auth": "./dist/esm/cli/index.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/esm/index.d.ts",
|
|
14
|
+
"default": "./dist/esm/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"proofkit",
|
|
21
|
+
"better-auth",
|
|
22
|
+
"fmdapi",
|
|
23
|
+
"proofgeist",
|
|
24
|
+
"filemaker",
|
|
25
|
+
"fmrest"
|
|
26
|
+
],
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"src"
|
|
30
|
+
],
|
|
31
|
+
"author": "",
|
|
32
|
+
"license": "ISC",
|
|
33
|
+
"homepage": "https://proofkit.dev",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/proofgeist/proofkit.git"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@babel/preset-react": "^7.27.1",
|
|
40
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
41
|
+
"@commander-js/extra-typings": "^14.0.0",
|
|
42
|
+
"@tanstack/vite-config": "^0.2.0",
|
|
43
|
+
"better-auth": "^1.2.10",
|
|
44
|
+
"c12": "^3.0.4",
|
|
45
|
+
"chalk": "5.4.1",
|
|
46
|
+
"commander": "^14.0.0",
|
|
47
|
+
"dotenv": "^16.5.0",
|
|
48
|
+
"execa": "^9.5.3",
|
|
49
|
+
"fm-odata-client": "^3.0.1",
|
|
50
|
+
"fs-extra": "^11.3.0",
|
|
51
|
+
"prompts": "^2.4.2",
|
|
52
|
+
"vite": "^6.3.4",
|
|
53
|
+
"zod": "3.25.64",
|
|
54
|
+
"@proofkit/fmdapi": "5.0.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/fs-extra": "^11.0.4",
|
|
58
|
+
"@types/prompts": "^2.4.9",
|
|
59
|
+
"publint": "^0.3.12",
|
|
60
|
+
"typescript": "^5.8.3",
|
|
61
|
+
"vitest": "^3.2.3"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"dev": "pnpm build:watch",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"build": "vite build && publint --strict",
|
|
67
|
+
"build:watch": "vite build --watch",
|
|
68
|
+
"ci": "pnpm run build && pnpm run test"
|
|
69
|
+
}
|
|
70
|
+
}
|