pecunia-root 0.0.3 → 0.0.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["lazyOptions: PecuniaOptions | null","db","clause: SQL<unknown>[]","count","adapterOptions: AdapterFactoryOptions | null"],"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
+ {"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":";;;;AAwEA,MAAa,kBAAkB,IAAQ,WAAiC;CACvE,IAAI,cAAqC;CACzC,MAAM,uBACJ,UACA,EAAE,cAAc,cAAc;EAC9B,SAAS,UAAU,OAAe;GACjC,MAAM,SAAS,OAAO,UAAUA,KAAG,EAAE;AACrC,OAAI,CAAC,OACJ,OAAM,IAAI,aACT,wHACA;GAEF,MAAM,cAAc,OAAO;AAC3B,OAAI,CAAC,YACJ,OAAM,IAAI,aACT,mCAAmC,MAAM,+FACzC;AAEF,UAAO;;EAER,MAAM,gBAAgB,OACrB,OACA,SACA,MACA,UACI;AACJ,OAAI,OAAO,aAAa,QAEvB,SADU,MAAM,QAAQ,WAAW,EAC1B;AAEV,SAAM,QAAQ,SAAS;GACvB,MAAM,cAAc,UAAU,MAAM;GACpC,MAAM,aAAa,QAAQ,QAAQ;AACnC,OAAI,OAAO,QAAQ;IAUlB,MAAM,SAAS,mBARM,MAAM,KAAK,MAAM;AAErC,SAAI,KAAK,EAAE,WAAW,OACrB,QAAO;MAAE,GAAG;MAAG,OAAO,KAAK,EAAE;MAAQ;AAEtC,YAAO;MACN,EAE8C,MAAM;AAKtD,YAJY,MAAMA,KAChB,QAAQ,CACR,KAAK,YAAY,CACjB,MAAM,GAAG,OAAO,EACP;cACD,cAAc,WAAW,IAAI,IAAI,OAAO;IAClD,IAAI,MAAM,WAAW,IAAI,IAAI;AAC7B,QAAI,CAAC,IAOJ,QALqB,MAAMA,KACzB,OAAO,EAAE,IAAI,GAAG,oBAAoB,CAAC,CACrC,KAAK,YAAY,CACjB,QAAQ,KAAK,YAAY,GAAG,CAAC,CAC7B,MAAM,EAAE,EACS,GAAG;AAQvB,YANY,MAAMA,KAChB,QAAQ,CACR,KAAK,YAAY,CACjB,MAAM,GAAG,YAAY,IAAI,IAAI,CAAC,CAC9B,MAAM,EAAE,CACR,SAAS,EACA;cACD,KAAK,GAOf,SANY,MAAMA,KAChB,QAAQ,CACR,KAAK,YAAY,CACjB,MAAM,GAAG,YAAY,IAAI,KAAK,GAAG,CAAC,CAClC,MAAM,EAAE,CACR,SAAS,EACA;QACL;AAGN,QAAI,EAAE,QAAQ,aACb,OAAM,IAAI,aACT,cAAc,MAAM,+EACpB;AAQF,YANY,MAAMA,KAChB,QAAQ,CACR,KAAK,YAAY,CACjB,QAAQ,KAAK,YAAY,GAAG,CAAC,CAC7B,MAAM,EAAE,CACR,SAAS,EACA;;;EAGb,SAAS,mBAAmB,OAAgB,OAAe;GAC1D,MAAM,cAAc,UAAU,MAAM;AACpC,OAAI,CAAC,MAAO,QAAO,EAAE;AACrB,OAAI,MAAM,WAAW,GAAG;IACvB,MAAM,IAAI,MAAM;AAChB,QAAI,CAAC,EACJ,QAAO,EAAE;IAEV,MAAM,QAAQ,aAAa;KAAE;KAAO,OAAO,EAAE;KAAO,CAAC;AACrD,QAAI,CAAC,YAAY,OAChB,OAAM,IAAI,aACT,cAAc,EAAE,MAAM,gDAAgD,MAAM,+BAC5E;AAEF,QAAI,EAAE,aAAa,MAAM;AACxB,SAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,CAC1B,OAAM,IAAI,aACT,4BAA4B,EAAE,MAAM,kDACpC;AAEF,YAAO,CAAC,QAAQ,YAAY,QAAQ,EAAE,MAAM,CAAC;;AAG9C,QAAI,EAAE,aAAa,UAAU;AAC5B,SAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,CAC1B,OAAM,IAAI,aACT,4BAA4B,EAAE,MAAM,sDACpC;AAEF,YAAO,CAAC,WAAW,YAAY,QAAQ,EAAE,MAAM,CAAC;;AAGjD,QAAI,EAAE,aAAa,WAClB,QAAO,CAAC,KAAK,YAAY,QAAQ,IAAI,EAAE,MAAM,GAAG,CAAC;AAGlD,QAAI,EAAE,aAAa,cAClB,QAAO,CAAC,KAAK,YAAY,QAAQ,GAAG,EAAE,MAAM,GAAG,CAAC;AAGjD,QAAI,EAAE,aAAa,YAClB,QAAO,CAAC,KAAK,YAAY,QAAQ,IAAI,EAAE,QAAQ,CAAC;AAGjD,QAAI,EAAE,aAAa,KAClB,QAAO,CAAC,GAAG,YAAY,QAAQ,EAAE,MAAM,CAAC;AAGzC,QAAI,EAAE,aAAa,MAClB,QAAO,CAAC,IAAI,YAAY,QAAQ,EAAE,MAAM,CAAC;AAG1C,QAAI,EAAE,aAAa,KAClB,QAAO,CAAC,GAAG,YAAY,QAAQ,EAAE,MAAM,CAAC;AAGzC,QAAI,EAAE,aAAa,KAClB,QAAO,CAAC,GAAG,YAAY,QAAQ,EAAE,MAAM,CAAC;AAGzC,QAAI,EAAE,aAAa,MAClB,QAAO,CAAC,IAAI,YAAY,QAAQ,EAAE,MAAM,CAAC;AAG1C,WAAO,CAAC,GAAG,YAAY,QAAQ,EAAE,MAAM,CAAC;;GAEzC,MAAM,WAAW,MAAM,QACrB,MAAM,EAAE,cAAc,SAAS,CAAC,EAAE,UACnC;GACD,MAAM,UAAU,MAAM,QAAQ,MAAM,EAAE,cAAc,KAAK;GAEzD,MAAM,YAAY,IACjB,GAAG,SAAS,KAAK,MAAM;IACtB,MAAM,QAAQ,aAAa;KAAE;KAAO,OAAO,EAAE;KAAO,CAAC;AACrD,QAAI,EAAE,aAAa,MAAM;AACxB,SAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,CAC1B,OAAM,IAAI,aACT,4BAA4B,EAAE,MAAM,kDACpC;AAEF,YAAO,QAAQ,YAAY,QAAQ,EAAE,MAAM;;AAE5C,QAAI,EAAE,aAAa,UAAU;AAC5B,SAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,CAC1B,OAAM,IAAI,aACT,4BAA4B,EAAE,MAAM,sDACpC;AAEF,YAAO,WAAW,YAAY,QAAQ,EAAE,MAAM;;AAE/C,QAAI,EAAE,aAAa,WAClB,QAAO,KAAK,YAAY,QAAQ,IAAI,EAAE,MAAM,GAAG;AAEhD,QAAI,EAAE,aAAa,cAClB,QAAO,KAAK,YAAY,QAAQ,GAAG,EAAE,MAAM,GAAG;AAE/C,QAAI,EAAE,aAAa,YAClB,QAAO,KAAK,YAAY,QAAQ,IAAI,EAAE,QAAQ;AAE/C,QAAI,EAAE,aAAa,KAClB,QAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;AAEvC,QAAI,EAAE,aAAa,MAClB,QAAO,IAAI,YAAY,QAAQ,EAAE,MAAM;AAExC,QAAI,EAAE,aAAa,KAClB,QAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;AAEvC,QAAI,EAAE,aAAa,MAClB,QAAO,IAAI,YAAY,QAAQ,EAAE,MAAM;AAExC,QAAI,EAAE,aAAa,KAClB,QAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;AAEvC,WAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;KACrC,CACF;GACD,MAAM,WAAW,GAChB,GAAG,QAAQ,KAAK,MAAM;IACrB,MAAM,QAAQ,aAAa;KAAE;KAAO,OAAO,EAAE;KAAO,CAAC;AACrD,QAAI,EAAE,aAAa,MAAM;AACxB,SAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,CAC1B,OAAM,IAAI,aACT,4BAA4B,EAAE,MAAM,kDACpC;AAEF,YAAO,QAAQ,YAAY,QAAQ,EAAE,MAAM;;AAE5C,QAAI,EAAE,aAAa,UAAU;AAC5B,SAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,CAC1B,OAAM,IAAI,aACT,4BAA4B,EAAE,MAAM,sDACpC;AAEF,YAAO,WAAW,YAAY,QAAQ,EAAE,MAAM;;AAE/C,QAAI,EAAE,aAAa,WAClB,QAAO,KAAK,YAAY,QAAQ,IAAI,EAAE,MAAM,GAAG;AAEhD,QAAI,EAAE,aAAa,cAClB,QAAO,KAAK,YAAY,QAAQ,GAAG,EAAE,MAAM,GAAG;AAE/C,QAAI,EAAE,aAAa,YAClB,QAAO,KAAK,YAAY,QAAQ,IAAI,EAAE,QAAQ;AAE/C,QAAI,EAAE,aAAa,KAClB,QAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;AAEvC,QAAI,EAAE,aAAa,MAClB,QAAO,IAAI,YAAY,QAAQ,EAAE,MAAM;AAExC,QAAI,EAAE,aAAa,KAClB,QAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;AAEvC,QAAI,EAAE,aAAa,MAClB,QAAO,IAAI,YAAY,QAAQ,EAAE,MAAM;AAExC,QAAI,EAAE,aAAa,KAClB,QAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;AAEvC,WAAO,GAAG,YAAY,QAAQ,EAAE,MAAM;KACrC,CACF;GAED,MAAM,SAAyB,EAAE;AAEjC,OAAI,SAAS,OAAQ,QAAO,KAAK,UAAW;AAC5C,OAAI,QAAQ,OAAQ,QAAO,KAAK,SAAU;AAC1C,UAAO;;EAER,SAAS,mBACR,QACA,OACA,QACC;AACD,OAAI,CAAC,OACJ,OAAM,IAAI,aACT,gIACA;AAEF,QAAK,MAAM,OAAO,OACjB,KAAI,CAAC,OAAO,KACX,OAAM,IAAI,aACT,cAAc,IAAI,2BAA2B,MAAM,8GACnD;;AAKJ,SAAO;GACN,MAAM,OAAO,EAAE,OAAO,MAAM,UAAU;IACrC,MAAM,cAAc,UAAU,MAAM;AACpC,uBAAmB,aAAa,OAAO,OAAO;AAG9C,WADiB,MAAM,cAAc,OADrBA,KAAG,OAAO,YAAY,CAAC,OAAO,OAAO,EACA,OAAO;;GAG7D,MAAM,QAAQ,EAAE,OAAO,SAAS;IAC/B,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,mBAAmB,OAAO,MAAM;IAO/C,MAAM,MAAM,MALAA,KACV,QAAQ,CACR,KAAK,YAAY,CACjB,MAAM,GAAG,OAAO;AAIlB,QAAI,CAAC,IAAI,OAAQ,QAAO;AACxB,WAAO,IAAI;;GAEZ,MAAM,SAAS,EAAE,OAAO,OAAO,QAAQ,OAAO,UAAU;IACvD,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,QAAQ,mBAAmB,OAAO,MAAM,GAAG,EAAE;IAC5D,MAAM,SAAS,QAAQ,cAAc,SAAS,OAAO;IAErD,IAAI,UAAUA,KAAG,QAAQ,CAAC,KAAK,YAAY;IAE3C,MAAM,iBAAiB;IACvB,MAAM,kBAAkB;AAExB,QAAI,OAAO,mBAAmB,YAC7B,WAAU,QAAQ,MAAM,eAAe;AAGxC,QAAI,OAAO,oBAAoB,YAC9B,WAAU,QAAQ,OAAO,gBAAgB;AAG1C,QAAI,QAAQ,MACX,WAAU,QAAQ,QACjB,OACC,YAAY,aAAa;KAAE;KAAO,OAAO,QAAQ;KAAO,CAAC,EACzD,CACD;AAIF,WADY,MAAM,QAAQ,MAAM,GAAG,OAAO;;GAG3C,MAAM,MAAM,EAAE,OAAO,SAAS;IAC7B,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,QAAQ,mBAAmB,OAAO,MAAM,GAAG,EAAE;AAK5D,YAJY,MAAMA,KAChB,OAAO,EAAE,OAAO,OAAO,EAAE,CAAC,CAC1B,KAAK,YAAY,CACjB,MAAM,GAAG,OAAO,EACP,GAAG;;GAEf,MAAM,OAAO,EAAE,OAAO,OAAO,QAAQ,UAAU;IAC9C,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,mBAAmB,OAAO,MAAM;AAK/C,WAAO,MAAM,cAAc,OAJXA,KACd,OAAO,YAAY,CACnB,IAAI,OAAO,CACX,MAAM,GAAG,OAAO,EACyB,QAAe,MAAM;;GAEjE,MAAM,WAAW,EAAE,OAAO,OAAO,QAAQ,UAAU;IAClD,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,mBAAmB,OAAO,MAAM;AAK/C,WAAO,MAJSA,KACd,OAAO,YAAY,CACnB,IAAI,OAAO,CACX,MAAM,GAAG,OAAO;;GAGnB,MAAM,OAAO,EAAE,OAAO,SAAS;IAC9B,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,mBAAmB,OAAO,MAAM;AAE/C,WAAO,MADSA,KAAG,OAAO,YAAY,CAAC,MAAM,GAAG,OAAO;;GAGxD,MAAM,WAAW,EAAE,OAAO,SAAS;IAClC,MAAM,cAAc,UAAU,MAAM;IACpC,MAAM,SAAS,mBAAmB,OAAO,MAAM;IAE/C,MAAM,MAAM,MADIA,KAAG,OAAO,YAAY,CAAC,MAAM,GAAG,OAAO;IAEvD,IAAIC,UAAQ;AACZ,QAAI,OAAO,cAAc,IAAK,WAAQ,IAAI;aACjC,MAAM,QAAQ,IAAI,CAAE,WAAQ,IAAI;aAExC,QACC,kBAAkB,OAAO,kBAAkB,OAAO,aAAa,KAEhE,WAAQ,IAAI,gBAAgB,IAAI,gBAAgB,IAAI;AACrD,QAAI,OAAOA,YAAU,SACpB,QAAO,MACN,kHACA;KAAE;KAAK;KAAO;KAAO,CACrB;AAEF,WAAOA;;GAER,SAAS;GACT;;CAEH,IAAI,iBAA+C;AACnD,kBAAiB;EAChB,QAAQ;GACP,WAAW;GACX,aAAa;GACb,WAAW,OAAO,aAAa;GAC/B,eAAe,OAAO,aAAa,OAAO,OAAO;GACjD,cACC,OAAO,aAAa,OACjB,OACA;GACJ,gBAAgB,OAAO,aAAa,OAAO,OAAO;GAClD,aACE,OAAO,eAAe,SACnB,OACD,GAAG,aAAa,OAAW;AAK1B,WAAO,GAJS,qBAAqB;KACpC,QAAQ,eAAgB;KACxB,SAAS,oBAAoB,GAAG;KAChC,CAAC,CAAC,YAAa,CACE;KACjB,GACF;GACJ;EACD,SAAS,oBAAoB,GAAG;EAChC;CACD,MAAM,UAAU,qBAAqB,eAAe;AACpD,SAAQ,YAAuD;AAC9D,gBAAc;AACd,SAAO,QAAQ,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-adapter.mjs","names":["adapter: DBAdapter<PecuniaOptions>"],"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,IAAIA;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/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 +1 @@
1
- {"version":3,"file":"dialect.mjs","names":["dialect: Dialect | undefined","DatabaseSync: typeof import(\"node:sqlite\").DatabaseSync | undefined","nodeSqlite: string","error: unknown"],"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,IAAIA,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,IAAIC,eACF;AACF,MAAI;GACF,IAAIC,aAAqB;AAGzB,IAAC,CAAE,gBAAiB,MAAM;;;IAGxB;;WAEKC,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
+ {"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 +1 @@
1
- {"version":3,"file":"index.mjs","names":["lazyOptions: PecuniaOptions | null","res: any","db","value: any","field: string | any","query: any","adapterOptions: AdapterFactoryOptions | null"],"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
+ {"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 +1 @@
1
- {"version":3,"file":"index.mjs","names":["lazyOptions: PecuniaOptions | null","condition: any","clause: any","db","pipeline: any[]","projection: any","lazyAdapter:\n | ((options: PecuniaOptions) => DBAdapter<PecuniaOptions>)\n | null","adapterOptions: AdapterFactoryOptions | null"],"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
+ {"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 +1 @@
1
- {"version":3,"file":"index.mjs","names":["lazyOptions: PecuniaOptions | null","prisma","and","or","orClause","result: Record<string, any>","andClause","e: any","adapterOptions: AdapterFactoryOptions | null"],"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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"}
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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["api: Record<\n\t\tstring,\n\t\t((\n\t\t\tcontext: EndpointContext<string, any> & InputContext<string, any>,\n\t\t) => Promise<any>) & {\n\t\t\tpath?: string | undefined;\n\t\t\toptions?: EndpointOptions | undefined;\n\t\t}\n\t>","internalContext: InternalContext"],"sources":["../../src/api/index.ts"],"sourcesContent":["import { type PecuniaEndpoint, type Awaitable, type PecuniaContext, type PecuniaOptions, type PecuniaMiddleware, runWithEndpointContext, type PecuniaPlugin, hasRequestState, runWithRequestState } from \"pecunia-core\";\nimport type {\n Endpoint,\n\tEndpointContext,\n\tEndpointOptions,\n\tInputContext,\n Middleware,\n UnionToIntersection,\n} from \"better-call\";\nimport { createRouter, toResponse } from \"better-call\";\nimport { createDefu } from \"defu\";\n\ntype InternalContext = Partial<\n\tInputContext<string, any> & EndpointContext<string, any>\n> & {\n\tpath: string;\n\tasResponse?: boolean | undefined;\n\tcontext: PecuniaContext & {\n\t\t// logger: PecuniaContext[\"logger\"];\n\t\treturned?: unknown | undefined;\n\t\tresponseHeaders?: Headers | undefined;\n\t};\n};\n\nconst defuReplaceArrays = createDefu((obj, key, value) => {\n\tif (Array.isArray(obj[key]) && Array.isArray(value)) {\n\t\tobj[key] = value;\n\t\treturn true;\n\t}\n});\n\nconst hooksSourceWeakMap = new WeakMap<\n\tPecuniaMiddleware,\n\t`user` | `plugin:${string}`\n>();\n\ntype UserInputContext = Partial<\n\tInputContext<string, any> & EndpointContext<string, any>\n >;\n\nexport function toAuthEndpoints<\n\tconst E extends Record<\n\t\tstring,\n\t\tOmit<PecuniaEndpoint<string, EndpointOptions, any>, \"wrap\">\n\t>,\n>(endpoints: E, ctx: PecuniaContext | Promise<PecuniaContext>): E {\n\tconst api: Record<\n\t\tstring,\n\t\t((\n\t\t\tcontext: EndpointContext<string, any> & InputContext<string, any>,\n\t\t) => Promise<any>) & {\n\t\t\tpath?: string | undefined;\n\t\t\toptions?: EndpointOptions | undefined;\n\t\t}\n\t> = {};\n\n\tfor (const [key, endpoint] of Object.entries(endpoints)) {\n\t\tapi[key] = async (context?: UserInputContext) => {\n\t\t\tconst run = async () => {\n\t\t\t\tconst authContext = await ctx;\n\t\t\t\tlet internalContext: InternalContext = {\n\t\t\t\t\t...context,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\t...authContext,\n\t\t\t\t\t\treturned: undefined,\n\t\t\t\t\t\tresponseHeaders: undefined,\n\t\t\t\t\t\tsession: null,\n\t\t\t\t\t},\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\theaders: context?.headers ? new Headers(context?.headers) : undefined,\n\t\t\t\t};\n\t\t\t\treturn runWithEndpointContext(internalContext, async () => {\n\t\t\t\t\tinternalContext.asResponse = false;\n\t\t\t\t\tinternalContext.returnHeaders = true;\n\t\t\t\t\tinternalContext.returnStatus = true;\n\t\t\t\t\tconst result = (await runWithEndpointContext(internalContext, () =>\n\t\t\t\t\t\t(endpoint as any)(internalContext as any),\n\t\t\t\t\t).catch((e: any) => {\n\t\t\t\t\t\t// if (isAPIError(e)) {\n\t\t\t\t\t\t// \t/**\n\t\t\t\t\t\t// \t * API Errors from response are caught\n\t\t\t\t\t\t// \t * and returned to hooks\n\t\t\t\t\t\t// \t */\n\t\t\t\t\t\t// \treturn {\n\t\t\t\t\t\t// \t\tresponse: e,\n\t\t\t\t\t\t// \t\tstatus: e.statusCode,\n\t\t\t\t\t\t// \t\theaders: e.headers ? new Headers(e.headers) : null,\n\t\t\t\t\t\t// \t};\n\t\t\t\t\t\t// }\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t})) as {\n\t\t\t\t\t\theaders: Headers;\n\t\t\t\t\t\tresponse: any;\n\t\t\t\t\t\tstatus: number;\n\t\t\t\t\t};\n\n\t\t\t\t\t//if response object is returned we skip after hooks and post processing\n\t\t\t\t\tif (result && result instanceof Response) {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\n\t\t\t\t\tinternalContext.context.returned = result.response;\n\t\t\t\t\tinternalContext.context.responseHeaders = result.headers;\n\n\t\t\t\t\t// const after = await runAfterHooks(internalContext, afterHooks);\n\n\t\t\t\t\t// if (after.response) {\n\t\t\t\t\t// \tresult.response = after.response;\n\t\t\t\t\t// }\n\n\t\t\t\t\t// if (\n\t\t\t\t\t// \tisAPIError(result.response) &&\n\t\t\t\t\t// \tshouldPublishLog(authContext.logger.level, \"debug\")\n\t\t\t\t\t// ) {\n\t\t\t\t\t// \t// inherit stack from errorStack if debug mode is enabled\n\t\t\t\t\t// \tresult.response.stack = result.response.errorStack;\n\t\t\t\t\t// }\n\n\t\t\t\t\t// if (isAPIError(result.response) && !context?.asResponse) {\n\t\t\t\t\t// \tthrow result.response;\n\t\t\t\t\t// }\n\n\t\t\t\t\tconst response = context?.asResponse\n\t\t\t\t\t\t? toResponse(result.response, {\n\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\tstatus: result.status,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: context?.returnHeaders\n\t\t\t\t\t\t\t? context?.returnStatus\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: result.response,\n\t\t\t\t\t\t\t\t\t\tstatus: result.status,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: result.response,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: context?.returnStatus\n\t\t\t\t\t\t\t\t? { response: result.response, status: result.status }\n\t\t\t\t\t\t\t\t: result.response;\n\t\t\t\t\treturn response;\n\t\t\t\t});\n\t\t\t};\n\t\t\tif (await hasRequestState()) {\n\t\t\t\treturn run();\n\t\t\t} else {\n\t\t\t\tconst store = new WeakMap();\n\t\t\t\treturn runWithRequestState(store, run);\n\t\t\t}\n\t\t};\n\t\tapi[key].path = endpoint.path;\n\t\tapi[key].options = endpoint.options;\n\t}\n\treturn api as unknown as E;\n}\nexport function getEndpoints<Option extends PecuniaOptions>(\n\tctx: Awaitable<PecuniaContext>,\n\toptions: Option,\n) {\n\tconst pluginEndpoints =\n\t\toptions.plugins?.reduce<Record<string, Endpoint>>((acc, plugin) => {\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t...plugin.endpoints,\n\t\t\t};\n\t\t}, {}) ?? {};\n\n\ttype PluginEndpoint = UnionToIntersection<\n\t\tOption[\"plugins\"] extends Array<infer T>\n\t\t\t? T extends PecuniaPlugin\n\t\t\t\t? T extends {\n\t\t\t\t\t\tendpoints: infer E;\n\t\t\t\t\t}\n\t\t\t\t\t? E\n\t\t\t\t\t: {}\n\t\t\t\t: {}\n\t\t\t: {}\n\t>;\n\n\tconst middlewares =\n\t\toptions.plugins\n\t\t\t?.map((plugin) =>\n\t\t\t\tplugin.middlewares?.map((m) => {\n\t\t\t\t\tconst middleware = (async (context: any) => {\n\t\t\t\t\t\tconst authContext = await ctx;\n\t\t\t\t\t\treturn m.middleware({\n\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t...authContext,\n\t\t\t\t\t\t\t\t...context.context,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}) as Middleware;\n\t\t\t\t\tmiddleware.options = m.middleware.options;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: m.path,\n\t\t\t\t\t\tmiddleware,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.filter((plugin) => plugin !== undefined)\n\t\t\t.flat() || [];\n\n\tconst baseEndpoints = {};\n\tconst endpoints = {\n\t\t...baseEndpoints,\n\t\t...pluginEndpoints,\n\t} as const;\n\tconst api = toAuthEndpoints(endpoints, ctx);\n\treturn {\n\t\tapi: api as typeof endpoints & PluginEndpoint,\n\t\tmiddlewares,\n\t};\n}\n\nexport const router = <Option extends PecuniaOptions>(\n\tctx: PecuniaContext,\n\toptions: Option,\n) => {\n\tconst { api, middlewares } = getEndpoints(ctx, options);\n\tconst basePath = new URL(ctx.baseURL).pathname;\n\n\treturn createRouter(api, {\n\t\trouterContext: ctx,\n\t\topenapi: {\n\t\t\tdisabled: true,\n\t\t},\n\t\tbasePath,\n\t\trouterMiddleware: [\n\t\t\t{\n\t\t\t\tpath: \"/**\",\n\t\t\t\tmiddleware: [],\n\t\t\t},\n\t\t\t...middlewares,\n\t\t],\n\t\tallowedMediaTypes: [\"application/json\"],\n\t\tasync onRequest(req) {\n\t\t\tlet currentRequest = req;\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onRequest) {\n\t\t\t\t\tconst response = await plugin.onRequest(currentRequest, ctx);\n\t\t\t\t\tif (response && \"response\" in response) {\n\t\t\t\t\t\treturn response.response;\n\t\t\t\t\t}\n\t\t\t\t\tif (response && \"request\" in response) {\n\t\t\t\t\t\tcurrentRequest = response.request;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// const rateLimitResponse = await onRequestRateLimit(currentRequest, ctx);\n\t\t\t// if (rateLimitResponse) {\n\t\t\t// \treturn rateLimitResponse;\n\t\t\t// }\n\n\t\t\treturn currentRequest;\n\t\t},\n\t\tasync onResponse(res) {\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onResponse) {\n\t\t\t\t\tconst response = await plugin.onResponse(res, ctx);\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\treturn response.response;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tonError(e) {\n\t\t\t// if (isAPIError(e) && e.status === \"FOUND\") {\n\t\t\t// \treturn;\n\t\t\t// }\n\n\t\t\t// const optLogLevel = options.logger?.level;\n\t\t\t// const log =\n\t\t\t// \toptLogLevel === \"error\" ||\n\t\t\t// \toptLogLevel === \"warn\" ||\n\t\t\t// \toptLogLevel === \"debug\"\n\t\t\t// \t\t? logger\n\t\t\t// \t\t: undefined;\n\t\t\t// if (options.logger?.disabled !== true) {\n\t\t\t// \tif (\n\t\t\t// \t\te &&\n\t\t\t// \t\ttypeof e === \"object\" &&\n\t\t\t// \t\t\"message\" in e &&\n\t\t\t// \t\ttypeof e.message === \"string\"\n\t\t\t// \t) {\n\t\t\t// \t\tif (\n\t\t\t// \t\t\te.message.includes(\"no column\") ||\n\t\t\t// \t\t\te.message.includes(\"column\") ||\n\t\t\t// \t\t\te.message.includes(\"relation\") ||\n\t\t\t// \t\t\te.message.includes(\"table\") ||\n\t\t\t// \t\t\te.message.includes(\"does not exist\")\n\t\t\t// \t\t) {\n\t\t\t// \t\t\tctx.logger?.error(e.message);\n\t\t\t// \t\t\treturn;\n\t\t\t// \t\t}\n\t\t\t// \t}\n\n\t\t\t// \tif (isAPIError(e)) {\n\t\t\t// \t\tif (e.status === \"INTERNAL_SERVER_ERROR\") {\n\t\t\t// \t\t\tctx.logger.error(e.status, e);\n\t\t\t// \t\t}\n\t\t\t// \t\tlog?.error(e.message);\n\t\t\t// \t} else {\n\t\t\t// \t\tctx.logger?.error(\n\t\t\t// \t\t\te && typeof e === \"object\" && \"name\" in e ? (e.name as string) : \"\",\n\t\t\t// \t\t\te,\n\t\t\t// \t\t);\n\t\t\t// \t}\n\t\t\t// }\n\t\t},\n\t});\n};"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/api/index.ts"],"sourcesContent":["import { type PecuniaEndpoint, type Awaitable, type PecuniaContext, type PecuniaOptions, type PecuniaMiddleware, runWithEndpointContext, type PecuniaPlugin, hasRequestState, runWithRequestState } from \"pecunia-core\";\nimport type {\n Endpoint,\n\tEndpointContext,\n\tEndpointOptions,\n\tInputContext,\n Middleware,\n UnionToIntersection,\n} from \"better-call\";\nimport { createRouter, toResponse } from \"better-call\";\nimport { createDefu } from \"defu\";\n\ntype InternalContext = Partial<\n\tInputContext<string, any> & EndpointContext<string, any>\n> & {\n\tpath: string;\n\tasResponse?: boolean | undefined;\n\tcontext: PecuniaContext & {\n\t\t// logger: PecuniaContext[\"logger\"];\n\t\treturned?: unknown | undefined;\n\t\tresponseHeaders?: Headers | undefined;\n\t};\n};\n\nconst defuReplaceArrays = createDefu((obj, key, value) => {\n\tif (Array.isArray(obj[key]) && Array.isArray(value)) {\n\t\tobj[key] = value;\n\t\treturn true;\n\t}\n});\n\nconst hooksSourceWeakMap = new WeakMap<\n\tPecuniaMiddleware,\n\t`user` | `plugin:${string}`\n>();\n\ntype UserInputContext = Partial<\n\tInputContext<string, any> & EndpointContext<string, any>\n >;\n\nexport function toAuthEndpoints<\n\tconst E extends Record<\n\t\tstring,\n\t\tOmit<PecuniaEndpoint<string, EndpointOptions, any>, \"wrap\">\n\t>,\n>(endpoints: E, ctx: PecuniaContext | Promise<PecuniaContext>): E {\n\tconst api: Record<\n\t\tstring,\n\t\t((\n\t\t\tcontext: EndpointContext<string, any> & InputContext<string, any>,\n\t\t) => Promise<any>) & {\n\t\t\tpath?: string | undefined;\n\t\t\toptions?: EndpointOptions | undefined;\n\t\t}\n\t> = {};\n\n\tfor (const [key, endpoint] of Object.entries(endpoints)) {\n\t\tapi[key] = async (context?: UserInputContext) => {\n\t\t\tconst run = async () => {\n\t\t\t\tconst authContext = await ctx;\n\t\t\t\tlet internalContext: InternalContext = {\n\t\t\t\t\t...context,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\t...authContext,\n\t\t\t\t\t\treturned: undefined,\n\t\t\t\t\t\tresponseHeaders: undefined,\n\t\t\t\t\t\tsession: null,\n\t\t\t\t\t},\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\theaders: context?.headers ? new Headers(context?.headers) : undefined,\n\t\t\t\t};\n\t\t\t\treturn runWithEndpointContext(internalContext, async () => {\n\t\t\t\t\tinternalContext.asResponse = false;\n\t\t\t\t\tinternalContext.returnHeaders = true;\n\t\t\t\t\tinternalContext.returnStatus = true;\n\t\t\t\t\tconst result = (await runWithEndpointContext(internalContext, () =>\n\t\t\t\t\t\t(endpoint as any)(internalContext as any),\n\t\t\t\t\t).catch((e: any) => {\n\t\t\t\t\t\t// if (isAPIError(e)) {\n\t\t\t\t\t\t// \t/**\n\t\t\t\t\t\t// \t * API Errors from response are caught\n\t\t\t\t\t\t// \t * and returned to hooks\n\t\t\t\t\t\t// \t */\n\t\t\t\t\t\t// \treturn {\n\t\t\t\t\t\t// \t\tresponse: e,\n\t\t\t\t\t\t// \t\tstatus: e.statusCode,\n\t\t\t\t\t\t// \t\theaders: e.headers ? new Headers(e.headers) : null,\n\t\t\t\t\t\t// \t};\n\t\t\t\t\t\t// }\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t})) as {\n\t\t\t\t\t\theaders: Headers;\n\t\t\t\t\t\tresponse: any;\n\t\t\t\t\t\tstatus: number;\n\t\t\t\t\t};\n\n\t\t\t\t\t//if response object is returned we skip after hooks and post processing\n\t\t\t\t\tif (result && result instanceof Response) {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\n\t\t\t\t\tinternalContext.context.returned = result.response;\n\t\t\t\t\tinternalContext.context.responseHeaders = result.headers;\n\n\t\t\t\t\t// const after = await runAfterHooks(internalContext, afterHooks);\n\n\t\t\t\t\t// if (after.response) {\n\t\t\t\t\t// \tresult.response = after.response;\n\t\t\t\t\t// }\n\n\t\t\t\t\t// if (\n\t\t\t\t\t// \tisAPIError(result.response) &&\n\t\t\t\t\t// \tshouldPublishLog(authContext.logger.level, \"debug\")\n\t\t\t\t\t// ) {\n\t\t\t\t\t// \t// inherit stack from errorStack if debug mode is enabled\n\t\t\t\t\t// \tresult.response.stack = result.response.errorStack;\n\t\t\t\t\t// }\n\n\t\t\t\t\t// if (isAPIError(result.response) && !context?.asResponse) {\n\t\t\t\t\t// \tthrow result.response;\n\t\t\t\t\t// }\n\n\t\t\t\t\tconst response = context?.asResponse\n\t\t\t\t\t\t? toResponse(result.response, {\n\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\tstatus: result.status,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: context?.returnHeaders\n\t\t\t\t\t\t\t? context?.returnStatus\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: result.response,\n\t\t\t\t\t\t\t\t\t\tstatus: result.status,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: result.response,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: context?.returnStatus\n\t\t\t\t\t\t\t\t? { response: result.response, status: result.status }\n\t\t\t\t\t\t\t\t: result.response;\n\t\t\t\t\treturn response;\n\t\t\t\t});\n\t\t\t};\n\t\t\tif (await hasRequestState()) {\n\t\t\t\treturn run();\n\t\t\t} else {\n\t\t\t\tconst store = new WeakMap();\n\t\t\t\treturn runWithRequestState(store, run);\n\t\t\t}\n\t\t};\n\t\tapi[key].path = endpoint.path;\n\t\tapi[key].options = endpoint.options;\n\t}\n\treturn api as unknown as E;\n}\nexport function getEndpoints<Option extends PecuniaOptions>(\n\tctx: Awaitable<PecuniaContext>,\n\toptions: Option,\n) {\n\tconst pluginEndpoints =\n\t\toptions.plugins?.reduce<Record<string, Endpoint>>((acc, plugin) => {\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t...plugin.endpoints,\n\t\t\t};\n\t\t}, {}) ?? {};\n\n\ttype PluginEndpoint = UnionToIntersection<\n\t\tOption[\"plugins\"] extends Array<infer T>\n\t\t\t? T extends PecuniaPlugin\n\t\t\t\t? T extends {\n\t\t\t\t\t\tendpoints: infer E;\n\t\t\t\t\t}\n\t\t\t\t\t? E\n\t\t\t\t\t: {}\n\t\t\t\t: {}\n\t\t\t: {}\n\t>;\n\n\tconst middlewares =\n\t\toptions.plugins\n\t\t\t?.map((plugin) =>\n\t\t\t\tplugin.middlewares?.map((m) => {\n\t\t\t\t\tconst middleware = (async (context: any) => {\n\t\t\t\t\t\tconst authContext = await ctx;\n\t\t\t\t\t\treturn m.middleware({\n\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t...authContext,\n\t\t\t\t\t\t\t\t...context.context,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}) as Middleware;\n\t\t\t\t\tmiddleware.options = m.middleware.options;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: m.path,\n\t\t\t\t\t\tmiddleware,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.filter((plugin) => plugin !== undefined)\n\t\t\t.flat() || [];\n\n\tconst baseEndpoints = {};\n\tconst endpoints = {\n\t\t...baseEndpoints,\n\t\t...pluginEndpoints,\n\t} as const;\n\tconst api = toAuthEndpoints(endpoints, ctx);\n\treturn {\n\t\tapi: api as typeof endpoints & PluginEndpoint,\n\t\tmiddlewares,\n\t};\n}\n\nexport const router = <Option extends PecuniaOptions>(\n\tctx: PecuniaContext,\n\toptions: Option,\n) => {\n\tconst { api, middlewares } = getEndpoints(ctx, options);\n\tconst basePath = new URL(ctx.baseURL).pathname;\n\n\treturn createRouter(api, {\n\t\trouterContext: ctx,\n\t\topenapi: {\n\t\t\tdisabled: true,\n\t\t},\n\t\tbasePath,\n\t\trouterMiddleware: [\n\t\t\t{\n\t\t\t\tpath: \"/**\",\n\t\t\t\tmiddleware: [],\n\t\t\t},\n\t\t\t...middlewares,\n\t\t],\n\t\tallowedMediaTypes: [\"application/json\"],\n\t\tasync onRequest(req) {\n\t\t\tlet currentRequest = req;\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onRequest) {\n\t\t\t\t\tconst response = await plugin.onRequest(currentRequest, ctx);\n\t\t\t\t\tif (response && \"response\" in response) {\n\t\t\t\t\t\treturn response.response;\n\t\t\t\t\t}\n\t\t\t\t\tif (response && \"request\" in response) {\n\t\t\t\t\t\tcurrentRequest = response.request;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// const rateLimitResponse = await onRequestRateLimit(currentRequest, ctx);\n\t\t\t// if (rateLimitResponse) {\n\t\t\t// \treturn rateLimitResponse;\n\t\t\t// }\n\n\t\t\treturn currentRequest;\n\t\t},\n\t\tasync onResponse(res) {\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onResponse) {\n\t\t\t\t\tconst response = await plugin.onResponse(res, ctx);\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\treturn response.response;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tonError(e) {\n\t\t\t// if (isAPIError(e) && e.status === \"FOUND\") {\n\t\t\t// \treturn;\n\t\t\t// }\n\n\t\t\t// const optLogLevel = options.logger?.level;\n\t\t\t// const log =\n\t\t\t// \toptLogLevel === \"error\" ||\n\t\t\t// \toptLogLevel === \"warn\" ||\n\t\t\t// \toptLogLevel === \"debug\"\n\t\t\t// \t\t? logger\n\t\t\t// \t\t: undefined;\n\t\t\t// if (options.logger?.disabled !== true) {\n\t\t\t// \tif (\n\t\t\t// \t\te &&\n\t\t\t// \t\ttypeof e === \"object\" &&\n\t\t\t// \t\t\"message\" in e &&\n\t\t\t// \t\ttypeof e.message === \"string\"\n\t\t\t// \t) {\n\t\t\t// \t\tif (\n\t\t\t// \t\t\te.message.includes(\"no column\") ||\n\t\t\t// \t\t\te.message.includes(\"column\") ||\n\t\t\t// \t\t\te.message.includes(\"relation\") ||\n\t\t\t// \t\t\te.message.includes(\"table\") ||\n\t\t\t// \t\t\te.message.includes(\"does not exist\")\n\t\t\t// \t\t) {\n\t\t\t// \t\t\tctx.logger?.error(e.message);\n\t\t\t// \t\t\treturn;\n\t\t\t// \t\t}\n\t\t\t// \t}\n\n\t\t\t// \tif (isAPIError(e)) {\n\t\t\t// \t\tif (e.status === \"INTERNAL_SERVER_ERROR\") {\n\t\t\t// \t\t\tctx.logger.error(e.status, e);\n\t\t\t// \t\t}\n\t\t\t// \t\tlog?.error(e.message);\n\t\t\t// \t} else {\n\t\t\t// \t\tctx.logger?.error(\n\t\t\t// \t\t\te && typeof e === \"object\" && \"name\" in e ? (e.name as string) : \"\",\n\t\t\t// \t\t\te,\n\t\t\t// \t\t);\n\t\t\t// \t}\n\t\t\t// }\n\t\t},\n\t});\n};"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["context: PecuniaContext","result: ReturnType<Required<PecuniaPlugin>[\"init\"]>"],"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,IAAIA,UAA0B;AAC9B,MAAK,MAAM,UAAU,QACpB,KAAI,OAAO,MAAM;EAChB,IAAI,cAAc,OAAO,KAAK,QAAQ;EACtC,IAAIC;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,IAAID;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/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 +1 @@
1
- {"version":3,"file":"index.mjs","names":["types: Partial<DbTypeBuckets>","toBeCreated: {\n table: string;\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }[]","toBeAdded: {\n table: string;\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }[]","toBeAddedFields: Record<string, DBFieldAttribute>","migrations: (\n | AlterTableColumnAlteringBuilder\n | ReturnType<AlterTableBuilder[\"addIndex\"]>\n | CreateTableBuilder<string, string>\n | CreateIndexBuilder\n )[]","typeMap: Record<\n StringOnlyUnion<DBFieldType> | \"id\" | \"foreignKeyId\",\n Record<KyselyDatabaseDialectType, ColumnDataType | RawBuilder<unknown>>\n >","toBeIndexed: CreateIndexBuilder[]"],"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/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 +1 @@
1
- {"version":3,"file":"get-schema.mjs","names":["schema: Record<\n string,\n {\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }\n >","actualFields: Record<string, DBFieldAttribute>","key"],"sources":["../../../src/db/schema/get-schema.ts"],"sourcesContent":["import { getPaymentTables } from \"pecunia-core\";\nimport type { PecuniaOptions } from \"pecunia-core\";\nimport type { DBFieldAttribute } from \"pecunia-core\";\n\nexport function getSchema(config: PecuniaOptions) {\n const tables = getPaymentTables(config);\n let schema: Record<\n string,\n {\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }\n > = {};\n for (const key in tables) {\n const table = tables[key]!;\n const fields = table.fields;\n let actualFields: Record<string, DBFieldAttribute> = {};\n Object.entries(fields).forEach(([key, field]) => {\n actualFields[field.fieldName || key] = field;\n if (field.references) {\n const refTable = tables[field.references.model];\n if (refTable) {\n actualFields[field.fieldName || key]!.references = {\n ...field.references,\n model: refTable.modelName,\n field: field.references.field,\n };\n }\n }\n });\n if (schema[table.modelName]) {\n schema[table.modelName]!.fields = {\n ...schema[table.modelName]!.fields,\n ...actualFields,\n };\n continue;\n }\n schema[table.modelName] = {\n fields: actualFields,\n order: table.order || Infinity,\n };\n }\n return schema;\n}\n"],"mappings":";;;AAIA,SAAgB,UAAU,QAAwB;CAChD,MAAM,SAAS,iBAAiB,OAAO;CACvC,IAAIA,SAMA,EAAE;AACN,MAAK,MAAM,OAAO,QAAQ;EACxB,MAAM,QAAQ,OAAO;EACrB,MAAM,SAAS,MAAM;EACrB,IAAIC,eAAiD,EAAE;AACvD,SAAO,QAAQ,OAAO,CAAC,SAAS,CAACC,OAAK,WAAW;AAC/C,gBAAa,MAAM,aAAaA,SAAO;AACvC,OAAI,MAAM,YAAY;IACpB,MAAM,WAAW,OAAO,MAAM,WAAW;AACzC,QAAI,SACF,cAAa,MAAM,aAAaA,OAAM,aAAa;KACjD,GAAG,MAAM;KACT,OAAO,SAAS;KAChB,OAAO,MAAM,WAAW;KACzB;;IAGL;AACF,MAAI,OAAO,MAAM,YAAY;AAC3B,UAAO,MAAM,WAAY,SAAS;IAChC,GAAG,OAAO,MAAM,WAAY;IAC5B,GAAG;IACJ;AACD;;AAEF,SAAO,MAAM,aAAa;GACxB,QAAQ;GACR,OAAO,MAAM,SAAS;GACvB;;AAEH,QAAO"}
1
+ {"version":3,"file":"get-schema.mjs","names":["key"],"sources":["../../../src/db/schema/get-schema.ts"],"sourcesContent":["import { getPaymentTables } from \"pecunia-core\";\nimport type { PecuniaOptions } from \"pecunia-core\";\nimport type { DBFieldAttribute } from \"pecunia-core\";\n\nexport function getSchema(config: PecuniaOptions) {\n const tables = getPaymentTables(config);\n let schema: Record<\n string,\n {\n fields: Record<string, DBFieldAttribute>;\n order: number;\n }\n > = {};\n for (const key in tables) {\n const table = tables[key]!;\n const fields = table.fields;\n let actualFields: Record<string, DBFieldAttribute> = {};\n Object.entries(fields).forEach(([key, field]) => {\n actualFields[field.fieldName || key] = field;\n if (field.references) {\n const refTable = tables[field.references.model];\n if (refTable) {\n actualFields[field.fieldName || key]!.references = {\n ...field.references,\n model: refTable.modelName,\n field: field.references.field,\n };\n }\n }\n });\n if (schema[table.modelName]) {\n schema[table.modelName]!.fields = {\n ...schema[table.modelName]!.fields,\n ...actualFields,\n };\n continue;\n }\n schema[table.modelName] = {\n fields: actualFields,\n order: table.order || Infinity,\n };\n }\n return schema;\n}\n"],"mappings":";;;AAIA,SAAgB,UAAU,QAAwB;CAChD,MAAM,SAAS,iBAAiB,OAAO;CACvC,IAAI,SAMA,EAAE;AACN,MAAK,MAAM,OAAO,QAAQ;EACxB,MAAM,QAAQ,OAAO;EACrB,MAAM,SAAS,MAAM;EACrB,IAAI,eAAiD,EAAE;AACvD,SAAO,QAAQ,OAAO,CAAC,SAAS,CAACA,OAAK,WAAW;AAC/C,gBAAa,MAAM,aAAaA,SAAO;AACvC,OAAI,MAAM,YAAY;IACpB,MAAM,WAAW,OAAO,MAAM,WAAW;AACzC,QAAI,SACF,cAAa,MAAM,aAAaA,OAAM,aAAa;KACjD,GAAG,MAAM;KACT,OAAO,SAAS;KAChB,OAAO,MAAM,WAAW;KACzB;;IAGL;AACF,MAAI,OAAO,MAAM,YAAY;AAC3B,UAAO,MAAM,WAAY,SAAS;IAChC,GAAG,OAAO,MAAM,WAAY;IAC5B,GAAG;IACJ;AACD;;AAEF,SAAO,MAAM,aAAa;GACxB,QAAQ;GACR,OAAO,MAAM,SAAS;GACvB;;AAEH,QAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pecunia-root",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -11,7 +11,7 @@
11
11
  "prepare": "",
12
12
  "typecheck": "tsc --project tsconfig.json"
13
13
  },
14
- "files": [
14
+ "files": [
15
15
  "dist"
16
16
  ],
17
17
  "main": "./dist/index.mjs",
@@ -74,18 +74,12 @@
74
74
  "*": [
75
75
  "./dist/index.d.mts"
76
76
  ],
77
- "minimal": [
78
- "./dist/auth/minimal.d.mts"
79
- ],
80
77
  "node": [
81
78
  "./dist/integrations/node.d.mts"
82
79
  ],
83
80
  "types": [
84
81
  "./dist/types/index.d.mts"
85
82
  ],
86
- "crypto": [
87
- "./dist/crypto/index.d.mts"
88
- ],
89
83
  "api": [
90
84
  "./dist/api/index.d.mts"
91
85
  ],
@@ -96,27 +90,25 @@
96
90
  "./dist/adapters/index.d.mts"
97
91
  ],
98
92
  "adapters/prisma": [
99
- "./dist/adapters/prisma-adapter/index.d.mts"
93
+ "./dist/adapters/prisma/index.d.mts"
100
94
  ],
101
95
  "adapters/drizzle": [
102
- "./dist/adapters/drizzle-adapter/index.d.mts"
96
+ "./dist/adapters/drizzle/index.d.mts"
103
97
  ],
104
98
  "adapters/mongodb": [
105
- "./dist/adapters/mongodb-adapter/index.d.mts"
99
+ "./dist/adapters/mongodb/index.d.mts"
106
100
  ]
107
101
  }
108
102
  },
109
103
  "dependencies": {
110
- "pecunia-core": "workspace:*",
111
- "@better-auth/utils": "catalog:",
112
- "@better-fetch/fetch": "catalog:",
113
104
  "@noble/ciphers": "^2.0.0",
114
105
  "@noble/hashes": "^2.0.0",
115
- "better-call": "catalog:",
106
+ "better-call": "^1.1.8",
116
107
  "defu": "^6.1.4",
117
108
  "jose": "^6.1.0",
118
109
  "kysely": "^0.28.5",
119
110
  "nanostores": "^1.0.1",
111
+ "pecunia-core": "^0.0.2",
120
112
  "zod": "^4.1.12"
121
113
  },
122
114
  "devDependencies": {
@@ -137,9 +129,9 @@
137
129
  "prisma": "^5.22.0",
138
130
  "tarn": "^3.0.2",
139
131
  "tedious": "^18.6.1",
140
- "tsdown": "catalog:",
132
+ "tsdown": "^0.19.0",
141
133
  "type-fest": "^5.2.0",
142
- "typescript": "catalog:",
134
+ "typescript": "^5.9.3",
143
135
  "vitest": "^4.0.15"
144
136
  },
145
137
  "peerDependencies": {