pecunia-root 0.0.7 → 0.0.9

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 (34) hide show
  1. package/dist/adapters/{drizzle → drizzle-adapter}/index.d.mts +1 -1
  2. package/dist/adapters/{drizzle → drizzle-adapter}/index.mjs +1 -1
  3. package/dist/adapters/drizzle-adapter/index.mjs.map +1 -0
  4. package/dist/adapters/get-adapter.mjs +2 -2
  5. package/dist/adapters/get-adapter.mjs.map +1 -1
  6. package/dist/adapters/{kysely → kysely-adapter}/bun-sqlite-dialect.mjs +1 -1
  7. package/dist/adapters/kysely-adapter/bun-sqlite-dialect.mjs.map +1 -0
  8. package/dist/adapters/{kysely → kysely-adapter}/dialect.mjs +1 -1
  9. package/dist/adapters/kysely-adapter/dialect.mjs.map +1 -0
  10. package/dist/adapters/{kysely → kysely-adapter}/index.d.mts +1 -1
  11. package/dist/adapters/{kysely → kysely-adapter}/index.mjs +1 -1
  12. package/dist/adapters/kysely-adapter/index.mjs.map +1 -0
  13. package/dist/adapters/{kysely → kysely-adapter}/node-sqlite-dialect.mjs +1 -1
  14. package/dist/adapters/kysely-adapter/node-sqlite-dialect.mjs.map +1 -0
  15. package/dist/adapters/{mongodb → mongodb-adapter}/index.d.mts +1 -1
  16. package/dist/adapters/{mongodb → mongodb-adapter}/index.mjs +1 -1
  17. package/dist/adapters/mongodb-adapter/index.mjs.map +1 -0
  18. package/dist/adapters/{prisma → prisma-adapter}/index.d.mts +1 -1
  19. package/dist/adapters/{prisma → prisma-adapter}/index.mjs +1 -1
  20. package/dist/adapters/prisma-adapter/index.mjs.map +1 -0
  21. package/dist/context/index.mjs +1 -1
  22. package/dist/context/index.mjs.map +1 -1
  23. package/dist/db/migrations/index.mjs +1 -1
  24. package/dist/db/migrations/index.mjs.map +1 -1
  25. package/dist/index.d.mts +4 -4
  26. package/dist/index.mjs +3 -3
  27. package/package.json +1 -1
  28. package/dist/adapters/drizzle/index.mjs.map +0 -1
  29. package/dist/adapters/kysely/bun-sqlite-dialect.mjs.map +0 -1
  30. package/dist/adapters/kysely/dialect.mjs.map +0 -1
  31. package/dist/adapters/kysely/index.mjs.map +0 -1
  32. package/dist/adapters/kysely/node-sqlite-dialect.mjs.map +0 -1
  33. package/dist/adapters/mongodb/index.mjs.map +0 -1
  34. package/dist/adapters/prisma/index.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { DBAdapter, DBAdapterDebugLogOption, PecuniaOptions } from "pecunia-core";
2
2
 
3
- //#region src/adapters/drizzle/index.d.ts
3
+ //#region src/adapters/drizzle-adapter/index.d.ts
4
4
  interface DB {
5
5
  [key: string]: any;
6
6
  }
@@ -1,7 +1,7 @@
1
1
  import { PecuniaError, createAdapterFactory, logger } from "pecunia-core";
2
2
  import { and, asc, count, desc, eq, gt, gte, inArray, like, lt, lte, ne, notInArray, or, sql } from "drizzle-orm";
3
3
 
