@better-auth/cli 1.4.6-beta.3 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +102 -38
  2. package/package.json +7 -6
package/dist/index.mjs CHANGED
@@ -104,19 +104,19 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
104
104
  mysql: `timestamp('${name}', { fsp: 3 })`
105
105
  },
106
106
  "number[]": {
107
- sqlite: `integer('${name}').array()`,
107
+ sqlite: `text('${name}', { mode: "json" })`,
108
108
  pg: field.bigint ? `bigint('${name}', { mode: 'number' }).array()` : `integer('${name}').array()`,
109
- mysql: field.bigint ? `bigint('${name}', { mode: 'number' }).array()` : `int('${name}').array()`
109
+ mysql: `text('${name}', { mode: 'json' })`
110
110
  },
111
111
  "string[]": {
112
- sqlite: `text('${name}').array()`,
112
+ sqlite: `text('${name}', { mode: "json" })`,
113
113
  pg: `text('${name}').array()`,
114
- mysql: `text('${name}').array()`
114
+ mysql: `text('${name}', { mode: "json" })`
115
115
  },
116
116
  json: {
117
- sqlite: `text('${name}')`,
117
+ sqlite: `text('${name}', { mode: "json" })`,
118
118
  pg: `jsonb('${name}')`,
119
- mysql: `json('${name}')`
119
+ mysql: `json('${name}', { mode: "json" })`
120
120
  }
121
121
  }[type];
122
122
  if (!dbTypeMap) throw new Error(`Unsupported field type '${field.type}' for field '${name}'.`);
@@ -174,50 +174,104 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
174
174
  let relationsString = "";
