{"version":3,"file":"sqlite.mjs","names":[],"sources":["../../src/storage/sqlite.ts"],"sourcesContent":["import path from \"node:path\";\nimport { DatabaseSync, type StatementSync } from \"node:sqlite\";\nimport type {\n\tCustomObject,\n\tInvalidInputError,\n\tProject,\n} from \"@commercetools/platform-sdk\";\nimport { CommercetoolsError } from \"#src/exceptions.ts\";\nimport { cloneObject } from \"../helpers.ts\";\nimport { parseQueryExpression } from \"../lib/predicateParser.ts\";\nimport { applySort } from \"../lib/sortParser.ts\";\nimport type {\n\tPagedQueryResponseMap,\n\tResourceMap,\n\tResourceType,\n} from \"../types.ts\";\nimport type { GetParams, QueryParams } from \"./abstract.ts\";\nimport { AbstractStorage } from \"./abstract.ts\";\n\nexport type SQLiteStorageOptions = {\n\t/**\n\t * Path to the SQLite database file.\n\t * Defaults to `commercetools-mock.db` in the current working directory.\n\t * Use `':memory:'` for an in-memory database.\n\t */\n\tfilename?: string;\n};\n\nconst DEFAULT_PROJECT: Omit<Project, \"key\"> = {\n\tname: \"\",\n\tcountries: [],\n\tcurrencies: [],\n\tlanguages: [],\n\tcreatedAt: \"2018-10-04T11:32:12.603Z\",\n\ttrialUntil: \"2018-12\",\n\tcarts: {\n\t\tcountryTaxRateFallbackEnabled: false,\n\t\tdeleteDaysAfterLastModification: 90,\n\t\tpriceRoundingMode: \"HalfEven\",\n\t\ttaxRoundingMode: \"HalfEven\",\n\t},\n\tshoppingLists: {\n\t\tdeleteDaysAfterLastModification: 360,\n\t},\n\tmessages: { enabled: false, deleteDaysAfterCreation: 15 },\n\tinventory: { releaseExpiredReservations: false },\n\tshippingRateInputType: undefined,\n\texternalOAuth: undefined,\n\tsearchIndexing: {\n\t\tproducts: {\n\t\t\tstatus: \"Deactivated\",\n\t\t},\n\t\tproductsSearch: {\n\t\t\tstatus: \"Deactivated\",\n\t\t},\n\t\torders: {\n\t\t\tstatus: \"Deactivated\",\n\t\t},\n\t\tcustomers: {\n\t\t\tstatus: \"Deactivated\",\n\t\t},\n\t\tbusinessUnits: {\n\t\t\tstatus: \"Deactivated\",\n\t\t},\n\t},\n\tdiscounts: {\n\t\tdiscountCombinationMode: \"Stacking\",\n\t},\n\tversion: 1,\n};\n\nconst SCHEMA = `\n  CREATE TABLE IF NOT EXISTS projects (\n    project_key TEXT PRIMARY KEY,\n    data TEXT NOT NULL\n  );\n\n  CREATE TABLE IF NOT EXISTS resources (\n    project_key TEXT NOT NULL,\n    type_id TEXT NOT NULL,\n    id TEXT NOT NULL,\n    key TEXT,\n    data TEXT NOT NULL,\n    PRIMARY KEY (project_key, type_id, id)\n  );\n\n  CREATE INDEX IF NOT EXISTS idx_resources_key\n    ON resources (project_key, type_id, key) WHERE key IS NOT NULL;\n\n  CREATE INDEX IF NOT EXISTS idx_resources_container_key\n    ON resources (\n      project_key,\n      json_extract(data, '$.container'),\n      json_extract(data, '$.key')\n    )\n    WHERE type_id = 'key-value-document';\n`;\n\nexport class SQLiteStorage extends AbstractStorage {\n\tprivate db: DatabaseSync;\n\n\t// Cache of known project keys to avoid redundant INSERT+SELECT on every add()\n\tprivate _knownProjects: Set<string> = new Set();\n\n\t// Prepared statements (lazily created)\n\tprivate _stmtInsertProject: StatementSync | null = null;\n\tprivate _stmtGetProject: StatementSync | null = null;\n\tprivate _stmtUpsertProject: StatementSync | null = null;\n\tprivate _stmtInsertResource: StatementSync | null = null;\n\tprivate _stmtGetResource: StatementSync | null = null;\n\tprivate _stmtGetResourceByKey: StatementSync | null = null;\n\tprivate _stmtAllResources: StatementSync | null = null;\n\tprivate _stmtDeleteResource: StatementSync | null = null;\n\tprivate _stmtClearResources: StatementSync | null = null;\n\tprivate _stmtGetResourceByContainerAndKey: StatementSync | null = null;\n\tprivate _stmtCountResources: StatementSync | null = null;\n\n\tconstructor(options: SQLiteStorageOptions = {}) {\n\t\tsuper();\n\n\t\tconst filename =\n\t\t\toptions.filename ?? path.join(process.cwd(), \"commercetools-mock.db\");\n\n\t\tthis.db = new DatabaseSync(filename);\n\t\tthis.db.exec(SCHEMA);\n\t}\n\n\t/**\n\t * Close the database connection. Call this when you're done using the storage.\n\t */\n\toverride close(): void {\n\t\tif (this.db.isOpen) {\n\t\t\tthis.db.close();\n\t\t}\n\t}\n\n\tprivate get stmtInsertProject() {\n\t\tif (!this._stmtInsertProject) {\n\t\t\tthis._stmtInsertProject = this.db.prepare(\n\t\t\t\t\"INSERT OR IGNORE INTO projects (project_key, data) VALUES (?, ?)\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtInsertProject;\n\t}\n\n\tprivate get stmtGetProject() {\n\t\tif (!this._stmtGetProject) {\n\t\t\tthis._stmtGetProject = this.db.prepare(\n\t\t\t\t\"SELECT data FROM projects WHERE project_key = ?\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtGetProject;\n\t}\n\n\tprivate get stmtUpsertProject() {\n\t\tif (!this._stmtUpsertProject) {\n\t\t\tthis._stmtUpsertProject = this.db.prepare(\n\t\t\t\t\"INSERT OR REPLACE INTO projects (project_key, data) VALUES (?, ?)\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtUpsertProject;\n\t}\n\n\tprivate get stmtInsertResource() {\n\t\tif (!this._stmtInsertResource) {\n\t\t\tthis._stmtInsertResource = this.db.prepare(\n\t\t\t\t\"INSERT OR REPLACE INTO resources (project_key, type_id, id, key, data) VALUES (?, ?, ?, ?, ?)\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtInsertResource;\n\t}\n\n\tprivate get stmtGetResource() {\n\t\tif (!this._stmtGetResource) {\n\t\t\tthis._stmtGetResource = this.db.prepare(\n\t\t\t\t\"SELECT data FROM resources WHERE project_key = ? AND type_id = ? AND id = ?\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtGetResource;\n\t}\n\n\tprivate get stmtGetResourceByKey() {\n\t\tif (!this._stmtGetResourceByKey) {\n\t\t\tthis._stmtGetResourceByKey = this.db.prepare(\n\t\t\t\t\"SELECT data FROM resources WHERE project_key = ? AND type_id = ? AND key = ?\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtGetResourceByKey;\n\t}\n\n\tprivate get stmtAllResources() {\n\t\tif (!this._stmtAllResources) {\n\t\t\tthis._stmtAllResources = this.db.prepare(\n\t\t\t\t\"SELECT data FROM resources WHERE project_key = ? AND type_id = ?\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtAllResources;\n\t}\n\n\tprivate get stmtCountResources() {\n\t\tif (!this._stmtCountResources) {\n\t\t\tthis._stmtCountResources = this.db.prepare(\n\t\t\t\t\"SELECT COUNT(*) as cnt FROM resources WHERE project_key = ? AND type_id = ?\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtCountResources;\n\t}\n\n\tprivate get stmtDeleteResource() {\n\t\tif (!this._stmtDeleteResource) {\n\t\t\tthis._stmtDeleteResource = this.db.prepare(\n\t\t\t\t\"DELETE FROM resources WHERE project_key = ? AND type_id = ? AND id = ?\",\n\t\t\t);\n\t\t}\n\t\treturn this._stmtDeleteResource;\n\t}\n\n\tprivate get stmtClearResources() {\n\t\tif (!this._stmtClearResources) {\n\t\t\tthis._stmtClearResources = this.db.prepare(\"DELETE FROM resources\");\n\t\t}\n\t\treturn this._stmtClearResources;\n\t}\n\n\tprivate get stmtGetResourceByContainerAndKey() {\n\t\tif (!this._stmtGetResourceByContainerAndKey) {\n\t\t\tthis._stmtGetResourceByContainerAndKey = this.db.prepare(\n\t\t\t\t`SELECT data FROM resources\n\t\t\t\t WHERE project_key = ?\n\t\t\t\t   AND type_id = 'key-value-document'\n\t\t\t\t   AND json_extract(data, '$.container') = ?\n\t\t\t\t   AND json_extract(data, '$.key') = ?`,\n\t\t\t);\n\t\t}\n\t\treturn this._stmtGetResourceByContainerAndKey;\n\t}\n\n\tprivate ensureProject(projectKey: string): void {\n\t\tif (this._knownProjects.has(projectKey)) {\n\t\t\treturn;\n\t\t}\n\t\tconst project: Project = { ...DEFAULT_PROJECT, key: projectKey };\n\t\tthis.stmtInsertProject.run(projectKey, JSON.stringify(project));\n\t\tthis._knownProjects.add(projectKey);\n\t}\n\n\tasync addProject(projectKey: string): Promise<Project> {\n\t\tthis.ensureProject(projectKey);\n\n\t\tconst row = this.stmtGetProject.get(projectKey) as\n\t\t\t| { data: string }\n\t\t\t| undefined;\n\t\tif (!row) {\n\t\t\tthrow new Error(`Failed to create project ${projectKey}`);\n\t\t}\n\t\treturn JSON.parse(row.data) as Project;\n\t}\n\n\tasync getProject(projectKey: string): Promise<Project> {\n\t\treturn this.addProject(projectKey);\n\t}\n\n\tasync saveProject(project: Project): Promise<Project> {\n\t\tthis.stmtUpsertProject.run(project.key, JSON.stringify(project));\n\t\treturn project;\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tthis.stmtClearResources.run();\n\t\tthis._knownProjects.clear();\n\t}\n\n\tasync all<RT extends ResourceType>(\n\t\tprojectKey: string,\n\t\ttypeId: RT,\n\t): Promise<ResourceMap[RT][]> {\n\t\tconst rows = this.stmtAllResources.all(projectKey, typeId) as Array<{\n\t\t\tdata: string;\n\t\t}>;\n\t\treturn rows.map((row) => JSON.parse(row.data) as ResourceMap[RT]);\n\t}\n\n\tasync count(projectKey: string, typeId: ResourceType): Promise<number> {\n\t\tconst row = this.stmtCountResources.get(projectKey, typeId) as\n\t\t\t| { cnt: number }\n\t\t\t| undefined;\n\t\treturn row?.cnt ?? 0;\n\t}\n\n\tasync add<RT extends ResourceType>(\n\t\tprojectKey: string,\n\t\ttypeId: RT,\n\t\tobj: ResourceMap[RT],\n\t\tparams: GetParams = {},\n\t): Promise<ResourceMap[RT]> {\n\t\t// Ensure the project exists (cached, no DB round-trip after first call)\n\t\tthis.ensureProject(projectKey);\n\n\t\tconst key = (obj as any).key ?? null;\n\n\t\tthis.stmtInsertResource.run(\n\t\t\tprojectKey,\n\t\t\ttypeId,\n\t\t\tobj.id,\n\t\t\tkey,\n\t\t\tJSON.stringify(obj),\n\t\t);\n\n\t\t// Return a clone instead of the caller's reference so that expand()\n\t\t// can safely mutate it without affecting the caller's object.\n\t\tconst clone = cloneObject(obj);\n\t\treturn this.expand(projectKey, clone, params.expand);\n\t}\n\n\tasync get<RT extends ResourceType>(\n\t\tprojectKey: string,\n\t\ttypeId: RT,\n\t\tid: string,\n\t\tparams: GetParams = {},\n\t): Promise<ResourceMap[RT] | null> {\n\t\tconst row = this.stmtGetResource.get(projectKey, typeId, id) as\n\t\t\t| { data: string }\n\t\t\t| undefined;\n\t\tif (row) {\n\t\t\tconst resource = JSON.parse(row.data) as ResourceMap[RT];\n\t\t\treturn this.expand(projectKey, resource, params.expand);\n\t\t}\n\t\treturn null;\n\t}\n\n\tasync getByKey<RT extends ResourceType>(\n\t\tprojectKey: string,\n\t\ttypeId: RT,\n\t\tkey: string,\n\t\tparams: GetParams = {},\n\t): Promise<ResourceMap[RT] | null> {\n\t\tconst row = this.stmtGetResourceByKey.get(projectKey, typeId, key) as\n\t\t\t| { data: string }\n\t\t\t| undefined;\n\t\tif (row) {\n\t\t\tconst resource = JSON.parse(row.data) as ResourceMap[RT];\n\t\t\treturn this.expand(projectKey, resource, params.expand);\n\t\t}\n\t\treturn null;\n\t}\n\n\tasync delete<RT extends ResourceType>(\n\t\tprojectKey: string,\n\t\ttypeId: RT,\n\t\tid: string,\n\t\tparams: GetParams = {},\n\t): Promise<ResourceMap[RT] | null> {\n\t\tconst resource = await this.get(projectKey, typeId, id);\n\t\tif (resource) {\n\t\t\tthis.stmtDeleteResource.run(projectKey, typeId, id);\n\t\t\treturn this.expand(projectKey, resource, params.expand);\n\t\t}\n\t\treturn null;\n\t}\n\n\tasync getByContainerAndKey(\n\t\tprojectKey: string,\n\t\tcontainer: string,\n\t\tkey: string,\n\t): Promise<CustomObject | null> {\n\t\tconst row = this.stmtGetResourceByContainerAndKey.get(\n\t\t\tprojectKey,\n\t\t\tcontainer,\n\t\t\tkey,\n\t\t) as { data: string } | undefined;\n\t\tif (row) {\n\t\t\treturn JSON.parse(row.data) as CustomObject;\n\t\t}\n\t\treturn null;\n\t}\n\n\tasync query<RT extends ResourceType>(\n\t\tprojectKey: string,\n\t\ttypeId: RT,\n\t\tparams: QueryParams,\n\t): Promise<PagedQueryResponseMap[RT]> {\n\t\tlet resources = await this.all<RT>(projectKey, typeId);\n\n\t\t// Apply predicates\n\t\tif (params.where) {\n\t\t\tconst vars = Object.fromEntries(\n\t\t\t\tObject.entries(params)\n\t\t\t\t\t.filter(([key]) => key.startsWith(\"var.\"))\n\t\t\t\t\t.map(([key, value]) => [key.slice(4), value]),\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst filterFunc = parseQueryExpression(params.where);\n\t\t\t\tresources = resources.filter((resource) => filterFunc(resource, vars));\n\t\t\t} catch (err) {\n\t\t\t\tthrow new CommercetoolsError<InvalidInputError>(\n\t\t\t\t\t{\n\t\t\t\t\t\tcode: \"InvalidInput\",\n\t\t\t\t\t\tmessage: (err as any).message,\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Apply sorting before paging: a cursor-based pager (`where id > \"...\"`\n\t\t// with `sort id asc`) depends on a deterministic order.\n\t\tresources = applySort(resources, params.sort);\n\n\t\t// Get the total before slicing the array\n\t\tconst totalResources = resources.length;\n\n\t\t// Apply offset, limit\n\t\tconst offset = params.offset || 0;\n\t\tconst limit = params.limit || 20;\n\t\tresources = resources.slice(offset, offset + limit);\n\n\t\t// Expand the resources\n\t\tif (params.expand !== undefined) {\n\t\t\tresources = await Promise.all(\n\t\t\t\tresources.map((resource) =>\n\t\t\t\t\tthis.expand(projectKey, resource, params.expand),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tcount: resources.length,\n\t\t\ttotal: totalResources,\n\t\t\toffset: offset,\n\t\t\tlimit: limit,\n\t\t\tresults: resources,\n\t\t} as PagedQueryResponseMap[RT];\n\t}\n}\n"],"mappings":"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"}