4
- //#region src/adapters/drizzle/index.ts
4
+ //#region src/adapters/drizzle-adapter/index.ts
5
5
  const drizzleAdapter = (db, config) => {
6
6
  let lazyOptions = null;
7
7
  const createCustomAdapter = (db$1) => ({ getFieldName, options }) => {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["db","count"],"sources":["../../../src/adapters/drizzle-adapter/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\"\nimport type {\n\tAdapterFactoryCreator,\n\tAdapterFactoryOptions,\n\tDBAdapter,\n\tDBAdapterDebugLogOption,\n\tWhere,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\"\nimport { logger } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\nimport type { SQL } from \"drizzle-orm\";\nimport {\n\tand,\n\tasc,\n\tcount,\n\tdesc,\n\teq,\n\tgt,\n\tgte,\n\tinArray,\n\tlike,\n\tlt,\n\tlte,\n\tne,\n\tnotInArray,\n\tor,\n\tsql,\n} from \"drizzle-orm\";\n\nexport interface DB {\n\t[key: string]: any;\n}\n\nexport interface DrizzleAdapterConfig {\n\t/**\n\t * The schema object that defines the tables and fields\n\t */\n\tschema?: Record<string, any> | undefined;\n\t/**\n\t * The database provider\n\t */\n\tprovider: \"pg\" | \"mysql\" | \"sqlite\";\n\t/**\n\t * If the table names in the schema are plural\n\t * set this to true. For example, if the schema\n\t * has an object with a key \"users\" instead of \"user\"\n\t */\n\tusePlural?: boolean | undefined;\n\t/**\n\t * Enable debug logs for the adapter\n\t *\n\t * @default false\n\t */\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n\t/**\n\t * By default snake case is used for table and field names\n\t * when the CLI is used to generate the schema. If you want\n\t * to use camel case, set this to true.\n\t * @default false\n\t */\n\tcamelCase?: boolean | undefined;\n\t/**\n\t * Whether to execute multiple operations in a transaction.\n\t *\n\t * If the database doesn't support transactions,\n\t * set this to `false` and operations will be executed sequentially.\n\t * @default false\n\t */\n\ttransaction?: boolean | undefined;\n}\n\nexport const drizzleAdapter = (db: DB, config: DrizzleAdapterConfig) => {\n\tlet lazyOptions: PecuniaOptions | null = null;\n\tconst createCustomAdapter =\n\t\t(db: DB): AdapterFactoryCreator =>\n\t\t({ getFieldName, options }) => {\n\t\t\tfunction getSchema(model: string) {\n\t\t\t\tconst schema = config.schema || db._.fullSchema;\n\t\t\t\tif (!schema) {\n\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\"Drizzle adapter failed to initialize. Schema not found. Please provide a schema object in the adapter options object.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst schemaModel = schema[model];\n\t\t\t\tif (!schemaModel) {\n\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t`[# Drizzle Adapter]: The model \"${model}\" was not found in the schema object. Please pass the schema directly to the adapter options.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn schemaModel;\n\t\t\t}\n\t\t\tconst withReturning = async (\n\t\t\t\tmodel: string,\n\t\t\t\tbuilder: any,\n\t\t\t\tdata: Record<string, any>,\n\t\t\t\twhere?: Where[] | undefined,\n\t\t\t) => {\n\t\t\t\tif (config.provider !== \"mysql\") {\n\t\t\t\t\tconst c = await builder.returning();\n\t\t\t\t\treturn c[0];\n\t\t\t\t}\n\t\t\t\tawait builder.execute();\n\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\tconst builderVal = builder.config?.values;\n\t\t\t\tif (where?.length) {\n\t\t\t\t\t// If we're updating a field that's in the where clause, use the new value\n\t\t\t\t\tconst updatedWhere = where.map((w) => {\n\t\t\t\t\t\t// If this field was updated, use the new value for lookup\n\t\t\t\t\t\tif (data[w.field] !== undefined) {\n\t\t\t\t\t\t\treturn { ...w, value: data[w.field] };\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn w;\n\t\t\t\t\t});\n\n\t\t\t\t\tconst clause = convertWhereClause(updatedWhere, model);\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn res[0];\n\t\t\t\t} else if (builderVal && builderVal[0]?.id?.value) {\n\t\t\t\t\tlet tId = builderVal[0]?.id?.value;\n\t\t\t\t\tif (!tId) {\n\t\t\t\t\t\t//get last inserted id\n\t\t\t\t\t\tconst lastInsertId = await db\n\t\t\t\t\t\t\t.select({ id: sql`LAST_INSERT_ID()` })\n\t\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t\t.orderBy(desc(schemaModel.id))\n\t\t\t\t\t\t\t.limit(1);\n\t\t\t\t\t\ttId = lastInsertId[0].id;\n\t\t\t\t\t}\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(eq(schemaModel.id, tId))\n\t\t\t\t\t\t.limit(1)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\treturn res[0];\n\t\t\t\t} else if (data.id) {\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(eq(schemaModel.id, data.id))\n\t\t\t\t\t\t.limit(1)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\treturn res[0];\n\t\t\t\t} else {\n\t\t\t\t\t// If the user doesn't have `id` as a field, then this will fail.\n\t\t\t\t\t// We expect that they defined `id` in all of their models.\n\t\t\t\t\tif (!(\"id\" in schemaModel)) {\n\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t`The model \"${model}\" does not have an \"id\" field. Please use the \"id\" field as your primary key.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.orderBy(desc(schemaModel.id))\n\t\t\t\t\t\t.limit(1)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\treturn res[0];\n\t\t\t\t}\n\t\t\t};\n\t\t\tfunction convertWhereClause(where: Where[], model: string) {\n\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\tif (!where) return [];\n\t\t\t\tif (where.length === 1) {\n\t\t\t\t\tconst w = where[0];\n\t\t\t\t\tif (!w) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\t\t\t\t\tconst field = getFieldName({ model, field: w.field });\n\t\t\t\t\tif (!schemaModel[field]) {\n\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t`The field \"${w.field}\" does not exist in the schema for the model \"${model}\". Please update your schema.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"in\" operator.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [inArray(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"not_in\") {\n\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"not_in\" operator.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [notInArray(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"contains\") {\n\t\t\t\t\t\treturn [like(schemaModel[field], `%${w.value}%`)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"starts_with\") {\n\t\t\t\t\t\treturn [like(schemaModel[field], `${w.value}%`)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"ends_with\") {\n\t\t\t\t\t\treturn [like(schemaModel[field], `%${w.value}`)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"lt\") {\n\t\t\t\t\t\treturn [lt(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"lte\") {\n\t\t\t\t\t\treturn [lte(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"ne\") {\n\t\t\t\t\t\treturn [ne(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"gt\") {\n\t\t\t\t\t\treturn [gt(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"gte\") {\n\t\t\t\t\t\treturn [gte(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [eq(schemaModel[field], w.value)];\n\t\t\t\t}\n\t\t\t\tconst andGroup = where.filter(\n\t\t\t\t\t(w) => w.connector === \"AND\" || !w.connector,\n\t\t\t\t);\n\t\t\t\tconst orGroup = where.filter((w) => w.connector === \"OR\");\n\n\t\t\t\tconst andClause = and(\n\t\t\t\t\t...andGroup.map((w) => {\n\t\t\t\t\t\tconst field = getFieldName({ model, field: w.field });\n\t\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn inArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"not_in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"not_in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn notInArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"contains\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"starts_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ends_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lt\") {\n\t\t\t\t\t\t\treturn lt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lte\") {\n\t\t\t\t\t\t\treturn lte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gt\") {\n\t\t\t\t\t\t\treturn gt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gte\") {\n\t\t\t\t\t\t\treturn gte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ne\") {\n\t\t\t\t\t\t\treturn ne(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn eq(schemaModel[field], w.value);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst orClause = or(\n\t\t\t\t\t...orGroup.map((w) => {\n\t\t\t\t\t\tconst field = getFieldName({ model, field: w.field });\n\t\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn inArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"not_in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"not_in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn notInArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"contains\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"starts_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ends_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lt\") {\n\t\t\t\t\t\t\treturn lt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lte\") {\n\t\t\t\t\t\t\treturn lte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gt\") {\n\t\t\t\t\t\t\treturn gt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gte\") {\n\t\t\t\t\t\t\treturn gte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ne\") {\n\t\t\t\t\t\t\treturn ne(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn eq(schemaModel[field], w.value);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst clause: SQL<unknown>[] = [];\n\n\t\t\t\tif (andGroup.length) clause.push(andClause!);\n\t\t\t\tif (orGroup.length) clause.push(orClause!);\n\t\t\t\treturn clause;\n\t\t\t}\n\t\t\tfunction checkMissingFields(\n\t\t\t\tschema: Record<string, any>,\n\t\t\t\tmodel: string,\n\t\t\t\tvalues: Record<string, any>,\n\t\t\t) {\n\t\t\t\tif (!schema) {\n\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\"Drizzle adapter failed to initialize. Drizzle Schema not found. Please provide a schema object in the adapter options object.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tfor (const key in values) {\n\t\t\t\t\tif (!schema[key]) {\n\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t`The field \"${key}\" does not exist in the \"${model}\" Drizzle schema. Please update your drizzle schema or re-generate using \"npx @pecunia/cli@latest generate\".`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tasync create({ model, data: values }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tcheckMissingFields(schemaModel, model, values);\n\t\t\t\t\tconst builder = db.insert(schemaModel).values(values);\n\t\t\t\t\tconst returned = await withReturning(model, builder, values);\n\t\t\t\t\treturn returned;\n\t\t\t\t},\n\t\t\t\tasync findOne({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\n\t\t\t\t\tlet query = db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(...clause);\n\n\t\t\t\t\tconst res = await query;\n\n\t\t\t\t\tif (!res.length) return null;\n\t\t\t\t\treturn res[0];\n\t\t\t\t},\n\t\t\t\tasync findMany({ model, where, sortBy, limit, offset }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = where ? convertWhereClause(where, model) : [];\n\t\t\t\t\tconst sortFn = sortBy?.direction === \"desc\" ? desc : asc;\n\n\t\t\t\t\tlet builder = db.select().from(schemaModel);\n\n\t\t\t\t\tconst effectiveLimit = limit;\n\t\t\t\t\tconst effectiveOffset = offset;\n\n\t\t\t\t\tif (typeof effectiveLimit !== \"undefined\") {\n\t\t\t\t\t\tbuilder = builder.limit(effectiveLimit);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (typeof effectiveOffset !== \"undefined\") {\n\t\t\t\t\t\tbuilder = builder.offset(effectiveOffset);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (sortBy?.field) {\n\t\t\t\t\t\tbuilder = builder.orderBy(\n\t\t\t\t\t\t\tsortFn(\n\t\t\t\t\t\t\t\tschemaModel[getFieldName({ model, field: sortBy?.field })],\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst res = await builder.where(...clause);\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t\tasync count({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = where ? convertWhereClause(where, model) : [];\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select({ count: count() })\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn res[0].count;\n\t\t\t\t},\n\t\t\t\tasync update({ model, where, update: values }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db\n\t\t\t\t\t\t.update(schemaModel)\n\t\t\t\t\t\t.set(values)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn await withReturning(model, builder, values as any, where);\n\t\t\t\t},\n\t\t\t\tasync updateMany({ model, where, update: values }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db\n\t\t\t\t\t\t.update(schemaModel)\n\t\t\t\t\t\t.set(values)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn await builder;\n\t\t\t\t},\n\t\t\t\tasync delete({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db.delete(schemaModel).where(...clause);\n\t\t\t\t\treturn await builder;\n\t\t\t\t},\n\t\t\t\tasync deleteMany({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db.delete(schemaModel).where(...clause);\n\t\t\t\t\tconst res = await builder;\n\t\t\t\t\tlet count = 0;\n\t\t\t\t\tif (res && \"rowCount\" in res) count = res.rowCount;\n\t\t\t\t\telse if (Array.isArray(res)) count = res.length;\n\t\t\t\t\telse if (\n\t\t\t\t\t\tres &&\n\t\t\t\t\t\t(\"affectedRows\" in res || \"rowsAffected\" in res || \"changes\" in res)\n\t\t\t\t\t)\n\t\t\t\t\t\tcount = res.affectedRows ?? res.rowsAffected ?? res.changes;\n\t\t\t\t\tif (typeof count !== \"number\") {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\"[Drizzle Adapter] The result of the deleteMany operation is not a number. This is likely a bug in the adapter.\",\n\t\t\t\t\t\t\t{ res, model, where },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn count;\n\t\t\t\t},\n\t\t\t\toptions: config,\n\t\t\t};\n\t\t};\n\tlet adapterOptions: AdapterFactoryOptions | null = null;\n\tadapterOptions = {\n\t\tconfig: {\n\t\t\tadapterId: \"drizzle\",\n\t\t\tadapterName: \"Drizzle Adapter\",\n\t\t\tusePlural: config.usePlural ?? false,\n\t\t\tsupportsUUIDs: config.provider === \"pg\" ? true : false,\n\t\t\tsupportsJSON:\n\t\t\t\tconfig.provider === \"pg\" // even though mysql also supports it, mysql requires to pass stringified json anyway.\n\t\t\t\t\t? true\n\t\t\t\t\t: false,\n\t\t\tsupportsArrays: config.provider === \"pg\" ? true : false,\n\t\t\ttransaction:\n\t\t\t\t(config.transaction ?? false)\n\t\t\t\t\t? (cb) =>\n\t\t\t\t\t\t\tdb.transaction((tx: DB) => {\n\t\t\t\t\t\t\t\tconst adapter = createAdapterFactory({\n\t\t\t\t\t\t\t\t\tconfig: adapterOptions!.config,\n\t\t\t\t\t\t\t\t\tadapter: createCustomAdapter(tx),\n\t\t\t\t\t\t\t\t})(lazyOptions!);\n\t\t\t\t\t\t\t\treturn cb(adapter);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t: false,\n\t\t},\n\t\tadapter: createCustomAdapter(db),\n\t};\n\tconst adapter = createAdapterFactory(adapterOptions);\n\treturn (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n\t\tlazyOptions = options;\n\t\treturn adapter(options);\n\t};\n};\n"],"mappings":"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"}
@@ -15,10 +15,10 @@ async function getBaseAdapter(options, handleDirectDatabase) {
15
15
  }
16
16
  async function getAdapter(options) {
17
17
  return getBaseAdapter(options, async (opts) => {
18
- const { createKyselyAdapter } = await import("./kysely/dialect.mjs");
18
+ const { createKyselyAdapter } = await import("./kysely-adapter/dialect.mjs");
19
19
  const { kysely, databaseType, transaction } = await createKyselyAdapter(opts);
20
20
  if (!kysely) throw new PecuniaError("Failed to initialize database adapter");
21
- const { kyselyAdapter } = await import("./kysely/index.mjs");
21
+ const { kyselyAdapter } = await import("./kysely-adapter/index.mjs");
22
22
  return kyselyAdapter(kysely, {
23
23
  type: databaseType || "sqlite",
24
24
  transaction
@@ -1 +1 @@
1
- {"version":3,"file":"get-adapter.mjs","names":[],"sources":["../../src/adapters/get-adapter.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\nimport type { DBAdapter } from \"pecunia-core\";\n\nexport async function getBaseAdapter(\n options: PecuniaOptions,\n handleDirectDatabase: (\n options: PecuniaOptions,\n ) => Promise<DBAdapter<PecuniaOptions>>,\n): Promise<DBAdapter<PecuniaOptions>> {\n let adapter: DBAdapter<PecuniaOptions>;\n if (typeof options.database === \"function\") {\n adapter = options.database(options);\n } else {\n adapter = await handleDirectDatabase(options);\n }\n\n if (!adapter.transaction) {\n console.warn(\n \"Adapter does not correctly implement transaction function, patching it automatically. Please update your adapter implementation.\",\n );\n adapter.transaction = async (cb) => {\n return cb(adapter);\n };\n }\n\n return adapter;\n}\n\nexport async function getAdapter(\n options: PecuniaOptions,\n): Promise<DBAdapter<PecuniaOptions>> {\n return getBaseAdapter(options, async (opts) => {\n const { createKyselyAdapter } = await import(\"./kysely/dialect\");\n const { kysely, databaseType, transaction } =\n await createKyselyAdapter(opts);\n if (!kysely) {\n throw new PecuniaError(\"Failed to initialize database adapter\");\n }\n const { kyselyAdapter } = await import(\"./kysely\");\n return kyselyAdapter(kysely, {\n type: databaseType || \"sqlite\",\n transaction: transaction,\n })(opts);\n });\n}\n"],"mappings":";;;AAIA,eAAsB,eACpB,SACA,sBAGoC;CACpC,IAAI;AACJ,KAAI,OAAO,QAAQ,aAAa,WAC9B,WAAU,QAAQ,SAAS,QAAQ;KAEnC,WAAU,MAAM,qBAAqB,QAAQ;AAG/C,KAAI,CAAC,QAAQ,aAAa;AACxB,UAAQ,KACN,mIACD;AACD,UAAQ,cAAc,OAAO,OAAO;AAClC,UAAO,GAAG,QAAQ;;;AAItB,QAAO;;AAGT,eAAsB,WACpB,SACoC;AACpC,QAAO,eAAe,SAAS,OAAO,SAAS;EAC7C,MAAM,EAAE,wBAAwB,MAAM,OAAO;EAC7C,MAAM,EAAE,QAAQ,cAAc,gBAC5B,MAAM,oBAAoB,KAAK;AACjC,MAAI,CAAC,OACH,OAAM,IAAI,aAAa,wCAAwC;EAEjE,MAAM,EAAE,kBAAkB,MAAM,OAAO;AACvC,SAAO,cAAc,QAAQ;GAC3B,MAAM,gBAAgB;GACT;GACd,CAAC,CAAC,KAAK;GACR"}
1
+ {"version":3,"file":"get-adapter.mjs","names":[],"sources":["../../src/adapters/get-adapter.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\nimport type { DBAdapter } from \"pecunia-core\";\n\nexport async function getBaseAdapter(\n options: PecuniaOptions,\n handleDirectDatabase: (\n options: PecuniaOptions,\n ) => Promise<DBAdapter<PecuniaOptions>>,\n): Promise<DBAdapter<PecuniaOptions>> {\n let adapter: DBAdapter<PecuniaOptions>;\n if (typeof options.database === \"function\") {\n adapter = options.database(options);\n } else {\n adapter = await handleDirectDatabase(options);\n }\n\n if (!adapter.transaction) {\n console.warn(\n \"Adapter does not correctly implement transaction function, patching it automatically. Please update your adapter implementation.\",\n );\n adapter.transaction = async (cb) => {\n return cb(adapter);\n };\n }\n\n return adapter;\n}\n\nexport async function getAdapter(\n options: PecuniaOptions,\n): Promise<DBAdapter<PecuniaOptions>> {\n return getBaseAdapter(options, async (opts) => {\n const { createKyselyAdapter } = await import(\"./kysely-adapter/dialect\");\n const { kysely, databaseType, transaction } =\n await createKyselyAdapter(opts);\n if (!kysely) {\n throw new PecuniaError(\"Failed to initialize database adapter\");\n }\n const { kyselyAdapter } = await import(\"./kysely-adapter\");\n return kyselyAdapter(kysely, {\n type: databaseType || \"sqlite\",\n transaction: transaction,\n })(opts);\n });\n}\n"],"mappings":";;;AAIA,eAAsB,eACpB,SACA,sBAGoC;CACpC,IAAI;AACJ,KAAI,OAAO,QAAQ,aAAa,WAC9B,WAAU,QAAQ,SAAS,QAAQ;KAEnC,WAAU,MAAM,qBAAqB,QAAQ;AAG/C,KAAI,CAAC,QAAQ,aAAa;AACxB,UAAQ,KACN,mIACD;AACD,UAAQ,cAAc,OAAO,OAAO;AAClC,UAAO,GAAG,QAAQ;;;AAItB,QAAO;;AAGT,eAAsB,WACpB,SACoC;AACpC,QAAO,eAAe,SAAS,OAAO,SAAS;EAC7C,MAAM,EAAE,wBAAwB,MAAM,OAAO;EAC7C,MAAM,EAAE,QAAQ,cAAc,gBAC5B,MAAM,oBAAoB,KAAK;AACjC,MAAI,CAAC,OACH,OAAM,IAAI,aAAa,wCAAwC;EAEjE,MAAM,EAAE,kBAAkB,MAAM,OAAO;AACvC,SAAO,cAAc,QAAQ;GAC3B,MAAM,gBAAgB;GACT;GACd,CAAC,CAAC,KAAK;GACR"}
@@ -1,6 +1,6 @@
1
1
  import { CompiledQuery, DEFAULT_MIGRATION_LOCK_TABLE, DEFAULT_MIGRATION_TABLE, DefaultQueryCompiler, sql } from "kysely";
2
2
 
3
- //#region src/adapters/kysely/bun-sqlite-dialect.ts
3
+ //#region src/adapters/kysely-adapter/bun-sqlite-dialect.ts
4
4
  var BunSqliteAdapter = class {
5
5
  get supportsCreateIfNotExists() {
6
6
  return true;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bun-sqlite-dialect.mjs","names":["#config","#connectionMutex","#db","#connection","sql","#promise","#resolve","#getTableMetadata"],"sources":["../../../src/adapters/kysely-adapter/bun-sqlite-dialect.ts"],"sourcesContent":["/**\n * @see {@link https://github.com/dylanblokhuis/kysely-bun-sqlite} - Fork of the original kysely-bun-sqlite package by @dylanblokhuis\n */\n\nimport type { Database } from \"bun:sqlite\";\nimport type {\n DatabaseConnection,\n DatabaseIntrospector,\n DatabaseMetadata,\n DatabaseMetadataOptions,\n Dialect,\n DialectAdapter,\n DialectAdapterBase,\n Driver,\n Kysely,\n QueryCompiler,\n QueryResult,\n SchemaMetadata,\n TableMetadata,\n} from \"kysely\";\nimport {\n CompiledQuery,\n DEFAULT_MIGRATION_LOCK_TABLE,\n DEFAULT_MIGRATION_TABLE,\n DefaultQueryCompiler,\n sql,\n} from \"kysely\";\n\nclass BunSqliteAdapter implements DialectAdapterBase {\n get supportsCreateIfNotExists(): boolean {\n return true;\n }\n\n get supportsTransactionalDdl(): boolean {\n return false;\n }\n\n get supportsReturning(): boolean {\n return true;\n }\n\n async acquireMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n\n async releaseMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n get supportsOutput(): boolean {\n return true;\n }\n}\n\n/**\n * Config for the SQLite dialect.\n */\nexport interface BunSqliteDialectConfig {\n /**\n * An sqlite Database instance or a function that returns one.\n */\n database: Database;\n\n /**\n * Called once when the first query is executed.\n */\n onCreateConnection?:\n | ((connection: DatabaseConnection) => Promise<void>)\n | undefined;\n}\n\nclass BunSqliteDriver implements Driver {\n readonly #config: BunSqliteDialectConfig;\n readonly #connectionMutex = new ConnectionMutex();\n\n #db?: Database;\n #connection?: DatabaseConnection;\n\n constructor(config: BunSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n async init(): Promise<void> {\n this.#db = this.#config.database;\n\n this.#connection = new BunSqliteConnection(this.#db);\n\n if (this.#config.onCreateConnection) {\n await this.#config.onCreateConnection(this.#connection);\n }\n }\n\n async acquireConnection(): Promise<DatabaseConnection> {\n // SQLite only has one single connection. We use a mutex here to wait\n // until the single connection has been released.\n await this.#connectionMutex.lock();\n return this.#connection!;\n }\n\n async beginTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"begin\"));\n }\n\n async commitTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"commit\"));\n }\n\n async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"rollback\"));\n }\n\n async releaseConnection(): Promise<void> {\n this.#connectionMutex.unlock();\n }\n\n async destroy(): Promise<void> {\n this.#db?.close();\n }\n}\n\nclass BunSqliteConnection implements DatabaseConnection {\n readonly #db: Database;\n\n constructor(db: Database) {\n this.#db = db;\n }\n\n executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n const { sql, parameters } = compiledQuery;\n const stmt = this.#db.prepare(sql);\n\n return Promise.resolve({\n rows: stmt.all(parameters as any) as O[],\n });\n }\n\n async *streamQuery() {\n throw new Error(\"Streaming query is not supported by SQLite driver.\");\n }\n}\n\nclass ConnectionMutex {\n #promise?: Promise<void>;\n #resolve?: () => void;\n\n async lock(): Promise<void> {\n while (this.#promise) {\n await this.#promise;\n }\n\n this.#promise = new Promise((resolve) => {\n this.#resolve = resolve;\n });\n }\n\n unlock(): void {\n const resolve = this.#resolve;\n\n this.#promise = undefined;\n this.#resolve = undefined;\n\n resolve?.();\n }\n}\n\nclass BunSqliteIntrospector implements DatabaseIntrospector {\n readonly #db: Kysely<unknown>;\n\n constructor(db: Kysely<unknown>) {\n this.#db = db;\n }\n\n async getSchemas(): Promise<SchemaMetadata[]> {\n // Sqlite doesn't support schemas.\n return [];\n }\n\n async getTables(\n options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n ): Promise<TableMetadata[]> {\n let query = this.#db\n // @ts-expect-error\n .selectFrom(\"sqlite_schema\")\n // @ts-expect-error\n .where(\"type\", \"=\", \"table\")\n // @ts-expect-error\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select(\"name\")\n .$castTo<{ name: string }>();\n\n if (!options.withInternalKyselyTables) {\n query = query\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_TABLE)\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_LOCK_TABLE);\n }\n\n const tables = await query.execute();\n return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));\n }\n\n async getMetadata(\n options?: DatabaseMetadataOptions | undefined,\n ): Promise<DatabaseMetadata> {\n return {\n tables: await this.getTables(options),\n };\n }\n\n async #getTableMetadata(table: string): Promise<TableMetadata> {\n const db = this.#db;\n\n // Get the SQL that was used to create the table.\n const createSql = await db\n // @ts-expect-error\n .selectFrom(\"sqlite_master\")\n // @ts-expect-error\n .where(\"name\", \"=\", table)\n .select(\"sql\")\n .$castTo<{ sql: string | undefined }>()\n .execute();\n\n // Try to find the name of the column that has `autoincrement` 🤦\n const autoIncrementCol = createSql[0]?.sql\n ?.split(/[\\(\\),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = await db\n .selectFrom(\n sql<{\n name: string;\n type: string;\n notnull: 0 | 1;\n dflt_value: any;\n }>`pragma_table_info(${table})`.as(\"table_info\"),\n )\n .select([\"name\", \"type\", \"notnull\", \"dflt_value\"])\n .execute();\n\n return {\n name: table,\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n })),\n isView: true,\n };\n }\n}\n\nclass BunSqliteQueryCompiler extends DefaultQueryCompiler {\n protected override getCurrentParameterPlaceholder() {\n return \"?\";\n }\n\n protected override getLeftIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getRightIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getAutoIncrement() {\n return \"autoincrement\";\n }\n}\n\nexport class BunSqliteDialect implements Dialect {\n readonly #config: BunSqliteDialectConfig;\n\n constructor(config: BunSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n createDriver(): Driver {\n return new BunSqliteDriver(this.#config);\n }\n\n createQueryCompiler(): QueryCompiler {\n return new BunSqliteQueryCompiler();\n }\n\n createAdapter(): DialectAdapter {\n return new BunSqliteAdapter();\n }\n\n createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n return new BunSqliteIntrospector(db);\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { Kysely, MssqlDialect, MysqlDialect, PostgresDialect, SqliteDialect } from "kysely";
2
2
 
3
- //#region src/adapters/kysely/dialect.ts
3
+ //#region src/adapters/kysely-adapter/dialect.ts
4
4
  function isSqliteDatabase(x) {
5
5
  return typeof x === "object" && x !== null && "prepare" in x;
6
6
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialect.mjs","names":[],"sources":["../../../src/adapters/kysely-adapter/dialect.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type { Dialect, SqliteDatabase } from \"kysely\";\nimport {\n Kysely,\n MssqlDialect,\n MysqlDialect,\n PostgresDialect,\n SqliteDialect,\n} from \"kysely\";\nimport type { Database as BunSqliteDatabase } from \"bun:sqlite\";\nimport type { KyselyDatabaseDialectType } from \"pecunia-core\";\nfunction isSqliteDatabase(x: unknown): x is SqliteDatabase {\n return typeof x === \"object\" && x !== null && \"prepare\" in x;\n}\n\nfunction isSqliteDatabaseFactory(\n x: unknown,\n): x is () => Promise<SqliteDatabase> {\n return typeof x === \"function\";\n}\n\nfunction isBunSqliteDatabase(x: unknown): x is BunSqliteDatabase {\n return typeof x === \"object\" && x !== null && \"fileControl\" in x;\n}\n\nexport function getKyselyDatabaseType(\n db: PecuniaOptions[\"database\"],\n): KyselyDatabaseDialectType | null {\n if (!db) {\n return null;\n }\n if (\"dialect\" in db) {\n return getKyselyDatabaseType(db.dialect as Dialect);\n }\n if (\"createDriver\" in db) {\n if (db instanceof SqliteDialect) {\n return \"sqlite\";\n }\n if (db instanceof MysqlDialect) {\n return \"mysql\";\n }\n if (db instanceof PostgresDialect) {\n return \"postgres\";\n }\n if (db instanceof MssqlDialect) {\n return \"mssql\";\n }\n }\n if (\"aggregate\" in db) {\n return \"sqlite\";\n }\n\n if (\"getConnection\" in db) {\n return \"mysql\";\n }\n if (\"connect\" in db) {\n return \"postgres\";\n }\n if (\"fileControl\" in db) {\n return \"sqlite\";\n }\n if (\"open\" in db && \"close\" in db && \"prepare\" in db) {\n return \"sqlite\";\n }\n return null;\n}\n\nexport const createKyselyAdapter = async (config: PecuniaOptions) => {\n const db = config.database;\n\n if (!db) {\n return {\n kysely: null,\n databaseType: null,\n transaction: undefined,\n };\n }\n\n if (\"db\" in db) {\n return {\n kysely: db.db,\n databaseType: db.type,\n transaction: db.transaction,\n };\n }\n\n if (\"dialect\" in db) {\n return {\n kysely: new Kysely<any>({ dialect: db.dialect }),\n databaseType: db.type,\n transaction: db.transaction,\n };\n }\n\n let dialect: Dialect | undefined = undefined;\n\n const databaseType = getKyselyDatabaseType(db);\n\n if (\"createDriver\" in db) {\n dialect = db;\n }\n\n if (\"aggregate\" in db) {\n if (isSqliteDatabase(db) || isSqliteDatabaseFactory(db)) {\n dialect = new SqliteDialect({ database: db });\n } else {\n throw new Error(\n \"db matched 'aggregate' check, but is not a Kysely SqliteDatabase\",\n );\n }\n }\n\n if (\"getConnection\" in db) {\n // @ts-expect-error - mysql2/promise\n dialect = new MysqlDialect(db);\n }\n\n if (\"connect\" in db) {\n dialect = new PostgresDialect({\n pool: db,\n });\n }\n\n if (isBunSqliteDatabase(db)) {\n const { BunSqliteDialect } = await import(\"./bun-sqlite-dialect\");\n dialect = new BunSqliteDialect({\n database: db,\n });\n }\n\n if (\"createSession\" in db && typeof window === \"undefined\") {\n let DatabaseSync: typeof import(\"node:sqlite\").DatabaseSync | undefined =\n undefined;\n try {\n let nodeSqlite: string = \"node:sqlite\";\n // Ignore both Vite and Webpack for dynamic import as they both try to pre-bundle 'node:sqlite' which might fail\n // It's okay because we are in a try-catch block\n ({ DatabaseSync } = await import(\n /* @vite-ignore */\n /* webpackIgnore: true */\n nodeSqlite\n ));\n } catch (error: unknown) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code !== \"ERR_UNKNOWN_BUILTIN_MODULE\"\n ) {\n throw error;\n }\n }\n if (DatabaseSync && db instanceof DatabaseSync) {\n const { NodeSqliteDialect } = await import(\"./node-sqlite-dialect\");\n dialect = new NodeSqliteDialect({\n database: db,\n });\n }\n }\n\n return {\n kysely: dialect ? new Kysely<any>({ dialect }) : null,\n databaseType,\n transaction: undefined,\n };\n};\n"],"mappings":";;;AAWA,SAAS,iBAAiB,GAAiC;AACzD,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,aAAa;;AAG7D,SAAS,wBACP,GACoC;AACpC,QAAO,OAAO,MAAM;;AAGtB,SAAS,oBAAoB,GAAoC;AAC/D,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,iBAAiB;;AAGjE,SAAgB,sBACd,IACkC;AAClC,KAAI,CAAC,GACH,QAAO;AAET,KAAI,aAAa,GACf,QAAO,sBAAsB,GAAG,QAAmB;AAErD,KAAI,kBAAkB,IAAI;AACxB,MAAI,cAAc,cAChB,QAAO;AAET,MAAI,cAAc,aAChB,QAAO;AAET,MAAI,cAAc,gBAChB,QAAO;AAET,MAAI,cAAc,aAChB,QAAO;;AAGX,KAAI,eAAe,GACjB,QAAO;AAGT,KAAI,mBAAmB,GACrB,QAAO;AAET,KAAI,aAAa,GACf,QAAO;AAET,KAAI,iBAAiB,GACnB,QAAO;AAET,KAAI,UAAU,MAAM,WAAW,MAAM,aAAa,GAChD,QAAO;AAET,QAAO;;AAGT,MAAa,sBAAsB,OAAO,WAA2B;CACnE,MAAM,KAAK,OAAO;AAElB,KAAI,CAAC,GACH,QAAO;EACL,QAAQ;EACR,cAAc;EACd,aAAa;EACd;AAGH,KAAI,QAAQ,GACV,QAAO;EACL,QAAQ,GAAG;EACX,cAAc,GAAG;EACjB,aAAa,GAAG;EACjB;AAGH,KAAI,aAAa,GACf,QAAO;EACL,QAAQ,IAAI,OAAY,EAAE,SAAS,GAAG,SAAS,CAAC;EAChD,cAAc,GAAG;EACjB,aAAa,GAAG;EACjB;CAGH,IAAI,UAA+B;CAEnC,MAAM,eAAe,sBAAsB,GAAG;AAE9C,KAAI,kBAAkB,GACpB,WAAU;AAGZ,KAAI,eAAe,GACjB,KAAI,iBAAiB,GAAG,IAAI,wBAAwB,GAAG,CACrD,WAAU,IAAI,cAAc,EAAE,UAAU,IAAI,CAAC;KAE7C,OAAM,IAAI,MACR,mEACD;AAIL,KAAI,mBAAmB,GAErB,WAAU,IAAI,aAAa,GAAG;AAGhC,KAAI,aAAa,GACf,WAAU,IAAI,gBAAgB,EAC5B,MAAM,IACP,CAAC;AAGJ,KAAI,oBAAoB,GAAG,EAAE;EAC3B,MAAM,EAAE,qBAAqB,MAAM,OAAO;AAC1C,YAAU,IAAI,iBAAiB,EAC7B,UAAU,IACX,CAAC;;AAGJ,KAAI,mBAAmB,MAAM,OAAO,WAAW,aAAa;EAC1D,IAAI,eACF;AACF,MAAI;GACF,IAAI,aAAqB;AAGzB,IAAC,CAAE,gBAAiB,MAAM;;;IAGxB;;WAEK,OAAgB;AACvB,OACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,MAAM,SAAS,6BAEf,OAAM;;AAGV,MAAI,gBAAgB,cAAc,cAAc;GAC9C,MAAM,EAAE,sBAAsB,MAAM,OAAO;AAC3C,aAAU,IAAI,kBAAkB,EAC9B,UAAU,IACX,CAAC;;;AAIN,QAAO;EACL,QAAQ,UAAU,IAAI,OAAY,EAAE,SAAS,CAAC,GAAG;EACjD;EACA,aAAa;EACd"}
@@ -1,7 +1,7 @@
1
1
  import { DBAdapter, DBAdapterDebugLogOption, KyselyDatabaseDialectType, PecuniaOptions } from "pecunia-core";
2
2
  import { Kysely } from "kysely";
3
3
 
4
- //#region src/adapters/kysely/index.d.ts
4
+ //#region src/adapters/kysely-adapter/index.d.ts
5
5
  interface KyselyAdapterConfig {
6
6
  /**
7
7
  * Database type.
@@ -1,6 +1,6 @@
1
1
  import { createAdapterFactory } from "pecunia-core";
2
2
 
3
- //#region src/adapters/kysely/index.ts
3
+ //#region src/adapters/kysely-adapter/index.ts
4
4
  const kyselyAdapter = (db, config) => {
5
5
  let lazyOptions = null;
6
6
  const createCustomAdapter = (db$1) => {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["db"],"sources":["../../../src/adapters/kysely-adapter/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type {\n AdapterFactoryCreator,\n AdapterFactoryOptions,\n DBAdapter,\n DBAdapterDebugLogOption,\n Where,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\";\nimport type { InsertQueryBuilder, Kysely, UpdateQueryBuilder } from \"kysely\";\n\ninterface KyselyAdapterConfig {\n /**\n * Database type.\n */\n type?: KyselyDatabaseDialectType | undefined;\n /**\n * Enable debug logs for the adapter\n *\n * @default false\n */\n debugLogs?: DBAdapterDebugLogOption | undefined;\n /**\n * Use plural for table names.\n *\n * @default false\n */\n usePlural?: boolean | undefined;\n /**\n * Whether to execute multiple operations in a transaction.\n *\n * If the database doesn't support transactions,\n * set this to `false` and operations will be executed sequentially.\n * @default false\n */\n transaction?: boolean | undefined;\n}\n\nimport type { KyselyDatabaseDialectType } from \"pecunia-core\";\n\nexport const kyselyAdapter = (\n db: Kysely<any>,\n config?: KyselyAdapterConfig | undefined,\n) => {\n let lazyOptions: PecuniaOptions | null = null;\n\n const createCustomAdapter = (db: Kysely<any>): AdapterFactoryCreator => {\n return ({\n getFieldName,\n getDefaultFieldName,\n getDefaultModelName,\n schema,\n }) => {\n const withReturning = async (\n values: Record<string, any>,\n builder:\n | InsertQueryBuilder<any, any, any>\n | UpdateQueryBuilder<any, string, string, any>,\n model: string,\n where: Where[],\n ) => {\n let res: any;\n\n if (config?.type === \"mysql\") {\n // Kysely doesn't support returning() in MySQL.\n await builder.execute();\n\n const field = values.id\n ? \"id\"\n : where.length > 0 && where[0]?.field\n ? where[0].field\n : \"id\";\n\n if (!values.id && where.length === 0) {\n res = await db\n .selectFrom(model)\n .selectAll()\n .orderBy(getFieldName({ model, field }), \"desc\")\n .limit(1)\n .executeTakeFirst();\n return res;\n }\n\n const value = values[field] || where[0]?.value;\n\n res = await db\n .selectFrom(model)\n .selectAll()\n .orderBy(getFieldName({ model, field }), \"desc\")\n .where(getFieldName({ model, field }), \"=\", value)\n .limit(1)\n .executeTakeFirst();\n\n return res;\n }\n\n if (config?.type === \"mssql\") {\n res = await builder.outputAll(\"inserted\").executeTakeFirst();\n return res;\n }\n\n res = await builder.returningAll().executeTakeFirst();\n return res;\n };\n\n function convertWhereClause(model: string, w?: Where[] | undefined) {\n if (!w) {\n return {\n and: null,\n or: null,\n };\n }\n\n const conditions = {\n and: [] as any[],\n or: [] as any[],\n };\n\n w.forEach((condition) => {\n let {\n field: _field,\n value: _value,\n operator = \"=\",\n connector = \"AND\",\n } = condition;\n\n const value: any = _value;\n\n const field: string | any = getFieldName({\n model,\n field: _field,\n });\n\n const expr = (eb: any) => {\n const f = `${model}.${field}`;\n\n if (operator.toLowerCase() === \"in\") {\n return eb(f, \"in\", Array.isArray(value) ? value : [value]);\n }\n\n if (operator.toLowerCase() === \"not_in\") {\n return eb(f, \"not in\", Array.isArray(value) ? value : [value]);\n }\n\n if (operator === \"contains\") {\n return eb(f, \"like\", `%${value}%`);\n }\n\n if (operator === \"starts_with\") {\n return eb(f, \"like\", `${value}%`);\n }\n\n if (operator === \"ends_with\") {\n return eb(f, \"like\", `%${value}`);\n }\n\n if (operator === \"eq\") {\n return eb(f, \"=\", value);\n }\n\n if (operator === \"ne\") {\n return eb(f, \"<>\", value);\n }\n\n if (operator === \"gt\") {\n return eb(f, \">\", value);\n }\n\n if (operator === \"gte\") {\n return eb(f, \">=\", value);\n }\n\n if (operator === \"lt\") {\n return eb(f, \"<\", value);\n }\n\n if (operator === \"lte\") {\n return eb(f, \"<=\", value);\n }\n\n return eb(f, operator, value);\n };\n\n if (connector === \"OR\") {\n conditions.or.push(expr);\n } else {\n conditions.and.push(expr);\n }\n });\n\n return {\n and: conditions.and.length ? conditions.and : null,\n or: conditions.or.length ? conditions.or : null,\n };\n }\n\n return {\n async create({ data, model }) {\n const builder = db.insertInto(model).values(data);\n const returned = await withReturning(data, builder, model, []);\n return returned;\n },\n\n async findOne({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query: any = db.selectFrom(model).selectAll();\n\n if (and) {\n query = query.where((eb: any) =>\n eb.and(and.map((expr: any) => expr(eb))),\n );\n }\n\n if (or) {\n query = query.where((eb: any) =>\n eb.or(or.map((expr: any) => expr(eb))),\n );\n }\n\n const row = await query.executeTakeFirst();\n return row ?? null;\n },\n\n async findMany({ model, where, limit, offset, sortBy }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query: any = db.selectFrom(model).selectAll();\n\n if (config?.type === \"mssql\") {\n if (offset !== undefined) {\n if (!sortBy) {\n query = query.orderBy(getFieldName({ model, field: \"id\" }));\n }\n query = query.offset(offset).fetch(limit || 100);\n } else if (limit !== undefined) {\n query = query.top(limit);\n }\n } else {\n if (limit !== undefined) {\n query = query.limit(limit);\n }\n if (offset !== undefined) {\n query = query.offset(offset);\n }\n }\n\n if (sortBy?.field) {\n query = query.orderBy(\n `${getFieldName({ model, field: sortBy.field })}`,\n sortBy.direction,\n );\n }\n\n if (and) {\n query = query.where((eb: any) =>\n eb.and(and.map((expr: any) => expr(eb))),\n );\n }\n\n if (or) {\n query = query.where((eb: any) =>\n eb.or(or.map((expr: any) => expr(eb))),\n );\n }\n\n const res = await query.execute();\n return res ?? [];\n },\n\n async update({ model, where, update: values }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.updateTable(model).set(values as any);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n return await withReturning(values as any, query, model, where);\n },\n\n async updateMany({ model, where, update: values }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.updateTable(model).set(values as any);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n const res = (await query.executeTakeFirst()).numUpdatedRows;\n\n return res > Number.MAX_SAFE_INTEGER\n ? Number.MAX_SAFE_INTEGER\n : Number(res);\n },\n\n async count({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db\n .selectFrom(model)\n .select(db.fn.count(\"id\").as(\"count\"));\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n const res = await query.execute();\n\n if (typeof res[0]!.count === \"number\") return res[0]!.count;\n if (typeof res[0]!.count === \"bigint\") return Number(res[0]!.count);\n\n return parseInt(res[0]!.count);\n },\n\n async delete({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.deleteFrom(model);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n await query.execute();\n },\n\n async deleteMany({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.deleteFrom(model);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n const res = (await query.executeTakeFirst()).numDeletedRows;\n\n return res > Number.MAX_SAFE_INTEGER\n ? Number.MAX_SAFE_INTEGER\n : Number(res);\n },\n\n options: config,\n };\n };\n };\n\n let adapterOptions: AdapterFactoryOptions | null = null;\n\n adapterOptions = {\n config: {\n adapterId: \"kysely\",\n adapterName: \"Kysely Adapter\",\n usePlural: config?.usePlural,\n supportsBooleans:\n config?.type === \"sqlite\" ||\n config?.type === \"mssql\" ||\n config?.type === \"mysql\" ||\n !config?.type\n ? false\n : true,\n supportsDates:\n config?.type === \"sqlite\" || config?.type === \"mssql\" || !config?.type\n ? false\n : true,\n supportsJSON: config?.type === \"postgres\" ? true : false,\n supportsArrays: false,\n supportsUUIDs: config?.type === \"postgres\" ? true : false,\n transaction: config?.transaction\n ? (cb) =>\n db.transaction().execute((trx) => {\n const adapter = createAdapterFactory({\n config: adapterOptions!.config,\n adapter: createCustomAdapter(trx),\n })(lazyOptions!);\n\n return cb(adapter);\n })\n : false,\n },\n adapter: createCustomAdapter(db),\n };\n\n const adapter = createAdapterFactory(adapterOptions);\n\n return (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n lazyOptions = options;\n return adapter(options);\n };\n};\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { CompiledQuery, DEFAULT_MIGRATION_LOCK_TABLE, DEFAULT_MIGRATION_TABLE, DefaultQueryCompiler, sql } from "kysely";
2
2
 
3
- //#region src/adapters/kysely/node-sqlite-dialect.ts
3
+ //#region src/adapters/kysely-adapter/node-sqlite-dialect.ts
4
4
  var NodeSqliteAdapter = class {
5
5
  get supportsCreateIfNotExists() {
6
6
  return true;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-sqlite-dialect.mjs","names":["#config","#connectionMutex","#db","#connection","sql","#promise","#resolve","#getTableMetadata"],"sources":["../../../src/adapters/kysely-adapter/node-sqlite-dialect.ts"],"sourcesContent":["/**\n * @see {@link https://nodejs.org/api/sqlite.html} - Node.js SQLite API documentation\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type {\n DatabaseConnection,\n DatabaseIntrospector,\n DatabaseMetadata,\n DatabaseMetadataOptions,\n Dialect,\n DialectAdapter,\n DialectAdapterBase,\n Driver,\n Kysely,\n QueryCompiler,\n QueryResult,\n SchemaMetadata,\n TableMetadata,\n} from \"kysely\";\nimport {\n CompiledQuery,\n DEFAULT_MIGRATION_LOCK_TABLE,\n DEFAULT_MIGRATION_TABLE,\n DefaultQueryCompiler,\n sql,\n} from \"kysely\";\n\nclass NodeSqliteAdapter implements DialectAdapterBase {\n get supportsCreateIfNotExists(): boolean {\n return true;\n }\n\n get supportsTransactionalDdl(): boolean {\n return false;\n }\n\n get supportsReturning(): boolean {\n return true;\n }\n\n async acquireMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n\n async releaseMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n get supportsOutput(): boolean {\n return true;\n }\n}\n\n/**\n * Config for the SQLite dialect.\n */\nexport interface NodeSqliteDialectConfig {\n /**\n * A sqlite DatabaseSync instance or a function that returns one.\n */\n database: DatabaseSync;\n\n /**\n * Called once when the first query is executed.\n */\n onCreateConnection?:\n | ((connection: DatabaseConnection) => Promise<void>)\n | undefined;\n}\n\nclass NodeSqliteDriver implements Driver {\n readonly #config: NodeSqliteDialectConfig;\n readonly #connectionMutex = new ConnectionMutex();\n\n #db?: DatabaseSync;\n #connection?: DatabaseConnection;\n\n constructor(config: NodeSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n async init(): Promise<void> {\n this.#db = this.#config.database;\n\n this.#connection = new NodeSqliteConnection(this.#db);\n\n if (this.#config.onCreateConnection) {\n await this.#config.onCreateConnection(this.#connection);\n }\n }\n\n async acquireConnection(): Promise<DatabaseConnection> {\n // SQLite only has one single connection. We use a mutex here to wait\n // until the single connection has been released.\n await this.#connectionMutex.lock();\n return this.#connection!;\n }\n\n async beginTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"begin\"));\n }\n\n async commitTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"commit\"));\n }\n\n async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"rollback\"));\n }\n\n async releaseConnection(): Promise<void> {\n this.#connectionMutex.unlock();\n }\n\n async destroy(): Promise<void> {\n this.#db?.close();\n }\n}\n\nclass NodeSqliteConnection implements DatabaseConnection {\n readonly #db: DatabaseSync;\n\n constructor(db: DatabaseSync) {\n this.#db = db;\n }\n\n executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n const { sql, parameters } = compiledQuery;\n const stmt = this.#db.prepare(sql);\n\n const rows = stmt.all(...(parameters as any[])) as O[];\n\n return Promise.resolve({\n rows,\n });\n }\n\n async *streamQuery() {\n throw new Error(\"Streaming query is not supported by SQLite driver.\");\n }\n}\n\nclass ConnectionMutex {\n #promise?: Promise<void>;\n #resolve?: () => void;\n\n async lock(): Promise<void> {\n while (this.#promise) {\n await this.#promise;\n }\n\n this.#promise = new Promise((resolve) => {\n this.#resolve = resolve;\n });\n }\n\n unlock(): void {\n const resolve = this.#resolve;\n\n this.#promise = undefined;\n this.#resolve = undefined;\n\n resolve?.();\n }\n}\n\nclass NodeSqliteIntrospector implements DatabaseIntrospector {\n readonly #db: Kysely<unknown>;\n\n constructor(db: Kysely<unknown>) {\n this.#db = db;\n }\n\n async getSchemas(): Promise<SchemaMetadata[]> {\n // Sqlite doesn't support schemas.\n return [];\n }\n\n async getTables(\n options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n ): Promise<TableMetadata[]> {\n let query = this.#db\n // @ts-expect-error\n .selectFrom(\"sqlite_schema\")\n // @ts-expect-error\n .where(\"type\", \"=\", \"table\")\n // @ts-expect-error\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select(\"name\")\n .$castTo<{ name: string }>();\n\n if (!options.withInternalKyselyTables) {\n query = query\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_TABLE)\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_LOCK_TABLE);\n }\n\n const tables = await query.execute();\n return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));\n }\n\n async getMetadata(\n options?: DatabaseMetadataOptions | undefined,\n ): Promise<DatabaseMetadata> {\n return {\n tables: await this.getTables(options),\n };\n }\n\n async #getTableMetadata(table: string): Promise<TableMetadata> {\n const db = this.#db;\n\n // Get the SQL that was used to create the table.\n const createSql = await db\n // @ts-expect-error\n .selectFrom(\"sqlite_master\")\n // @ts-expect-error\n .where(\"name\", \"=\", table)\n .select(\"sql\")\n .$castTo<{ sql: string | undefined }>()\n .execute();\n\n // Try to find the name of the column that has `autoincrement` >&\n const autoIncrementCol = createSql[0]?.sql\n ?.split(/[\\(\\),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = await db\n .selectFrom(\n sql<{\n name: string;\n type: string;\n notnull: 0 | 1;\n dflt_value: any;\n }>`pragma_table_info(${table})`.as(\"table_info\"),\n )\n .select([\"name\", \"type\", \"notnull\", \"dflt_value\"])\n .execute();\n\n return {\n name: table,\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n })),\n isView: true,\n };\n }\n}\n\nclass NodeSqliteQueryCompiler extends DefaultQueryCompiler {\n protected override getCurrentParameterPlaceholder() {\n return \"?\";\n }\n\n protected override getLeftIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getRightIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getAutoIncrement() {\n return \"autoincrement\";\n }\n}\n\nexport class NodeSqliteDialect implements Dialect {\n readonly #config: NodeSqliteDialectConfig;\n\n constructor(config: NodeSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n createDriver(): Driver {\n return new NodeSqliteDriver(this.#config);\n }\n\n createQueryCompiler(): QueryCompiler {\n return new NodeSqliteQueryCompiler();\n }\n\n createAdapter(): DialectAdapter {\n return new NodeSqliteAdapter();\n }\n\n createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n return new NodeSqliteIntrospector(db);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { DBAdapter, DBAdapterDebugLogOption, PecuniaOptions } from "pecunia-core";
2
2
  import { Db, MongoClient } from "mongodb";
3
3
 
4
- //#region src/adapters/mongodb/index.d.ts
4
+ //#region src/adapters/mongodb-adapter/index.d.ts
5
5
  interface MongoDBAdapterConfig {
6
6
  /**
7
7
  * MongoDB client instance
@@ -1,7 +1,7 @@
1
1
  import { createAdapterFactory } from "pecunia-core";
2
2
  import { ObjectId } from "mongodb";
3
3
 
4
- //#region src/adapters/mongodb/index.ts
4
+ //#region src/adapters/mongodb-adapter/index.ts
5
5
  const mongodbAdapter = (db, config) => {
6
6
  let lazyOptions;
7
7
  const createCustomAdapter = (db$1, session) => ({ getFieldName, schema, getDefaultModelName, options }) => {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["db"],"sources":["../../../src/adapters/mongodb-adapter/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type {\n AdapterFactoryCreator,\n AdapterFactoryOptions,\n DBAdapter,\n DBAdapterDebugLogOption,\n Where,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\";\nimport type { ClientSession, Db, MongoClient } from \"mongodb\";\nimport { ObjectId } from \"mongodb\";\n\nexport interface MongoDBAdapterConfig {\n /**\n * MongoDB client instance\n * If not provided, Database transactions won't be enabled.\n */\n client?: MongoClient | undefined;\n /**\n * Enable debug logs for the adapter\n *\n * @default false\n */\n debugLogs?: DBAdapterDebugLogOption | undefined;\n /**\n * Use plural table names\n *\n * @default false\n */\n usePlural?: boolean | undefined;\n /**\n * Whether to execute multiple operations in a transaction.\n *\n * If the database doesn't support transactions,\n * set this to `false` and operations will be executed sequentially.\n * @default false\n */\n transaction?: boolean | undefined;\n}\n\nexport const mongodbAdapter = (\n db: Db,\n config?: MongoDBAdapterConfig | undefined,\n) => {\n let lazyOptions: PecuniaOptions | null;\n\n const createCustomAdapter =\n (db: Db, session?: ClientSession | undefined): AdapterFactoryCreator =>\n ({ getFieldName, schema, getDefaultModelName, options }) => {\n function serializeID({\n field,\n value,\n model,\n }: {\n field: string;\n value: any;\n model: string;\n }) {\n model = getDefaultModelName(model);\n\n if (\n field === \"id\" ||\n field === \"_id\" ||\n schema[model]!.fields[field]?.references?.field === \"id\"\n ) {\n if (value === null || value === undefined) return value;\n\n if (typeof value !== \"string\") {\n if (value instanceof ObjectId) return value;\n\n if (Array.isArray(value)) {\n return value.map((v) => {\n if (v === null || v === undefined) return v;\n\n if (typeof v === \"string\") {\n try {\n return new ObjectId(v);\n } catch {\n return v;\n }\n }\n\n if (v instanceof ObjectId) return v;\n\n throw new Error(\n \"Invalid id value, received: \" + JSON.stringify(v),\n );\n });\n }\n\n throw new Error(\n \"Invalid id value, received: \" + JSON.stringify(value),\n );\n }\n\n try {\n return new ObjectId(value);\n } catch {\n return value;\n }\n }\n\n return value;\n }\n\n function convertWhereClause({\n where,\n model,\n }: {\n where: Where[];\n model: string;\n }) {\n if (!where.length) return {};\n\n const conditions = where.map((w) => {\n const {\n field: field_,\n value,\n operator = \"eq\",\n connector = \"AND\",\n } = w;\n\n let condition: any;\n let field = getFieldName({ model, field: field_ });\n if (field === \"id\") field = \"_id\";\n\n switch (operator.toLowerCase()) {\n case \"eq\":\n condition = {\n [field]: serializeID({ field, value, model }),\n };\n break;\n\n case \"in\":\n condition = {\n [field]: {\n $in: Array.isArray(value)\n ? value.map((v) => serializeID({ field, value: v, model }))\n : [serializeID({ field, value, model })],\n },\n };\n break;\n\n case \"not_in\":\n condition = {\n [field]: {\n $nin: Array.isArray(value)\n ? value.map((v) => serializeID({ field, value: v, model }))\n : [serializeID({ field, value, model })],\n },\n };\n break;\n\n case \"gt\":\n condition = {\n [field]: { $gt: serializeID({ field, value, model }) },\n };\n break;\n\n case \"gte\":\n condition = {\n [field]: { $gte: serializeID({ field, value, model }) },\n };\n break;\n\n case \"lt\":\n condition = {\n [field]: { $lt: serializeID({ field, value, model }) },\n };\n break;\n\n case \"lte\":\n condition = {\n [field]: { $lte: serializeID({ field, value, model }) },\n };\n break;\n\n case \"ne\":\n condition = {\n [field]: { $ne: serializeID({ field, value, model }) },\n };\n break;\n\n case \"contains\":\n condition = {\n [field]: {\n $regex: `.*${escapeForMongoRegex(value as string)}.*`,\n },\n };\n break;\n\n case \"starts_with\":\n condition = {\n [field]: {\n $regex: `^${escapeForMongoRegex(value as string)}`,\n },\n };\n break;\n\n case \"ends_with\":\n condition = {\n [field]: {\n $regex: `${escapeForMongoRegex(value as string)}$`,\n },\n };\n break;\n\n default:\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n return { condition, connector };\n });\n\n if (conditions.length === 1) {\n return conditions[0]!.condition;\n }\n\n const andConditions = conditions\n .filter((c) => c.connector === \"AND\")\n .map((c) => c.condition);\n\n const orConditions = conditions\n .filter((c) => c.connector === \"OR\")\n .map((c) => c.condition);\n\n let clause: any = {};\n if (andConditions.length) clause = { ...clause, $and: andConditions };\n if (orConditions.length) clause = { ...clause, $or: orConditions };\n\n return clause;\n }\n\n return {\n async create({ model, data: values }) {\n const res = await db.collection(model).insertOne(values, { session });\n const insertedData = { _id: res.insertedId.toString(), ...values };\n return insertedData as any;\n },\n\n async findOne({ model, where, select }) {\n const matchStage = where\n ? { $match: convertWhereClause({ where, model }) }\n : { $match: {} };\n\n const pipeline: any[] = [matchStage];\n\n if (select) {\n const projection: any = {};\n select.forEach((field) => {\n projection[getFieldName({ field, model })] = 1;\n });\n pipeline.push({ $project: projection });\n }\n\n pipeline.push({ $limit: 1 });\n\n const res = await db\n .collection(model)\n .aggregate(pipeline, { session })\n .toArray();\n\n if (!res || res.length === 0) return null;\n return res[0] as any;\n },\n\n async findMany({ model, where, limit, offset, sortBy }) {\n const matchStage = where\n ? { $match: convertWhereClause({ where, model }) }\n : { $match: {} };\n\n const pipeline: any[] = [matchStage];\n\n if (sortBy) {\n pipeline.push({\n $sort: {\n [getFieldName({ field: sortBy.field, model })]:\n sortBy.direction === \"desc\" ? -1 : 1,\n },\n });\n }\n\n if (offset) {\n pipeline.push({ $skip: offset });\n }\n\n if (limit) {\n pipeline.push({ $limit: limit });\n }\n\n const res = await db\n .collection(model)\n .aggregate(pipeline, { session })\n .toArray();\n\n return res as any;\n },\n\n async count({ model, where }) {\n const matchStage = where\n ? { $match: convertWhereClause({ where, model }) }\n : { $match: {} };\n\n const pipeline: any[] = [matchStage, { $count: \"total\" }];\n\n const res = await db\n .collection(model)\n .aggregate(pipeline, { session })\n .toArray();\n\n if (!res || res.length === 0) return 0;\n return res[0]?.total ?? 0;\n },\n\n async update({ model, where, update: values }) {\n const clause = convertWhereClause({ where, model });\n\n const res = await db.collection(model).findOneAndUpdate(\n clause,\n { $set: values as any },\n {\n session,\n returnDocument: \"after\",\n includeResultMetadata: true,\n },\n );\n\n const doc = (res as any)?.value ?? null;\n if (!doc) return null;\n return doc as any;\n },\n\n async updateMany({ model, where, update: values }) {\n const clause = convertWhereClause({ where, model });\n\n const res = await db\n .collection(model)\n .updateMany(clause, { $set: values as any }, { session });\n\n return res.modifiedCount;\n },\n\n async delete({ model, where }) {\n const clause = convertWhereClause({ where, model });\n await db.collection(model).deleteOne(clause, { session });\n },\n\n async deleteMany({ model, where }) {\n const clause = convertWhereClause({ where, model });\n const res = await db\n .collection(model)\n .deleteMany(clause, { session });\n return res.deletedCount;\n },\n };\n };\n\n let lazyAdapter:\n | ((options: PecuniaOptions) => DBAdapter<PecuniaOptions>)\n | null = null;\n\n let adapterOptions: AdapterFactoryOptions | null = null;\n\n adapterOptions = {\n config: {\n adapterId: \"mongodb-adapter\",\n adapterName: \"MongoDB Adapter\",\n usePlural: config?.usePlural ?? false,\n mapKeysTransformInput: {\n id: \"_id\",\n },\n mapKeysTransformOutput: {\n _id: \"id\",\n },\n supportsArrays: true,\n supportsNumericIds: false,\n transaction:\n config?.client && (config?.transaction ?? true)\n ? async (cb) => {\n if (!config.client) {\n return cb(lazyAdapter!(lazyOptions!));\n }\n\n const session = config.client.startSession();\n\n try {\n session.startTransaction();\n\n const adapter = createAdapterFactory({\n config: adapterOptions!.config,\n adapter: createCustomAdapter(db, session),\n })(lazyOptions!);\n\n const result = await cb(adapter);\n\n await session.commitTransaction();\n return result;\n } catch (err) {\n await session.abortTransaction();\n throw err;\n } finally {\n await session.endSession();\n }\n }\n : false,\n customTransformInput({ action, data, field, fieldAttributes, options }) {\n if (field === \"_id\" || fieldAttributes.references?.field === \"id\") {\n if (action !== \"create\") return data;\n\n if (Array.isArray(data)) {\n return data.map((v) => {\n if (typeof v === \"string\") {\n try {\n return new ObjectId(v);\n } catch {\n return v;\n }\n }\n return v;\n });\n }\n\n if (typeof data === \"string\") {\n try {\n return new ObjectId(data);\n } catch {\n return data;\n }\n }\n\n if (\n fieldAttributes?.references?.field === \"id\" &&\n !fieldAttributes?.required &&\n data === null\n ) {\n return null;\n }\n\n return new ObjectId();\n }\n\n return data;\n },\n customTransformOutput({ data, field, fieldAttributes }) {\n if (field === \"id\" || fieldAttributes.references?.field === \"id\") {\n if (data instanceof ObjectId) return data.toHexString();\n\n if (Array.isArray(data)) {\n return data.map((v) => {\n if (v instanceof ObjectId) return v.toHexString();\n return v;\n });\n }\n\n return data;\n }\n\n return data;\n },\n customIdGenerator() {\n return new ObjectId().toString();\n },\n },\n adapter: createCustomAdapter(db),\n };\n\n lazyAdapter = createAdapterFactory(adapterOptions);\n\n return (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n lazyOptions = options;\n return lazyAdapter(options);\n };\n};\n\n/**\n * Safely escape user input for use in a MongoDB regex.\n * This ensures the resulting pattern is treated as literal text,\n * and not as a regex with special syntax.\n *\n * @param input - The input string to escape. Any type that isn't a string will be converted to an empty string.\n * @param maxLength - The maximum length of the input string to escape. Defaults to 256. This is to prevent DOS attacks.\n * @returns The escaped string.\n */\nfunction escapeForMongoRegex(input: string, maxLength = 256): string {\n if (typeof input !== \"string\") return \"\";\n\n // Escape all PCRE special characters\n // Source: PCRE docs — https://www.pcre.org/original/doc/html/pcrepattern.html\n return input.slice(0, maxLength).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { DBAdapter, DBAdapterDebugLogOption, PecuniaOptions } from "pecunia-core";
2
2
 
3
- //#region src/adapters/prisma/index.d.ts
3
+ //#region src/adapters/prisma-adapter/index.d.ts
4
4
  interface PrismaConfig {
5
5
  /**
6
6
  * Database provider.
@@ -1,6 +1,6 @@
1
1
  import { PecuniaError, createAdapterFactory } from "pecunia-core";
2
2
 
3
- //#region src/adapters/prisma/index.ts
3
+ //#region src/adapters/prisma-adapter/index.ts
4
4
  const prismaAdapter = (prisma, config) => {
5
5
  let lazyOptions = null;
6
6
  const createCustomAdapter = (prisma$1) => ({ getFieldName }) => {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["prisma","and","or","orClause","andClause"],"sources":["../../../src/adapters/prisma-adapter/index.ts"],"sourcesContent":["import type { Awaitable, PecuniaOptions } from \"pecunia-core\";\nimport type {\n AdapterFactoryCreator,\n AdapterFactoryOptions,\n DBAdapter,\n DBAdapterDebugLogOption,\n Where,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\n\nexport interface PrismaConfig {\n /**\n * Database provider.\n */\n provider:\n | \"sqlite\"\n | \"cockroachdb\"\n | \"mysql\"\n | \"postgresql\"\n | \"sqlserver\"\n | \"mongodb\";\n\n /**\n * Enable debug logs for the adapter\n *\n * @default false\n */\n debugLogs?: DBAdapterDebugLogOption | undefined;\n\n /**\n * Use plural table names\n *\n * @default false\n */\n usePlural?: boolean | undefined;\n\n /**\n * Whether to execute multiple operations in a transaction.\n *\n * If the database doesn't support transactions,\n * set this to `false` and operations will be executed sequentially.\n * @default false\n */\n transaction?: boolean | undefined;\n}\n\ninterface PrismaClient {}\n\ntype PrismaClientInternal = {\n $transaction: (\n callback: (db: PrismaClient) => Awaitable<any>,\n ) => Promise<any>;\n} & {\n [model: string]: {\n create: (data: any) => Promise<any>;\n findFirst: (data: any) => Promise<any>;\n findMany: (data: any) => Promise<any>;\n update: (data: any) => Promise<any>;\n updateMany: (data: any) => Promise<any>;\n delete: (data: any) => Promise<any>;\n count: (data: any) => Promise<any>;\n [key: string]: any;\n };\n};\n\nexport const prismaAdapter = (prisma: PrismaClient, config: PrismaConfig) => {\n let lazyOptions: PecuniaOptions | null = null;\n\n const createCustomAdapter =\n (prisma: PrismaClient): AdapterFactoryCreator =>\n ({ getFieldName }) => {\n const db = prisma as PrismaClientInternal;\n\n function operatorToPrismaOperator(operator: string) {\n switch (operator) {\n case \"starts_with\":\n return \"startsWith\";\n case \"ends_with\":\n return \"endsWith\";\n case \"ne\":\n return \"not\";\n case \"not_in\":\n return \"notIn\";\n default:\n return operator;\n }\n }\n\n const convertWhereClause = ({\n action,\n model,\n where,\n }: {\n model: string;\n where?: Where[] | undefined;\n action:\n | \"create\"\n | \"update\"\n | \"delete\"\n | \"findOne\"\n | \"findMany\"\n | \"count\"\n | \"updateMany\"\n | \"deleteMany\";\n }) => {\n if (!where || !where.length) return {};\n\n const buildSingleCondition = (w: Where) => {\n const fieldName = getFieldName({ model, field: w.field });\n\n // Prisma null semantics: \"not: null\" on nullable can behave unexpectedly;\n // for non-nullable fields it's a tautology. Skip.\n if (w.operator === \"ne\" && w.value === null) {\n return {};\n }\n\n if (\n (w.operator === \"in\" || w.operator === \"not_in\") &&\n Array.isArray(w.value)\n ) {\n const filtered = w.value.filter((v) => v != null);\n\n if (filtered.length === 0) {\n if (w.operator === \"in\") {\n return {\n AND: [\n { [fieldName]: { equals: \"__never__\" } },\n { [fieldName]: { not: \"__never__\" } },\n ],\n };\n }\n return {};\n }\n\n const prismaOp = operatorToPrismaOperator(w.operator);\n return { [fieldName]: { [prismaOp]: filtered } };\n }\n\n if (w.operator === \"eq\" || !w.operator) {\n return { [fieldName]: w.value };\n }\n\n return {\n [fieldName]: {\n [operatorToPrismaOperator(w.operator)]: w.value,\n },\n };\n };\n\n // Update: extract simple equality AND conditions to root (Prisma unique where)\n if (action === \"update\") {\n const and = where.filter(\n (w) => w.connector === \"AND\" || !w.connector,\n );\n const or = where.filter((w) => w.connector === \"OR\");\n\n const andSimple = and.filter(\n (w) => w.operator === \"eq\" || !w.operator,\n );\n const andComplex = and.filter(\n (w) => w.operator !== \"eq\" && w.operator !== undefined,\n );\n\n const andSimpleClause = andSimple.map((w) => buildSingleCondition(w));\n const andComplexClause = andComplex.map((w) =>\n buildSingleCondition(w),\n );\n const orClause = or.map((w) => buildSingleCondition(w));\n\n const result: Record<string, any> = {};\n for (const clause of andSimpleClause) Object.assign(result, clause);\n if (andComplexClause.length > 0) result.AND = andComplexClause;\n if (orClause.length > 0) result.OR = orClause;\n\n return result;\n }\n\n // Delete: extract id to root if present\n if (action === \"delete\") {\n const idCondition = where.find((w) => w.field === \"id\");\n if (idCondition) {\n const idFieldName = getFieldName({ model, field: \"id\" });\n const idClause = buildSingleCondition(idCondition);\n const remainingWhere = where.filter((w) => w.field !== \"id\");\n\n if (remainingWhere.length === 0) return idClause;\n\n const and = remainingWhere.filter(\n (w) => w.connector === \"AND\" || !w.connector,\n );\n const or = remainingWhere.filter((w) => w.connector === \"OR\");\n const andClause = and.map((w) => buildSingleCondition(w));\n const orClause = or.map((w) => buildSingleCondition(w));\n\n const result: Record<string, any> = {};\n\n if (idFieldName in idClause) {\n result[idFieldName] = (idClause as Record<string, any>)[\n idFieldName\n ];\n } else {\n Object.assign(result, idClause);\n }\n\n if (andClause.length > 0) result.AND = andClause;\n if (orClause.length > 0) result.OR = orClause;\n\n return result;\n }\n }\n\n if (where.length === 1) {\n return buildSingleCondition(where[0]!);\n }\n\n const and = where.filter((w) => w.connector === \"AND\" || !w.connector);\n const or = where.filter((w) => w.connector === \"OR\");\n\n const andClause = and.map((w) => buildSingleCondition(w));\n const orClause = or.map((w) => buildSingleCondition(w));\n\n return {\n ...(andClause.length ? { AND: andClause } : {}),\n ...(orClause.length ? { OR: orClause } : {}),\n };\n };\n\n return {\n async create({ model, data: values, select }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const result = await db[model]!.create({\n data: values,\n select: select\n ? Object.fromEntries(\n select.map((field) => [getFieldName({ model, field }), true]),\n )\n : undefined,\n });\n\n return result;\n },\n\n async findOne({ model, where, select }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"findOne\",\n });\n\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n return await db[model]!.findFirst({\n where: whereClause,\n select: select\n ? Object.fromEntries(\n select.map((field) => [getFieldName({ model, field }), true]),\n )\n : undefined,\n });\n },\n\n async findMany({ model, where, limit, offset, sortBy }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"findMany\",\n });\n\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n return await db[model]!.findMany({\n where: whereClause,\n take: limit || 100,\n skip: offset || 0,\n ...(sortBy?.field\n ? {\n orderBy: {\n [getFieldName({ model, field: sortBy.field })]:\n sortBy.direction === \"desc\" ? \"desc\" : \"asc\",\n },\n }\n : {}),\n select: undefined,\n });\n },\n\n async count({ model, where }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"count\",\n });\n\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n return await db[model]!.count({ where: whereClause });\n },\n\n async update({ model, where, update }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"update\",\n });\n\n return await db[model]!.update({\n where: whereClause,\n data: update,\n });\n },\n\n async updateMany({ model, where, update }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"updateMany\",\n });\n\n const result = await db[model]!.updateMany({\n where: whereClause,\n data: update,\n });\n\n return result ? (result.count as number) : 0;\n },\n\n async delete({ model, where }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"delete\",\n });\n\n try {\n await db[model]!.delete({ where: whereClause });\n } catch (e: any) {\n if (e?.meta?.cause === \"Record to delete does not exist.\") return;\n console.log(e);\n }\n },\n\n async deleteMany({ model, where }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"deleteMany\",\n });\n\n const result = await db[model]!.deleteMany({\n where: whereClause,\n });\n\n return result ? (result.count as number) : 0;\n },\n\n options: config,\n };\n };\n\n let adapterOptions: AdapterFactoryOptions | null = null;\n\n adapterOptions = {\n config: {\n adapterId: \"prisma\",\n adapterName: \"Prisma Adapter\",\n usePlural: config.usePlural ?? false,\n supportsUUIDs: config.provider === \"postgresql\" ? true : false,\n supportsArrays:\n config.provider === \"postgresql\" || config.provider === \"mongodb\"\n ? true\n : false,\n transaction:\n (config.transaction ?? false)\n ? (cb) =>\n (prisma as PrismaClientInternal).$transaction((tx) => {\n const adapter = createAdapterFactory({\n config: adapterOptions!.config,\n adapter: createCustomAdapter(tx),\n })(lazyOptions!);\n return cb(adapter);\n })\n : false,\n },\n adapter: createCustomAdapter(prisma),\n };\n\n const adapter = createAdapterFactory(adapterOptions);\n\n return (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n lazyOptions = options;\n return adapter(options);\n };\n};\n"],"mappings":";;;AAkEA,MAAa,iBAAiB,QAAsB,WAAyB;CAC3E,IAAI,cAAqC;CAEzC,MAAM,uBACH,cACA,EAAE,mBAAmB;EACpB,MAAM,KAAKA;EAEX,SAAS,yBAAyB,UAAkB;AAClD,WAAQ,UAAR;IACE,KAAK,cACH,QAAO;IACT,KAAK,YACH,QAAO;IACT,KAAK,KACH,QAAO;IACT,KAAK,SACH,QAAO;IACT,QACE,QAAO;;;EAIb,MAAM,sBAAsB,EAC1B,QACA,OACA,YAaI;AACJ,OAAI,CAAC,SAAS,CAAC,MAAM,OAAQ,QAAO,EAAE;GAEtC,MAAM,wBAAwB,MAAa;IACzC,MAAM,YAAY,aAAa;KAAE;KAAO,OAAO,EAAE;KAAO,CAAC;AAIzD,QAAI,EAAE,aAAa,QAAQ,EAAE,UAAU,KACrC,QAAO,EAAE;AAGX,SACG,EAAE,aAAa,QAAQ,EAAE,aAAa,aACvC,MAAM,QAAQ,EAAE,MAAM,EACtB;KACA,MAAM,WAAW,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK;AAEjD,SAAI,SAAS,WAAW,GAAG;AACzB,UAAI,EAAE,aAAa,KACjB,QAAO,EACL,KAAK,CACH,GAAG,YAAY,EAAE,QAAQ,aAAa,EAAE,EACxC,GAAG,YAAY,EAAE,KAAK,aAAa,EAAE,CACtC,EACF;AAEH,aAAO,EAAE;;KAGX,MAAM,WAAW,yBAAyB,EAAE,SAAS;AACrD,YAAO,GAAG,YAAY,GAAG,WAAW,UAAU,EAAE;;AAGlD,QAAI,EAAE,aAAa,QAAQ,CAAC,EAAE,SAC5B,QAAO,GAAG,YAAY,EAAE,OAAO;AAGjC,WAAO,GACJ,YAAY,GACV,yBAAyB,EAAE,SAAS,GAAG,EAAE,OAC3C,EACF;;AAIH,OAAI,WAAW,UAAU;IACvB,MAAMC,QAAM,MAAM,QACf,MAAM,EAAE,cAAc,SAAS,CAAC,EAAE,UACpC;IACD,MAAMC,OAAK,MAAM,QAAQ,MAAM,EAAE,cAAc,KAAK;IAEpD,MAAM,YAAYD,MAAI,QACnB,MAAM,EAAE,aAAa,QAAQ,CAAC,EAAE,SAClC;IACD,MAAM,aAAaA,MAAI,QACpB,MAAM,EAAE,aAAa,QAAQ,EAAE,aAAa,OAC9C;IAED,MAAM,kBAAkB,UAAU,KAAK,MAAM,qBAAqB,EAAE,CAAC;IACrE,MAAM,mBAAmB,WAAW,KAAK,MACvC,qBAAqB,EAAE,CACxB;IACD,MAAME,aAAWD,KAAG,KAAK,MAAM,qBAAqB,EAAE,CAAC;IAEvD,MAAM,SAA8B,EAAE;AACtC,SAAK,MAAM,UAAU,gBAAiB,QAAO,OAAO,QAAQ,OAAO;AACnE,QAAI,iBAAiB,SAAS,EAAG,QAAO,MAAM;AAC9C,QAAIC,WAAS,SAAS,EAAG,QAAO,KAAKA;AAErC,WAAO;;AAIT,OAAI,WAAW,UAAU;IACvB,MAAM,cAAc,MAAM,MAAM,MAAM,EAAE,UAAU,KAAK;AACvD,QAAI,aAAa;KACf,MAAM,cAAc,aAAa;MAAE;MAAO,OAAO;MAAM,CAAC;KACxD,MAAM,WAAW,qBAAqB,YAAY;KAClD,MAAM,iBAAiB,MAAM,QAAQ,MAAM,EAAE,UAAU,KAAK;AAE5D,SAAI,eAAe,WAAW,EAAG,QAAO;KAExC,MAAMF,QAAM,eAAe,QACxB,MAAM,EAAE,cAAc,SAAS,CAAC,EAAE,UACpC;KACD,MAAMC,OAAK,eAAe,QAAQ,MAAM,EAAE,cAAc,KAAK;KAC7D,MAAME,cAAYH,MAAI,KAAK,MAAM,qBAAqB,EAAE,CAAC;KACzD,MAAME,aAAWD,KAAG,KAAK,MAAM,qBAAqB,EAAE,CAAC;KAEvD,MAAM,SAA8B,EAAE;AAEtC,SAAI,eAAe,SACjB,QAAO,eAAgB,SACrB;SAGF,QAAO,OAAO,QAAQ,SAAS;AAGjC,SAAIE,YAAU,SAAS,EAAG,QAAO,MAAMA;AACvC,SAAID,WAAS,SAAS,EAAG,QAAO,KAAKA;AAErC,YAAO;;;AAIX,OAAI,MAAM,WAAW,EACnB,QAAO,qBAAqB,MAAM,GAAI;GAGxC,MAAM,MAAM,MAAM,QAAQ,MAAM,EAAE,cAAc,SAAS,CAAC,EAAE,UAAU;GACtE,MAAM,KAAK,MAAM,QAAQ,MAAM,EAAE,cAAc,KAAK;GAEpD,MAAM,YAAY,IAAI,KAAK,MAAM,qBAAqB,EAAE,CAAC;GACzD,MAAM,WAAW,GAAG,KAAK,MAAM,qBAAqB,EAAE,CAAC;AAEvD,UAAO;IACL,GAAI,UAAU,SAAS,EAAE,KAAK,WAAW,GAAG,EAAE;IAC9C,GAAI,SAAS,SAAS,EAAE,IAAI,UAAU,GAAG,EAAE;IAC5C;;AAGH,SAAO;GACL,MAAM,OAAO,EAAE,OAAO,MAAM,QAAQ,UAAU;AAC5C,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;AAYH,WATe,MAAM,GAAG,OAAQ,OAAO;KACrC,MAAM;KACN,QAAQ,SACJ,OAAO,YACL,OAAO,KAAK,UAAU,CAAC,aAAa;MAAE;MAAO;MAAO,CAAC,EAAE,KAAK,CAAC,CAC9D,GACD;KACL,CAAC;;GAKJ,MAAM,QAAQ,EAAE,OAAO,OAAO,UAAU;IACtC,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;AAEF,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;AAGH,WAAO,MAAM,GAAG,OAAQ,UAAU;KAChC,OAAO;KACP,QAAQ,SACJ,OAAO,YACL,OAAO,KAAK,UAAU,CAAC,aAAa;MAAE;MAAO;MAAO,CAAC,EAAE,KAAK,CAAC,CAC9D,GACD;KACL,CAAC;;GAGJ,MAAM,SAAS,EAAE,OAAO,OAAO,OAAO,QAAQ,UAAU;IACtD,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;AAEF,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;AAGH,WAAO,MAAM,GAAG,OAAQ,SAAS;KAC/B,OAAO;KACP,MAAM,SAAS;KACf,MAAM,UAAU;KAChB,GAAI,QAAQ,QACR,EACE,SAAS,GACN,aAAa;MAAE;MAAO,OAAO,OAAO;MAAO,CAAC,GAC3C,OAAO,cAAc,SAAS,SAAS,OAC1C,EACF,GACD,EAAE;KACN,QAAQ;KACT,CAAC;;GAGJ,MAAM,MAAM,EAAE,OAAO,SAAS;IAC5B,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;AAEF,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;AAGH,WAAO,MAAM,GAAG,OAAQ,MAAM,EAAE,OAAO,aAAa,CAAC;;GAGvD,MAAM,OAAO,EAAE,OAAO,OAAO,UAAU;AACrC,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;IAGH,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;AAEF,WAAO,MAAM,GAAG,OAAQ,OAAO;KAC7B,OAAO;KACP,MAAM;KACP,CAAC;;GAGJ,MAAM,WAAW,EAAE,OAAO,OAAO,UAAU;AACzC,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;IAGH,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;IAEF,MAAM,SAAS,MAAM,GAAG,OAAQ,WAAW;KACzC,OAAO;KACP,MAAM;KACP,CAAC;AAEF,WAAO,SAAU,OAAO,QAAmB;;GAG7C,MAAM,OAAO,EAAE,OAAO,SAAS;AAC7B,QAAI,CAAC,GAAG,OACN,OAAM,IAAI,aACR,SAAS,MAAM,oHAChB;IAGH,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;AAEF,QAAI;AACF,WAAM,GAAG,OAAQ,OAAO,EAAE,OAAO,aAAa,CAAC;aACxC,GAAQ;AACf,SAAI,GAAG,MAAM,UAAU,mCAAoC;AAC3D,aAAQ,IAAI,EAAE;;;GAIlB,MAAM,WAAW,EAAE,OAAO,SAAS;IACjC,MAAM,cAAc,mBAAmB;KACrC;KACA;KACA,QAAQ;KACT,CAAC;IAEF,MAAM,SAAS,MAAM,GAAG,OAAQ,WAAW,EACzC,OAAO,aACR,CAAC;AAEF,WAAO,SAAU,OAAO,QAAmB;;GAG7C,SAAS;GACV;;CAGL,IAAI,iBAA+C;AAEnD,kBAAiB;EACf,QAAQ;GACN,WAAW;GACX,aAAa;GACb,WAAW,OAAO,aAAa;GAC/B,eAAe,OAAO,aAAa,eAAe,OAAO;GACzD,gBACE,OAAO,aAAa,gBAAgB,OAAO,aAAa,YACpD,OACA;GACN,aACG,OAAO,eAAe,SAClB,OACE,OAAgC,cAAc,OAAO;AAKpD,WAAO,GAJS,qBAAqB;KACnC,QAAQ,eAAgB;KACxB,SAAS,oBAAoB,GAAG;KACjC,CAAC,CAAC,YAAa,CACE;KAClB,GACJ;GACP;EACD,SAAS,oBAAoB,OAAO;EACrC;CAED,MAAM,UAAU,qBAAqB,eAAe;AAEpD,SAAQ,YAAuD;AAC7D,gBAAc;AACd,SAAO,QAAQ,QAAQ"}
@@ -1,4 +1,4 @@
1
- import { getKyselyDatabaseType } from "../adapters/kysely/dialect.mjs";
1
+ import { getKyselyDatabaseType } from "../adapters/kysely-adapter/dialect.mjs";
2
2
  import { getMigrations } from "../db/migrations/index.mjs";
3
3
  import { createInternalAdapter } from "../adapters/internal/index.mjs";
4
4
  import { isPromise } from "../utils/is-promise.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/context/index.ts"],"sourcesContent":["import type { PecuniaContext, PecuniaOptions, PecuniaPlugin } from \"pecunia-core\";\nimport { getPaymentTables } from \"pecunia-core\";\nimport type { DBAdapter } from \"pecunia-core\";\nimport { createLogger, env, isProduction, isTest } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\nimport defu from \"defu\";\n// import type { Entries } from \"type-fest\";\n// import { checkEndpointConflicts } from \"../api\";\n// import { matchesOriginPattern } from \"../payment/trusted-origins\";\nimport { createInternalAdapter } from \"../adapters/internal\";\nimport { isPromise } from \"../utils/is-promise\";\nimport { getBaseURL } from \"../utils/url\";\nimport { getKyselyDatabaseType } from \"../adapters/kysely/dialect\";\nimport { getMigrations } from \"../db/migrations\";\nimport { getAdapter } from \"../adapters/get-adapter\";\n\nexport const init = async (options: PecuniaOptions) => {\n\tconst adapter = await getAdapter(options);\n\n\t// Get database type using Kysely's dialect detection\n\tconst getDatabaseType = (database: PecuniaOptions[\"database\"]) =>\n\t\tgetKyselyDatabaseType(database) || \"unknown\";\n\n\t// Use base context creation\n\tconst ctx = await createPecuniaContext(adapter, options, getDatabaseType);\n\n\t// Add runMigrations with Kysely support\n\tctx.runMigrations = async function () {\n\t\t// only run migrations if database is provided and it's not an adapter\n\t\tif (!options.database || \"updateMany\" in options.database) {\n\t\t\tthrow new PecuniaError(\n\t\t\t\t\"Database is not provided or it's an adapter. Migrations are only supported with a database instance.\",\n\t\t\t);\n\t\t}\n\t\tconst { runMigrations } = await getMigrations(options);\n\t\tawait runMigrations();\n\t};\n\n\treturn ctx;\n};\n\n\nexport async function runPluginInit(ctx: PecuniaContext) {\n\tlet options = ctx.options;\n\tconst plugins = options.plugins || [];\n\tlet context: PecuniaContext = ctx;\n\tfor (const plugin of plugins) {\n\t\tif (plugin.init) {\n\t\t\tlet initPromise = plugin.init(context);\n\t\t\tlet result: ReturnType<Required<PecuniaPlugin>[\"init\"]>;\n\t\t\tif (isPromise(initPromise)) {\n\t\t\t\tresult = await initPromise;\n\t\t\t} else {\n\t\t\t\tresult = initPromise;\n\t\t\t}\n\t\t\tif (typeof result === \"object\") {\n\t\t\t\tif (result.options) {\n\t\t\t\t\tconst { ...restOpts } = result.options;\n\t\t\t\t\toptions = defu(options, restOpts);\n\t\t\t\t}\n\t\t\t\tif (result.context) {\n\t\t\t\t\tcontext = {\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\t...(result.context as Partial<PecuniaContext>),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tcontext.internalAdapter = createInternalAdapter(context.adapter, {\n\t\toptions\n\t});\n\tcontext.options = options;\n\treturn { context };\n}\n\nexport async function createPecuniaContext(\n\tadapter: DBAdapter<PecuniaOptions>,\n\toptions: PecuniaOptions,\n\tgetDatabaseType: (database: PecuniaOptions[\"database\"]) => string,\n): Promise<PecuniaContext> {\n\tconst plugins = options.plugins || [];\n\tconst baseURL = getBaseURL(options.baseURL, options.basePath);\n\n\tif (!baseURL) {\n\t\tconsole.warn(\n\t\t\t`[senly] Base URL could not be determined. Please set a valid base URL using the baseURL config option or the BETTER_AUTH_BASE_URL environment variable. Without this, callbacks and redirects may not work correctly.`,\n\t\t);\n\t}\n\n\tconst secret =\n\t\tenv.BETTER_AUTH_SECRET ||\n\t\tenv.AUTH_SECRET\n\n\toptions = {\n\t\t...options,\n\t\t// secret,\n\t\tbaseURL: baseURL ? new URL(baseURL).origin : \"\",\n\t\tbasePath: options.basePath || \"/api/payment\",\n\t\tplugins\n\t};\n\n\t// checkEndpointConflicts(options);\n\tconst tables = getPaymentTables(options);\n\n\n\tlet ctx: PecuniaContext = {\n\t\tappName: 'Pecunia',\n\t\toptions,\n\t\ttables,\n\t\t// trustedOrigins: await getTrustedOrigins(options),\n\t\t// isTrustedOrigin(\n\t\t// \turl: string,\n\t\t// \tsettings?: {\n\t\t// \t\tallowRelativePaths: boolean;\n\t\t// \t},\n\t\t// ) {\n\t\t// \treturn this.trustedOrigins.some((origin) =>\n\t\t// \t\tmatchesOriginPattern(url, origin, settings),\n\t\t// \t);\n\t\t// },\n\t\tbaseURL: baseURL || \"\",\n\t\t// generateId: generateIdFunc,\n\t\tadapter: adapter,\n\t\tinternalAdapter: createInternalAdapter(adapter, {\n\t\t\toptions\n\t\t}),\n\t\tasync runMigrations() {\n\t\t\tthrow new PecuniaError(\n\t\t\t\t\"runMigrations will be set by the specific init implementation\",\n\t\t\t);\n\t\t},\n\t};\n\n\tconst initOrPromise = runPluginInit(ctx);\n\tlet context: PecuniaContext;\n\tif (isPromise(initOrPromise)) {\n\t\t({ context } = await initOrPromise);\n\t} else {\n\t\t({ context } = initOrPromise);\n\t}\n\n\treturn context;\n}\n"],"mappings":";;;;;;;;;;AAgBA,MAAa,OAAO,OAAO,YAA4B;CACtD,MAAM,UAAU,MAAM,WAAW,QAAQ;CAGzC,MAAM,mBAAmB,aACxB,sBAAsB,SAAS,IAAI;CAGpC,MAAM,MAAM,MAAM,qBAAqB,SAAS,SAAS,gBAAgB;AAGzE,KAAI,gBAAgB,iBAAkB;AAErC,MAAI,CAAC,QAAQ,YAAY,gBAAgB,QAAQ,SAChD,OAAM,IAAI,aACT,uGACA;EAEF,MAAM,EAAE,kBAAkB,MAAM,cAAc,QAAQ;AACtD,QAAM,eAAe;;AAGtB,QAAO;;AAIR,eAAsB,cAAc,KAAqB;CACxD,IAAI,UAAU,IAAI;CAClB,MAAM,UAAU,QAAQ,WAAW,EAAE;CACrC,IAAI,UAA0B;AAC9B,MAAK,MAAM,UAAU,QACpB,KAAI,OAAO,MAAM;EAChB,IAAI,cAAc,OAAO,KAAK,QAAQ;EACtC,IAAI;AACJ,MAAI,UAAU,YAAY,CACzB,UAAS,MAAM;MAEf,UAAS;AAEV,MAAI,OAAO,WAAW,UAAU;AAC/B,OAAI,OAAO,SAAS;IACnB,MAAM,EAAE,GAAG,aAAa,OAAO;AAC/B,cAAU,KAAK,SAAS,SAAS;;AAElC,OAAI,OAAO,QACV,WAAU;IACT,GAAG;IACH,GAAI,OAAO;IACX;;;AAKL,SAAQ,kBAAkB,sBAAsB,QAAQ,SAAS,EAChE,SACA,CAAC;AACF,SAAQ,UAAU;AAClB,QAAO,EAAE,SAAS;;AAGnB,eAAsB,qBACrB,SACA,SACA,iBAC0B;CAC1B,MAAM,UAAU,QAAQ,WAAW,EAAE;CACrC,MAAM,UAAU,WAAW,QAAQ,SAAS,QAAQ,SAAS;AAE7D,KAAI,CAAC,QACJ,SAAQ,KACP,wNACA;AAID,KAAI,sBACJ,IAAI;AAEL,WAAU;EACT,GAAG;EAEH,SAAS,UAAU,IAAI,IAAI,QAAQ,CAAC,SAAS;EAC7C,UAAU,QAAQ,YAAY;EAC9B;EACA;CAGD,MAAM,SAAS,iBAAiB,QAAQ;CA+BxC,MAAM,gBAAgB,cA5BI;EACzB,SAAS;EACT;EACA;EAYA,SAAS,WAAW;EAEX;EACT,iBAAiB,sBAAsB,SAAS,EAC/C,SACA,CAAC;EACF,MAAM,gBAAgB;AACrB,SAAM,IAAI,aACT,gEACA;;EAEF,CAEuC;CACxC,IAAI;AACJ,KAAI,UAAU,cAAc,CAC3B,EAAC,CAAE,WAAY,MAAM;KAErB,EAAC,CAAE,WAAY;AAGhB,QAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/context/index.ts"],"sourcesContent":["import type { PecuniaContext, PecuniaOptions, PecuniaPlugin } from \"pecunia-core\";\nimport { getPaymentTables } from \"pecunia-core\";\nimport type { DBAdapter } from \"pecunia-core\";\nimport { createLogger, env, isProduction, isTest } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\nimport defu from \"defu\";\n// import type { Entries } from \"type-fest\";\n// import { checkEndpointConflicts } from \"../api\";\n// import { matchesOriginPattern } from \"../payment/trusted-origins\";\nimport { createInternalAdapter } from \"../adapters/internal\";\nimport { isPromise } from \"../utils/is-promise\";\nimport { getBaseURL } from \"../utils/url\";\nimport { getKyselyDatabaseType } from \"../adapters/kysely-adapter/dialect\";\nimport { getMigrations } from \"../db/migrations\";\nimport { getAdapter } from \"../adapters/get-adapter\";\n\nexport const init = async (options: PecuniaOptions) => {\n\tconst adapter = await getAdapter(options);\n\n\t// Get database type using Kysely's dialect detection\n\tconst getDatabaseType = (database: PecuniaOptions[\"database\"]) =>\n\t\tgetKyselyDatabaseType(database) || \"unknown\";\n\n\t// Use base context creation\n\tconst ctx = await createPecuniaContext(adapter, options, getDatabaseType);\n\n\t// Add runMigrations with Kysely support\n\tctx.runMigrations = async function () {\n\t\t// only run migrations if database is provided and it's not an adapter\n\t\tif (!options.database || \"updateMany\" in options.database) {\n\t\t\tthrow new PecuniaError(\n\t\t\t\t\"Database is not provided or it's an adapter. Migrations are only supported with a database instance.\",\n\t\t\t);\n\t\t}\n\t\tconst { runMigrations } = await getMigrations(options);\n\t\tawait runMigrations();\n\t};\n\n\treturn ctx;\n};\n\n\nexport async function runPluginInit(ctx: PecuniaContext) {\n\tlet options = ctx.options;\n\tconst plugins = options.plugins || [];\n\tlet context: PecuniaContext = ctx;\n\tfor (const plugin of plugins) {\n\t\tif (plugin.init) {\n\t\t\tlet initPromise = plugin.init(context);\n\t\t\tlet result: ReturnType<Required<PecuniaPlugin>[\"init\"]>;\n\t\t\tif (isPromise(initPromise)) {\n\t\t\t\tresult = await initPromise;\n\t\t\t} else {\n\t\t\t\tresult = initPromise;\n\t\t\t}\n\t\t\tif (typeof result === \"object\") {\n\t\t\t\tif (result.options) {\n\t\t\t\t\tconst { ...restOpts } = result.options;\n\t\t\t\t\toptions = defu(options, restOpts);\n\t\t\t\t}\n\t\t\t\tif (result.context) {\n\t\t\t\t\tcontext = {\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\t...(result.context as Partial<PecuniaContext>),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tcontext.internalAdapter = createInternalAdapter(context.adapter, {\n\t\toptions\n\t});\n\tcontext.options = options;\n\treturn { context };\n}\n\nexport async function createPecuniaContext(\n\tadapter: DBAdapter<PecuniaOptions>,\n\toptions: PecuniaOptions,\n\tgetDatabaseType: (database: PecuniaOptions[\"database\"]) => string,\n): Promise<PecuniaContext> {\n\tconst plugins = options.plugins || [];\n\tconst baseURL = getBaseURL(options.baseURL, options.basePath);\n\n\tif (!baseURL) {\n\t\tconsole.warn(\n\t\t\t`[senly] Base URL could not be determined. Please set a valid base URL using the baseURL config option or the BETTER_AUTH_BASE_URL environment variable. Without this, callbacks and redirects may not work correctly.`,\n\t\t);\n\t}\n\n\tconst secret =\n\t\tenv.BETTER_AUTH_SECRET ||\n\t\tenv.AUTH_SECRET\n\n\toptions = {\n\t\t...options,\n\t\t// secret,\n\t\tbaseURL: baseURL ? new URL(baseURL).origin : \"\",\n\t\tbasePath: options.basePath || \"/api/payment\",\n\t\tplugins\n\t};\n\n\t// checkEndpointConflicts(options);\n\tconst tables = getPaymentTables(options);\n\n\n\tlet ctx: PecuniaContext = {\n\t\tappName: 'Pecunia',\n\t\toptions,\n\t\ttables,\n\t\t// trustedOrigins: await getTrustedOrigins(options),\n\t\t// isTrustedOrigin(\n\t\t// \turl: string,\n\t\t// \tsettings?: {\n\t\t// \t\tallowRelativePaths: boolean;\n\t\t// \t},\n\t\t// ) {\n\t\t// \treturn this.trustedOrigins.some((origin) =>\n\t\t// \t\tmatchesOriginPattern(url, origin, settings),\n\t\t// \t);\n\t\t// },\n\t\tbaseURL: baseURL || \"\",\n\t\t// generateId: generateIdFunc,\n\t\tadapter: adapter,\n\t\tinternalAdapter: createInternalAdapter(adapter, {\n\t\t\toptions\n\t\t}),\n\t\tasync runMigrations() {\n\t\t\tthrow new PecuniaError(\n\t\t\t\t\"runMigrations will be set by the specific init implementation\",\n\t\t\t);\n\t\t},\n\t};\n\n\tconst initOrPromise = runPluginInit(ctx);\n\tlet context: PecuniaContext;\n\tif (isPromise(initOrPromise)) {\n\t\t({ context } = await initOrPromise);\n\t} else {\n\t\t({ context } = initOrPromise);\n\t}\n\n\treturn context;\n}\n"],"mappings":";;;;;;;;;;AAgBA,MAAa,OAAO,OAAO,YAA4B;CACtD,MAAM,UAAU,MAAM,WAAW,QAAQ;CAGzC,MAAM,mBAAmB,aACxB,sBAAsB,SAAS,IAAI;CAGpC,MAAM,MAAM,MAAM,qBAAqB,SAAS,SAAS,gBAAgB;AAGzE,KAAI,gBAAgB,iBAAkB;AAErC,MAAI,CAAC,QAAQ,YAAY,gBAAgB,QAAQ,SAChD,OAAM,IAAI,aACT,uGACA;EAEF,MAAM,EAAE,kBAAkB,MAAM,cAAc,QAAQ;AACtD,QAAM,eAAe;;AAGtB,QAAO;;AAIR,eAAsB,cAAc,KAAqB;CACxD,IAAI,UAAU,IAAI;CAClB,MAAM,UAAU,QAAQ,WAAW,EAAE;CACrC,IAAI,UAA0B;AAC9B,MAAK,MAAM,UAAU,QACpB,KAAI,OAAO,MAAM;EAChB,IAAI,cAAc,OAAO,KAAK,QAAQ;EACtC,IAAI;AACJ,MAAI,UAAU,YAAY,CACzB,UAAS,MAAM;MAEf,UAAS;AAEV,MAAI,OAAO,WAAW,UAAU;AAC/B,OAAI,OAAO,SAAS;IACnB,MAAM,EAAE,GAAG,aAAa,OAAO;AAC/B,cAAU,KAAK,SAAS,SAAS;;AAElC,OAAI,OAAO,QACV,WAAU;IACT,GAAG;IACH,GAAI,OAAO;IACX;;;AAKL,SAAQ,kBAAkB,sBAAsB,QAAQ,SAAS,EAChE,SACA,CAAC;AACF,SAAQ,UAAU;AAClB,QAAO,EAAE,SAAS;;AAGnB,eAAsB,qBACrB,SACA,SACA,iBAC0B;CAC1B,MAAM,UAAU,QAAQ,WAAW,EAAE;CACrC,MAAM,UAAU,WAAW,QAAQ,SAAS,QAAQ,SAAS;AAE7D,KAAI,CAAC,QACJ,SAAQ,KACP,wNACA;AAID,KAAI,sBACJ,IAAI;AAEL,WAAU;EACT,GAAG;EAEH,SAAS,UAAU,IAAI,IAAI,QAAQ,CAAC,SAAS;EAC7C,UAAU,QAAQ,YAAY;EAC9B;EACA;CAGD,MAAM,SAAS,iBAAiB,QAAQ;CA+BxC,MAAM,gBAAgB,cA5BI;EACzB,SAAS;EACT;EACA;EAYA,SAAS,WAAW;EAEX;EACT,iBAAiB,sBAAsB,SAAS,EAC/C,SACA,CAAC;EACF,MAAM,gBAAgB;AACrB,SAAM,IAAI,aACT,gEACA;;EAEF,CAEuC;CACxC,IAAI;AACJ,KAAI,UAAU,cAAc,CAC3B,EAAC,CAAE,WAAY,MAAM;KAErB,EAAC,CAAE,WAAY;AAGhB,QAAO"}
@@ -1,4 +1,4 @@
1
- import { createKyselyAdapter } from "../../adapters/kysely/dialect.mjs";
1
+ import { createKyselyAdapter } from "../../adapters/kysely-adapter/dialect.mjs";
2
2
  import { getSchema } from "../schema/get-schema.mjs";
3
3
  import { getPaymentTables, initGetFieldName, initGetModelName } from "pecunia-core";
4
4
  import { sql } from "kysely";
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/db/migrations/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type { DBFieldAttribute, DBFieldType } from \"pecunia-core\";\nimport { initGetFieldName, initGetModelName } from \"pecunia-core\";\nimport type {\n AlterTableBuilder,\n AlterTableColumnAlteringBuilder,\n ColumnDataType,\n CreateIndexBuilder,\n CreateTableBuilder,\n Kysely,\n RawBuilder,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport { createKyselyAdapter } from \"../../adapters/kysely/dialect\";\nimport type { KyselyDatabaseDialectType } from \"pecunia-core\";\nimport { getSchema } from \"../schema/get-schema\";\nimport { getPaymentTables } from \"pecunia-core\";\n\ntype DbTypeBuckets = Record<\n \"string\" | \"uuid\" | \"number\" | \"boolean\" | \"date\" | \"json\",\n string[]\n>;\n\nconst postgresMap = {\n string: [\"character varying\", \"varchar\", \"text\", \"uuid\"],\n number: [\n \"int4\",\n \"integer\",\n \"bigint\",\n \"smallint\",\n \"numeric\",\n \"real\",\n \"double precision\",\n ],\n boolean: [\"bool\", \"boolean\"],\n date: [\"timestamptz\", \"timestamp\", \"date\"],\n json: [\"json\", \"jsonb\"],\n};\n\nconst mysqlMap = {\n string: [\"varchar\", \"text\", \"uuid\"],\n number: [\n \"integer\",\n \"int\",\n \"bigint\",\n \"smallint\",\n \"decimal\",\n \"float\",\n \"double\",\n ],\n boolean: [\"boolean\", \"tinyint\"],\n date: [\"timestamp\", \"datetime\", \"date\"],\n json: [\"json\"],\n};\n\nconst sqliteMap = {\n string: [\"TEXT\"],\n number: [\"INTEGER\", \"REAL\"],\n boolean: [\"INTEGER\", \"BOOLEAN\"], // 0 or 1\n date: [\"DATE\", \"INTEGER\"],\n json: [\"TEXT\"],\n};\n\nconst mssqlMap = {\n string: [\"varchar\", \"nvarchar\", \"uniqueidentifier\"],\n number: [\"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\"],\n boolean: [\"bit\", \"smallint\"],\n date: [\"datetime2\", \"date\", \"datetime\"],\n json: [\"varchar\", \"nvarchar\"],\n};\n\nconst map = {\n postgres: postgresMap,\n mysql: mysqlMap,\n sqlite: sqliteMap,\n mssql: mssqlMap,\n};\n\nexport function matchType(\n columnDataType: string,\n fieldType: DBFieldType,\n dbType: KyselyDatabaseDialectType,\n) {\n function normalize(type: string) {\n return type.toLowerCase().split(\"(\")[0]!.trim();\n }\n\n if (fieldType === \"string[]\" || fieldType === \"number[]\") {\n return columnDataType.toLowerCase().includes(\"json\");\n }\n\n const types: Partial<DbTypeBuckets> = map[dbType]!;\n const expected = Array.isArray(fieldType)\n ? types.string?.map((t) => t.toLowerCase())\n : types[fieldType]!.map((t: string) => t.toLowerCase());\n\n return expected?.includes(normalize(columnDataType));\n}\n\n/**\n * Get the current PostgreSQL schema (search_path) for the database connection\n * Returns the first schema in the search_path, defaulting to 'public' if not found\n */\nasync function getPostgresSchema(db: Kysely<unknown>): Promise<string> {\n try {\n const result = await sql<{ search_path: string }>`SHOW search_path`.execute(\n db,\n );\n\n if (result.rows[0]?.search_path) {\n const schemas = result.rows[0].search_path\n .split(\",\")\n .map((s) => s.trim())\n .map((s) => s.replace(/^[\"']|[\"']$/g, \"\"))\n .filter((s) => !s.startsWith(\"$\"));\n\n return schemas[0] || \"public\";\n }\n } catch {\n // fall back to public schema\n }\n\n return \"public\";\n}\n\nexport async function getMigrations(config: PecuniaOptions) {\n const billingEngineSchema = getSchema(config);\n\n let { kysely: db, databaseType: dbType } = await createKyselyAdapter(config);\n\n if (!dbType) {\n console.warn(\n \"Could not determine database type, defaulting to sqlite. Please provide a type in the database options to avoid this.\",\n );\n dbType = \"sqlite\";\n }\n\n if (!db) {\n console.error(\n \"Only kysely adapter is supported for migrations. You can use `generate` command to generate the schema, if you're using a different adapter.\",\n );\n process.exit(1);\n }\n\n // For PostgreSQL, detect and log the current schema being used\n let currentSchema = \"public\";\n if (dbType === \"postgres\") {\n currentSchema = await getPostgresSchema(db);\n console.debug(\n `PostgreSQL migration: Using schema '${currentSchema}' (from search_path)`,\n );\n\n // Verify the schema exists\n try {\n const schemaCheck = await sql<{ schema_name: string }>`\n SELECT schema_name\n FROM information_schema.schemata\n WHERE schema_name = ${currentSchema}\n `.execute(db);\n\n if (!schemaCheck.rows[0]) {\n console.warn(\n `Schema '${currentSchema}' does not exist. Tables will be inspected from available schemas. Consider creating the schema first or checking your database configuration.`,\n );\n }\n } catch (error) {\n console.debug(\n `Could not verify schema existence: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n const allTableMetadata = await db.introspection.getTables();\n\n // For PostgreSQL, filter tables to only those in the target schema\n let tableMetadata = allTableMetadata;\n if (dbType === \"postgres\") {\n try {\n const tablesInSchema = await sql<{\n table_name: string;\n }>`\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = ${currentSchema}\n AND table_type = 'BASE TABLE'\n `.execute(db);\n\n const tableNamesInSchema = new Set(\n tablesInSchema.rows.map((row) => row.table_name),\n );\n\n tableMetadata = allTableMetadata.filter(\n (table) =>\n table.schema === currentSchema && tableNamesInSchema.has(table.name),\n );\n\n console.debug(\n `Found ${tableMetadata.length} table(s) in schema '${currentSchema}': ${\n tableMetadata.map((t) => t.name).join(\", \") || \"(none)\"\n }`,\n );\n } catch (error) {\n console.warn(\n `Could not filter tables by schema. Using all discovered tables. Error: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n const toBeCreated: {\n table: string;\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }[] = [];\n\n const toBeAdded: {\n table: string;\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }[] = [];\n\n for (const [key, value] of Object.entries(billingEngineSchema)) {\n const table = tableMetadata.find((t) => t.name === key);\n\n if (!table) {\n const tIndex = toBeCreated.findIndex((t) => t.table === key);\n const tableData = {\n table: key,\n fields: value.fields,\n order: value.order || Infinity,\n };\n\n const insertIndex = toBeCreated.findIndex(\n (t) => (t.order || Infinity) > tableData.order,\n );\n\n if (insertIndex === -1) {\n if (tIndex === -1) {\n toBeCreated.push(tableData);\n } else {\n toBeCreated[tIndex]!.fields = {\n ...toBeCreated[tIndex]!.fields,\n ...value.fields,\n };\n }\n } else {\n toBeCreated.splice(insertIndex, 0, tableData);\n }\n\n continue;\n }\n\n const toBeAddedFields: Record<string, DBFieldAttribute> = {};\n\n for (const [fieldName, field] of Object.entries(value.fields)) {\n const column = table.columns.find((c) => c.name === fieldName);\n\n if (!column) {\n toBeAddedFields[fieldName] = field;\n continue;\n }\n\n if (matchType(column.dataType, field.type, dbType)) {\n continue;\n }\n\n console.warn(\n `Field ${fieldName} in table ${key} has a different type in the database. Expected ${field.type} but got ${column.dataType}.`,\n );\n }\n\n if (Object.keys(toBeAddedFields).length > 0) {\n toBeAdded.push({\n table: key,\n fields: toBeAddedFields,\n order: value.order || Infinity,\n });\n }\n }\n\n const migrations: (\n | AlterTableColumnAlteringBuilder\n | ReturnType<AlterTableBuilder[\"addIndex\"]>\n | CreateTableBuilder<string, string>\n | CreateIndexBuilder\n )[] = [];\n\n // Adapter-enforced strategy: UUID ids at the DB level\n const useUUIDs = true;\n\n function getType(field: DBFieldAttribute, fieldName: string) {\n const type = field.type;\n const provider = dbType || \"sqlite\";\n\n type StringOnlyUnion<T> = T extends string ? T : never;\n\n const typeMap: Record<\n StringOnlyUnion<DBFieldType> | \"id\" | \"foreignKeyId\",\n Record<KyselyDatabaseDialectType, ColumnDataType | RawBuilder<unknown>>\n > = {\n uuid: {\n postgres: \"uuid\",\n mysql: \"varchar(36)\",\n mssql: \"varchar(36)\",\n sqlite: \"text\",\n },\n string: {\n sqlite: \"text\",\n postgres: \"text\",\n mysql: field.unique\n ? \"varchar(255)\"\n : field.references\n ? \"varchar(36)\"\n : field.sortable\n ? \"varchar(255)\"\n : field.index\n ? \"varchar(255)\"\n : \"text\",\n mssql:\n field.unique || field.sortable\n ? \"varchar(255)\"\n : field.references\n ? \"varchar(36)\"\n : \"varchar(8000)\",\n },\n boolean: {\n sqlite: \"integer\",\n postgres: \"boolean\",\n mysql: \"boolean\",\n mssql: \"smallint\",\n },\n number: {\n sqlite: field.bigint ? \"bigint\" : \"integer\",\n postgres: field.bigint ? \"bigint\" : \"integer\",\n mysql: field.bigint ? \"bigint\" : \"integer\",\n mssql: field.bigint ? \"bigint\" : \"integer\",\n },\n date: {\n sqlite: \"date\",\n postgres: \"timestamptz\",\n mysql: \"timestamp(3)\",\n mssql: sql`datetime2(3)`,\n },\n json: {\n sqlite: \"text\",\n postgres: \"jsonb\",\n mysql: \"json\",\n mssql: \"varchar(8000)\",\n },\n id: {\n postgres: useUUIDs ? \"uuid\" : \"text\",\n mysql: \"varchar(36)\",\n mssql: \"varchar(36)\", // ideally UNIQUEIDENTIFIER, but not in Kysely's type interface\n sqlite: \"text\",\n },\n foreignKeyId: {\n postgres: useUUIDs ? \"uuid\" : \"text\",\n mysql: \"varchar(36)\",\n mssql: \"varchar(36)\",\n sqlite: \"text\",\n },\n \"string[]\": {\n sqlite: \"text\",\n postgres: \"jsonb\",\n mysql: \"json\",\n mssql: \"varchar(8000)\",\n },\n \"number[]\": {\n sqlite: \"text\",\n postgres: \"jsonb\",\n mysql: \"json\",\n mssql: \"varchar(8000)\",\n },\n } as const;\n\n if (fieldName === \"id\" || field.references?.field === \"id\") {\n if (fieldName === \"id\") return typeMap.id[provider];\n return typeMap.foreignKeyId[provider];\n }\n\n if (Array.isArray(type)) return \"text\";\n\n if (!(type in typeMap)) {\n throw new Error(\n `Unsupported field type '${String(type)}' for field '${fieldName}'. Allowed types are: string, number, boolean, date, string[], number[]. If you need to store structured data, store it as a JSON string (type: \"string\") or split it into primitive fields. See https://better-auth.com/docs/advanced/schema#additional-fields`,\n );\n }\n\n return typeMap[type][provider];\n }\n\n const getModelName = initGetModelName({\n schema: getPaymentTables(config),\n usePlural: false,\n });\n\n const getFieldName = initGetFieldName({\n schema: getPaymentTables(config),\n usePlural: false,\n });\n\n function getReferencePath(model: string, field: string): string {\n try {\n const modelName = getModelName(model);\n const fieldName = getFieldName({ model, field });\n return `${modelName}.${fieldName}`;\n } catch {\n return `${model}.${field}`;\n }\n }\n\n if (toBeAdded.length) {\n for (const table of toBeAdded) {\n for (const [fieldName, field] of Object.entries(table.fields)) {\n const type = getType(field, fieldName);\n\n if (field.index) {\n const index = db.schema\n .alterTable(table.table)\n .addIndex(`${table.table}_${fieldName}_idx`);\n migrations.push(index);\n }\n\n const built = db.schema\n .alterTable(table.table)\n .addColumn(fieldName, type, (col) => {\n col = field.required !== false ? col.notNull() : col;\n\n if (field.references) {\n col = col\n .references(\n getReferencePath(\n field.references.model,\n field.references.field,\n ),\n )\n .onDelete(field.references.onDelete || \"cascade\");\n }\n\n if (field.unique) col = col.unique();\n\n if (\n field.type === \"date\" &&\n typeof field.defaultValue === \"function\" &&\n (dbType === \"postgres\" ||\n dbType === \"mysql\" ||\n dbType === \"mssql\")\n ) {\n col =\n dbType === \"mysql\"\n ? col.defaultTo(sql`CURRENT_TIMESTAMP(3)`)\n : col.defaultTo(sql`CURRENT_TIMESTAMP`);\n }\n\n return col;\n });\n\n migrations.push(built);\n }\n }\n }\n\n const toBeIndexed: CreateIndexBuilder[] = [];\n\n if (toBeCreated.length) {\n for (const table of toBeCreated) {\n const idType = getType({ type: \"string\" }, \"id\");\n\n let dbT = db.schema\n .createTable(table.table)\n .addColumn(\"id\", idType, (col) => {\n // UUID IDs at DB level\n if (dbType === \"postgres\") {\n return col\n .primaryKey()\n .defaultTo(sql`pg_catalog.gen_random_uuid()`)\n .notNull();\n }\n // For non-postgres, don't assume a DB-level UUID generator exists.\n // UUIDs can still be generated in application code.\n return col.primaryKey().notNull();\n });\n\n for (const [fieldName, field] of Object.entries(table.fields)) {\n const type = getType(field, fieldName);\n\n dbT = dbT.addColumn(fieldName, type, (col) => {\n col = field.required !== false ? col.notNull() : col;\n\n if (field.references) {\n col = col\n .references(\n getReferencePath(\n field.references.model,\n field.references.field,\n ),\n )\n .onDelete(field.references.onDelete || \"cascade\");\n }\n\n if (field.unique) col = col.unique();\n\n if (\n field.type === \"date\" &&\n typeof field.defaultValue === \"function\" &&\n (dbType === \"postgres\" || dbType === \"mysql\" || dbType === \"mssql\")\n ) {\n col =\n dbType === \"mysql\"\n ? col.defaultTo(sql`CURRENT_TIMESTAMP(3)`)\n : col.defaultTo(sql`CURRENT_TIMESTAMP`);\n }\n\n return col;\n });\n\n if (field.index) {\n const idx = db.schema\n .createIndex(\n `${table.table}_${fieldName}_${field.unique ? \"uidx\" : \"idx\"}`,\n )\n .on(table.table)\n .columns([fieldName]);\n\n toBeIndexed.push(field.unique ? idx.unique() : idx);\n }\n }\n\n migrations.push(dbT);\n }\n }\n\n for (const index of toBeIndexed) {\n migrations.push(index);\n }\n\n async function runMigrations() {\n for (const migration of migrations) {\n await migration.execute();\n }\n }\n\n async function compileMigrations() {\n const compiled = migrations.map((m) => m.compile().sql);\n return compiled.join(\";\\n\\n\") + \";\";\n }\n\n return { toBeCreated, toBeAdded, runMigrations, compileMigrations };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/db/migrations/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type { DBFieldAttribute, DBFieldType } from \"pecunia-core\";\nimport { initGetFieldName, initGetModelName } from \"pecunia-core\";\nimport type {\n AlterTableBuilder,\n AlterTableColumnAlteringBuilder,\n ColumnDataType,\n CreateIndexBuilder,\n CreateTableBuilder,\n Kysely,\n RawBuilder,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport { createKyselyAdapter } from \"../../adapters/kysely-adapter/dialect\";\nimport type { KyselyDatabaseDialectType } from \"pecunia-core\";\nimport { getSchema } from \"../schema/get-schema\";\nimport { getPaymentTables } from \"pecunia-core\";\n\ntype DbTypeBuckets = Record<\n \"string\" | \"uuid\" | \"number\" | \"boolean\" | \"date\" | \"json\",\n string[]\n>;\n\nconst postgresMap = {\n string: [\"character varying\", \"varchar\", \"text\", \"uuid\"],\n number: [\n \"int4\",\n \"integer\",\n \"bigint\",\n \"smallint\",\n \"numeric\",\n \"real\",\n \"double precision\",\n ],\n boolean: [\"bool\", \"boolean\"],\n date: [\"timestamptz\", \"timestamp\", \"date\"],\n json: [\"json\", \"jsonb\"],\n};\n\nconst mysqlMap = {\n string: [\"varchar\", \"text\", \"uuid\"],\n number: [\n \"integer\",\n \"int\",\n \"bigint\",\n \"smallint\",\n \"decimal\",\n \"float\",\n \"double\",\n ],\n boolean: [\"boolean\", \"tinyint\"],\n date: [\"timestamp\", \"datetime\", \"date\"],\n json: [\"json\"],\n};\n\nconst sqliteMap = {\n string: [\"TEXT\"],\n number: [\"INTEGER\", \"REAL\"],\n boolean: [\"INTEGER\", \"BOOLEAN\"], // 0 or 1\n date: [\"DATE\", \"INTEGER\"],\n json: [\"TEXT\"],\n};\n\nconst mssqlMap = {\n string: [\"varchar\", \"nvarchar\", \"uniqueidentifier\"],\n number: [\"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\"],\n boolean: [\"bit\", \"smallint\"],\n date: [\"datetime2\", \"date\", \"datetime\"],\n json: [\"varchar\", \"nvarchar\"],\n};\n\nconst map = {\n postgres: postgresMap,\n mysql: mysqlMap,\n sqlite: sqliteMap,\n mssql: mssqlMap,\n};\n\nexport function matchType(\n columnDataType: string,\n fieldType: DBFieldType,\n dbType: KyselyDatabaseDialectType,\n) {\n function normalize(type: string) {\n return type.toLowerCase().split(\"(\")[0]!.trim();\n }\n\n if (fieldType === \"string[]\" || fieldType === \"number[]\") {\n return columnDataType.toLowerCase().includes(\"json\");\n }\n\n const types: Partial<DbTypeBuckets> = map[dbType]!;\n const expected = Array.isArray(fieldType)\n ? types.string?.map((t) => t.toLowerCase())\n : types[fieldType]!.map((t: string) => t.toLowerCase());\n\n return expected?.includes(normalize(columnDataType));\n}\n\n/**\n * Get the current PostgreSQL schema (search_path) for the database connection\n * Returns the first schema in the search_path, defaulting to 'public' if not found\n */\nasync function getPostgresSchema(db: Kysely<unknown>): Promise<string> {\n try {\n const result = await sql<{ search_path: string }>`SHOW search_path`.execute(\n db,\n );\n\n if (result.rows[0]?.search_path) {\n const schemas = result.rows[0].search_path\n .split(\",\")\n .map((s) => s.trim())\n .map((s) => s.replace(/^[\"']|[\"']$/g, \"\"))\n .filter((s) => !s.startsWith(\"$\"));\n\n return schemas[0] || \"public\";\n }\n } catch {\n // fall back to public schema\n }\n\n return \"public\";\n}\n\nexport async function getMigrations(config: PecuniaOptions) {\n const billingEngineSchema = getSchema(config);\n\n let { kysely: db, databaseType: dbType } = await createKyselyAdapter(config);\n\n if (!dbType) {\n console.warn(\n \"Could not determine database type, defaulting to sqlite. Please provide a type in the database options to avoid this.\",\n );\n dbType = \"sqlite\";\n }\n\n if (!db) {\n console.error(\n \"Only kysely adapter is supported for migrations. You can use `generate` command to generate the schema, if you're using a different adapter.\",\n );\n process.exit(1);\n }\n\n // For PostgreSQL, detect and log the current schema being used\n let currentSchema = \"public\";\n if (dbType === \"postgres\") {\n currentSchema = await getPostgresSchema(db);\n console.debug(\n `PostgreSQL migration: Using schema '${currentSchema}' (from search_path)`,\n );\n\n // Verify the schema exists\n try {\n const schemaCheck = await sql<{ schema_name: string }>`\n SELECT schema_name\n FROM information_schema.schemata\n WHERE schema_name = ${currentSchema}\n `.execute(db);\n\n if (!schemaCheck.rows[0]) {\n console.warn(\n `Schema '${currentSchema}' does not exist. Tables will be inspected from available schemas. Consider creating the schema first or checking your database configuration.`,\n );\n }\n } catch (error) {\n console.debug(\n `Could not verify schema existence: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n const allTableMetadata = await db.introspection.getTables();\n\n // For PostgreSQL, filter tables to only those in the target schema\n let tableMetadata = allTableMetadata;\n if (dbType === \"postgres\") {\n try {\n const tablesInSchema = await sql<{\n table_name: string;\n }>`\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = ${currentSchema}\n AND table_type = 'BASE TABLE'\n `.execute(db);\n\n const tableNamesInSchema = new Set(\n tablesInSchema.rows.map((row) => row.table_name),\n );\n\n tableMetadata = allTableMetadata.filter(\n (table) =>\n table.schema === currentSchema && tableNamesInSchema.has(table.name),\n );\n\n console.debug(\n `Found ${tableMetadata.length} table(s) in schema '${currentSchema}': ${\n tableMetadata.map((t) => t.name).join(\", \") || \"(none)\"\n }`,\n );\n } catch (error) {\n console.warn(\n `Could not filter tables by schema. Using all discovered tables. Error: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n const toBeCreated: {\n table: string;\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }[] = [];\n\n const toBeAdded: {\n table: string;\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }[] = [];\n\n for (const [key, value] of Object.entries(billingEngineSchema)) {\n const table = tableMetadata.find((t) => t.name === key);\n\n if (!table) {\n const tIndex = toBeCreated.findIndex((t) => t.table === key);\n const tableData = {\n table: key,\n fields: value.fields,\n order: value.order || Infinity,\n };\n\n const insertIndex = toBeCreated.findIndex(\n (t) => (t.order || Infinity) > tableData.order,\n );\n\n if (insertIndex === -1) {\n if (tIndex === -1) {\n toBeCreated.push(tableData);\n } else {\n toBeCreated[tIndex]!.fields = {\n ...toBeCreated[tIndex]!.fields,\n ...value.fields,\n };\n }\n } else {\n toBeCreated.splice(insertIndex, 0, tableData);\n }\n\n continue;\n }\n\n const toBeAddedFields: Record<string, DBFieldAttribute> = {};\n\n for (const [fieldName, field] of Object.entries(value.fields)) {\n const column = table.columns.find((c) => c.name === fieldName);\n\n if (!column) {\n toBeAddedFields[fieldName] = field;\n continue;\n }\n\n if (matchType(column.dataType, field.type, dbType)) {\n continue;\n }\n\n console.warn(\n `Field ${fieldName} in table ${key} has a different type in the database. Expected ${field.type} but got ${column.dataType}.`,\n );\n }\n\n if (Object.keys(toBeAddedFields).length > 0) {\n toBeAdded.push({\n table: key,\n fields: toBeAddedFields,\n order: value.order || Infinity,\n });\n }\n }\n\n const migrations: (\n | AlterTableColumnAlteringBuilder\n | ReturnType<AlterTableBuilder[\"addIndex\"]>\n | CreateTableBuilder<string, string>\n | CreateIndexBuilder\n )[] = [];\n\n // Adapter-enforced strategy: UUID ids at the DB level\n const useUUIDs = true;\n\n function getType(field: DBFieldAttribute, fieldName: string) {\n const type = field.type;\n const provider = dbType || \"sqlite\";\n\n type StringOnlyUnion<T> = T extends string ? T : never;\n\n const typeMap: Record<\n StringOnlyUnion<DBFieldType> | \"id\" | \"foreignKeyId\",\n Record<KyselyDatabaseDialectType, ColumnDataType | RawBuilder<unknown>>\n > = {\n uuid: {\n postgres: \"uuid\",\n mysql: \"varchar(36)\",\n mssql: \"varchar(36)\",\n sqlite: \"text\",\n },\n string: {\n sqlite: \"text\",\n postgres: \"text\",\n mysql: field.unique\n ? \"varchar(255)\"\n : field.references\n ? \"varchar(36)\"\n : field.sortable\n ? \"varchar(255)\"\n : field.index\n ? \"varchar(255)\"\n : \"text\",\n mssql:\n field.unique || field.sortable\n ? \"varchar(255)\"\n : field.references\n ? \"varchar(36)\"\n : \"varchar(8000)\",\n },\n boolean: {\n sqlite: \"integer\",\n postgres: \"boolean\",\n mysql: \"boolean\",\n mssql: \"smallint\",\n },\n number: {\n sqlite: field.bigint ? \"bigint\" : \"integer\",\n postgres: field.bigint ? \"bigint\" : \"integer\",\n mysql: field.bigint ? \"bigint\" : \"integer\",\n mssql: field.bigint ? \"bigint\" : \"integer\",\n },\n date: {\n sqlite: \"date\",\n postgres: \"timestamptz\",\n mysql: \"timestamp(3)\",\n mssql: sql`datetime2(3)`,\n },\n json: {\n sqlite: \"text\",\n postgres: \"jsonb\",\n mysql: \"json\",\n mssql: \"varchar(8000)\",\n },\n id: {\n postgres: useUUIDs ? \"uuid\" : \"text\",\n mysql: \"varchar(36)\",\n mssql: \"varchar(36)\", // ideally UNIQUEIDENTIFIER, but not in Kysely's type interface\n sqlite: \"text\",\n },\n foreignKeyId: {\n postgres: useUUIDs ? \"uuid\" : \"text\",\n mysql: \"varchar(36)\",\n mssql: \"varchar(36)\",\n sqlite: \"text\",\n },\n \"string[]\": {\n sqlite: \"text\",\n postgres: \"jsonb\",\n mysql: \"json\",\n mssql: \"varchar(8000)\",\n },\n \"number[]\": {\n sqlite: \"text\",\n postgres: \"jsonb\",\n mysql: \"json\",\n mssql: \"varchar(8000)\",\n },\n } as const;\n\n if (fieldName === \"id\" || field.references?.field === \"id\") {\n if (fieldName === \"id\") return typeMap.id[provider];\n return typeMap.foreignKeyId[provider];\n }\n\n if (Array.isArray(type)) return \"text\";\n\n if (!(type in typeMap)) {\n throw new Error(\n `Unsupported field type '${String(type)}' for field '${fieldName}'. Allowed types are: string, number, boolean, date, string[], number[]. If you need to store structured data, store it as a JSON string (type: \"string\") or split it into primitive fields. See https://better-auth.com/docs/advanced/schema#additional-fields`,\n );\n }\n\n return typeMap[type][provider];\n }\n\n const getModelName = initGetModelName({\n schema: getPaymentTables(config),\n usePlural: false,\n });\n\n const getFieldName = initGetFieldName({\n schema: getPaymentTables(config),\n usePlural: false,\n });\n\n function getReferencePath(model: string, field: string): string {\n try {\n const modelName = getModelName(model);\n const fieldName = getFieldName({ model, field });\n return `${modelName}.${fieldName}`;\n } catch {\n return `${model}.${field}`;\n }\n }\n\n if (toBeAdded.length) {\n for (const table of toBeAdded) {\n for (const [fieldName, field] of Object.entries(table.fields)) {\n const type = getType(field, fieldName);\n\n if (field.index) {\n const index = db.schema\n .alterTable(table.table)\n .addIndex(`${table.table}_${fieldName}_idx`);\n migrations.push(index);\n }\n\n const built = db.schema\n .alterTable(table.table)\n .addColumn(fieldName, type, (col) => {\n col = field.required !== false ? col.notNull() : col;\n\n if (field.references) {\n col = col\n .references(\n getReferencePath(\n field.references.model,\n field.references.field,\n ),\n )\n .onDelete(field.references.onDelete || \"cascade\");\n }\n\n if (field.unique) col = col.unique();\n\n if (\n field.type === \"date\" &&\n typeof field.defaultValue === \"function\" &&\n (dbType === \"postgres\" ||\n dbType === \"mysql\" ||\n dbType === \"mssql\")\n ) {\n col =\n dbType === \"mysql\"\n ? col.defaultTo(sql`CURRENT_TIMESTAMP(3)`)\n : col.defaultTo(sql`CURRENT_TIMESTAMP`);\n }\n\n return col;\n });\n\n migrations.push(built);\n }\n }\n }\n\n const toBeIndexed: CreateIndexBuilder[] = [];\n\n if (toBeCreated.length) {\n for (const table of toBeCreated) {\n const idType = getType({ type: \"string\" }, \"id\");\n\n let dbT = db.schema\n .createTable(table.table)\n .addColumn(\"id\", idType, (col) => {\n // UUID IDs at DB level\n if (dbType === \"postgres\") {\n return col\n .primaryKey()\n .defaultTo(sql`pg_catalog.gen_random_uuid()`)\n .notNull();\n }\n // For non-postgres, don't assume a DB-level UUID generator exists.\n // UUIDs can still be generated in application code.\n return col.primaryKey().notNull();\n });\n\n for (const [fieldName, field] of Object.entries(table.fields)) {\n const type = getType(field, fieldName);\n\n dbT = dbT.addColumn(fieldName, type, (col) => {\n col = field.required !== false ? col.notNull() : col;\n\n if (field.references) {\n col = col\n .references(\n getReferencePath(\n field.references.model,\n field.references.field,\n ),\n )\n .onDelete(field.references.onDelete || \"cascade\");\n }\n\n if (field.unique) col = col.unique();\n\n if (\n field.type === \"date\" &&\n typeof field.defaultValue === \"function\" &&\n (dbType === \"postgres\" || dbType === \"mysql\" || dbType === \"mssql\")\n ) {\n col =\n dbType === \"mysql\"\n ? col.defaultTo(sql`CURRENT_TIMESTAMP(3)`)\n : col.defaultTo(sql`CURRENT_TIMESTAMP`);\n }\n\n return col;\n });\n\n if (field.index) {\n const idx = db.schema\n .createIndex(\n `${table.table}_${fieldName}_${field.unique ? \"uidx\" : \"idx\"}`,\n )\n .on(table.table)\n .columns([fieldName]);\n\n toBeIndexed.push(field.unique ? idx.unique() : idx);\n }\n }\n\n migrations.push(dbT);\n }\n }\n\n for (const index of toBeIndexed) {\n migrations.push(index);\n }\n\n async function runMigrations() {\n for (const migration of migrations) {\n await migration.execute();\n }\n }\n\n async function compileMigrations() {\n const compiled = migrations.map((m) => m.compile().sql);\n return compiled.join(\";\\n\\n\") + \";\";\n }\n\n return { toBeCreated, toBeAdded, runMigrations, compileMigrations };\n}\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { drizzleAdapter } from "./adapters/drizzle/index.mjs";
2
- import { kyselyAdapter } from "./adapters/kysely/index.mjs";
3
- import { MongoDBAdapterConfig, mongodbAdapter } from "./adapters/mongodb/index.mjs";
1
+ import { drizzleAdapter } from "./adapters/drizzle-adapter/index.mjs";
2
+ import { kyselyAdapter } from "./adapters/kysely-adapter/index.mjs";
3
+ import { mongodbAdapter } from "./adapters/mongodb-adapter/index.mjs";
4
4
  import { getMigrations, matchType } from "./db/migrations/index.mjs";
5
5
  import { getSchema } from "./db/schema/get-schema.mjs";
6
6
  import "./db/index.mjs";
@@ -10,4 +10,4 @@ export * from "pecunia-core";
10
10
  export * from "zod";
11
11
  export * from "zod/v4";
12
12
  export * from "zod/v4/core";
13
- export { MongoDBAdapterConfig, drizzleAdapter, getAdapter, getMigrations, getSchema, kyselyAdapter, matchType, mongodbAdapter, pecunia };
13
+ export { drizzleAdapter, getAdapter, getMigrations, getSchema, kyselyAdapter, matchType, mongodbAdapter, pecunia };
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import { getSchema } from "./db/schema/get-schema.mjs";
2
2
  import { getMigrations, matchType } from "./db/migrations/index.mjs";
3
3
  import "./db/index.mjs";
4
- import { drizzleAdapter } from "./adapters/drizzle/index.mjs";
5
- import { kyselyAdapter } from "./adapters/kysely/index.mjs";
6
- import { mongodbAdapter } from "./adapters/mongodb/index.mjs";
4
+ import { drizzleAdapter } from "./adapters/drizzle-adapter/index.mjs";
5
+ import { mongodbAdapter } from "./adapters/mongodb-adapter/index.mjs";
6
+ import { kyselyAdapter } from "./adapters/kysely-adapter/index.mjs";
7
7
  import { getAdapter } from "./adapters/get-adapter.mjs";
8
8
  import { pecunia } from "./payment/index.mjs";
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pecunia-root",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["db","count"],"sources":["../../../src/adapters/drizzle/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\"\nimport type {\n\tAdapterFactoryCreator,\n\tAdapterFactoryOptions,\n\tDBAdapter,\n\tDBAdapterDebugLogOption,\n\tWhere,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\"\nimport { logger } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\nimport type { SQL } from \"drizzle-orm\";\nimport {\n\tand,\n\tasc,\n\tcount,\n\tdesc,\n\teq,\n\tgt,\n\tgte,\n\tinArray,\n\tlike,\n\tlt,\n\tlte,\n\tne,\n\tnotInArray,\n\tor,\n\tsql,\n} from \"drizzle-orm\";\n\nexport interface DB {\n\t[key: string]: any;\n}\n\nexport interface DrizzleAdapterConfig {\n\t/**\n\t * The schema object that defines the tables and fields\n\t */\n\tschema?: Record<string, any> | undefined;\n\t/**\n\t * The database provider\n\t */\n\tprovider: \"pg\" | \"mysql\" | \"sqlite\";\n\t/**\n\t * If the table names in the schema are plural\n\t * set this to true. For example, if the schema\n\t * has an object with a key \"users\" instead of \"user\"\n\t */\n\tusePlural?: boolean | undefined;\n\t/**\n\t * Enable debug logs for the adapter\n\t *\n\t * @default false\n\t */\n\tdebugLogs?: DBAdapterDebugLogOption | undefined;\n\t/**\n\t * By default snake case is used for table and field names\n\t * when the CLI is used to generate the schema. If you want\n\t * to use camel case, set this to true.\n\t * @default false\n\t */\n\tcamelCase?: boolean | undefined;\n\t/**\n\t * Whether to execute multiple operations in a transaction.\n\t *\n\t * If the database doesn't support transactions,\n\t * set this to `false` and operations will be executed sequentially.\n\t * @default false\n\t */\n\ttransaction?: boolean | undefined;\n}\n\nexport const drizzleAdapter = (db: DB, config: DrizzleAdapterConfig) => {\n\tlet lazyOptions: PecuniaOptions | null = null;\n\tconst createCustomAdapter =\n\t\t(db: DB): AdapterFactoryCreator =>\n\t\t({ getFieldName, options }) => {\n\t\t\tfunction getSchema(model: string) {\n\t\t\t\tconst schema = config.schema || db._.fullSchema;\n\t\t\t\tif (!schema) {\n\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\"Drizzle adapter failed to initialize. Schema not found. Please provide a schema object in the adapter options object.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst schemaModel = schema[model];\n\t\t\t\tif (!schemaModel) {\n\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t`[# Drizzle Adapter]: The model \"${model}\" was not found in the schema object. Please pass the schema directly to the adapter options.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn schemaModel;\n\t\t\t}\n\t\t\tconst withReturning = async (\n\t\t\t\tmodel: string,\n\t\t\t\tbuilder: any,\n\t\t\t\tdata: Record<string, any>,\n\t\t\t\twhere?: Where[] | undefined,\n\t\t\t) => {\n\t\t\t\tif (config.provider !== \"mysql\") {\n\t\t\t\t\tconst c = await builder.returning();\n\t\t\t\t\treturn c[0];\n\t\t\t\t}\n\t\t\t\tawait builder.execute();\n\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\tconst builderVal = builder.config?.values;\n\t\t\t\tif (where?.length) {\n\t\t\t\t\t// If we're updating a field that's in the where clause, use the new value\n\t\t\t\t\tconst updatedWhere = where.map((w) => {\n\t\t\t\t\t\t// If this field was updated, use the new value for lookup\n\t\t\t\t\t\tif (data[w.field] !== undefined) {\n\t\t\t\t\t\t\treturn { ...w, value: data[w.field] };\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn w;\n\t\t\t\t\t});\n\n\t\t\t\t\tconst clause = convertWhereClause(updatedWhere, model);\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn res[0];\n\t\t\t\t} else if (builderVal && builderVal[0]?.id?.value) {\n\t\t\t\t\tlet tId = builderVal[0]?.id?.value;\n\t\t\t\t\tif (!tId) {\n\t\t\t\t\t\t//get last inserted id\n\t\t\t\t\t\tconst lastInsertId = await db\n\t\t\t\t\t\t\t.select({ id: sql`LAST_INSERT_ID()` })\n\t\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t\t.orderBy(desc(schemaModel.id))\n\t\t\t\t\t\t\t.limit(1);\n\t\t\t\t\t\ttId = lastInsertId[0].id;\n\t\t\t\t\t}\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(eq(schemaModel.id, tId))\n\t\t\t\t\t\t.limit(1)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\treturn res[0];\n\t\t\t\t} else if (data.id) {\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(eq(schemaModel.id, data.id))\n\t\t\t\t\t\t.limit(1)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\treturn res[0];\n\t\t\t\t} else {\n\t\t\t\t\t// If the user doesn't have `id` as a field, then this will fail.\n\t\t\t\t\t// We expect that they defined `id` in all of their models.\n\t\t\t\t\tif (!(\"id\" in schemaModel)) {\n\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t`The model \"${model}\" does not have an \"id\" field. Please use the \"id\" field as your primary key.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.orderBy(desc(schemaModel.id))\n\t\t\t\t\t\t.limit(1)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\treturn res[0];\n\t\t\t\t}\n\t\t\t};\n\t\t\tfunction convertWhereClause(where: Where[], model: string) {\n\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\tif (!where) return [];\n\t\t\t\tif (where.length === 1) {\n\t\t\t\t\tconst w = where[0];\n\t\t\t\t\tif (!w) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\t\t\t\t\tconst field = getFieldName({ model, field: w.field });\n\t\t\t\t\tif (!schemaModel[field]) {\n\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t`The field \"${w.field}\" does not exist in the schema for the model \"${model}\". Please update your schema.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"in\" operator.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [inArray(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"not_in\") {\n\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"not_in\" operator.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [notInArray(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"contains\") {\n\t\t\t\t\t\treturn [like(schemaModel[field], `%${w.value}%`)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"starts_with\") {\n\t\t\t\t\t\treturn [like(schemaModel[field], `${w.value}%`)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"ends_with\") {\n\t\t\t\t\t\treturn [like(schemaModel[field], `%${w.value}`)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"lt\") {\n\t\t\t\t\t\treturn [lt(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"lte\") {\n\t\t\t\t\t\treturn [lte(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"ne\") {\n\t\t\t\t\t\treturn [ne(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"gt\") {\n\t\t\t\t\t\treturn [gt(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (w.operator === \"gte\") {\n\t\t\t\t\t\treturn [gte(schemaModel[field], w.value)];\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [eq(schemaModel[field], w.value)];\n\t\t\t\t}\n\t\t\t\tconst andGroup = where.filter(\n\t\t\t\t\t(w) => w.connector === \"AND\" || !w.connector,\n\t\t\t\t);\n\t\t\t\tconst orGroup = where.filter((w) => w.connector === \"OR\");\n\n\t\t\t\tconst andClause = and(\n\t\t\t\t\t...andGroup.map((w) => {\n\t\t\t\t\t\tconst field = getFieldName({ model, field: w.field });\n\t\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn inArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"not_in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"not_in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn notInArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"contains\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"starts_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ends_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lt\") {\n\t\t\t\t\t\t\treturn lt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lte\") {\n\t\t\t\t\t\t\treturn lte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gt\") {\n\t\t\t\t\t\t\treturn gt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gte\") {\n\t\t\t\t\t\t\treturn gte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ne\") {\n\t\t\t\t\t\t\treturn ne(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn eq(schemaModel[field], w.value);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst orClause = or(\n\t\t\t\t\t...orGroup.map((w) => {\n\t\t\t\t\t\tconst field = getFieldName({ model, field: w.field });\n\t\t\t\t\t\tif (w.operator === \"in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn inArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"not_in\") {\n\t\t\t\t\t\t\tif (!Array.isArray(w.value)) {\n\t\t\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t\t\t`The value for the field \"${w.field}\" must be an array when using the \"not_in\" operator.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn notInArray(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"contains\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"starts_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `${w.value}%`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ends_with\") {\n\t\t\t\t\t\t\treturn like(schemaModel[field], `%${w.value}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lt\") {\n\t\t\t\t\t\t\treturn lt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"lte\") {\n\t\t\t\t\t\t\treturn lte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gt\") {\n\t\t\t\t\t\t\treturn gt(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"gte\") {\n\t\t\t\t\t\t\treturn gte(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (w.operator === \"ne\") {\n\t\t\t\t\t\t\treturn ne(schemaModel[field], w.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn eq(schemaModel[field], w.value);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst clause: SQL<unknown>[] = [];\n\n\t\t\t\tif (andGroup.length) clause.push(andClause!);\n\t\t\t\tif (orGroup.length) clause.push(orClause!);\n\t\t\t\treturn clause;\n\t\t\t}\n\t\t\tfunction checkMissingFields(\n\t\t\t\tschema: Record<string, any>,\n\t\t\t\tmodel: string,\n\t\t\t\tvalues: Record<string, any>,\n\t\t\t) {\n\t\t\t\tif (!schema) {\n\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\"Drizzle adapter failed to initialize. Drizzle Schema not found. Please provide a schema object in the adapter options object.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tfor (const key in values) {\n\t\t\t\t\tif (!schema[key]) {\n\t\t\t\t\t\tthrow new PecuniaError(\n\t\t\t\t\t\t\t`The field \"${key}\" does not exist in the \"${model}\" Drizzle schema. Please update your drizzle schema or re-generate using \"npx @pecunia/cli@latest generate\".`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tasync create({ model, data: values }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tcheckMissingFields(schemaModel, model, values);\n\t\t\t\t\tconst builder = db.insert(schemaModel).values(values);\n\t\t\t\t\tconst returned = await withReturning(model, builder, values);\n\t\t\t\t\treturn returned;\n\t\t\t\t},\n\t\t\t\tasync findOne({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\n\t\t\t\t\tlet query = db\n\t\t\t\t\t\t.select()\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(...clause);\n\n\t\t\t\t\tconst res = await query;\n\n\t\t\t\t\tif (!res.length) return null;\n\t\t\t\t\treturn res[0];\n\t\t\t\t},\n\t\t\t\tasync findMany({ model, where, sortBy, limit, offset }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = where ? convertWhereClause(where, model) : [];\n\t\t\t\t\tconst sortFn = sortBy?.direction === \"desc\" ? desc : asc;\n\n\t\t\t\t\tlet builder = db.select().from(schemaModel);\n\n\t\t\t\t\tconst effectiveLimit = limit;\n\t\t\t\t\tconst effectiveOffset = offset;\n\n\t\t\t\t\tif (typeof effectiveLimit !== \"undefined\") {\n\t\t\t\t\t\tbuilder = builder.limit(effectiveLimit);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (typeof effectiveOffset !== \"undefined\") {\n\t\t\t\t\t\tbuilder = builder.offset(effectiveOffset);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (sortBy?.field) {\n\t\t\t\t\t\tbuilder = builder.orderBy(\n\t\t\t\t\t\t\tsortFn(\n\t\t\t\t\t\t\t\tschemaModel[getFieldName({ model, field: sortBy?.field })],\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst res = await builder.where(...clause);\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t\tasync count({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = where ? convertWhereClause(where, model) : [];\n\t\t\t\t\tconst res = await db\n\t\t\t\t\t\t.select({ count: count() })\n\t\t\t\t\t\t.from(schemaModel)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn res[0].count;\n\t\t\t\t},\n\t\t\t\tasync update({ model, where, update: values }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db\n\t\t\t\t\t\t.update(schemaModel)\n\t\t\t\t\t\t.set(values)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn await withReturning(model, builder, values as any, where);\n\t\t\t\t},\n\t\t\t\tasync updateMany({ model, where, update: values }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db\n\t\t\t\t\t\t.update(schemaModel)\n\t\t\t\t\t\t.set(values)\n\t\t\t\t\t\t.where(...clause);\n\t\t\t\t\treturn await builder;\n\t\t\t\t},\n\t\t\t\tasync delete({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db.delete(schemaModel).where(...clause);\n\t\t\t\t\treturn await builder;\n\t\t\t\t},\n\t\t\t\tasync deleteMany({ model, where }) {\n\t\t\t\t\tconst schemaModel = getSchema(model);\n\t\t\t\t\tconst clause = convertWhereClause(where, model);\n\t\t\t\t\tconst builder = db.delete(schemaModel).where(...clause);\n\t\t\t\t\tconst res = await builder;\n\t\t\t\t\tlet count = 0;\n\t\t\t\t\tif (res && \"rowCount\" in res) count = res.rowCount;\n\t\t\t\t\telse if (Array.isArray(res)) count = res.length;\n\t\t\t\t\telse if (\n\t\t\t\t\t\tres &&\n\t\t\t\t\t\t(\"affectedRows\" in res || \"rowsAffected\" in res || \"changes\" in res)\n\t\t\t\t\t)\n\t\t\t\t\t\tcount = res.affectedRows ?? res.rowsAffected ?? res.changes;\n\t\t\t\t\tif (typeof count !== \"number\") {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\"[Drizzle Adapter] The result of the deleteMany operation is not a number. This is likely a bug in the adapter.\",\n\t\t\t\t\t\t\t{ res, model, where },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn count;\n\t\t\t\t},\n\t\t\t\toptions: config,\n\t\t\t};\n\t\t};\n\tlet adapterOptions: AdapterFactoryOptions | null = null;\n\tadapterOptions = {\n\t\tconfig: {\n\t\t\tadapterId: \"drizzle\",\n\t\t\tadapterName: \"Drizzle Adapter\",\n\t\t\tusePlural: config.usePlural ?? false,\n\t\t\tsupportsUUIDs: config.provider === \"pg\" ? true : false,\n\t\t\tsupportsJSON:\n\t\t\t\tconfig.provider === \"pg\" // even though mysql also supports it, mysql requires to pass stringified json anyway.\n\t\t\t\t\t? true\n\t\t\t\t\t: false,\n\t\t\tsupportsArrays: config.provider === \"pg\" ? true : false,\n\t\t\ttransaction:\n\t\t\t\t(config.transaction ?? false)\n\t\t\t\t\t? (cb) =>\n\t\t\t\t\t\t\tdb.transaction((tx: DB) => {\n\t\t\t\t\t\t\t\tconst adapter = createAdapterFactory({\n\t\t\t\t\t\t\t\t\tconfig: adapterOptions!.config,\n\t\t\t\t\t\t\t\t\tadapter: createCustomAdapter(tx),\n\t\t\t\t\t\t\t\t})(lazyOptions!);\n\t\t\t\t\t\t\t\treturn cb(adapter);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t: false,\n\t\t},\n\t\tadapter: createCustomAdapter(db),\n\t};\n\tconst adapter = createAdapterFactory(adapterOptions);\n\treturn (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n\t\tlazyOptions = options;\n\t\treturn adapter(options);\n\t};\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bun-sqlite-dialect.mjs","names":["#config","#connectionMutex","#db","#connection","sql","#promise","#resolve","#getTableMetadata"],"sources":["../../../src/adapters/kysely/bun-sqlite-dialect.ts"],"sourcesContent":["/**\n * @see {@link https://github.com/dylanblokhuis/kysely-bun-sqlite} - Fork of the original kysely-bun-sqlite package by @dylanblokhuis\n */\n\nimport type { Database } from \"bun:sqlite\";\nimport type {\n DatabaseConnection,\n DatabaseIntrospector,\n DatabaseMetadata,\n DatabaseMetadataOptions,\n Dialect,\n DialectAdapter,\n DialectAdapterBase,\n Driver,\n Kysely,\n QueryCompiler,\n QueryResult,\n SchemaMetadata,\n TableMetadata,\n} from \"kysely\";\nimport {\n CompiledQuery,\n DEFAULT_MIGRATION_LOCK_TABLE,\n DEFAULT_MIGRATION_TABLE,\n DefaultQueryCompiler,\n sql,\n} from \"kysely\";\n\nclass BunSqliteAdapter implements DialectAdapterBase {\n get supportsCreateIfNotExists(): boolean {\n return true;\n }\n\n get supportsTransactionalDdl(): boolean {\n return false;\n }\n\n get supportsReturning(): boolean {\n return true;\n }\n\n async acquireMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n\n async releaseMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n get supportsOutput(): boolean {\n return true;\n }\n}\n\n/**\n * Config for the SQLite dialect.\n */\nexport interface BunSqliteDialectConfig {\n /**\n * An sqlite Database instance or a function that returns one.\n */\n database: Database;\n\n /**\n * Called once when the first query is executed.\n */\n onCreateConnection?:\n | ((connection: DatabaseConnection) => Promise<void>)\n | undefined;\n}\n\nclass BunSqliteDriver implements Driver {\n readonly #config: BunSqliteDialectConfig;\n readonly #connectionMutex = new ConnectionMutex();\n\n #db?: Database;\n #connection?: DatabaseConnection;\n\n constructor(config: BunSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n async init(): Promise<void> {\n this.#db = this.#config.database;\n\n this.#connection = new BunSqliteConnection(this.#db);\n\n if (this.#config.onCreateConnection) {\n await this.#config.onCreateConnection(this.#connection);\n }\n }\n\n async acquireConnection(): Promise<DatabaseConnection> {\n // SQLite only has one single connection. We use a mutex here to wait\n // until the single connection has been released.\n await this.#connectionMutex.lock();\n return this.#connection!;\n }\n\n async beginTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"begin\"));\n }\n\n async commitTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"commit\"));\n }\n\n async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"rollback\"));\n }\n\n async releaseConnection(): Promise<void> {\n this.#connectionMutex.unlock();\n }\n\n async destroy(): Promise<void> {\n this.#db?.close();\n }\n}\n\nclass BunSqliteConnection implements DatabaseConnection {\n readonly #db: Database;\n\n constructor(db: Database) {\n this.#db = db;\n }\n\n executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n const { sql, parameters } = compiledQuery;\n const stmt = this.#db.prepare(sql);\n\n return Promise.resolve({\n rows: stmt.all(parameters as any) as O[],\n });\n }\n\n async *streamQuery() {\n throw new Error(\"Streaming query is not supported by SQLite driver.\");\n }\n}\n\nclass ConnectionMutex {\n #promise?: Promise<void>;\n #resolve?: () => void;\n\n async lock(): Promise<void> {\n while (this.#promise) {\n await this.#promise;\n }\n\n this.#promise = new Promise((resolve) => {\n this.#resolve = resolve;\n });\n }\n\n unlock(): void {\n const resolve = this.#resolve;\n\n this.#promise = undefined;\n this.#resolve = undefined;\n\n resolve?.();\n }\n}\n\nclass BunSqliteIntrospector implements DatabaseIntrospector {\n readonly #db: Kysely<unknown>;\n\n constructor(db: Kysely<unknown>) {\n this.#db = db;\n }\n\n async getSchemas(): Promise<SchemaMetadata[]> {\n // Sqlite doesn't support schemas.\n return [];\n }\n\n async getTables(\n options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n ): Promise<TableMetadata[]> {\n let query = this.#db\n // @ts-expect-error\n .selectFrom(\"sqlite_schema\")\n // @ts-expect-error\n .where(\"type\", \"=\", \"table\")\n // @ts-expect-error\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select(\"name\")\n .$castTo<{ name: string }>();\n\n if (!options.withInternalKyselyTables) {\n query = query\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_TABLE)\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_LOCK_TABLE);\n }\n\n const tables = await query.execute();\n return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));\n }\n\n async getMetadata(\n options?: DatabaseMetadataOptions | undefined,\n ): Promise<DatabaseMetadata> {\n return {\n tables: await this.getTables(options),\n };\n }\n\n async #getTableMetadata(table: string): Promise<TableMetadata> {\n const db = this.#db;\n\n // Get the SQL that was used to create the table.\n const createSql = await db\n // @ts-expect-error\n .selectFrom(\"sqlite_master\")\n // @ts-expect-error\n .where(\"name\", \"=\", table)\n .select(\"sql\")\n .$castTo<{ sql: string | undefined }>()\n .execute();\n\n // Try to find the name of the column that has `autoincrement` 🤦\n const autoIncrementCol = createSql[0]?.sql\n ?.split(/[\\(\\),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = await db\n .selectFrom(\n sql<{\n name: string;\n type: string;\n notnull: 0 | 1;\n dflt_value: any;\n }>`pragma_table_info(${table})`.as(\"table_info\"),\n )\n .select([\"name\", \"type\", \"notnull\", \"dflt_value\"])\n .execute();\n\n return {\n name: table,\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n })),\n isView: true,\n };\n }\n}\n\nclass BunSqliteQueryCompiler extends DefaultQueryCompiler {\n protected override getCurrentParameterPlaceholder() {\n return \"?\";\n }\n\n protected override getLeftIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getRightIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getAutoIncrement() {\n return \"autoincrement\";\n }\n}\n\nexport class BunSqliteDialect implements Dialect {\n readonly #config: BunSqliteDialectConfig;\n\n constructor(config: BunSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n createDriver(): Driver {\n return new BunSqliteDriver(this.#config);\n }\n\n createQueryCompiler(): QueryCompiler {\n return new BunSqliteQueryCompiler();\n }\n\n createAdapter(): DialectAdapter {\n return new BunSqliteAdapter();\n }\n\n createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n return new BunSqliteIntrospector(db);\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dialect.mjs","names":[],"sources":["../../../src/adapters/kysely/dialect.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type { Dialect, SqliteDatabase } from \"kysely\";\nimport {\n Kysely,\n MssqlDialect,\n MysqlDialect,\n PostgresDialect,\n SqliteDialect,\n} from \"kysely\";\nimport type { Database as BunSqliteDatabase } from \"bun:sqlite\";\nimport type { KyselyDatabaseDialectType } from \"pecunia-core\";\nfunction isSqliteDatabase(x: unknown): x is SqliteDatabase {\n return typeof x === \"object\" && x !== null && \"prepare\" in x;\n}\n\nfunction isSqliteDatabaseFactory(\n x: unknown,\n): x is () => Promise<SqliteDatabase> {\n return typeof x === \"function\";\n}\n\nfunction isBunSqliteDatabase(x: unknown): x is BunSqliteDatabase {\n return typeof x === \"object\" && x !== null && \"fileControl\" in x;\n}\n\nexport function getKyselyDatabaseType(\n db: PecuniaOptions[\"database\"],\n): KyselyDatabaseDialectType | null {\n if (!db) {\n return null;\n }\n if (\"dialect\" in db) {\n return getKyselyDatabaseType(db.dialect as Dialect);\n }\n if (\"createDriver\" in db) {\n if (db instanceof SqliteDialect) {\n return \"sqlite\";\n }\n if (db instanceof MysqlDialect) {\n return \"mysql\";\n }\n if (db instanceof PostgresDialect) {\n return \"postgres\";\n }\n if (db instanceof MssqlDialect) {\n return \"mssql\";\n }\n }\n if (\"aggregate\" in db) {\n return \"sqlite\";\n }\n\n if (\"getConnection\" in db) {\n return \"mysql\";\n }\n if (\"connect\" in db) {\n return \"postgres\";\n }\n if (\"fileControl\" in db) {\n return \"sqlite\";\n }\n if (\"open\" in db && \"close\" in db && \"prepare\" in db) {\n return \"sqlite\";\n }\n return null;\n}\n\nexport const createKyselyAdapter = async (config: PecuniaOptions) => {\n const db = config.database;\n\n if (!db) {\n return {\n kysely: null,\n databaseType: null,\n transaction: undefined,\n };\n }\n\n if (\"db\" in db) {\n return {\n kysely: db.db,\n databaseType: db.type,\n transaction: db.transaction,\n };\n }\n\n if (\"dialect\" in db) {\n return {\n kysely: new Kysely<any>({ dialect: db.dialect }),\n databaseType: db.type,\n transaction: db.transaction,\n };\n }\n\n let dialect: Dialect | undefined = undefined;\n\n const databaseType = getKyselyDatabaseType(db);\n\n if (\"createDriver\" in db) {\n dialect = db;\n }\n\n if (\"aggregate\" in db) {\n if (isSqliteDatabase(db) || isSqliteDatabaseFactory(db)) {\n dialect = new SqliteDialect({ database: db });\n } else {\n throw new Error(\n \"db matched 'aggregate' check, but is not a Kysely SqliteDatabase\",\n );\n }\n }\n\n if (\"getConnection\" in db) {\n // @ts-expect-error - mysql2/promise\n dialect = new MysqlDialect(db);\n }\n\n if (\"connect\" in db) {\n dialect = new PostgresDialect({\n pool: db,\n });\n }\n\n if (isBunSqliteDatabase(db)) {\n const { BunSqliteDialect } = await import(\"./bun-sqlite-dialect\");\n dialect = new BunSqliteDialect({\n database: db,\n });\n }\n\n if (\"createSession\" in db && typeof window === \"undefined\") {\n let DatabaseSync: typeof import(\"node:sqlite\").DatabaseSync | undefined =\n undefined;\n try {\n let nodeSqlite: string = \"node:sqlite\";\n // Ignore both Vite and Webpack for dynamic import as they both try to pre-bundle 'node:sqlite' which might fail\n // It's okay because we are in a try-catch block\n ({ DatabaseSync } = await import(\n /* @vite-ignore */\n /* webpackIgnore: true */\n nodeSqlite\n ));\n } catch (error: unknown) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code !== \"ERR_UNKNOWN_BUILTIN_MODULE\"\n ) {\n throw error;\n }\n }\n if (DatabaseSync && db instanceof DatabaseSync) {\n const { NodeSqliteDialect } = await import(\"./node-sqlite-dialect\");\n dialect = new NodeSqliteDialect({\n database: db,\n });\n }\n }\n\n return {\n kysely: dialect ? new Kysely<any>({ dialect }) : null,\n databaseType,\n transaction: undefined,\n };\n};\n"],"mappings":";;;AAWA,SAAS,iBAAiB,GAAiC;AACzD,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,aAAa;;AAG7D,SAAS,wBACP,GACoC;AACpC,QAAO,OAAO,MAAM;;AAGtB,SAAS,oBAAoB,GAAoC;AAC/D,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,iBAAiB;;AAGjE,SAAgB,sBACd,IACkC;AAClC,KAAI,CAAC,GACH,QAAO;AAET,KAAI,aAAa,GACf,QAAO,sBAAsB,GAAG,QAAmB;AAErD,KAAI,kBAAkB,IAAI;AACxB,MAAI,cAAc,cAChB,QAAO;AAET,MAAI,cAAc,aAChB,QAAO;AAET,MAAI,cAAc,gBAChB,QAAO;AAET,MAAI,cAAc,aAChB,QAAO;;AAGX,KAAI,eAAe,GACjB,QAAO;AAGT,KAAI,mBAAmB,GACrB,QAAO;AAET,KAAI,aAAa,GACf,QAAO;AAET,KAAI,iBAAiB,GACnB,QAAO;AAET,KAAI,UAAU,MAAM,WAAW,MAAM,aAAa,GAChD,QAAO;AAET,QAAO;;AAGT,MAAa,sBAAsB,OAAO,WAA2B;CACnE,MAAM,KAAK,OAAO;AAElB,KAAI,CAAC,GACH,QAAO;EACL,QAAQ;EACR,cAAc;EACd,aAAa;EACd;AAGH,KAAI,QAAQ,GACV,QAAO;EACL,QAAQ,GAAG;EACX,cAAc,GAAG;EACjB,aAAa,GAAG;EACjB;AAGH,KAAI,aAAa,GACf,QAAO;EACL,QAAQ,IAAI,OAAY,EAAE,SAAS,GAAG,SAAS,CAAC;EAChD,cAAc,GAAG;EACjB,aAAa,GAAG;EACjB;CAGH,IAAI,UAA+B;CAEnC,MAAM,eAAe,sBAAsB,GAAG;AAE9C,KAAI,kBAAkB,GACpB,WAAU;AAGZ,KAAI,eAAe,GACjB,KAAI,iBAAiB,GAAG,IAAI,wBAAwB,GAAG,CACrD,WAAU,IAAI,cAAc,EAAE,UAAU,IAAI,CAAC;KAE7C,OAAM,IAAI,MACR,mEACD;AAIL,KAAI,mBAAmB,GAErB,WAAU,IAAI,aAAa,GAAG;AAGhC,KAAI,aAAa,GACf,WAAU,IAAI,gBAAgB,EAC5B,MAAM,IACP,CAAC;AAGJ,KAAI,oBAAoB,GAAG,EAAE;EAC3B,MAAM,EAAE,qBAAqB,MAAM,OAAO;AAC1C,YAAU,IAAI,iBAAiB,EAC7B,UAAU,IACX,CAAC;;AAGJ,KAAI,mBAAmB,MAAM,OAAO,WAAW,aAAa;EAC1D,IAAI,eACF;AACF,MAAI;GACF,IAAI,aAAqB;AAGzB,IAAC,CAAE,gBAAiB,MAAM;;;IAGxB;;WAEK,OAAgB;AACvB,OACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,MAAM,SAAS,6BAEf,OAAM;;AAGV,MAAI,gBAAgB,cAAc,cAAc;GAC9C,MAAM,EAAE,sBAAsB,MAAM,OAAO;AAC3C,aAAU,IAAI,kBAAkB,EAC9B,UAAU,IACX,CAAC;;;AAIN,QAAO;EACL,QAAQ,UAAU,IAAI,OAAY,EAAE,SAAS,CAAC,GAAG;EACjD;EACA,aAAa;EACd"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["db"],"sources":["../../../src/adapters/kysely/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type {\n AdapterFactoryCreator,\n AdapterFactoryOptions,\n DBAdapter,\n DBAdapterDebugLogOption,\n Where,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\";\nimport type { InsertQueryBuilder, Kysely, UpdateQueryBuilder } from \"kysely\";\n\ninterface KyselyAdapterConfig {\n /**\n * Database type.\n */\n type?: KyselyDatabaseDialectType | undefined;\n /**\n * Enable debug logs for the adapter\n *\n * @default false\n */\n debugLogs?: DBAdapterDebugLogOption | undefined;\n /**\n * Use plural for table names.\n *\n * @default false\n */\n usePlural?: boolean | undefined;\n /**\n * Whether to execute multiple operations in a transaction.\n *\n * If the database doesn't support transactions,\n * set this to `false` and operations will be executed sequentially.\n * @default false\n */\n transaction?: boolean | undefined;\n}\n\nimport type { KyselyDatabaseDialectType } from \"pecunia-core\";\n\nexport const kyselyAdapter = (\n db: Kysely<any>,\n config?: KyselyAdapterConfig | undefined,\n) => {\n let lazyOptions: PecuniaOptions | null = null;\n\n const createCustomAdapter = (db: Kysely<any>): AdapterFactoryCreator => {\n return ({\n getFieldName,\n getDefaultFieldName,\n getDefaultModelName,\n schema,\n }) => {\n const withReturning = async (\n values: Record<string, any>,\n builder:\n | InsertQueryBuilder<any, any, any>\n | UpdateQueryBuilder<any, string, string, any>,\n model: string,\n where: Where[],\n ) => {\n let res: any;\n\n if (config?.type === \"mysql\") {\n // Kysely doesn't support returning() in MySQL.\n await builder.execute();\n\n const field = values.id\n ? \"id\"\n : where.length > 0 && where[0]?.field\n ? where[0].field\n : \"id\";\n\n if (!values.id && where.length === 0) {\n res = await db\n .selectFrom(model)\n .selectAll()\n .orderBy(getFieldName({ model, field }), \"desc\")\n .limit(1)\n .executeTakeFirst();\n return res;\n }\n\n const value = values[field] || where[0]?.value;\n\n res = await db\n .selectFrom(model)\n .selectAll()\n .orderBy(getFieldName({ model, field }), \"desc\")\n .where(getFieldName({ model, field }), \"=\", value)\n .limit(1)\n .executeTakeFirst();\n\n return res;\n }\n\n if (config?.type === \"mssql\") {\n res = await builder.outputAll(\"inserted\").executeTakeFirst();\n return res;\n }\n\n res = await builder.returningAll().executeTakeFirst();\n return res;\n };\n\n function convertWhereClause(model: string, w?: Where[] | undefined) {\n if (!w) {\n return {\n and: null,\n or: null,\n };\n }\n\n const conditions = {\n and: [] as any[],\n or: [] as any[],\n };\n\n w.forEach((condition) => {\n let {\n field: _field,\n value: _value,\n operator = \"=\",\n connector = \"AND\",\n } = condition;\n\n const value: any = _value;\n\n const field: string | any = getFieldName({\n model,\n field: _field,\n });\n\n const expr = (eb: any) => {\n const f = `${model}.${field}`;\n\n if (operator.toLowerCase() === \"in\") {\n return eb(f, \"in\", Array.isArray(value) ? value : [value]);\n }\n\n if (operator.toLowerCase() === \"not_in\") {\n return eb(f, \"not in\", Array.isArray(value) ? value : [value]);\n }\n\n if (operator === \"contains\") {\n return eb(f, \"like\", `%${value}%`);\n }\n\n if (operator === \"starts_with\") {\n return eb(f, \"like\", `${value}%`);\n }\n\n if (operator === \"ends_with\") {\n return eb(f, \"like\", `%${value}`);\n }\n\n if (operator === \"eq\") {\n return eb(f, \"=\", value);\n }\n\n if (operator === \"ne\") {\n return eb(f, \"<>\", value);\n }\n\n if (operator === \"gt\") {\n return eb(f, \">\", value);\n }\n\n if (operator === \"gte\") {\n return eb(f, \">=\", value);\n }\n\n if (operator === \"lt\") {\n return eb(f, \"<\", value);\n }\n\n if (operator === \"lte\") {\n return eb(f, \"<=\", value);\n }\n\n return eb(f, operator, value);\n };\n\n if (connector === \"OR\") {\n conditions.or.push(expr);\n } else {\n conditions.and.push(expr);\n }\n });\n\n return {\n and: conditions.and.length ? conditions.and : null,\n or: conditions.or.length ? conditions.or : null,\n };\n }\n\n return {\n async create({ data, model }) {\n const builder = db.insertInto(model).values(data);\n const returned = await withReturning(data, builder, model, []);\n return returned;\n },\n\n async findOne({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query: any = db.selectFrom(model).selectAll();\n\n if (and) {\n query = query.where((eb: any) =>\n eb.and(and.map((expr: any) => expr(eb))),\n );\n }\n\n if (or) {\n query = query.where((eb: any) =>\n eb.or(or.map((expr: any) => expr(eb))),\n );\n }\n\n const row = await query.executeTakeFirst();\n return row ?? null;\n },\n\n async findMany({ model, where, limit, offset, sortBy }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query: any = db.selectFrom(model).selectAll();\n\n if (config?.type === \"mssql\") {\n if (offset !== undefined) {\n if (!sortBy) {\n query = query.orderBy(getFieldName({ model, field: \"id\" }));\n }\n query = query.offset(offset).fetch(limit || 100);\n } else if (limit !== undefined) {\n query = query.top(limit);\n }\n } else {\n if (limit !== undefined) {\n query = query.limit(limit);\n }\n if (offset !== undefined) {\n query = query.offset(offset);\n }\n }\n\n if (sortBy?.field) {\n query = query.orderBy(\n `${getFieldName({ model, field: sortBy.field })}`,\n sortBy.direction,\n );\n }\n\n if (and) {\n query = query.where((eb: any) =>\n eb.and(and.map((expr: any) => expr(eb))),\n );\n }\n\n if (or) {\n query = query.where((eb: any) =>\n eb.or(or.map((expr: any) => expr(eb))),\n );\n }\n\n const res = await query.execute();\n return res ?? [];\n },\n\n async update({ model, where, update: values }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.updateTable(model).set(values as any);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n return await withReturning(values as any, query, model, where);\n },\n\n async updateMany({ model, where, update: values }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.updateTable(model).set(values as any);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n const res = (await query.executeTakeFirst()).numUpdatedRows;\n\n return res > Number.MAX_SAFE_INTEGER\n ? Number.MAX_SAFE_INTEGER\n : Number(res);\n },\n\n async count({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db\n .selectFrom(model)\n .select(db.fn.count(\"id\").as(\"count\"));\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n const res = await query.execute();\n\n if (typeof res[0]!.count === \"number\") return res[0]!.count;\n if (typeof res[0]!.count === \"bigint\") return Number(res[0]!.count);\n\n return parseInt(res[0]!.count);\n },\n\n async delete({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.deleteFrom(model);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n await query.execute();\n },\n\n async deleteMany({ model, where }) {\n const { and, or } = convertWhereClause(model, where);\n\n let query = db.deleteFrom(model);\n\n if (and) {\n query = query.where((eb) => eb.and(and.map((expr) => expr(eb))));\n }\n\n if (or) {\n query = query.where((eb) => eb.or(or.map((expr) => expr(eb))));\n }\n\n const res = (await query.executeTakeFirst()).numDeletedRows;\n\n return res > Number.MAX_SAFE_INTEGER\n ? Number.MAX_SAFE_INTEGER\n : Number(res);\n },\n\n options: config,\n };\n };\n };\n\n let adapterOptions: AdapterFactoryOptions | null = null;\n\n adapterOptions = {\n config: {\n adapterId: \"kysely\",\n adapterName: \"Kysely Adapter\",\n usePlural: config?.usePlural,\n supportsBooleans:\n config?.type === \"sqlite\" ||\n config?.type === \"mssql\" ||\n config?.type === \"mysql\" ||\n !config?.type\n ? false\n : true,\n supportsDates:\n config?.type === \"sqlite\" || config?.type === \"mssql\" || !config?.type\n ? false\n : true,\n supportsJSON: config?.type === \"postgres\" ? true : false,\n supportsArrays: false,\n supportsUUIDs: config?.type === \"postgres\" ? true : false,\n transaction: config?.transaction\n ? (cb) =>\n db.transaction().execute((trx) => {\n const adapter = createAdapterFactory({\n config: adapterOptions!.config,\n adapter: createCustomAdapter(trx),\n })(lazyOptions!);\n\n return cb(adapter);\n })\n : false,\n },\n adapter: createCustomAdapter(db),\n };\n\n const adapter = createAdapterFactory(adapterOptions);\n\n return (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n lazyOptions = options;\n return adapter(options);\n };\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"node-sqlite-dialect.mjs","names":["#config","#connectionMutex","#db","#connection","sql","#promise","#resolve","#getTableMetadata"],"sources":["../../../src/adapters/kysely/node-sqlite-dialect.ts"],"sourcesContent":["/**\n * @see {@link https://nodejs.org/api/sqlite.html} - Node.js SQLite API documentation\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type {\n DatabaseConnection,\n DatabaseIntrospector,\n DatabaseMetadata,\n DatabaseMetadataOptions,\n Dialect,\n DialectAdapter,\n DialectAdapterBase,\n Driver,\n Kysely,\n QueryCompiler,\n QueryResult,\n SchemaMetadata,\n TableMetadata,\n} from \"kysely\";\nimport {\n CompiledQuery,\n DEFAULT_MIGRATION_LOCK_TABLE,\n DEFAULT_MIGRATION_TABLE,\n DefaultQueryCompiler,\n sql,\n} from \"kysely\";\n\nclass NodeSqliteAdapter implements DialectAdapterBase {\n get supportsCreateIfNotExists(): boolean {\n return true;\n }\n\n get supportsTransactionalDdl(): boolean {\n return false;\n }\n\n get supportsReturning(): boolean {\n return true;\n }\n\n async acquireMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n\n async releaseMigrationLock(): Promise<void> {\n // SQLite only has one connection that's reserved by the migration system\n // for the whole time between acquireMigrationLock and releaseMigrationLock.\n // We don't need to do anything here.\n }\n get supportsOutput(): boolean {\n return true;\n }\n}\n\n/**\n * Config for the SQLite dialect.\n */\nexport interface NodeSqliteDialectConfig {\n /**\n * A sqlite DatabaseSync instance or a function that returns one.\n */\n database: DatabaseSync;\n\n /**\n * Called once when the first query is executed.\n */\n onCreateConnection?:\n | ((connection: DatabaseConnection) => Promise<void>)\n | undefined;\n}\n\nclass NodeSqliteDriver implements Driver {\n readonly #config: NodeSqliteDialectConfig;\n readonly #connectionMutex = new ConnectionMutex();\n\n #db?: DatabaseSync;\n #connection?: DatabaseConnection;\n\n constructor(config: NodeSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n async init(): Promise<void> {\n this.#db = this.#config.database;\n\n this.#connection = new NodeSqliteConnection(this.#db);\n\n if (this.#config.onCreateConnection) {\n await this.#config.onCreateConnection(this.#connection);\n }\n }\n\n async acquireConnection(): Promise<DatabaseConnection> {\n // SQLite only has one single connection. We use a mutex here to wait\n // until the single connection has been released.\n await this.#connectionMutex.lock();\n return this.#connection!;\n }\n\n async beginTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"begin\"));\n }\n\n async commitTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"commit\"));\n }\n\n async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"rollback\"));\n }\n\n async releaseConnection(): Promise<void> {\n this.#connectionMutex.unlock();\n }\n\n async destroy(): Promise<void> {\n this.#db?.close();\n }\n}\n\nclass NodeSqliteConnection implements DatabaseConnection {\n readonly #db: DatabaseSync;\n\n constructor(db: DatabaseSync) {\n this.#db = db;\n }\n\n executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n const { sql, parameters } = compiledQuery;\n const stmt = this.#db.prepare(sql);\n\n const rows = stmt.all(...(parameters as any[])) as O[];\n\n return Promise.resolve({\n rows,\n });\n }\n\n async *streamQuery() {\n throw new Error(\"Streaming query is not supported by SQLite driver.\");\n }\n}\n\nclass ConnectionMutex {\n #promise?: Promise<void>;\n #resolve?: () => void;\n\n async lock(): Promise<void> {\n while (this.#promise) {\n await this.#promise;\n }\n\n this.#promise = new Promise((resolve) => {\n this.#resolve = resolve;\n });\n }\n\n unlock(): void {\n const resolve = this.#resolve;\n\n this.#promise = undefined;\n this.#resolve = undefined;\n\n resolve?.();\n }\n}\n\nclass NodeSqliteIntrospector implements DatabaseIntrospector {\n readonly #db: Kysely<unknown>;\n\n constructor(db: Kysely<unknown>) {\n this.#db = db;\n }\n\n async getSchemas(): Promise<SchemaMetadata[]> {\n // Sqlite doesn't support schemas.\n return [];\n }\n\n async getTables(\n options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n ): Promise<TableMetadata[]> {\n let query = this.#db\n // @ts-expect-error\n .selectFrom(\"sqlite_schema\")\n // @ts-expect-error\n .where(\"type\", \"=\", \"table\")\n // @ts-expect-error\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select(\"name\")\n .$castTo<{ name: string }>();\n\n if (!options.withInternalKyselyTables) {\n query = query\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_TABLE)\n // @ts-expect-error\n .where(\"name\", \"!=\", DEFAULT_MIGRATION_LOCK_TABLE);\n }\n\n const tables = await query.execute();\n return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));\n }\n\n async getMetadata(\n options?: DatabaseMetadataOptions | undefined,\n ): Promise<DatabaseMetadata> {\n return {\n tables: await this.getTables(options),\n };\n }\n\n async #getTableMetadata(table: string): Promise<TableMetadata> {\n const db = this.#db;\n\n // Get the SQL that was used to create the table.\n const createSql = await db\n // @ts-expect-error\n .selectFrom(\"sqlite_master\")\n // @ts-expect-error\n .where(\"name\", \"=\", table)\n .select(\"sql\")\n .$castTo<{ sql: string | undefined }>()\n .execute();\n\n // Try to find the name of the column that has `autoincrement` >&\n const autoIncrementCol = createSql[0]?.sql\n ?.split(/[\\(\\),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = await db\n .selectFrom(\n sql<{\n name: string;\n type: string;\n notnull: 0 | 1;\n dflt_value: any;\n }>`pragma_table_info(${table})`.as(\"table_info\"),\n )\n .select([\"name\", \"type\", \"notnull\", \"dflt_value\"])\n .execute();\n\n return {\n name: table,\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n })),\n isView: true,\n };\n }\n}\n\nclass NodeSqliteQueryCompiler extends DefaultQueryCompiler {\n protected override getCurrentParameterPlaceholder() {\n return \"?\";\n }\n\n protected override getLeftIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getRightIdentifierWrapper(): string {\n return '\"';\n }\n\n protected override getAutoIncrement() {\n return \"autoincrement\";\n }\n}\n\nexport class NodeSqliteDialect implements Dialect {\n readonly #config: NodeSqliteDialectConfig;\n\n constructor(config: NodeSqliteDialectConfig) {\n this.#config = { ...config };\n }\n\n createDriver(): Driver {\n return new NodeSqliteDriver(this.#config);\n }\n\n createQueryCompiler(): QueryCompiler {\n return new NodeSqliteQueryCompiler();\n }\n\n createAdapter(): DialectAdapter {\n return new NodeSqliteAdapter();\n }\n\n createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n return new NodeSqliteIntrospector(db);\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["db"],"sources":["../../../src/adapters/mongodb/index.ts"],"sourcesContent":["import type { PecuniaOptions } from \"pecunia-core\";\nimport type {\n AdapterFactoryCreator,\n AdapterFactoryOptions,\n DBAdapter,\n DBAdapterDebugLogOption,\n Where,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\";\nimport type { ClientSession, Db, MongoClient } from \"mongodb\";\nimport { ObjectId } from \"mongodb\";\n\nexport interface MongoDBAdapterConfig {\n /**\n * MongoDB client instance\n * If not provided, Database transactions won't be enabled.\n */\n client?: MongoClient | undefined;\n /**\n * Enable debug logs for the adapter\n *\n * @default false\n */\n debugLogs?: DBAdapterDebugLogOption | undefined;\n /**\n * Use plural table names\n *\n * @default false\n */\n usePlural?: boolean | undefined;\n /**\n * Whether to execute multiple operations in a transaction.\n *\n * If the database doesn't support transactions,\n * set this to `false` and operations will be executed sequentially.\n * @default false\n */\n transaction?: boolean | undefined;\n}\n\nexport const mongodbAdapter = (\n db: Db,\n config?: MongoDBAdapterConfig | undefined,\n) => {\n let lazyOptions: PecuniaOptions | null;\n\n const createCustomAdapter =\n (db: Db, session?: ClientSession | undefined): AdapterFactoryCreator =>\n ({ getFieldName, schema, getDefaultModelName, options }) => {\n function serializeID({\n field,\n value,\n model,\n }: {\n field: string;\n value: any;\n model: string;\n }) {\n model = getDefaultModelName(model);\n\n if (\n field === \"id\" ||\n field === \"_id\" ||\n schema[model]!.fields[field]?.references?.field === \"id\"\n ) {\n if (value === null || value === undefined) return value;\n\n if (typeof value !== \"string\") {\n if (value instanceof ObjectId) return value;\n\n if (Array.isArray(value)) {\n return value.map((v) => {\n if (v === null || v === undefined) return v;\n\n if (typeof v === \"string\") {\n try {\n return new ObjectId(v);\n } catch {\n return v;\n }\n }\n\n if (v instanceof ObjectId) return v;\n\n throw new Error(\n \"Invalid id value, received: \" + JSON.stringify(v),\n );\n });\n }\n\n throw new Error(\n \"Invalid id value, received: \" + JSON.stringify(value),\n );\n }\n\n try {\n return new ObjectId(value);\n } catch {\n return value;\n }\n }\n\n return value;\n }\n\n function convertWhereClause({\n where,\n model,\n }: {\n where: Where[];\n model: string;\n }) {\n if (!where.length) return {};\n\n const conditions = where.map((w) => {\n const {\n field: field_,\n value,\n operator = \"eq\",\n connector = \"AND\",\n } = w;\n\n let condition: any;\n let field = getFieldName({ model, field: field_ });\n if (field === \"id\") field = \"_id\";\n\n switch (operator.toLowerCase()) {\n case \"eq\":\n condition = {\n [field]: serializeID({ field, value, model }),\n };\n break;\n\n case \"in\":\n condition = {\n [field]: {\n $in: Array.isArray(value)\n ? value.map((v) => serializeID({ field, value: v, model }))\n : [serializeID({ field, value, model })],\n },\n };\n break;\n\n case \"not_in\":\n condition = {\n [field]: {\n $nin: Array.isArray(value)\n ? value.map((v) => serializeID({ field, value: v, model }))\n : [serializeID({ field, value, model })],\n },\n };\n break;\n\n case \"gt\":\n condition = {\n [field]: { $gt: serializeID({ field, value, model }) },\n };\n break;\n\n case \"gte\":\n condition = {\n [field]: { $gte: serializeID({ field, value, model }) },\n };\n break;\n\n case \"lt\":\n condition = {\n [field]: { $lt: serializeID({ field, value, model }) },\n };\n break;\n\n case \"lte\":\n condition = {\n [field]: { $lte: serializeID({ field, value, model }) },\n };\n break;\n\n case \"ne\":\n condition = {\n [field]: { $ne: serializeID({ field, value, model }) },\n };\n break;\n\n case \"contains\":\n condition = {\n [field]: {\n $regex: `.*${escapeForMongoRegex(value as string)}.*`,\n },\n };\n break;\n\n case \"starts_with\":\n condition = {\n [field]: {\n $regex: `^${escapeForMongoRegex(value as string)}`,\n },\n };\n break;\n\n case \"ends_with\":\n condition = {\n [field]: {\n $regex: `${escapeForMongoRegex(value as string)}$`,\n },\n };\n break;\n\n default:\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n return { condition, connector };\n });\n\n if (conditions.length === 1) {\n return conditions[0]!.condition;\n }\n\n const andConditions = conditions\n .filter((c) => c.connector === \"AND\")\n .map((c) => c.condition);\n\n const orConditions = conditions\n .filter((c) => c.connector === \"OR\")\n .map((c) => c.condition);\n\n let clause: any = {};\n if (andConditions.length) clause = { ...clause, $and: andConditions };\n if (orConditions.length) clause = { ...clause, $or: orConditions };\n\n return clause;\n }\n\n return {\n async create({ model, data: values }) {\n const res = await db.collection(model).insertOne(values, { session });\n const insertedData = { _id: res.insertedId.toString(), ...values };\n return insertedData as any;\n },\n\n async findOne({ model, where, select }) {\n const matchStage = where\n ? { $match: convertWhereClause({ where, model }) }\n : { $match: {} };\n\n const pipeline: any[] = [matchStage];\n\n if (select) {\n const projection: any = {};\n select.forEach((field) => {\n projection[getFieldName({ field, model })] = 1;\n });\n pipeline.push({ $project: projection });\n }\n\n pipeline.push({ $limit: 1 });\n\n const res = await db\n .collection(model)\n .aggregate(pipeline, { session })\n .toArray();\n\n if (!res || res.length === 0) return null;\n return res[0] as any;\n },\n\n async findMany({ model, where, limit, offset, sortBy }) {\n const matchStage = where\n ? { $match: convertWhereClause({ where, model }) }\n : { $match: {} };\n\n const pipeline: any[] = [matchStage];\n\n if (sortBy) {\n pipeline.push({\n $sort: {\n [getFieldName({ field: sortBy.field, model })]:\n sortBy.direction === \"desc\" ? -1 : 1,\n },\n });\n }\n\n if (offset) {\n pipeline.push({ $skip: offset });\n }\n\n if (limit) {\n pipeline.push({ $limit: limit });\n }\n\n const res = await db\n .collection(model)\n .aggregate(pipeline, { session })\n .toArray();\n\n return res as any;\n },\n\n async count({ model, where }) {\n const matchStage = where\n ? { $match: convertWhereClause({ where, model }) }\n : { $match: {} };\n\n const pipeline: any[] = [matchStage, { $count: \"total\" }];\n\n const res = await db\n .collection(model)\n .aggregate(pipeline, { session })\n .toArray();\n\n if (!res || res.length === 0) return 0;\n return res[0]?.total ?? 0;\n },\n\n async update({ model, where, update: values }) {\n const clause = convertWhereClause({ where, model });\n\n const res = await db.collection(model).findOneAndUpdate(\n clause,\n { $set: values as any },\n {\n session,\n returnDocument: \"after\",\n includeResultMetadata: true,\n },\n );\n\n const doc = (res as any)?.value ?? null;\n if (!doc) return null;\n return doc as any;\n },\n\n async updateMany({ model, where, update: values }) {\n const clause = convertWhereClause({ where, model });\n\n const res = await db\n .collection(model)\n .updateMany(clause, { $set: values as any }, { session });\n\n return res.modifiedCount;\n },\n\n async delete({ model, where }) {\n const clause = convertWhereClause({ where, model });\n await db.collection(model).deleteOne(clause, { session });\n },\n\n async deleteMany({ model, where }) {\n const clause = convertWhereClause({ where, model });\n const res = await db\n .collection(model)\n .deleteMany(clause, { session });\n return res.deletedCount;\n },\n };\n };\n\n let lazyAdapter:\n | ((options: PecuniaOptions) => DBAdapter<PecuniaOptions>)\n | null = null;\n\n let adapterOptions: AdapterFactoryOptions | null = null;\n\n adapterOptions = {\n config: {\n adapterId: \"mongodb-adapter\",\n adapterName: \"MongoDB Adapter\",\n usePlural: config?.usePlural ?? false,\n mapKeysTransformInput: {\n id: \"_id\",\n },\n mapKeysTransformOutput: {\n _id: \"id\",\n },\n supportsArrays: true,\n supportsNumericIds: false,\n transaction:\n config?.client && (config?.transaction ?? true)\n ? async (cb) => {\n if (!config.client) {\n return cb(lazyAdapter!(lazyOptions!));\n }\n\n const session = config.client.startSession();\n\n try {\n session.startTransaction();\n\n const adapter = createAdapterFactory({\n config: adapterOptions!.config,\n adapter: createCustomAdapter(db, session),\n })(lazyOptions!);\n\n const result = await cb(adapter);\n\n await session.commitTransaction();\n return result;\n } catch (err) {\n await session.abortTransaction();\n throw err;\n } finally {\n await session.endSession();\n }\n }\n : false,\n customTransformInput({ action, data, field, fieldAttributes, options }) {\n if (field === \"_id\" || fieldAttributes.references?.field === \"id\") {\n if (action !== \"create\") return data;\n\n if (Array.isArray(data)) {\n return data.map((v) => {\n if (typeof v === \"string\") {\n try {\n return new ObjectId(v);\n } catch {\n return v;\n }\n }\n return v;\n });\n }\n\n if (typeof data === \"string\") {\n try {\n return new ObjectId(data);\n } catch {\n return data;\n }\n }\n\n if (\n fieldAttributes?.references?.field === \"id\" &&\n !fieldAttributes?.required &&\n data === null\n ) {\n return null;\n }\n\n return new ObjectId();\n }\n\n return data;\n },\n customTransformOutput({ data, field, fieldAttributes }) {\n if (field === \"id\" || fieldAttributes.references?.field === \"id\") {\n if (data instanceof ObjectId) return data.toHexString();\n\n if (Array.isArray(data)) {\n return data.map((v) => {\n if (v instanceof ObjectId) return v.toHexString();\n return v;\n });\n }\n\n return data;\n }\n\n return data;\n },\n customIdGenerator() {\n return new ObjectId().toString();\n },\n },\n adapter: createCustomAdapter(db),\n };\n\n lazyAdapter = createAdapterFactory(adapterOptions);\n\n return (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n lazyOptions = options;\n return lazyAdapter(options);\n };\n};\n\n/**\n * Safely escape user input for use in a MongoDB regex.\n * This ensures the resulting pattern is treated as literal text,\n * and not as a regex with special syntax.\n *\n * @param input - The input string to escape. Any type that isn't a string will be converted to an empty string.\n * @param maxLength - The maximum length of the input string to escape. Defaults to 256. This is to prevent DOS attacks.\n * @returns The escaped string.\n */\nfunction escapeForMongoRegex(input: string, maxLength = 256): string {\n if (typeof input !== \"string\") return \"\";\n\n // Escape all PCRE special characters\n // Source: PCRE docs — https://www.pcre.org/original/doc/html/pcrepattern.html\n return input.slice(0, maxLength).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["prisma","and","or","orClause","andClause"],"sources":["../../../src/adapters/prisma/index.ts"],"sourcesContent":["import type { Awaitable, PecuniaOptions } from \"pecunia-core\";\nimport type {\n AdapterFactoryCreator,\n AdapterFactoryOptions,\n DBAdapter,\n DBAdapterDebugLogOption,\n Where,\n} from \"pecunia-core\";\nimport { createAdapterFactory } from \"pecunia-core\";\nimport { PecuniaError } from \"pecunia-core\";\n\nexport interface PrismaConfig {\n /**\n * Database provider.\n */\n provider:\n | \"sqlite\"\n | \"cockroachdb\"\n | \"mysql\"\n | \"postgresql\"\n | \"sqlserver\"\n | \"mongodb\";\n\n /**\n * Enable debug logs for the adapter\n *\n * @default false\n */\n debugLogs?: DBAdapterDebugLogOption | undefined;\n\n /**\n * Use plural table names\n *\n * @default false\n */\n usePlural?: boolean | undefined;\n\n /**\n * Whether to execute multiple operations in a transaction.\n *\n * If the database doesn't support transactions,\n * set this to `false` and operations will be executed sequentially.\n * @default false\n */\n transaction?: boolean | undefined;\n}\n\ninterface PrismaClient {}\n\ntype PrismaClientInternal = {\n $transaction: (\n callback: (db: PrismaClient) => Awaitable<any>,\n ) => Promise<any>;\n} & {\n [model: string]: {\n create: (data: any) => Promise<any>;\n findFirst: (data: any) => Promise<any>;\n findMany: (data: any) => Promise<any>;\n update: (data: any) => Promise<any>;\n updateMany: (data: any) => Promise<any>;\n delete: (data: any) => Promise<any>;\n count: (data: any) => Promise<any>;\n [key: string]: any;\n };\n};\n\nexport const prismaAdapter = (prisma: PrismaClient, config: PrismaConfig) => {\n let lazyOptions: PecuniaOptions | null = null;\n\n const createCustomAdapter =\n (prisma: PrismaClient): AdapterFactoryCreator =>\n ({ getFieldName }) => {\n const db = prisma as PrismaClientInternal;\n\n function operatorToPrismaOperator(operator: string) {\n switch (operator) {\n case \"starts_with\":\n return \"startsWith\";\n case \"ends_with\":\n return \"endsWith\";\n case \"ne\":\n return \"not\";\n case \"not_in\":\n return \"notIn\";\n default:\n return operator;\n }\n }\n\n const convertWhereClause = ({\n action,\n model,\n where,\n }: {\n model: string;\n where?: Where[] | undefined;\n action:\n | \"create\"\n | \"update\"\n | \"delete\"\n | \"findOne\"\n | \"findMany\"\n | \"count\"\n | \"updateMany\"\n | \"deleteMany\";\n }) => {\n if (!where || !where.length) return {};\n\n const buildSingleCondition = (w: Where) => {\n const fieldName = getFieldName({ model, field: w.field });\n\n // Prisma null semantics: \"not: null\" on nullable can behave unexpectedly;\n // for non-nullable fields it's a tautology. Skip.\n if (w.operator === \"ne\" && w.value === null) {\n return {};\n }\n\n if (\n (w.operator === \"in\" || w.operator === \"not_in\") &&\n Array.isArray(w.value)\n ) {\n const filtered = w.value.filter((v) => v != null);\n\n if (filtered.length === 0) {\n if (w.operator === \"in\") {\n return {\n AND: [\n { [fieldName]: { equals: \"__never__\" } },\n { [fieldName]: { not: \"__never__\" } },\n ],\n };\n }\n return {};\n }\n\n const prismaOp = operatorToPrismaOperator(w.operator);\n return { [fieldName]: { [prismaOp]: filtered } };\n }\n\n if (w.operator === \"eq\" || !w.operator) {\n return { [fieldName]: w.value };\n }\n\n return {\n [fieldName]: {\n [operatorToPrismaOperator(w.operator)]: w.value,\n },\n };\n };\n\n // Update: extract simple equality AND conditions to root (Prisma unique where)\n if (action === \"update\") {\n const and = where.filter(\n (w) => w.connector === \"AND\" || !w.connector,\n );\n const or = where.filter((w) => w.connector === \"OR\");\n\n const andSimple = and.filter(\n (w) => w.operator === \"eq\" || !w.operator,\n );\n const andComplex = and.filter(\n (w) => w.operator !== \"eq\" && w.operator !== undefined,\n );\n\n const andSimpleClause = andSimple.map((w) => buildSingleCondition(w));\n const andComplexClause = andComplex.map((w) =>\n buildSingleCondition(w),\n );\n const orClause = or.map((w) => buildSingleCondition(w));\n\n const result: Record<string, any> = {};\n for (const clause of andSimpleClause) Object.assign(result, clause);\n if (andComplexClause.length > 0) result.AND = andComplexClause;\n if (orClause.length > 0) result.OR = orClause;\n\n return result;\n }\n\n // Delete: extract id to root if present\n if (action === \"delete\") {\n const idCondition = where.find((w) => w.field === \"id\");\n if (idCondition) {\n const idFieldName = getFieldName({ model, field: \"id\" });\n const idClause = buildSingleCondition(idCondition);\n const remainingWhere = where.filter((w) => w.field !== \"id\");\n\n if (remainingWhere.length === 0) return idClause;\n\n const and = remainingWhere.filter(\n (w) => w.connector === \"AND\" || !w.connector,\n );\n const or = remainingWhere.filter((w) => w.connector === \"OR\");\n const andClause = and.map((w) => buildSingleCondition(w));\n const orClause = or.map((w) => buildSingleCondition(w));\n\n const result: Record<string, any> = {};\n\n if (idFieldName in idClause) {\n result[idFieldName] = (idClause as Record<string, any>)[\n idFieldName\n ];\n } else {\n Object.assign(result, idClause);\n }\n\n if (andClause.length > 0) result.AND = andClause;\n if (orClause.length > 0) result.OR = orClause;\n\n return result;\n }\n }\n\n if (where.length === 1) {\n return buildSingleCondition(where[0]!);\n }\n\n const and = where.filter((w) => w.connector === \"AND\" || !w.connector);\n const or = where.filter((w) => w.connector === \"OR\");\n\n const andClause = and.map((w) => buildSingleCondition(w));\n const orClause = or.map((w) => buildSingleCondition(w));\n\n return {\n ...(andClause.length ? { AND: andClause } : {}),\n ...(orClause.length ? { OR: orClause } : {}),\n };\n };\n\n return {\n async create({ model, data: values, select }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const result = await db[model]!.create({\n data: values,\n select: select\n ? Object.fromEntries(\n select.map((field) => [getFieldName({ model, field }), true]),\n )\n : undefined,\n });\n\n return result;\n },\n\n async findOne({ model, where, select }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"findOne\",\n });\n\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n return await db[model]!.findFirst({\n where: whereClause,\n select: select\n ? Object.fromEntries(\n select.map((field) => [getFieldName({ model, field }), true]),\n )\n : undefined,\n });\n },\n\n async findMany({ model, where, limit, offset, sortBy }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"findMany\",\n });\n\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n return await db[model]!.findMany({\n where: whereClause,\n take: limit || 100,\n skip: offset || 0,\n ...(sortBy?.field\n ? {\n orderBy: {\n [getFieldName({ model, field: sortBy.field })]:\n sortBy.direction === \"desc\" ? \"desc\" : \"asc\",\n },\n }\n : {}),\n select: undefined,\n });\n },\n\n async count({ model, where }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"count\",\n });\n\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n return await db[model]!.count({ where: whereClause });\n },\n\n async update({ model, where, update }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"update\",\n });\n\n return await db[model]!.update({\n where: whereClause,\n data: update,\n });\n },\n\n async updateMany({ model, where, update }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"updateMany\",\n });\n\n const result = await db[model]!.updateMany({\n where: whereClause,\n data: update,\n });\n\n return result ? (result.count as number) : 0;\n },\n\n async delete({ model, where }) {\n if (!db[model]) {\n throw new PecuniaError(\n `Model ${model} does not exist in the database. If you haven't generated the Prisma client, you need to run 'npx prisma generate'`,\n );\n }\n\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"delete\",\n });\n\n try {\n await db[model]!.delete({ where: whereClause });\n } catch (e: any) {\n if (e?.meta?.cause === \"Record to delete does not exist.\") return;\n console.log(e);\n }\n },\n\n async deleteMany({ model, where }) {\n const whereClause = convertWhereClause({\n model,\n where,\n action: \"deleteMany\",\n });\n\n const result = await db[model]!.deleteMany({\n where: whereClause,\n });\n\n return result ? (result.count as number) : 0;\n },\n\n options: config,\n };\n };\n\n let adapterOptions: AdapterFactoryOptions | null = null;\n\n adapterOptions = {\n config: {\n adapterId: \"prisma\",\n adapterName: \"Prisma Adapter\",\n usePlural: config.usePlural ?? false,\n supportsUUIDs: config.provider === \"postgresql\" ? true : false,\n supportsArrays:\n config.provider === \"postgresql\" || config.provider === \"mongodb\"\n ? true\n : false,\n transaction:\n (config.transaction ?? false)\n ? (cb) =>\n (prisma as PrismaClientInternal).$transaction((tx) => {\n const adapter = createAdapterFactory({\n config: adapterOptions!.config,\n adapter: createCustomAdapter(tx),\n })(lazyOptions!);\n return cb(adapter);\n })\n : false,\n },\n adapter: createCustomAdapter(prisma),\n };\n\n const adapter = createAdapterFactory(adapterOptions);\n\n return (options: PecuniaOptions): DBAdapter<PecuniaOptions> => {\n lazyOptions = options;\n return adapter(options);\n };\n};\n"],"mappings":"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"}