175
175
  for (const tableKey in tables) {
176
176
  const table = tables[tableKey];
177
- const relations = [];
177
+ const modelName = getModelName(tableKey);
178
+ const oneRelations = [];
179
+ const manyRelations = [];
180
+ const manyRelationsSet = /* @__PURE__ */ new Set();
178
181
  const foreignFields = Object.entries(table.fields).filter(([_, field]) => field.references);
179
182
  for (const [fieldName, field] of foreignFields) {
180
183
  const referencedModel = field.references.model;
181
- relations.push({
182
- key: getModelName(referencedModel),
184
+ const relationKey = getModelName(referencedModel);
185
+ const fieldRef = `${getModelName(tableKey)}.${getFieldName({
186
+ model: tableKey,
187
+ field: fieldName
188
+ })}`;
189
+ const referenceRef = `${getModelName(referencedModel)}.${getFieldName({
190
+ model: referencedModel,
191
+ field: field.references.field || "id"
192
+ })}`;
193
+ oneRelations.push({
194
+ key: relationKey,
183
195
  model: getModelName(referencedModel),
184
196
  type: "one",
185
197
  reference: {
186
- field: `${getModelName(tableKey)}.${getFieldName({
187
- model: tableKey,
188
- field: fieldName
189
- })}`,
190
- references: `${getModelName(referencedModel)}.${getFieldName({
191
- model: referencedModel,
192
- field: field.references.field || "id"
193
- })}`
198
+ field: fieldRef,
199
+ references: referenceRef,
200
+ fieldName
194
201
  }
195
202
  });
196
203
  }
197
- const otherModels = Object.entries(tables).filter(([modelName]) => modelName !== tableKey);
198
- for (const [modelName, otherTable] of otherModels) {
204
+ const otherModels = Object.entries(tables).filter(([modelName$1]) => modelName$1 !== tableKey);
205
+ const modelRelationsMap = /* @__PURE__ */ new Map();
206
+ for (const [modelName$1, otherTable] of otherModels) {
199
207
  const foreignKeysPointingHere = Object.entries(otherTable.fields).filter(([_, field]) => field.references?.model === tableKey || field.references?.model === getModelName(tableKey));
200
- for (const [fieldName, field] of foreignKeysPointingHere) {
201
- const isUnique = !!field.unique;
202
- let relationKey = getModelName(modelName);
203
- if (!adapter.options?.adapterConfig?.usePlural && !isUnique) relationKey = `${relationKey}s`;
204
- const model = getModelName(modelName);
205
- relations.push({
208
+ if (foreignKeysPointingHere.length === 0) continue;
209
+ const hasUnique = foreignKeysPointingHere.some(([_, field]) => !!field.unique);
210
+ const hasMany$1 = foreignKeysPointingHere.some(([_, field]) => !field.unique);
211
+ modelRelationsMap.set(modelName$1, {
212
+ modelName: modelName$1,
213
+ hasUnique,
214
+ hasMany: hasMany$1
215
+ });
216
+ }
217
+ for (const { modelName: modelName$1, hasUnique, hasMany: hasMany$1 } of modelRelationsMap.values()) {
218
+ const relationType = hasMany$1 ? "many" : "one";
219
+ let relationKey = getModelName(modelName$1);
220
+ if (!adapter.options?.adapterConfig?.usePlural && relationType === "many") relationKey = `${relationKey}s`;
221
+ if (!manyRelationsSet.has(relationKey)) {
222
+ manyRelationsSet.add(relationKey);
223
+ manyRelations.push({
206
224
  key: relationKey,
207
- model,
208
- type: isUnique ? "one" : "many"
225
+ model: getModelName(modelName$1),
226
+ type: relationType
209
227
  });
210
228
  }
211
229
  }
212
- const hasOne = relations.some((relation) => relation.type === "one");
213
- const hasMany = relations.some((relation) => relation.type === "many");
214
- let tableRelation = `export const ${table.modelName}Relations = relations(${getModelName(table.modelName)}, ({ ${hasOne ? "one" : ""}${hasMany ? `${hasOne ? ", " : ""}many` : ""} }) => ({
215
- ${relations.map(({ key, type, model, reference }) => ` ${key}: ${type}(${model}${!reference ? "" : `, {
216
- fields: [${reference.field}],
217
- references: [${reference.references}],
218
- }`})`).join(",\n ")}
230
+ const relationsByModel = /* @__PURE__ */ new Map();
231
+ for (const relation of oneRelations) if (relation.reference) {
232
+ const modelKey = relation.key;
233
+ if (!relationsByModel.has(modelKey)) relationsByModel.set(modelKey, []);
234
+ relationsByModel.get(modelKey).push(relation);
235
+ }
236
+ const duplicateRelations = [];
237
+ const singleRelations = [];
238
+ for (const [modelKey, relations] of relationsByModel.entries()) if (relations.length > 1) duplicateRelations.push(...relations);
239
+ else singleRelations.push(relations[0]);
240
+ for (const relation of duplicateRelations) if (relation.reference) {
241
+ const fieldName = relation.reference.fieldName;
242
+ const tableRelation = `export const ${`${modelName}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}Relations`} = relations(${getModelName(table.modelName)}, ({ one }) => ({
243
+ ${relation.key}: one(${relation.model}, {
244
+ fields: [${relation.reference.field}],
245
+ references: [${relation.reference.references}],
246
+ })
247
+ }))`;
248
+ relationsString += `\n${tableRelation}\n`;
249
+ }
250
+ const hasOne = singleRelations.length > 0;
251
+ const hasMany = manyRelations.length > 0;
252
+ if (hasOne && hasMany) {
253
+ const tableRelation = `export const ${modelName}Relations = relations(${getModelName(table.modelName)}, ({ one, many }) => ({
254
+ ${singleRelations.map((relation) => relation.reference ? ` ${relation.key}: one(${relation.model}, {
255
+ fields: [${relation.reference.field}],
256
+ references: [${relation.reference.references}],
257
+ })` : "").filter((x) => x !== "").join(",\n ")}${singleRelations.length > 0 && manyRelations.length > 0 ? "," : ""}
258
+ ${manyRelations.map(({ key, model }) => ` ${key}: many(${model})`).join(",\n ")}
259
+ }))`;
260
+ relationsString += `\n${tableRelation}\n`;
261
+ } else if (hasOne) {
262
+ const tableRelation = `export const ${modelName}Relations = relations(${getModelName(table.modelName)}, ({ one }) => ({
263
+ ${singleRelations.map((relation) => relation.reference ? ` ${relation.key}: one(${relation.model}, {
264
+ fields: [${relation.reference.field}],
265
+ references: [${relation.reference.references}],
266
+ })` : "").filter((x) => x !== "").join(",\n ")}
219
267
  }))`;
220
- if (relations.length > 0) relationsString += `\n${tableRelation}\n`;
268
+ relationsString += `\n${tableRelation}\n`;
269
+ } else if (hasMany) {
270
+ const tableRelation = `export const ${modelName}Relations = relations(${getModelName(table.modelName)}, ({ many }) => ({
271
+ ${manyRelations.map(({ key, model }) => ` ${key}: many(${model})`).join(",\n ")}
272
+ }))`;
273
+ relationsString += `\n${tableRelation}\n`;
274
+ }
221
275
  }
222
276
  code += `\n${relationsString}`;
223
277
  return {
@@ -361,9 +415,18 @@ const generatePrismaSchema = async ({ adapter, options, file }) => {
361
415
  if (type === "number") return isOptional ? "Int?" : "Int";
362
416
  if (type === "boolean") return isOptional ? "Boolean?" : "Boolean";
363
417
  if (type === "date") return isOptional ? "DateTime?" : "DateTime";
364
- if (type === "json") return isOptional ? "Json?" : "Json";
365
- if (type === "string[]") return isOptional ? "String[]" : "String[]";
366
- if (type === "number[]") return isOptional ? "Int[]" : "Int[]";
418
+ if (type === "json") {
419
+ if (provider === "sqlite" || provider === "mysql") return isOptional ? "String?" : "String";
420
+ return isOptional ? "Json?" : "Json";
421
+ }
422
+ if (type === "string[]") {
423
+ if (provider === "sqlite" || provider === "mysql") return isOptional ? "String?" : "String";
424
+ return "String[]";
425
+ }
426
+ if (type === "number[]") {
427
+ if (provider === "sqlite" || provider === "mysql") return "String";
428
+ return "Int[]";
429
+ }
367
430
  }
368
431
  const prismaModel = builder.findByType("model", { name: modelName });
369
432
  if (!prismaModel) if (provider === "mongodb") builder.model(modelName).field("id", "String").attribute("id").attribute(`map("_id")`);
@@ -2964,6 +3027,7 @@ const mcp = new Command("mcp").description("Add Better Auth MCP server to MCP Cl
2964
3027
 
2965
3028
  //#endregion
2966
3029
  //#region src/commands/migrate.ts
3030
+ /** @internal */
2967
3031
  async function migrateAction(opts) {
2968
3032
  const options = z.object({
2969
3033
  cwd: z.string(),
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@better-auth/cli",
3
- "version": "1.4.6-beta.3",
3
+ "version": "1.4.6",
4
4
  "type": "module",
5
5
  "description": "The CLI for Better Auth",
6
6
  "module": "dist/index.mjs",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/better-auth/better-auth",
9
+ "url": "git+https://github.com/better-auth/better-auth.git",
10
10
  "directory": "packages/cli"
11
11
  },
12
12
  "homepage": "https://www.better-auth.com/docs/concepts/cli",
@@ -37,7 +37,7 @@
37
37
  "tsx": "^4.20.6",
38
38
  "type-fest": "^5.2.0",
39
39
  "typescript": "^5.9.3",
40
- "@better-auth/passkey": "1.4.6-beta.3"
40
+ "@better-auth/passkey": "1.4.6"
41
41
  },
42
42
  "dependencies": {
43
43
  "@babel/core": "^7.28.4",
@@ -61,9 +61,9 @@
61
61
  "semver": "^7.7.2",
62
62
  "yocto-spinner": "^0.2.3",
63
63
  "zod": "^4.1.12",
64
- "@better-auth/core": "1.4.6-beta.3",
65
- "@better-auth/telemetry": "1.4.6-beta.3",
66
- "better-auth": "^1.4.6-beta.3"
64
+ "@better-auth/core": "1.4.6",
65
+ "@better-auth/telemetry": "1.4.6",
66
+ "better-auth": "^1.4.6"
67
67
  },
68
68
  "files": [
69
69
  "dist"
@@ -74,6 +74,7 @@
74
74
  "lint:package": "publint run --strict",
75
75
  "dev": "tsx ./src/index.ts",
76
76
  "test": "vitest",
77
+ "coverage": "vitest run --coverage",
77
78
  "typecheck": "tsc --project tsconfig.json"
78
79
  }
79
80
  }