@proofkit/better-auth 0.2.4 → 0.3.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/dist/esm/adapter.js +102 -58
- package/dist/esm/adapter.js.map +1 -1
- package/dist/esm/cli/index.js +5 -3
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/migrate.d.ts +4 -4
- package/dist/esm/migrate.js +22 -3
- package/dist/esm/migrate.js.map +1 -1
- package/dist/esm/odata/index.d.ts +11 -85
- package/dist/esm/odata/index.js +182 -66
- package/dist/esm/odata/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +125 -61
- package/src/cli/index.ts +3 -2
- package/src/migrate.ts +29 -7
- package/src/odata/index.ts +229 -68
package/dist/esm/adapter.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createAdapter } from "better-auth/adapters";
|
|
2
|
-
import {
|
|
2
|
+
import { createRawFetch } from "./odata/index.js";
|
|
3
3
|
import { z, prettifyError } from "zod/v4";
|
|
4
4
|
import { logger } from "better-auth";
|
|
5
|
+
import buildQuery from "odata-query";
|
|
5
6
|
const configSchema = z.object({
|
|
6
7
|
debugLogs: z.unknown().optional(),
|
|
7
8
|
usePlural: z.boolean().optional(),
|
|
@@ -98,7 +99,7 @@ const FileMakerAdapter = (_config = defaultConfig) => {
|
|
|
98
99
|
throw new Error(`Invalid configuration: ${prettifyError(parsed.error)}`);
|
|
99
100
|
}
|
|
100
101
|
const config = parsed.data;
|
|
101
|
-
const fetch =
|
|
102
|
+
const { fetch } = createRawFetch({
|
|
102
103
|
...config.odata,
|
|
103
104
|
logging: config.debugLogs ? "verbose" : "none"
|
|
104
105
|
});
|
|
@@ -140,11 +141,11 @@ const FileMakerAdapter = (_config = defaultConfig) => {
|
|
|
140
141
|
var _a;
|
|
141
142
|
const filter = parseWhere(where);
|
|
142
143
|
logger.debug("$filter", filter);
|
|
143
|
-
const
|
|
144
|
+
const query = buildQuery({
|
|
145
|
+
filter: filter.length > 0 ? filter : void 0
|
|
146
|
+
});
|
|
147
|
+
const result = await fetch(`/${model}/$count${query}`, {
|
|
144
148
|
method: "GET",
|
|
145
|
-
query: {
|
|
146
|
-
$filter: filter
|
|
147
|
-
},
|
|
148
149
|
output: z.object({ value: z.number() })
|
|
149
150
|
});
|
|
150
151
|
if (!result.data) {
|
|
@@ -156,12 +157,12 @@ const FileMakerAdapter = (_config = defaultConfig) => {
|
|
|
156
157
|
var _a, _b;
|
|
157
158
|
const filter = parseWhere(where);
|
|
158
159
|
logger.debug("$filter", filter);
|
|
159
|
-
const
|
|
160
|
+
const query = buildQuery({
|
|
161
|
+
top: 1,
|
|
162
|
+
filter: filter.length > 0 ? filter : void 0
|
|
163
|
+
});
|
|
164
|
+
const result = await fetch(`/${model}${query}`, {
|
|
160
165
|
method: "GET",
|
|
161
|
-
query: {
|
|
162
|
-
...filter.length > 0 ? { $filter: filter } : {},
|
|
163
|
-
$top: 1
|
|
164
|
-
},
|
|
165
166
|
output: z.object({ value: z.array(z.any()) })
|
|
166
167
|
});
|
|
167
168
|
if (result.error) {
|
|
@@ -172,79 +173,122 @@ const FileMakerAdapter = (_config = defaultConfig) => {
|
|
|
172
173
|
findMany: async ({ model, where, limit, offset, sortBy }) => {
|
|
173
174
|
var _a;
|
|
174
175
|
const filter = parseWhere(where);
|
|
175
|
-
logger.debug("
|
|
176
|
-
const
|
|
176
|
+
logger.debug("FIND MANY", { where, filter });
|
|
177
|
+
const query = buildQuery({
|
|
178
|
+
top: limit,
|
|
179
|
+
skip: offset,
|
|
180
|
+
orderBy: sortBy ? `${sortBy.field} ${sortBy.direction ?? "asc"}` : void 0,
|
|
181
|
+
filter: filter.length > 0 ? filter : void 0
|
|
182
|
+
});
|
|
183
|
+
logger.debug("QUERY", query);
|
|
184
|
+
const result = await fetch(`/${model}${query}`, {
|
|
177
185
|
method: "GET",
|
|
178
|
-
query: {
|
|
179
|
-
...filter.length > 0 ? { $filter: filter } : {},
|
|
180
|
-
$top: limit,
|
|
181
|
-
$skip: offset,
|
|
182
|
-
...sortBy ? { $orderby: `"${sortBy.field}" ${sortBy.direction ?? "asc"}` } : {}
|
|
183
|
-
},
|
|
184
186
|
output: z.object({ value: z.array(z.any()) })
|
|
185
187
|
});
|
|
186
|
-
|
|
188
|
+
logger.debug("RESULT", result);
|
|
189
|
+
if (result.error) {
|
|
187
190
|
throw new Error("Failed to find records");
|
|
188
191
|
}
|
|
189
|
-
return ((_a =
|
|
192
|
+
return ((_a = result.data) == null ? void 0 : _a.value) ?? [];
|
|
190
193
|
},
|
|
191
194
|
delete: async ({ model, where }) => {
|
|
195
|
+
var _a, _b, _c;
|
|
192
196
|
const filter = parseWhere(where);
|
|
197
|
+
console.log("DELETE", { model, where, filter });
|
|
193
198
|
logger.debug("$filter", filter);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
const query = buildQuery({
|
|
200
|
+
top: 1,
|
|
201
|
+
select: [`"id"`],
|
|
202
|
+
filter: filter.length > 0 ? filter : void 0
|
|
203
|
+
});
|
|
204
|
+
const toDelete = await fetch(`/${model}${query}`, {
|
|
205
|
+
method: "GET",
|
|
206
|
+
output: z.object({ value: z.array(z.object({ id: z.string() })) })
|
|
207
|
+
});
|
|
208
|
+
const id = (_c = (_b = (_a = toDelete.data) == null ? void 0 : _a.value) == null ? void 0 : _b[0]) == null ? void 0 : _c.id;
|
|
209
|
+
if (!id) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const result = await fetch(`/${model}('${id}')`, {
|
|
213
|
+
method: "DELETE"
|
|
201
214
|
});
|
|
202
215
|
if (result.error) {
|
|
216
|
+
console.log("DELETE ERROR", result.error);
|
|
203
217
|
throw new Error("Failed to delete record");
|
|
204
218
|
}
|
|
205
219
|
},
|
|
206
220
|
deleteMany: async ({ model, where }) => {
|
|
221
|
+
var _a, _b;
|
|
207
222
|
const filter = parseWhere(where);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const result = await fetch(`/${model}/$count`, {
|
|
213
|
-
method: "DELETE",
|
|
214
|
-
query: {
|
|
215
|
-
...where.length > 0 ? { $filter: filter } : {}
|
|
216
|
-
},
|
|
217
|
-
output: z.coerce.number()
|
|
223
|
+
console.log("DELETE MANY", { model, where, filter });
|
|
224
|
+
const query = buildQuery({
|
|
225
|
+
select: [`"id"`],
|
|
226
|
+
filter: filter.length > 0 ? filter : void 0
|
|
218
227
|
});
|
|
219
|
-
|
|
220
|
-
|
|
228
|
+
const rows = await fetch(`/${model}${query}`, {
|
|
229
|
+
method: "GET",
|
|
230
|
+
output: z.object({ value: z.array(z.object({ id: z.string() })) })
|
|
231
|
+
});
|
|
232
|
+
const ids = ((_b = (_a = rows.data) == null ? void 0 : _a.value) == null ? void 0 : _b.map((r) => r.id)) ?? [];
|
|
233
|
+
let deleted = 0;
|
|
234
|
+
for (const id of ids) {
|
|
235
|
+
const res = await fetch(`/${model}('${id}')`, {
|
|
236
|
+
method: "DELETE"
|
|
237
|
+
});
|
|
238
|
+
if (!res.error) deleted++;
|
|
221
239
|
}
|
|
222
|
-
return
|
|
240
|
+
return deleted;
|
|
223
241
|
},
|
|
224
242
|
update: async ({ model, where, update }) => {
|
|
225
|
-
var _a, _b;
|
|
226
|
-
const
|
|
243
|
+
var _a, _b, _c;
|
|
244
|
+
const filter = parseWhere(where);
|
|
245
|
+
logger.debug("UPDATE", { model, where, update });
|
|
246
|
+
logger.debug("$filter", filter);
|
|
247
|
+
const query = buildQuery({
|
|
248
|
+
select: [`"id"`],
|
|
249
|
+
filter: filter.length > 0 ? filter : void 0
|
|
250
|
+
});
|
|
251
|
+
const existing = await fetch(`/${model}${query}`, {
|
|
252
|
+
method: "GET",
|
|
253
|
+
output: z.object({ value: z.array(z.object({ id: z.string() })) })
|
|
254
|
+
});
|
|
255
|
+
logger.debug("EXISTING", existing.data);
|
|
256
|
+
const id = (_c = (_b = (_a = existing.data) == null ? void 0 : _a.value) == null ? void 0 : _b[0]) == null ? void 0 : _c.id;
|
|
257
|
+
if (!id) return null;
|
|
258
|
+
const patchRes = await fetch(`/${model}('${id}')`, {
|
|
227
259
|
method: "PATCH",
|
|
228
|
-
|
|
229
|
-
...where.length > 0 ? { $filter: parseWhere(where) } : {},
|
|
230
|
-
$top: 1,
|
|
231
|
-
$select: [`"id"`]
|
|
232
|
-
},
|
|
233
|
-
body: update,
|
|
234
|
-
output: z.object({ value: z.array(z.any()) })
|
|
260
|
+
body: update
|
|
235
261
|
});
|
|
236
|
-
|
|
262
|
+
logger.debug("PATCH RES", patchRes.data);
|
|
263
|
+
if (patchRes.error) return null;
|
|
264
|
+
const readBack = await fetch(`/${model}('${id}')`, {
|
|
265
|
+
method: "GET",
|
|
266
|
+
output: z.record(z.string(), z.unknown())
|
|
267
|
+
});
|
|
268
|
+
logger.debug("READ BACK", readBack.data);
|
|
269
|
+
return readBack.data ?? null;
|
|
237
270
|
},
|
|
238
271
|
updateMany: async ({ model, where, update }) => {
|
|
272
|
+
var _a, _b;
|
|
239
273
|
const filter = parseWhere(where);
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
...where.length > 0 ? { $filter: filter } : {}
|
|
244
|
-
},
|
|
245
|
-
body: update
|
|
274
|
+
const query = buildQuery({
|
|
275
|
+
select: [`"id"`],
|
|
276
|
+
filter: filter.length > 0 ? filter : void 0
|
|
246
277
|
});
|
|
247
|
-
|
|
278
|
+
const rows = await fetch(`/${model}${query}`, {
|
|
279
|
+
method: "GET",
|
|
280
|
+
output: z.object({ value: z.array(z.object({ id: z.string() })) })
|
|
281
|
+
});
|
|
282
|
+
const ids = ((_b = (_a = rows.data) == null ? void 0 : _a.value) == null ? void 0 : _b.map((r) => r.id)) ?? [];
|
|
283
|
+
let updated = 0;
|
|
284
|
+
for (const id of ids) {
|
|
285
|
+
const res = await fetch(`/${model}('${id}')`, {
|
|
286
|
+
method: "PATCH",
|
|
287
|
+
body: update
|
|
288
|
+
});
|
|
289
|
+
if (!res.error) updated++;
|
|
290
|
+
}
|
|
291
|
+
return updated;
|
|
248
292
|
}
|
|
249
293
|
};
|
|
250
294
|
}
|
package/dist/esm/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sources":["../../src/adapter.ts"],"sourcesContent":["import {\n CleanedWhere,\n createAdapter,\n type AdapterDebugLogs,\n} from \"better-auth/adapters\";\nimport { createFmOdataFetch, type FmOdataConfig } from \"./odata\";\nimport { prettifyError, z } from \"zod/v4\";\nimport { logger } from \"better-auth\";\n\nconst configSchema = z.object({\n debugLogs: z.unknown().optional(),\n usePlural: z.boolean().optional(),\n odata: z.object({\n serverUrl: z.url(),\n auth: z.union([\n z.object({ username: z.string(), password: z.string() }),\n z.object({ apiKey: z.string() }),\n ]),\n database: z.string().endsWith(\".fmp12\"),\n }),\n});\n\ninterface FileMakerAdapterConfig {\n /**\n * Helps you debug issues with the adapter.\n */\n debugLogs?: AdapterDebugLogs;\n /**\n * If the table names in the schema are plural.\n */\n usePlural?: boolean;\n\n /**\n * Connection details for the FileMaker server.\n */\n odata: FmOdataConfig;\n}\n\nexport type AdapterOptions = {\n config: FileMakerAdapterConfig;\n};\n\nconst defaultConfig: Required<FileMakerAdapterConfig> = {\n debugLogs: false,\n usePlural: false,\n odata: {\n serverUrl: \"\",\n auth: { username: \"\", password: \"\" },\n database: \"\",\n },\n};\n\n/**\n * Parse the where clause to an OData filter string.\n * @param where - The where clause to parse.\n * @returns The OData filter string.\n * @internal\n */\nexport function parseWhere(where?: CleanedWhere[]): string {\n if (!where || where.length === 0) return \"\";\n\n // Helper to quote field names with special chars or if field is 'id'\n function quoteField(field: string, value?: any) {\n // Never quote for null or date values (per test expectations)\n if (value === null || value instanceof Date) return field;\n // Always quote if field is 'id' or has space or underscore\n if (field === \"id\" || /[\\s_]/.test(field)) return `\"${field}\"`;\n return field;\n }\n\n // Helper to format values for OData\n function formatValue(value: any): string {\n if (value === null) return \"null\";\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (value instanceof Date) return value.toISOString();\n if (Array.isArray(value)) return `(${value.map(formatValue).join(\",\")})`;\n\n // Handle strings - check if it's an ISO date string first\n if (typeof value === \"string\") {\n // Check if it's an ISO date string (YYYY-MM-DDTHH:mm:ss.sssZ format)\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z?$/;\n if (isoDateRegex.test(value)) {\n return value; // Return ISO date strings without quotes\n }\n return `'${value.replace(/'/g, \"''\")}'`; // Regular strings get quotes\n }\n\n return value?.toString() ?? \"\";\n }\n\n // Map our operators to OData\n const opMap: Record<string, string> = {\n eq: \"eq\",\n ne: \"ne\",\n lt: \"lt\",\n lte: \"le\",\n gt: \"gt\",\n gte: \"ge\",\n };\n\n // Build each clause\n const clauses: string[] = [];\n for (let i = 0; i < where.length; i++) {\n const cond = where[i];\n if (!cond) continue;\n const field = quoteField(cond.field, cond.value);\n let clause = \"\";\n switch (cond.operator) {\n case \"eq\":\n case \"ne\":\n case \"lt\":\n case \"lte\":\n case \"gt\":\n case \"gte\":\n clause = `${field} ${opMap[cond.operator!]} ${formatValue(cond.value)}`;\n break;\n case \"in\":\n if (Array.isArray(cond.value)) {\n clause = cond.value\n .map((v) => `${field} eq ${formatValue(v)}`)\n .join(\" or \");\n clause = `(${clause})`;\n }\n break;\n case \"contains\":\n clause = `contains(${field}, ${formatValue(cond.value)})`;\n break;\n case \"starts_with\":\n clause = `startswith(${field}, ${formatValue(cond.value)})`;\n break;\n case \"ends_with\":\n clause = `endswith(${field}, ${formatValue(cond.value)})`;\n break;\n default:\n clause = `${field} eq ${formatValue(cond.value)}`;\n }\n clauses.push(clause);\n // Add connector if not last\n if (i < where.length - 1) {\n clauses.push((cond.connector || \"and\").toLowerCase());\n }\n }\n return clauses.join(\" \");\n}\n\nexport const FileMakerAdapter = (\n _config: FileMakerAdapterConfig = defaultConfig,\n) => {\n const parsed = configSchema.loose().safeParse(_config);\n\n if (!parsed.success) {\n throw new Error(`Invalid configuration: ${prettifyError(parsed.error)}`);\n }\n const config = parsed.data;\n\n const fetch = createFmOdataFetch({\n ...config.odata,\n logging: config.debugLogs ? \"verbose\" : \"none\",\n });\n\n return createAdapter({\n config: {\n adapterId: \"filemaker\",\n adapterName: \"FileMaker\",\n usePlural: config.usePlural ?? false, // Whether the table names in the schema are plural.\n debugLogs: config.debugLogs ?? false, // Whether to enable debug logs.\n supportsJSON: false, // Whether the database supports JSON. (Default: false)\n supportsDates: false, // Whether the database supports dates. (Default: true)\n supportsBooleans: false, // Whether the database supports booleans. (Default: true)\n supportsNumericIds: false, // Whether the database supports auto-incrementing numeric IDs. (Default: true)\n },\n adapter: ({ options }) => {\n return {\n options: { config },\n create: async ({ data, model, select }) => {\n if (model === \"session\") {\n console.log(\"session\", data);\n }\n\n const result = await fetch(`/${model}`, {\n method: \"POST\",\n body: data,\n output: z.looseObject({ id: z.string() }),\n });\n\n if (result.error) {\n throw new Error(\"Failed to create record\");\n }\n\n return result.data as any;\n },\n count: async ({ model, where }) => {\n const filter = parseWhere(where);\n logger.debug(\"$filter\", filter);\n const result = await fetch(`/${model}/$count`, {\n method: \"GET\",\n query: {\n $filter: filter,\n },\n output: z.object({ value: z.number() }),\n });\n if (!result.data) {\n throw new Error(\"Failed to count records\");\n }\n return result.data?.value ?? 0;\n },\n findOne: async ({ model, where }) => {\n const filter = parseWhere(where);\n logger.debug(\"$filter\", filter);\n const result = await fetch(`/${model}`, {\n method: \"GET\",\n query: {\n ...(filter.length > 0 ? { $filter: filter } : {}),\n $top: 1,\n },\n output: z.object({ value: z.array(z.any()) }),\n });\n if (result.error) {\n throw new Error(\"Failed to find record\");\n }\n return result.data?.value?.[0] ?? null;\n },\n findMany: async ({ model, where, limit, offset, sortBy }) => {\n const filter = parseWhere(where);\n logger.debug(\"$filter\", filter);\n\n const rows = await fetch(`/${model}`, {\n method: \"GET\",\n query: {\n ...(filter.length > 0 ? { $filter: filter } : {}),\n $top: limit,\n $skip: offset,\n ...(sortBy\n ? { $orderby: `\"${sortBy.field}\" ${sortBy.direction ?? \"asc\"}` }\n : {}),\n },\n output: z.object({ value: z.array(z.any()) }),\n });\n if (rows.error) {\n throw new Error(\"Failed to find records\");\n }\n return rows.data?.value ?? [];\n },\n delete: async ({ model, where }) => {\n const filter = parseWhere(where);\n logger.debug(\"$filter\", filter);\n console.log(\"delete\", model, where, filter);\n const result = await fetch(`/${model}`, {\n method: \"DELETE\",\n query: {\n ...(where.length > 0 ? { $filter: filter } : {}),\n $top: 1,\n },\n });\n if (result.error) {\n throw new Error(\"Failed to delete record\");\n }\n },\n deleteMany: async ({ model, where }) => {\n const filter = parseWhere(where);\n logger.debug(\n where\n .map((o) => `typeof ${o.value} is ${typeof o.value}`)\n .join(\"\\n\"),\n );\n logger.debug(\"$filter\", filter);\n\n const result = await fetch(`/${model}/$count`, {\n method: \"DELETE\",\n query: {\n ...(where.length > 0 ? { $filter: filter } : {}),\n },\n output: z.coerce.number(),\n });\n if (result.error) {\n throw new Error(\"Failed to delete record\");\n }\n return result.data ?? 0;\n },\n update: async ({ model, where, update }) => {\n const result = await fetch(`/${model}`, {\n method: \"PATCH\",\n query: {\n ...(where.length > 0 ? { $filter: parseWhere(where) } : {}),\n $top: 1,\n $select: [`\"id\"`],\n },\n body: update,\n output: z.object({ value: z.array(z.any()) }),\n });\n return result.data?.value?.[0] ?? null;\n },\n updateMany: async ({ model, where, update }) => {\n const filter = parseWhere(where);\n const result = await fetch(`/${model}`, {\n method: \"PATCH\",\n query: {\n ...(where.length > 0 ? { $filter: filter } : {}),\n },\n body: update,\n });\n return result.data as any;\n },\n };\n },\n });\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapter.js","sources":["../../src/adapter.ts"],"sourcesContent":["import {\n CleanedWhere,\n createAdapter,\n type AdapterDebugLogs,\n} from \"better-auth/adapters\";\nimport { createRawFetch, type FmOdataConfig } from \"./odata\";\nimport { prettifyError, z } from \"zod/v4\";\nimport { logger } from \"better-auth\";\nimport buildQuery from \"odata-query\";\n\nconst configSchema = z.object({\n debugLogs: z.unknown().optional(),\n usePlural: z.boolean().optional(),\n odata: z.object({\n serverUrl: z.url(),\n auth: z.union([\n z.object({ username: z.string(), password: z.string() }),\n z.object({ apiKey: z.string() }),\n ]),\n database: z.string().endsWith(\".fmp12\"),\n }),\n});\n\ninterface FileMakerAdapterConfig {\n /**\n * Helps you debug issues with the adapter.\n */\n debugLogs?: AdapterDebugLogs;\n /**\n * If the table names in the schema are plural.\n */\n usePlural?: boolean;\n\n /**\n * Connection details for the FileMaker server.\n */\n odata: FmOdataConfig;\n}\n\nexport type AdapterOptions = {\n config: FileMakerAdapterConfig;\n};\n\nconst defaultConfig: Required<FileMakerAdapterConfig> = {\n debugLogs: false,\n usePlural: false,\n odata: {\n serverUrl: \"\",\n auth: { username: \"\", password: \"\" },\n database: \"\",\n },\n};\n\n/**\n * Parse the where clause to an OData filter string.\n * @param where - The where clause to parse.\n * @returns The OData filter string.\n * @internal\n */\nexport function parseWhere(where?: CleanedWhere[]): string {\n if (!where || where.length === 0) return \"\";\n\n // Helper to quote field names with special chars or if field is 'id'\n function quoteField(field: string, value?: any) {\n // Never quote for null or date values (per test expectations)\n if (value === null || value instanceof Date) return field;\n // Always quote if field is 'id' or has space or underscore\n if (field === \"id\" || /[\\s_]/.test(field)) return `\"${field}\"`;\n return field;\n }\n\n // Helper to format values for OData\n function formatValue(value: any): string {\n if (value === null) return \"null\";\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (value instanceof Date) return value.toISOString();\n if (Array.isArray(value)) return `(${value.map(formatValue).join(\",\")})`;\n\n // Handle strings - check if it's an ISO date string first\n if (typeof value === \"string\") {\n // Check if it's an ISO date string (YYYY-MM-DDTHH:mm:ss.sssZ format)\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z?$/;\n if (isoDateRegex.test(value)) {\n return value; // Return ISO date strings without quotes\n }\n return `'${value.replace(/'/g, \"''\")}'`; // Regular strings get quotes\n }\n\n return value?.toString() ?? \"\";\n }\n\n // Map our operators to OData\n const opMap: Record<string, string> = {\n eq: \"eq\",\n ne: \"ne\",\n lt: \"lt\",\n lte: \"le\",\n gt: \"gt\",\n gte: \"ge\",\n };\n\n // Build each clause\n const clauses: string[] = [];\n for (let i = 0; i < where.length; i++) {\n const cond = where[i];\n if (!cond) continue;\n const field = quoteField(cond.field, cond.value);\n let clause = \"\";\n switch (cond.operator) {\n case \"eq\":\n case \"ne\":\n case \"lt\":\n case \"lte\":\n case \"gt\":\n case \"gte\":\n clause = `${field} ${opMap[cond.operator!]} ${formatValue(cond.value)}`;\n break;\n case \"in\":\n if (Array.isArray(cond.value)) {\n clause = cond.value\n .map((v) => `${field} eq ${formatValue(v)}`)\n .join(\" or \");\n clause = `(${clause})`;\n }\n break;\n case \"contains\":\n clause = `contains(${field}, ${formatValue(cond.value)})`;\n break;\n case \"starts_with\":\n clause = `startswith(${field}, ${formatValue(cond.value)})`;\n break;\n case \"ends_with\":\n clause = `endswith(${field}, ${formatValue(cond.value)})`;\n break;\n default:\n clause = `${field} eq ${formatValue(cond.value)}`;\n }\n clauses.push(clause);\n // Add connector if not last\n if (i < where.length - 1) {\n clauses.push((cond.connector || \"and\").toLowerCase());\n }\n }\n return clauses.join(\" \");\n}\n\nexport const FileMakerAdapter = (\n _config: FileMakerAdapterConfig = defaultConfig,\n) => {\n const parsed = configSchema.loose().safeParse(_config);\n\n if (!parsed.success) {\n throw new Error(`Invalid configuration: ${prettifyError(parsed.error)}`);\n }\n const config = parsed.data;\n\n const { fetch, baseURL } = createRawFetch({\n ...config.odata,\n logging: config.debugLogs ? \"verbose\" : \"none\",\n });\n\n return createAdapter({\n config: {\n adapterId: \"filemaker\",\n adapterName: \"FileMaker\",\n usePlural: config.usePlural ?? false, // Whether the table names in the schema are plural.\n debugLogs: config.debugLogs ?? false, // Whether to enable debug logs.\n supportsJSON: false, // Whether the database supports JSON. (Default: false)\n supportsDates: false, // Whether the database supports dates. (Default: true)\n supportsBooleans: false, // Whether the database supports booleans. (Default: true)\n supportsNumericIds: false, // Whether the database supports auto-incrementing numeric IDs. (Default: true)\n },\n adapter: ({ options }) => {\n return {\n options: { config },\n create: async ({ data, model, select }) => {\n if (model === \"session\") {\n console.log(\"session\", data);\n }\n\n const result = await fetch(`/${model}`, {\n method: \"POST\",\n body: data,\n output: z.looseObject({ id: z.string() }),\n });\n\n if (result.error) {\n throw new Error(\"Failed to create record\");\n }\n\n return result.data as any;\n },\n count: async ({ model, where }) => {\n const filter = parseWhere(where);\n logger.debug(\"$filter\", filter);\n\n const query = buildQuery({\n filter: filter.length > 0 ? filter : undefined,\n });\n\n const result = await fetch(`/${model}/$count${query}`, {\n method: \"GET\",\n output: z.object({ value: z.number() }),\n });\n if (!result.data) {\n throw new Error(\"Failed to count records\");\n }\n return (result.data?.value as any) ?? 0;\n },\n findOne: async ({ model, where }) => {\n const filter = parseWhere(where);\n logger.debug(\"$filter\", filter);\n\n const query = buildQuery({\n top: 1,\n filter: filter.length > 0 ? filter : undefined,\n });\n\n const result = await fetch(`/${model}${query}`, {\n method: \"GET\",\n output: z.object({ value: z.array(z.any()) }),\n });\n if (result.error) {\n throw new Error(\"Failed to find record\");\n }\n return (result.data?.value?.[0] as any) ?? null;\n },\n findMany: async ({ model, where, limit, offset, sortBy }) => {\n const filter = parseWhere(where);\n logger.debug(\"FIND MANY\", { where, filter });\n\n const query = buildQuery({\n top: limit,\n skip: offset,\n orderBy: sortBy\n ? `${sortBy.field} ${sortBy.direction ?? \"asc\"}`\n : undefined,\n filter: filter.length > 0 ? filter : undefined,\n });\n logger.debug(\"QUERY\", query);\n\n const result = await fetch(`/${model}${query}`, {\n method: \"GET\",\n output: z.object({ value: z.array(z.any()) }),\n });\n logger.debug(\"RESULT\", result);\n\n if (result.error) {\n throw new Error(\"Failed to find records\");\n }\n\n return (result.data?.value as any) ?? [];\n },\n delete: async ({ model, where }) => {\n const filter = parseWhere(where);\n console.log(\"DELETE\", { model, where, filter });\n logger.debug(\"$filter\", filter);\n\n // Find a single id matching the filter\n const query = buildQuery({\n top: 1,\n select: [`\"id\"`],\n filter: filter.length > 0 ? filter : undefined,\n });\n\n const toDelete = await fetch(`/${model}${query}`, {\n method: \"GET\",\n output: z.object({ value: z.array(z.object({ id: z.string() })) }),\n });\n\n const id = toDelete.data?.value?.[0]?.id;\n if (!id) {\n // Nothing to delete\n return;\n }\n\n const result = await fetch(`/${model}('${id}')`, {\n method: \"DELETE\",\n });\n if (result.error) {\n console.log(\"DELETE ERROR\", result.error);\n throw new Error(\"Failed to delete record\");\n }\n },\n deleteMany: async ({ model, where }) => {\n const filter = parseWhere(where);\n console.log(\"DELETE MANY\", { model, where, filter });\n\n // Find all ids matching the filter\n const query = buildQuery({\n select: [`\"id\"`],\n filter: filter.length > 0 ? filter : undefined,\n });\n\n const rows = await fetch(`/${model}${query}`, {\n method: \"GET\",\n output: z.object({ value: z.array(z.object({ id: z.string() })) }),\n });\n\n const ids = rows.data?.value?.map((r: any) => r.id) ?? [];\n let deleted = 0;\n for (const id of ids) {\n const res = await fetch(`/${model}('${id}')`, {\n method: \"DELETE\",\n });\n if (!res.error) deleted++;\n }\n return deleted;\n },\n update: async ({ model, where, update }) => {\n const filter = parseWhere(where);\n logger.debug(\"UPDATE\", { model, where, update });\n logger.debug(\"$filter\", filter);\n // Find one id to update\n const query = buildQuery({\n select: [`\"id\"`],\n filter: filter.length > 0 ? filter : undefined,\n });\n\n const existing = await fetch(`/${model}${query}`, {\n method: \"GET\",\n output: z.object({ value: z.array(z.object({ id: z.string() })) }),\n });\n logger.debug(\"EXISTING\", existing.data);\n\n const id = existing.data?.value?.[0]?.id;\n if (!id) return null;\n\n const patchRes = await fetch(`/${model}('${id}')`, {\n method: \"PATCH\",\n body: update,\n });\n logger.debug(\"PATCH RES\", patchRes.data);\n if (patchRes.error) return null;\n\n // Read back the updated record\n const readBack = await fetch(`/${model}('${id}')`, {\n method: \"GET\",\n output: z.record(z.string(), z.unknown()),\n });\n logger.debug(\"READ BACK\", readBack.data);\n return (readBack.data as any) ?? null;\n },\n updateMany: async ({ model, where, update }) => {\n const filter = parseWhere(where);\n // Find all ids matching the filter\n const query = buildQuery({\n select: [`\"id\"`],\n filter: filter.length > 0 ? filter : undefined,\n });\n\n const rows = await fetch(`/${model}${query}`, {\n method: \"GET\",\n output: z.object({ value: z.array(z.object({ id: z.string() })) }),\n });\n\n const ids = rows.data?.value?.map((r: any) => r.id) ?? [];\n let updated = 0;\n for (const id of ids) {\n const res = await fetch(`/${model}('${id}')`, {\n method: \"PATCH\",\n body: update,\n });\n if (!res.error) updated++;\n }\n return updated as any;\n },\n };\n },\n });\n};\n"],"names":[],"mappings":"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"}
|
package/dist/esm/cli/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { getConfig } from "../better-auth-cli/utils/get-config.js";
|
|
|
7
7
|
import { logger } from "better-auth";
|
|
8
8
|
import prompts from "prompts";
|
|
9
9
|
import chalk from "chalk";
|
|
10
|
-
import {
|
|
10
|
+
import { createRawFetch } from "../odata/index.js";
|
|
11
11
|
import "dotenv/config";
|
|
12
12
|
async function main() {
|
|
13
13
|
const program = new Command();
|
|
@@ -43,7 +43,7 @@ async function main() {
|
|
|
43
43
|
}
|
|
44
44
|
const betterAuthSchema = getAuthTables(config);
|
|
45
45
|
const adapterConfig = adapter.options.config;
|
|
46
|
-
const fetch =
|
|
46
|
+
const { fetch } = createRawFetch({
|
|
47
47
|
...adapterConfig.odata,
|
|
48
48
|
auth: (
|
|
49
49
|
// If the username and password are provided in the CLI, use them to authenticate instead of what's in the config file.
|
|
@@ -51,7 +51,9 @@ async function main() {
|
|
|
51
51
|
username: options.username,
|
|
52
52
|
password: options.password
|
|
53
53
|
} : adapterConfig.odata.auth
|
|
54
|
-
)
|
|
54
|
+
),
|
|
55
|
+
logging: "verbose"
|
|
56
|
+
// Enable logging for CLI operations
|
|
55
57
|
});
|
|
56
58
|
const migrationPlan = await planMigration(
|
|
57
59
|
fetch,
|
|
@@ -1 +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 prompts from \"prompts\";\nimport chalk from \"chalk\";\nimport { AdapterOptions } from \"../adapter\";\nimport {
|
|
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 prompts from \"prompts\";\nimport chalk from \"chalk\";\nimport { AdapterOptions } from \"../adapter\";\nimport { createRawFetch } from \"../odata\";\nimport \"dotenv/config\";\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 { fetch } = createRawFetch({\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 logging: \"verbose\", // Enable logging for CLI operations\n });\n\n const migrationPlan = await planMigration(\n fetch,\n betterAuthSchema,\n adapterConfig.odata.database,\n );\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(fetch, 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,EAAE,MAAM,IAAI,eAAe;AAAA,MAC/B,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,MAC1B,SAAS;AAAA;AAAA,IAAA,CACV;AAED,UAAM,gBAAgB,MAAM;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,cAAc,MAAM;AAAA,IACtB;AAEI,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,OAAO,aAAa;AAE3C,WAAO,KAAK,iCAAiC;AAAA,EAAA,CAC9C;AACG,QAAA,QAAQ,WAAW,QAAQ,IAAI;AACrC,UAAQ,KAAK,CAAC;AAChB;AAEA,OAAO,MAAM,QAAQ,KAAK;"}
|
package/dist/esm/migrate.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BetterAuthDbSchema } from 'better-auth/db';
|
|
2
2
|
import { Metadata } from 'fm-odata-client';
|
|
3
3
|
import { default as z } from 'zod/v4';
|
|
4
|
-
import {
|
|
5
|
-
export declare function getMetadata(fetch: ReturnType<typeof
|
|
6
|
-
export declare function planMigration(fetch: ReturnType<typeof
|
|
7
|
-
export declare function executeMigration(fetch: ReturnType<typeof
|
|
4
|
+
import { createRawFetch } from './odata.js';
|
|
5
|
+
export declare function getMetadata(fetch: ReturnType<typeof createRawFetch>["fetch"], databaseName: string): Promise<Metadata | null>;
|
|
6
|
+
export declare function planMigration(fetch: ReturnType<typeof createRawFetch>["fetch"], betterAuthSchema: BetterAuthDbSchema, databaseName: string): Promise<MigrationPlan>;
|
|
7
|
+
export declare function executeMigration(fetch: ReturnType<typeof createRawFetch>["fetch"], migrationPlan: MigrationPlan): Promise<void>;
|
|
8
8
|
declare const migrationPlanSchema: z.ZodArray<z.ZodObject<{
|
|
9
9
|
tableName: z.ZodString;
|
|
10
10
|
operation: z.ZodEnum<{
|
package/dist/esm/migrate.js
CHANGED
|
@@ -11,6 +11,10 @@ async function getMetadata(fetch, databaseName) {
|
|
|
11
11
|
"@ServerVersion": z.string()
|
|
12
12
|
}).or(z.null()).catch(null)
|
|
13
13
|
});
|
|
14
|
+
if (result.error) {
|
|
15
|
+
console.error("Failed to get metadata:", result.error);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
14
18
|
return ((_a = result.data) == null ? void 0 : _a[databaseName]) ?? null;
|
|
15
19
|
}
|
|
16
20
|
async function planMigration(fetch, betterAuthSchema, databaseName) {
|
|
@@ -105,18 +109,33 @@ async function executeMigration(fetch, migrationPlan) {
|
|
|
105
109
|
for (const step of migrationPlan) {
|
|
106
110
|
if (step.operation === "create") {
|
|
107
111
|
console.log("Creating table:", step.tableName);
|
|
108
|
-
await fetch("
|
|
112
|
+
const result = await fetch("/FileMaker_Tables", {
|
|
113
|
+
method: "POST",
|
|
109
114
|
body: {
|
|
110
115
|
tableName: step.tableName,
|
|
111
116
|
fields: step.fields
|
|
112
117
|
}
|
|
113
118
|
});
|
|
119
|
+
if (result.error) {
|
|
120
|
+
console.error(
|
|
121
|
+
`Failed to create table ${step.tableName}:`,
|
|
122
|
+
result.error
|
|
123
|
+
);
|
|
124
|
+
throw new Error(`Migration failed: ${result.error}`);
|
|
125
|
+
}
|
|
114
126
|
} else if (step.operation === "update") {
|
|
115
127
|
console.log("Adding fields to table:", step.tableName);
|
|
116
|
-
await fetch(
|
|
117
|
-
|
|
128
|
+
const result = await fetch(`/FileMaker_Tables/${step.tableName}`, {
|
|
129
|
+
method: "PATCH",
|
|
118
130
|
body: { fields: step.fields }
|
|
119
131
|
});
|
|
132
|
+
if (result.error) {
|
|
133
|
+
console.error(
|
|
134
|
+
`Failed to update table ${step.tableName}:`,
|
|
135
|
+
result.error
|
|
136
|
+
);
|
|
137
|
+
throw new Error(`Migration failed: ${result.error}`);
|
|
138
|
+
}
|
|
120
139
|
}
|
|
121
140
|
}
|
|
122
141
|
}
|
package/dist/esm/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sources":["../../src/migrate.ts"],"sourcesContent":["import { type BetterAuthDbSchema } from \"better-auth/db\";\nimport { type Metadata } from \"fm-odata-client\";\nimport chalk from \"chalk\";\nimport z from \"zod/v4\";\nimport { createFmOdataFetch } from \"./odata\";\n\nexport async function getMetadata(\n fetch: ReturnType<typeof createFmOdataFetch>,\n databaseName: string,\n) {\n console.log(\"getting metadata...\");\n const result = await fetch(\"/$metadata\", {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n output: z\n .looseObject({\n $Version: z.string(),\n \"@ServerVersion\": z.string(),\n })\n .or(z.null())\n .catch(null),\n });\n\n return (result.data?.[databaseName] ?? null) as Metadata | null;\n}\n\nexport async function planMigration(\n fetch: ReturnType<typeof createFmOdataFetch>,\n betterAuthSchema: BetterAuthDbSchema,\n databaseName: string,\n): Promise<MigrationPlan> {\n const metadata = await getMetadata(fetch, databaseName);\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 ? \"varchar\"\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 : \"varchar\",\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 : \"varchar\",\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: \"varchar\",\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 fetch: ReturnType<typeof createFmOdataFetch>,\n migrationPlan: MigrationPlan,\n) {\n for (const step of migrationPlan) {\n if (step.operation === \"create\") {\n console.log(\"Creating table:\", step.tableName);\n await fetch(\"@post/FileMaker_Tables\", {\n body: {\n tableName: step.tableName,\n fields: step.fields,\n },\n });\n } else if (step.operation === \"update\") {\n console.log(\"Adding fields to table:\", step.tableName);\n await fetch(\"@post/FileMaker_Tables/:tableName\", {\n params: { tableName: step.tableName },\n body: { fields: step.fields },\n });\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(\"varchar\"),\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\ntype FmField = z.infer<typeof fieldSchema>;\n\nconst 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":";;AAMsB,eAAA,YACpB,OACA,cACA;;AACA,UAAQ,IAAI,qBAAqB;AAC3B,QAAA,SAAS,MAAM,MAAM,cAAc;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS,EAAE,QAAQ,mBAAmB;AAAA,IACtC,QAAQ,EACL,YAAY;AAAA,MACX,UAAU,EAAE,OAAO;AAAA,MACnB,kBAAkB,EAAE,OAAO;AAAA,IAAA,CAC5B,EACA,GAAG,EAAE,MAAM,EACX,MAAM,IAAI;AAAA,EAAA,CACd;AAEO,WAAA,YAAO,SAAP,mBAAc,kBAAiB;AACzC;AAEsB,eAAA,cACpB,OACA,kBACA,cACwB;AACxB,QAAM,WAAW,MAAM,YAAY,OAAO,YAAY;AAGtD,MAAI,kBAA0C,CAAC;AAC/C,MAAI,UAAU;AACZ,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,UAAI,MAAM,UAAU,eAAe,MAAM,OAAO;AAE9C,cAAM,UAAU,MAAM,MAAM,MAAM,GAAG,EAAE,IAAI;AAC3B,wBAAA,GAAG,IAAI,WAAW;AAAA,MAAA;AAAA,IACpC;AAAA,EACF;AAGF,QAAM,iBAAiB,WACnB,OAAO,QAAQ,eAAe,EAAE;AAAA,IAC9B,CAAC,KAAK,CAAC,eAAe,aAAa,MAAM;AACjC,YAAA,aAAa,SAAS,aAAa;AACrC,UAAA,CAAC,WAAmB,QAAA;AACxB,YAAM,SAAS,OAAO,QAAQ,UAAU,EACrC;AAAA,QACC,CAAC,CAAC,UAAU,UAAU,MACpB,OAAO,eAAe,YACtB,eAAe,QACf,WAAW;AAAA,QAEd,IAAI,CAAC,CAAC,UAAU,UAAU,OAAO;AAAA,QAChC,MAAM;AAAA,QACN,MACE,WAAW,UAAU,eACjB,YACA,WAAW,UAAU,uBACnB,cACA,WAAW,UAAU,iBACnB,WAAW,UAAU,eACrB,WAAW,UAAU,cACrB,YACA;AAAA,MAAA,EACV;AACJ,UAAI,aAAa,IAAI;AACd,aAAA;AAAA,IACT;AAAA,IACA,CAAA;AAAA,EAAC,IAEH,CAAC;AAEC,QAAA,WAAW,OAAO,QAAQ,gBAAgB,EAC7C,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,EACpD,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,IACtB,GAAG;AAAA,IACH,SAAS;AAAA,EAAA,EACT;AAEJ,QAAM,gBAA+B,CAAC;AAEtC,aAAW,WAAW,UAAU;AAC9B,UAAM,SAAoB,OAAO,QAAQ,QAAQ,MAAM,EAAE;AAAA,MACvD,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,QACjB,MAAM,MAAM,aAAa;AAAA,QACzB,MACE,MAAM,SAAS,aAAa,MAAM,KAAK,SAAS,QAAQ,IACpD,YACA,MAAM,SAAS,SACb,cACA;AAAA,MACV;AAAA,IACF;AAGM,UAAA,cAAc,OAAO,UAAU,eAAe;AAAA,MAClD;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,QAAI,CAAC,aAAa;AAChB,oBAAc,KAAK;AAAA,QACjB,WAAW,QAAQ;AAAA,QACnB,WAAW;AAAA,QACX,QAAQ;AAAA,UACN;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,SAAS;AAAA,YACT,QAAQ;AAAA,UACV;AAAA,UACA,GAAG;AAAA,QAAA;AAAA,MACL,CACD;AAAA,IAAA,OACI;AACL,YAAM,kBAAkB,eAAe,QAAQ,SAAS,KAAK,CAAA,GAAI;AAAA,QAC/D,CAAC,MAAM,EAAE;AAAA,MACX;AACA,YAAM,oBAAoB,eAAe,QAAQ,SAAS,KAAK,CAAA,GAAI;AAAA,QACjE,CAAC,KAAK,MAAM;AACN,cAAA,EAAE,IAAI,IAAI,EAAE;AACT,iBAAA;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAEO,aAAA,QAAQ,CAAC,UAAU;AAEtB,YAAA,eAAe,SAAS,MAAM,IAAI,KAClC,iBAAiB,MAAM,IAAI,MAAM,MAAM,MACvC;AACQ,kBAAA;AAAA,YACN,sBAAsB,MAAM,IAAI,eAAe,QAAQ,SAAS,0BAA0B,iBAAiB,MAAM,IAAI,CAAC,gBAAgB,MAAM,IAAI;AAAA,UAClJ;AAAA,QAAA;AAAA,MACF,CACD;AACD,YAAM,cAAc,OAAO;AAAA,QACzB,CAAC,MAAM,CAAC,eAAe,SAAS,EAAE,IAAI;AAAA,MACxC;AACI,UAAA,YAAY,SAAS,GAAG;AAC1B,sBAAc,KAAK;AAAA,UACjB,WAAW,QAAQ;AAAA,UACnB,WAAW;AAAA,UACX,QAAQ;AAAA,QAAA,CACT;AAAA,MAAA;AAAA,IACH;AAAA,EACF;AAGK,SAAA;AACT;AAEsB,eAAA,iBACpB,OACA,eACA;AACA,aAAW,QAAQ,eAAe;AAC5B,QAAA,KAAK,cAAc,UAAU;AACvB,cAAA,IAAI,mBAAmB,KAAK,SAAS;AAC7C,YAAM,MAAM,0BAA0B;AAAA,QACpC,MAAM;AAAA,UACJ,WAAW,KAAK;AAAA,UAChB,QAAQ,KAAK;AAAA,QAAA;AAAA,MACf,CACD;AAAA,IAAA,WACQ,KAAK,cAAc,UAAU;AAC9B,cAAA,IAAI,2BAA2B,KAAK,SAAS;AACrD,YAAM,MAAM,qCAAqC;AAAA,QAC/C,QAAQ,EAAE,WAAW,KAAK,UAAU;AAAA,QACpC,MAAM,EAAE,QAAQ,KAAK,OAAO;AAAA,MAAA,CAC7B;AAAA,IAAA;AAAA,EACH;AAEJ;AAEA,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,OAAO;AAAA,EACf,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC/B,SAAS,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC9B,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC7B,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC7B,aAAa,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AAED,MAAM,oBAAoB,mBAAmB,OAAO;AAAA,EAClD,MAAM,EAAE,QAAQ,SAAS;AAAA,EACzB,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,YAAY,cAAc,CAAC,EAAE,SAAS;AACjE,CAAC;AAED,MAAM,qBAAqB,mBAAmB,OAAO;AAAA,EACnD,MAAM,EAAE,QAAQ,SAAS;AAC3B,CAAC;AAED,MAAM,kBAAkB,mBAAmB,OAAO;AAAA,EAChD,MAAM,EAAE,QAAQ,MAAM;AAAA,EACtB,SAAS,EAAE,KAAK,CAAC,gBAAgB,SAAS,CAAC,EAAE,SAAS;AACxD,CAAC;AAED,MAAM,kBAAkB,mBAAmB,OAAO;AAAA,EAChD,MAAM,EAAE,QAAQ,MAAM;AAAA,EACtB,SAAS,EAAE,KAAK,CAAC,gBAAgB,SAAS,CAAC,EAAE,SAAS;AACxD,CAAC;AAED,MAAM,uBAAuB,mBAAmB,OAAO;AAAA,EACrD,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,SAAS,EAAE,KAAK,CAAC,qBAAqB,cAAc,CAAC,EAAE,SAAS;AAClE,CAAC;AAED,MAAM,uBAAuB,mBAAmB,OAAO;AAAA,EACrD,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAC1C,CAAC;AAED,MAAM,cAAc,EAAE,mBAAmB,QAAQ;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAI2B,EACzB,OAAO;AAAA,EACN,WAAW,EAAE,OAAO;AAAA,EACpB,WAAW,EAAE,KAAK,CAAC,UAAU,QAAQ,CAAC;AAAA,EACtC,QAAQ,EAAE,MAAM,WAAW;AAC7B,CAAC,EACA,MAAM;AAIF,SAAS,yBAAyB,eAA8B;AACjE,MAAA,CAAC,cAAc,QAAQ;AACzB,YAAQ,IAAI,8CAA8C;AAC1D;AAAA,EAAA;AAEF,UAAQ,IAAI,MAAM,KAAK,MAAM,iBAAiB,CAAC;AAC/C,aAAW,QAAQ,eAAe;AAChC,UAAM,QAAQ,KAAK,cAAc,WAAW,MAAM;AAC1C,YAAA;AAAA,MACN;AAAA,EAAK,KAAK,IAAI,KAAK,cAAc,WAAW,MAAM,KAAK,MAAM,cAAc,IAAI,MAAM,KAAK,OAAO,cAAc,CAAC,KAAK,KAAK,SAAS;AAAA,IACrI;AACI,QAAA,KAAK,OAAO,QAAQ;AACX,iBAAA,SAAS,KAAK,QAAQ;AAC/B,YAAI,YAAY,SAAS,MAAM,IAAI,KAAK,MAAM,IAAI;AAC9C,YAAA,MAAM,QAAsB,cAAA;AAC5B,YAAA,MAAM,OAAqB,cAAA;AAClB,qBAAA;AACb,gBAAQ,IAAI,SAAS;AAAA,MAAA;AAAA,IACvB,OACK;AACL,cAAQ,IAAI,wBAAwB;AAAA,IAAA;AAAA,EACtC;AAEF,UAAQ,IAAI,EAAE;AAChB;"}
|
|
1
|
+
{"version":3,"file":"migrate.js","sources":["../../src/migrate.ts"],"sourcesContent":["import { type BetterAuthDbSchema } from \"better-auth/db\";\nimport { type Metadata } from \"fm-odata-client\";\nimport chalk from \"chalk\";\nimport z from \"zod/v4\";\nimport { createRawFetch } from \"./odata\";\n\nexport async function getMetadata(\n fetch: ReturnType<typeof createRawFetch>[\"fetch\"],\n databaseName: string,\n) {\n console.log(\"getting metadata...\");\n const result = await fetch(\"/$metadata\", {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n output: z\n .looseObject({\n $Version: z.string(),\n \"@ServerVersion\": z.string(),\n })\n .or(z.null())\n .catch(null),\n });\n\n if (result.error) {\n console.error(\"Failed to get metadata:\", result.error);\n return null;\n }\n\n return (result.data?.[databaseName] ?? null) as Metadata | null;\n}\n\nexport async function planMigration(\n fetch: ReturnType<typeof createRawFetch>[\"fetch\"],\n betterAuthSchema: BetterAuthDbSchema,\n databaseName: string,\n): Promise<MigrationPlan> {\n const metadata = await getMetadata(fetch, databaseName);\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 ? \"varchar\"\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 : \"varchar\",\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 : \"varchar\",\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: \"varchar\",\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 fetch: ReturnType<typeof createRawFetch>[\"fetch\"],\n migrationPlan: MigrationPlan,\n) {\n for (const step of migrationPlan) {\n if (step.operation === \"create\") {\n console.log(\"Creating table:\", step.tableName);\n const result = await fetch(\"/FileMaker_Tables\", {\n method: \"POST\",\n body: {\n tableName: step.tableName,\n fields: step.fields,\n },\n });\n\n if (result.error) {\n console.error(\n `Failed to create table ${step.tableName}:`,\n result.error,\n );\n throw new Error(`Migration failed: ${result.error}`);\n }\n } else if (step.operation === \"update\") {\n console.log(\"Adding fields to table:\", step.tableName);\n const result = await fetch(`/FileMaker_Tables/${step.tableName}`, {\n method: \"PATCH\",\n body: { fields: step.fields },\n });\n\n if (result.error) {\n console.error(\n `Failed to update table ${step.tableName}:`,\n result.error,\n );\n throw new Error(`Migration failed: ${result.error}`);\n }\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(\"varchar\"),\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\ntype FmField = z.infer<typeof fieldSchema>;\n\nconst 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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"}
|
|
@@ -14,90 +14,16 @@ export type FmOdataConfig = {
|
|
|
14
14
|
database: string;
|
|
15
15
|
logging?: true | "verbose" | "none";
|
|
16
16
|
};
|
|
17
|
-
export declare function createFmOdataFetch(args: FmOdataConfig): import('@better-fetch/fetch').BetterFetch<{
|
|
18
|
-
baseURL: string;
|
|
19
|
-
auth: {
|
|
20
|
-
type: "Bearer";
|
|
21
|
-
token: string;
|
|
22
|
-
username?: undefined;
|
|
23
|
-
password?: undefined;
|
|
24
|
-
} | {
|
|
25
|
-
type: "Basic";
|
|
26
|
-
username: string;
|
|
27
|
-
password: string;
|
|
28
|
-
token?: undefined;
|
|
29
|
-
};
|
|
30
|
-
onError: (error: import('@better-fetch/fetch').ErrorContext) => void;
|
|
31
|
-
schema: {
|
|
32
|
-
schema: {
|
|
33
|
-
"@post/FileMaker_Tables": {
|
|
34
|
-
input: z.ZodObject<{
|
|
35
|
-
tableName: z.ZodString;
|
|
36
|
-
fields: z.ZodArray<z.ZodAny>;
|
|
37
|
-
}, z.core.$strip>;
|
|
38
|
-
};
|
|
39
|
-
"@patch/FileMaker_Tables/:tableName": {
|
|
40
|
-
params: z.ZodObject<{
|
|
41
|
-
tableName: z.ZodString;
|
|
42
|
-
}, z.core.$strip>;
|
|
43
|
-
input: z.ZodObject<{
|
|
44
|
-
fields: z.ZodArray<z.ZodAny>;
|
|
45
|
-
}, z.core.$strip>;
|
|
46
|
-
};
|
|
47
|
-
"@delete/FileMaker_Tables/:tableName": {
|
|
48
|
-
params: z.ZodObject<{
|
|
49
|
-
tableName: z.ZodString;
|
|
50
|
-
}, z.core.$strip>;
|
|
51
|
-
};
|
|
52
|
-
"@delete/FileMaker_Tables/:tableName/:fieldName": {
|
|
53
|
-
params: z.ZodObject<{
|
|
54
|
-
tableName: z.ZodString;
|
|
55
|
-
fieldName: z.ZodString;
|
|
56
|
-
}, z.core.$strip>;
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
config: import('@better-fetch/fetch').SchemaConfig;
|
|
60
|
-
};
|
|
61
|
-
plugins: {
|
|
62
|
-
id: string;
|
|
63
|
-
name: string;
|
|
64
|
-
version: string;
|
|
65
|
-
hooks: {
|
|
66
|
-
onRequest<T extends Record<string, any>>(context: import('@better-fetch/fetch').RequestContext<T>): void;
|
|
67
|
-
onSuccess(context: import('@better-fetch/fetch').SuccessContext<any>): Promise<void>;
|
|
68
|
-
onRetry(response: import('@better-fetch/fetch').ResponseContext): void;
|
|
69
|
-
onError(context: import('@better-fetch/fetch').ErrorContext): Promise<void>;
|
|
70
|
-
};
|
|
71
|
-
}[];
|
|
72
|
-
}, unknown, unknown, {
|
|
73
|
-
schema: {
|
|
74
|
-
"@post/FileMaker_Tables": {
|
|
75
|
-
input: z.ZodObject<{
|
|
76
|
-
tableName: z.ZodString;
|
|
77
|
-
fields: z.ZodArray<z.ZodAny>;
|
|
78
|
-
}, z.core.$strip>;
|
|
79
|
-
};
|
|
80
|
-
"@patch/FileMaker_Tables/:tableName": {
|
|
81
|
-
params: z.ZodObject<{
|
|
82
|
-
tableName: z.ZodString;
|
|
83
|
-
}, z.core.$strip>;
|
|
84
|
-
input: z.ZodObject<{
|
|
85
|
-
fields: z.ZodArray<z.ZodAny>;
|
|
86
|
-
}, z.core.$strip>;
|
|
87
|
-
};
|
|
88
|
-
"@delete/FileMaker_Tables/:tableName": {
|
|
89
|
-
params: z.ZodObject<{
|
|
90
|
-
tableName: z.ZodString;
|
|
91
|
-
}, z.core.$strip>;
|
|
92
|
-
};
|
|
93
|
-
"@delete/FileMaker_Tables/:tableName/:fieldName": {
|
|
94
|
-
params: z.ZodObject<{
|
|
95
|
-
tableName: z.ZodString;
|
|
96
|
-
fieldName: z.ZodString;
|
|
97
|
-
}, z.core.$strip>;
|
|
98
|
-
};
|
|
99
|
-
};
|
|
100
|
-
config: import('@better-fetch/fetch').SchemaConfig;
|
|
101
|
-
}>;
|
|
102
17
|
export declare function validateUrl(input: string): Result<URL, unknown>;
|
|
18
|
+
export declare function createRawFetch(args: FmOdataConfig): {
|
|
19
|
+
baseURL: string;
|
|
20
|
+
fetch: <TOutput = any>(input: string | URL | Request, options?: Omit<RequestInit, "body"> & {
|
|
21
|
+
body?: any;
|
|
22
|
+
output?: z.ZodSchema<TOutput>;
|
|
23
|
+
}) => Promise<{
|
|
24
|
+
data?: TOutput;
|
|
25
|
+
error?: string;
|
|
26
|
+
response?: Response;
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
103
29
|
export {};
|