@warlock.js/cascade 5.24.0 → 5.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +30 -5
  2. package/README.md +101 -101
  3. package/bin/cascade.js +0 -0
  4. package/cjs/index.cjs +307 -88
  5. package/cjs/index.cjs.map +1 -1
  6. package/esm/contracts/database-driver.contract.d.mts +22 -1
  7. package/esm/contracts/database-driver.contract.d.mts.map +1 -1
  8. package/esm/contracts/index.d.mts +1 -1
  9. package/esm/contracts/query-builder.contract.d.mts +7 -0
  10. package/esm/contracts/query-builder.contract.d.mts.map +1 -1
  11. package/esm/data-source/data-source-registry.d.mts +8 -6
  12. package/esm/data-source/data-source-registry.d.mts.map +1 -1
  13. package/esm/data-source/data-source-registry.mjs +7 -1
  14. package/esm/data-source/data-source-registry.mjs.map +1 -1
  15. package/esm/drivers/mongodb/mongodb-driver.d.mts +13 -0
  16. package/esm/drivers/mongodb/mongodb-driver.d.mts.map +1 -1
  17. package/esm/drivers/mongodb/mongodb-driver.mjs +71 -2
  18. package/esm/drivers/mongodb/mongodb-driver.mjs.map +1 -1
  19. package/esm/drivers/mongodb/mongodb-query-builder.d.mts +5 -0
  20. package/esm/drivers/mongodb/mongodb-query-builder.d.mts.map +1 -1
  21. package/esm/drivers/mongodb/mongodb-query-builder.mjs +11 -1
  22. package/esm/drivers/mongodb/mongodb-query-builder.mjs.map +1 -1
  23. package/esm/drivers/postgres/postgres-driver.d.mts +9 -0
  24. package/esm/drivers/postgres/postgres-driver.d.mts.map +1 -1
  25. package/esm/drivers/postgres/postgres-driver.mjs +55 -7
  26. package/esm/drivers/postgres/postgres-driver.mjs.map +1 -1
  27. package/esm/drivers/postgres/postgres-query-builder.d.mts +5 -0
  28. package/esm/drivers/postgres/postgres-query-builder.d.mts.map +1 -1
  29. package/esm/drivers/postgres/postgres-query-builder.mjs +15 -0
  30. package/esm/drivers/postgres/postgres-query-builder.mjs.map +1 -1
  31. package/esm/drivers/postgres/postgres-query-parser.d.mts +1 -4
  32. package/esm/drivers/postgres/postgres-query-parser.d.mts.map +1 -1
  33. package/esm/drivers/postgres/postgres-query-parser.mjs +4 -5
  34. package/esm/drivers/postgres/postgres-query-parser.mjs.map +1 -1
  35. package/esm/errors/unsafe-filter.error.mjs.map +1 -1
  36. package/esm/errors/unsafe-raw-expression.error.mjs.map +1 -1
  37. package/esm/errors/unsupported-lock-for-update.error.d.mts +11 -0
  38. package/esm/errors/unsupported-lock-for-update.error.d.mts.map +1 -0
  39. package/esm/errors/unsupported-lock-for-update.error.mjs +16 -0
  40. package/esm/errors/unsupported-lock-for-update.error.mjs.map +1 -0
  41. package/esm/events/model-events.mjs.map +1 -1
  42. package/esm/index.d.mts +4 -3
  43. package/esm/index.mjs +2 -1
  44. package/esm/migration/index.d.mts +1 -1
  45. package/esm/migration/migration-order.mjs +6 -3
  46. package/esm/migration/migration-order.mjs.map +1 -1
  47. package/esm/migration/migration-runner.d.mts +5 -3
  48. package/esm/migration/migration-runner.d.mts.map +1 -1
  49. package/esm/migration/migration-runner.mjs +3 -2
  50. package/esm/migration/migration-runner.mjs.map +1 -1
  51. package/esm/migration/migration.d.mts +11 -1
  52. package/esm/migration/migration.d.mts.map +1 -1
  53. package/esm/migration/migration.mjs +45 -2
  54. package/esm/migration/migration.mjs.map +1 -1
  55. package/esm/migration/sql-grammar.mjs.map +1 -1
  56. package/esm/model/generate-model-id.mjs +23 -0
  57. package/esm/model/generate-model-id.mjs.map +1 -0
  58. package/esm/model/methods/delete-methods.mjs.map +1 -1
  59. package/esm/model/methods/meta-methods.mjs.map +1 -1
  60. package/esm/model/methods/query-methods.mjs +38 -11
  61. package/esm/model/methods/query-methods.mjs.map +1 -1
  62. package/esm/model/methods/write-methods.mjs.map +1 -1
  63. package/esm/model/model.d.mts +2 -2
  64. package/esm/model/model.d.mts.map +1 -1
  65. package/esm/model/model.mjs +1 -1
  66. package/esm/model/model.mjs.map +1 -1
  67. package/esm/query-builder/query-builder.d.mts +5 -0
  68. package/esm/query-builder/query-builder.d.mts.map +1 -1
  69. package/esm/query-builder/query-builder.mjs +16 -1
  70. package/esm/query-builder/query-builder.mjs.map +1 -1
  71. package/esm/utils/sanitize-filter.mjs.map +1 -1
  72. package/esm/validation/plugins/database-rules-plugin.mjs.map +1 -1
  73. package/esm/writer/database-writer.d.mts +0 -33
  74. package/esm/writer/database-writer.d.mts.map +1 -1
  75. package/esm/writer/database-writer.mjs +3 -52
  76. package/esm/writer/database-writer.mjs.map +1 -1
  77. package/llms-full.txt +2911 -2864
  78. package/package.json +5 -5
  79. package/skills/aggregate-data/SKILL.md +165 -165
  80. package/skills/alter-migration/SKILL.md +531 -531
  81. package/skills/configure-delete-strategy/SKILL.md +130 -130
  82. package/skills/define-model/SKILL.md +205 -205
  83. package/skills/define-relations/SKILL.md +171 -171
  84. package/skills/manage-data-sources/SKILL.md +177 -140
  85. package/skills/manage-transactions/SKILL.md +215 -205
  86. package/skills/paginate-results/SKILL.md +122 -122
  87. package/skills/perform-atomic-ops/SKILL.md +156 -156
  88. package/skills/query-data/SKILL.md +213 -213
  89. package/skills/run-cascade-cli/SKILL.md +125 -125
  90. package/skills/search-by-vector/SKILL.md +127 -127
  91. package/skills/subscribe-to-model-events/SKILL.md +148 -148
  92. package/skills/track-changes/SKILL.md +127 -127
  93. package/skills/write-migration/SKILL.md +206 -206
@@ -1 +1 @@
1
- {"version":3,"file":"sql-grammar.mjs","names":[],"sources":["../../../../../../../cascade/src/migration/sql-grammar.ts"],"sourcesContent":["import { compareCreatedAt } from \"./parse-created-at\";\r\nimport type { SQLStatementType, TaggedSQL } from \"./types\";\r\n\r\n/**\r\n * Parses and sorts SQL statements globally based on their execution phase,\r\n * and classifies statements by their semantic type.\r\n */\r\nexport class SQLGrammar {\r\n /**\r\n * Determine the execution phase of a SQL statement (1–6).\r\n *\r\n * Phase ordering ensures DDL operations run in dependency-safe order\r\n * regardless of which migration file they originate from.\r\n *\r\n * | Phase | Statements |\r\n * |-------|-----------------------------------------------|\r\n * | 1 | CREATE EXTENSION, TYPE, DOMAIN, SCHEMA |\r\n * | 2 | CREATE TABLE |\r\n * | 3 | ADD COLUMN, ADD PRIMARY KEY |\r\n * | 4 | CREATE INDEX, ADD FOREIGN KEY |\r\n * | 5 | DROP COLUMN, ALTER COLUMN, DROP TABLE |\r\n * | 6 | Raw / unclassified |\r\n *\r\n * @example\r\n * SQLGrammar.phase(\"CREATE EXTENSION IF NOT EXISTS vector\"); // => 1\r\n * SQLGrammar.phase(\"ALTER TABLE users ADD COLUMN email TEXT\"); // => 3\r\n */\r\n public static phase(sql: string): 1 | 2 | 3 | 4 | 5 | 6 {\r\n const s = sql.trim().toUpperCase();\r\n\r\n // Phase 1: Preparation (Extensions, Enums, Domains, Types)\r\n if (\r\n s.startsWith(\"CREATE EXTENSION\") ||\r\n s.startsWith(\"CREATE TYPE\") ||\r\n s.startsWith(\"CREATE DOMAIN\") ||\r\n s.startsWith(\"CREATE SCHEMA\")\r\n ) {\r\n return 1;\r\n }\r\n\r\n // Phase 2: Table Creation\r\n if (s.startsWith(\"CREATE TABLE\")) {\r\n return 2;\r\n }\r\n\r\n // Phase 3 / 4 / 5: ALTER TABLE — broken down by clause\r\n if (s.startsWith(\"ALTER TABLE\")) {\r\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"FOREIGN KEY\")) return 4;\r\n if (s.includes(\"DROP COLUMN\") || s.includes(\"DROP CONSTRAINT\") || s.includes(\"ALTER COLUMN\")) return 5;\r\n if (s.includes(\"ADD COLUMN\")) return 3;\r\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"PRIMARY KEY\")) return 3;\r\n }\r\n\r\n // Phase 4: Index Creation\r\n if (s.startsWith(\"CREATE INDEX\") || s.startsWith(\"CREATE UNIQUE INDEX\")) {\r\n return 4;\r\n }\r\n\r\n // Phase 5: Destructive table/index operations\r\n if (s.startsWith(\"DROP TABLE\") || s.startsWith(\"TRUNCATE TABLE\") || s.startsWith(\"DROP INDEX\")) {\r\n return 5;\r\n }\r\n\r\n // Phase 6: Raw / unclassified (DML, triggers, procedures, views)\r\n return 6;\r\n }\r\n\r\n /**\r\n * Classify a SQL statement into its semantic statement type.\r\n *\r\n * This is independent of execution phase — it identifies *what* a statement\r\n * does, not *when* it should run. Use this for pre-flight checks, dry-run\r\n * display, selective filtering, and extension detection.\r\n *\r\n * @example\r\n * SQLGrammar.classify(\"CREATE EXTENSION IF NOT EXISTS vector\");\r\n * // => \"CREATE_EXTENSION\"\r\n *\r\n * SQLGrammar.classify(\"ALTER TABLE users ADD COLUMN email TEXT\");\r\n * // => \"ADD_COLUMN\"\r\n */\r\n public static classify(sql: string): SQLStatementType {\r\n const s = sql.trim().toUpperCase();\r\n\r\n if (s.startsWith(\"CREATE EXTENSION\")) return \"CREATE_EXTENSION\";\r\n if (s.startsWith(\"CREATE SCHEMA\")) return \"CREATE_SCHEMA\";\r\n if (s.startsWith(\"CREATE TYPE\")) return \"CREATE_TYPE\";\r\n if (s.startsWith(\"CREATE DOMAIN\")) return \"CREATE_DOMAIN\";\r\n if (s.startsWith(\"CREATE TABLE\")) return \"CREATE_TABLE\";\r\n if (s.startsWith(\"DROP TABLE\")) return \"DROP_TABLE\";\r\n if (s.startsWith(\"TRUNCATE TABLE\")) return \"TRUNCATE_TABLE\";\r\n if (s.startsWith(\"DROP INDEX\")) return \"DROP_INDEX\";\r\n\r\n // Must check UNIQUE before plain INDEX to avoid misclassification\r\n if (s.startsWith(\"CREATE UNIQUE INDEX\")) return \"CREATE_UNIQUE_INDEX\";\r\n if (s.startsWith(\"CREATE INDEX\")) return \"CREATE_INDEX\";\r\n\r\n if (s.startsWith(\"ALTER TABLE\")) {\r\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"FOREIGN KEY\")) return \"ADD_FOREIGN_KEY\";\r\n if (s.includes(\"DROP CONSTRAINT\") && s.includes(\"FOREIGN KEY\")) return \"DROP_FOREIGN_KEY\";\r\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"PRIMARY KEY\")) return \"ADD_PRIMARY_KEY\";\r\n if (s.includes(\"DROP CONSTRAINT\")) return \"DROP_PRIMARY_KEY\";\r\n if (s.includes(\"ADD COLUMN\")) return \"ADD_COLUMN\";\r\n if (s.includes(\"DROP COLUMN\")) return \"DROP_COLUMN\";\r\n if (s.includes(\"RENAME COLUMN\")) return \"RENAME_COLUMN\";\r\n if (s.includes(\"RENAME TO\")) return \"RENAME_TABLE\";\r\n if (s.includes(\"ALTER COLUMN\")) return \"MODIFY_COLUMN\";\r\n }\r\n\r\n return \"RAW\";\r\n }\r\n\r\n /**\r\n * Extract the extension name from a CREATE EXTENSION statement.\r\n *\r\n * Returns undefined if the statement is not a CREATE EXTENSION statement\r\n * or the name cannot be parsed.\r\n *\r\n * @example\r\n * SQLGrammar.extractExtensionName(\"CREATE EXTENSION IF NOT EXISTS vector\");\r\n * // => \"vector\"\r\n *\r\n * SQLGrammar.extractExtensionName(\"CREATE EXTENSION postgis\");\r\n * // => \"postgis\"\r\n */\r\n public static extractExtensionName(sql: string): string | undefined {\r\n // Matches: CREATE EXTENSION [IF NOT EXISTS] <name>\r\n const match = sql\r\n .trim()\r\n .match(/^CREATE\\s+EXTENSION\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(\\w+)/i);\r\n\r\n return match?.[1]?.toLowerCase();\r\n }\r\n\r\n /**\r\n * Sort an array of tagged SQL statements by phase, then creation date, then migration name.\r\n *\r\n * This is the sort that decides **execution order** — it runs across every\r\n * pending migration's statements at once, after the migration list itself\r\n * has been ordered, so whatever it decides is final.\r\n *\r\n * The creation date must go through {@link compareCreatedAt}. Parsing these\r\n * stamps with `new Date()` returns `Invalid Date` for the framework's own\r\n * `MM-DD-YYYY_HH-MM-SS` filename format, which collapsed every timestamp to\r\n * the same value and quietly handed the whole ordering to the alphabetical\r\n * tiebreaker below — running, for example, a January 2026 migration before a\r\n * December 2025 one.\r\n */\r\n public static sort(statements: TaggedSQL[]): TaggedSQL[] {\r\n return statements.slice().sort((a, b) => {\r\n // 1. Sort by Phase (ascending)\r\n if (a.phase !== b.phase) {\r\n return a.phase - b.phase;\r\n }\r\n\r\n // 2. Sort by CreatedAt (within same phase)\r\n const byCreatedAt = compareCreatedAt(a.createdAt, b.createdAt);\r\n\r\n if (byCreatedAt !== undefined) {\r\n return byCreatedAt;\r\n }\r\n\r\n // 3. Sort by Migration Name (tie-breaker)\r\n const nameA = a.migrationName || \"\";\r\n const nameB = b.migrationName || \"\";\r\n return nameA.localeCompare(nameB);\r\n });\r\n }\r\n}\r\n"],"mappings":";;;;;;;AAOA,IAAa,aAAb,MAAwB;;;;;;;;;;;;;;;;;;;;CAoBtB,OAAc,MAAM,KAAoC;EACtD,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,YAAY;EAGjC,IACE,EAAE,WAAW,kBAAkB,KAC/B,EAAE,WAAW,aAAa,KAC1B,EAAE,WAAW,eAAe,KAC5B,EAAE,WAAW,eAAe,GAE5B,OAAO;EAIT,IAAI,EAAE,WAAW,cAAc,GAC7B,OAAO;EAIT,IAAI,EAAE,WAAW,aAAa,GAAG;GAC/B,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACtE,IAAI,EAAE,SAAS,aAAa,KAAK,EAAE,SAAS,iBAAiB,KAAK,EAAE,SAAS,cAAc,GAAG,OAAO;GACrG,IAAI,EAAE,SAAS,YAAY,GAAG,OAAO;GACrC,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;EACxE;EAGA,IAAI,EAAE,WAAW,cAAc,KAAK,EAAE,WAAW,qBAAqB,GACpE,OAAO;EAIT,IAAI,EAAE,WAAW,YAAY,KAAK,EAAE,WAAW,gBAAgB,KAAK,EAAE,WAAW,YAAY,GAC3F,OAAO;EAIT,OAAO;CACT;;;;;;;;;;;;;;;CAgBA,OAAc,SAAS,KAA+B;EACpD,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,YAAY;EAEjC,IAAI,EAAE,WAAW,kBAAkB,GAAG,OAAO;EAC7C,IAAI,EAAE,WAAW,eAAe,GAAG,OAAO;EAC1C,IAAI,EAAE,WAAW,aAAa,GAAG,OAAO;EACxC,IAAI,EAAE,WAAW,eAAe,GAAG,OAAO;EAC1C,IAAI,EAAE,WAAW,cAAc,GAAG,OAAO;EACzC,IAAI,EAAE,WAAW,YAAY,GAAG,OAAO;EACvC,IAAI,EAAE,WAAW,gBAAgB,GAAG,OAAO;EAC3C,IAAI,EAAE,WAAW,YAAY,GAAG,OAAO;EAGvC,IAAI,EAAE,WAAW,qBAAqB,GAAG,OAAO;EAChD,IAAI,EAAE,WAAW,cAAc,GAAG,OAAO;EAEzC,IAAI,EAAE,WAAW,aAAa,GAAG;GAC/B,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACtE,IAAI,EAAE,SAAS,iBAAiB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACvE,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACtE,IAAI,EAAE,SAAS,iBAAiB,GAAG,OAAO;GAC1C,IAAI,EAAE,SAAS,YAAY,GAAG,OAAO;GACrC,IAAI,EAAE,SAAS,aAAa,GAAG,OAAO;GACtC,IAAI,EAAE,SAAS,eAAe,GAAG,OAAO;GACxC,IAAI,EAAE,SAAS,WAAW,GAAG,OAAO;GACpC,IAAI,EAAE,SAAS,cAAc,GAAG,OAAO;EACzC;EAEA,OAAO;CACT;;;;;;;;;;;;;;CAeA,OAAc,qBAAqB,KAAiC;EAMlE,OAJc,IACX,KAAK,CAAC,CACN,MAAM,uDAEE,CAAC,GAAG,EAAE,EAAE,YAAY;CACjC;;;;;;;;;;;;;;;CAgBA,OAAc,KAAK,YAAsC;EACvD,OAAO,WAAW,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM;GAEvC,IAAI,EAAE,UAAU,EAAE,OAChB,OAAO,EAAE,QAAQ,EAAE;GAIrB,MAAM,cAAc,iBAAiB,EAAE,WAAW,EAAE,SAAS;GAE7D,IAAI,gBAAgB,QAClB,OAAO;GAIT,MAAM,QAAQ,EAAE,iBAAiB;GACjC,MAAM,QAAQ,EAAE,iBAAiB;GACjC,OAAO,MAAM,cAAc,KAAK;EAClC,CAAC;CACH;AACF"}
1
+ {"version":3,"file":"sql-grammar.mjs","names":[],"sources":["../../../../../../../cascade/src/migration/sql-grammar.ts"],"sourcesContent":["import { compareCreatedAt } from \"./parse-created-at\";\nimport type { SQLStatementType, TaggedSQL } from \"./types\";\n\n/**\n * Parses and sorts SQL statements globally based on their execution phase,\n * and classifies statements by their semantic type.\n */\nexport class SQLGrammar {\n /**\n * Determine the execution phase of a SQL statement (1–6).\n *\n * Phase ordering ensures DDL operations run in dependency-safe order\n * regardless of which migration file they originate from.\n *\n * | Phase | Statements |\n * |-------|-----------------------------------------------|\n * | 1 | CREATE EXTENSION, TYPE, DOMAIN, SCHEMA |\n * | 2 | CREATE TABLE |\n * | 3 | ADD COLUMN, ADD PRIMARY KEY |\n * | 4 | CREATE INDEX, ADD FOREIGN KEY |\n * | 5 | DROP COLUMN, ALTER COLUMN, DROP TABLE |\n * | 6 | Raw / unclassified |\n *\n * @example\n * SQLGrammar.phase(\"CREATE EXTENSION IF NOT EXISTS vector\"); // => 1\n * SQLGrammar.phase(\"ALTER TABLE users ADD COLUMN email TEXT\"); // => 3\n */\n public static phase(sql: string): 1 | 2 | 3 | 4 | 5 | 6 {\n const s = sql.trim().toUpperCase();\n\n // Phase 1: Preparation (Extensions, Enums, Domains, Types)\n if (\n s.startsWith(\"CREATE EXTENSION\") ||\n s.startsWith(\"CREATE TYPE\") ||\n s.startsWith(\"CREATE DOMAIN\") ||\n s.startsWith(\"CREATE SCHEMA\")\n ) {\n return 1;\n }\n\n // Phase 2: Table Creation\n if (s.startsWith(\"CREATE TABLE\")) {\n return 2;\n }\n\n // Phase 3 / 4 / 5: ALTER TABLE — broken down by clause\n if (s.startsWith(\"ALTER TABLE\")) {\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"FOREIGN KEY\")) return 4;\n if (s.includes(\"DROP COLUMN\") || s.includes(\"DROP CONSTRAINT\") || s.includes(\"ALTER COLUMN\")) return 5;\n if (s.includes(\"ADD COLUMN\")) return 3;\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"PRIMARY KEY\")) return 3;\n }\n\n // Phase 4: Index Creation\n if (s.startsWith(\"CREATE INDEX\") || s.startsWith(\"CREATE UNIQUE INDEX\")) {\n return 4;\n }\n\n // Phase 5: Destructive table/index operations\n if (s.startsWith(\"DROP TABLE\") || s.startsWith(\"TRUNCATE TABLE\") || s.startsWith(\"DROP INDEX\")) {\n return 5;\n }\n\n // Phase 6: Raw / unclassified (DML, triggers, procedures, views)\n return 6;\n }\n\n /**\n * Classify a SQL statement into its semantic statement type.\n *\n * This is independent of execution phase — it identifies *what* a statement\n * does, not *when* it should run. Use this for pre-flight checks, dry-run\n * display, selective filtering, and extension detection.\n *\n * @example\n * SQLGrammar.classify(\"CREATE EXTENSION IF NOT EXISTS vector\");\n * // => \"CREATE_EXTENSION\"\n *\n * SQLGrammar.classify(\"ALTER TABLE users ADD COLUMN email TEXT\");\n * // => \"ADD_COLUMN\"\n */\n public static classify(sql: string): SQLStatementType {\n const s = sql.trim().toUpperCase();\n\n if (s.startsWith(\"CREATE EXTENSION\")) return \"CREATE_EXTENSION\";\n if (s.startsWith(\"CREATE SCHEMA\")) return \"CREATE_SCHEMA\";\n if (s.startsWith(\"CREATE TYPE\")) return \"CREATE_TYPE\";\n if (s.startsWith(\"CREATE DOMAIN\")) return \"CREATE_DOMAIN\";\n if (s.startsWith(\"CREATE TABLE\")) return \"CREATE_TABLE\";\n if (s.startsWith(\"DROP TABLE\")) return \"DROP_TABLE\";\n if (s.startsWith(\"TRUNCATE TABLE\")) return \"TRUNCATE_TABLE\";\n if (s.startsWith(\"DROP INDEX\")) return \"DROP_INDEX\";\n\n // Must check UNIQUE before plain INDEX to avoid misclassification\n if (s.startsWith(\"CREATE UNIQUE INDEX\")) return \"CREATE_UNIQUE_INDEX\";\n if (s.startsWith(\"CREATE INDEX\")) return \"CREATE_INDEX\";\n\n if (s.startsWith(\"ALTER TABLE\")) {\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"FOREIGN KEY\")) return \"ADD_FOREIGN_KEY\";\n if (s.includes(\"DROP CONSTRAINT\") && s.includes(\"FOREIGN KEY\")) return \"DROP_FOREIGN_KEY\";\n if (s.includes(\"ADD CONSTRAINT\") && s.includes(\"PRIMARY KEY\")) return \"ADD_PRIMARY_KEY\";\n if (s.includes(\"DROP CONSTRAINT\")) return \"DROP_PRIMARY_KEY\";\n if (s.includes(\"ADD COLUMN\")) return \"ADD_COLUMN\";\n if (s.includes(\"DROP COLUMN\")) return \"DROP_COLUMN\";\n if (s.includes(\"RENAME COLUMN\")) return \"RENAME_COLUMN\";\n if (s.includes(\"RENAME TO\")) return \"RENAME_TABLE\";\n if (s.includes(\"ALTER COLUMN\")) return \"MODIFY_COLUMN\";\n }\n\n return \"RAW\";\n }\n\n /**\n * Extract the extension name from a CREATE EXTENSION statement.\n *\n * Returns undefined if the statement is not a CREATE EXTENSION statement\n * or the name cannot be parsed.\n *\n * @example\n * SQLGrammar.extractExtensionName(\"CREATE EXTENSION IF NOT EXISTS vector\");\n * // => \"vector\"\n *\n * SQLGrammar.extractExtensionName(\"CREATE EXTENSION postgis\");\n * // => \"postgis\"\n */\n public static extractExtensionName(sql: string): string | undefined {\n // Matches: CREATE EXTENSION [IF NOT EXISTS] <name>\n const match = sql\n .trim()\n .match(/^CREATE\\s+EXTENSION\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(\\w+)/i);\n\n return match?.[1]?.toLowerCase();\n }\n\n /**\n * Sort an array of tagged SQL statements by phase, then creation date, then migration name.\n *\n * This is the sort that decides **execution order** — it runs across every\n * pending migration's statements at once, after the migration list itself\n * has been ordered, so whatever it decides is final.\n *\n * The creation date must go through {@link compareCreatedAt}. Parsing these\n * stamps with `new Date()` returns `Invalid Date` for the framework's own\n * `MM-DD-YYYY_HH-MM-SS` filename format, which collapsed every timestamp to\n * the same value and quietly handed the whole ordering to the alphabetical\n * tiebreaker below — running, for example, a January 2026 migration before a\n * December 2025 one.\n */\n public static sort(statements: TaggedSQL[]): TaggedSQL[] {\n return statements.slice().sort((a, b) => {\n // 1. Sort by Phase (ascending)\n if (a.phase !== b.phase) {\n return a.phase - b.phase;\n }\n\n // 2. Sort by CreatedAt (within same phase)\n const byCreatedAt = compareCreatedAt(a.createdAt, b.createdAt);\n\n if (byCreatedAt !== undefined) {\n return byCreatedAt;\n }\n\n // 3. Sort by Migration Name (tie-breaker)\n const nameA = a.migrationName || \"\";\n const nameB = b.migrationName || \"\";\n return nameA.localeCompare(nameB);\n });\n }\n}\n"],"mappings":";;;;;;;AAOA,IAAa,aAAb,MAAwB;;;;;;;;;;;;;;;;;;;;CAoBtB,OAAc,MAAM,KAAoC;EACtD,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,YAAY;EAGjC,IACE,EAAE,WAAW,kBAAkB,KAC/B,EAAE,WAAW,aAAa,KAC1B,EAAE,WAAW,eAAe,KAC5B,EAAE,WAAW,eAAe,GAE5B,OAAO;EAIT,IAAI,EAAE,WAAW,cAAc,GAC7B,OAAO;EAIT,IAAI,EAAE,WAAW,aAAa,GAAG;GAC/B,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACtE,IAAI,EAAE,SAAS,aAAa,KAAK,EAAE,SAAS,iBAAiB,KAAK,EAAE,SAAS,cAAc,GAAG,OAAO;GACrG,IAAI,EAAE,SAAS,YAAY,GAAG,OAAO;GACrC,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;EACxE;EAGA,IAAI,EAAE,WAAW,cAAc,KAAK,EAAE,WAAW,qBAAqB,GACpE,OAAO;EAIT,IAAI,EAAE,WAAW,YAAY,KAAK,EAAE,WAAW,gBAAgB,KAAK,EAAE,WAAW,YAAY,GAC3F,OAAO;EAIT,OAAO;CACT;;;;;;;;;;;;;;;CAgBA,OAAc,SAAS,KAA+B;EACpD,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,YAAY;EAEjC,IAAI,EAAE,WAAW,kBAAkB,GAAG,OAAO;EAC7C,IAAI,EAAE,WAAW,eAAe,GAAG,OAAO;EAC1C,IAAI,EAAE,WAAW,aAAa,GAAG,OAAO;EACxC,IAAI,EAAE,WAAW,eAAe,GAAG,OAAO;EAC1C,IAAI,EAAE,WAAW,cAAc,GAAG,OAAO;EACzC,IAAI,EAAE,WAAW,YAAY,GAAG,OAAO;EACvC,IAAI,EAAE,WAAW,gBAAgB,GAAG,OAAO;EAC3C,IAAI,EAAE,WAAW,YAAY,GAAG,OAAO;EAGvC,IAAI,EAAE,WAAW,qBAAqB,GAAG,OAAO;EAChD,IAAI,EAAE,WAAW,cAAc,GAAG,OAAO;EAEzC,IAAI,EAAE,WAAW,aAAa,GAAG;GAC/B,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACtE,IAAI,EAAE,SAAS,iBAAiB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACvE,IAAI,EAAE,SAAS,gBAAgB,KAAK,EAAE,SAAS,aAAa,GAAG,OAAO;GACtE,IAAI,EAAE,SAAS,iBAAiB,GAAG,OAAO;GAC1C,IAAI,EAAE,SAAS,YAAY,GAAG,OAAO;GACrC,IAAI,EAAE,SAAS,aAAa,GAAG,OAAO;GACtC,IAAI,EAAE,SAAS,eAAe,GAAG,OAAO;GACxC,IAAI,EAAE,SAAS,WAAW,GAAG,OAAO;GACpC,IAAI,EAAE,SAAS,cAAc,GAAG,OAAO;EACzC;EAEA,OAAO;CACT;;;;;;;;;;;;;;CAeA,OAAc,qBAAqB,KAAiC;EAMlE,OAJc,IACX,KAAK,CAAC,CACN,MAAM,uDAEE,CAAC,GAAG,EAAE,EAAE,YAAY;CACjC;;;;;;;;;;;;;;;CAgBA,OAAc,KAAK,YAAsC;EACvD,OAAO,WAAW,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM;GAEvC,IAAI,EAAE,UAAU,EAAE,OAChB,OAAO,EAAE,QAAQ,EAAE;GAIrB,MAAM,cAAc,iBAAiB,EAAE,WAAW,EAAE,SAAS;GAE7D,IAAI,gBAAgB,QAClB,OAAO;GAIT,MAAM,QAAQ,EAAE,iBAAiB;GACjC,MAAM,QAAQ,EAAE,iBAAiB;GACjC,OAAO,MAAM,cAAc,KAAK;EAClC,CAAC;CACH;AACF"}
@@ -0,0 +1,23 @@
1
+ //#region ../cascade/src/model/generate-model-id.ts
2
+ /**
3
+ * Generate the next model id using the model's configured sequence options.
4
+ *
5
+ * This is shared by normal inserts and MongoDB upserts so both write paths
6
+ * resolve random and configured sequence settings identically.
7
+ */
8
+ async function generateModelId(ModelClass) {
9
+ const idGenerator = ModelClass.getDataSource().idGenerator;
10
+ if (!idGenerator) return;
11
+ const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
12
+ const initialId = ModelClass.initialId ? ModelClass.initialId : ModelClass.randomInitialId ? typeof ModelClass.randomInitialId === "function" ? ModelClass.randomInitialId() : randomInt(1e4, 499999) : 1;
13
+ const incrementIdBy = ModelClass.randomIncrement ? typeof ModelClass.randomIncrement === "function" ? ModelClass.randomIncrement() : randomInt(1, 10) : ModelClass.incrementIdBy || 1;
14
+ return await idGenerator.generateNextId({
15
+ table: ModelClass.table,
16
+ initialId,
17
+ incrementIdBy
18
+ });
19
+ }
20
+
21
+ //#endregion
22
+ export { generateModelId };
23
+ //# sourceMappingURL=generate-model-id.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-model-id.mjs","names":[],"sources":["../../../../../../../cascade/src/model/generate-model-id.ts"],"sourcesContent":["import type { ChildModel, Model } from \"./model\";\n\n/**\n * Generate the next model id using the model's configured sequence options.\n *\n * This is shared by normal inserts and MongoDB upserts so both write paths\n * resolve random and configured sequence settings identically.\n */\nexport async function generateModelId<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n): Promise<number | undefined> {\n const idGenerator = ModelClass.getDataSource().idGenerator;\n\n if (!idGenerator) {\n return undefined;\n }\n\n const randomInt = (min: number, max: number) =>\n Math.floor(Math.random() * (max - min + 1)) + min;\n const initialId = ModelClass.initialId\n ? ModelClass.initialId\n : ModelClass.randomInitialId\n ? typeof ModelClass.randomInitialId === \"function\"\n ? ModelClass.randomInitialId()\n : randomInt(10000, 499999)\n : 1;\n const incrementIdBy = ModelClass.randomIncrement\n ? typeof ModelClass.randomIncrement === \"function\"\n ? ModelClass.randomIncrement()\n : randomInt(1, 10)\n : ModelClass.incrementIdBy || 1;\n\n return await idGenerator.generateNextId({\n table: ModelClass.table,\n initialId,\n incrementIdBy,\n });\n}\n"],"mappings":";;;;;;;AAQA,eAAsB,gBACpB,YAC6B;CAC7B,MAAM,cAAc,WAAW,cAAc,CAAC,CAAC;CAE/C,IAAI,CAAC,aACH;CAGF,MAAM,aAAa,KAAa,QAC9B,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;CAChD,MAAM,YAAY,WAAW,YACzB,WAAW,YACX,WAAW,kBACT,OAAO,WAAW,oBAAoB,aACpC,WAAW,gBAAgB,IAC3B,UAAU,KAAO,MAAM,IACzB;CACN,MAAM,gBAAgB,WAAW,kBAC7B,OAAO,WAAW,oBAAoB,aACpC,WAAW,gBAAgB,IAC3B,UAAU,GAAG,EAAE,IACjB,WAAW,iBAAiB;CAEhC,OAAO,MAAM,YAAY,eAAe;EACtC,OAAO,WAAW;EAClB;EACA;CACF,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"delete-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/delete-methods.ts"],"sourcesContent":["import { DatabaseRemover } from \"../../remover/database-remover\";\r\nimport type { DeleteStrategy } from \"../../types\";\r\nimport type { RemoverResult } from \"../../contracts\";\r\nimport { sanitizeFilter } from \"../../utils/sanitize-filter\";\r\nimport type { ChildModel, Model } from \"../model\";\r\n\r\nexport async function destroyModel(\r\n model: Model,\r\n options?: { strategy?: DeleteStrategy; skipEvents?: boolean },\r\n): Promise<RemoverResult> {\r\n const remover = new DatabaseRemover(model);\r\n return remover.destroy(options);\r\n}\r\n\r\nexport async function deleteRecords(\r\n ModelClass: ChildModel<any>,\r\n filter?: Record<string, unknown>,\r\n): Promise<number> {\r\n const sanitized = filter ? sanitizeFilter(filter) : undefined;\r\n\r\n if (!sanitized || Object.keys(sanitized).length === 0) {\r\n throw new Error(\r\n `${ModelClass.name}.delete() requires a filter: pass an explicit filter, or use ${ModelClass.name}.deleteAll() / ${ModelClass.name}.query().delete() to delete every row.`,\r\n );\r\n }\r\n\r\n // Through the query builder so global scopes (tenant, soft delete) apply.\r\n return ModelClass.query().where(sanitized).delete();\r\n}\r\n\r\n/** Delete every row visible to the model's global scopes. Explicit on purpose. */\r\nexport async function deleteAllRecords(ModelClass: ChildModel<any>): Promise<number> {\r\n return ModelClass.query().delete();\r\n}\r\n\r\nexport async function deleteOneRecord(\r\n ModelClass: ChildModel<any>,\r\n filter?: Record<string, unknown>,\r\n): Promise<number> {\r\n const query = ModelClass.query();\r\n\r\n if (filter && Object.keys(filter).length > 0) {\r\n query.where(sanitizeFilter(filter));\r\n }\r\n\r\n return query.deleteOne();\r\n}\r\n"],"mappings":";;;;AAMA,eAAsB,aACpB,OACA,SACwB;CAExB,OAAO,IADa,gBAAgB,KACvB,CAAC,CAAC,QAAQ,OAAO;AAChC;AAEA,eAAsB,cACpB,YACA,QACiB;CACjB,MAAM,YAAY,SAAS,eAAe,MAAM,IAAI;CAEpD,IAAI,CAAC,aAAa,OAAO,KAAK,SAAS,CAAC,CAAC,WAAW,GAClD,MAAM,IAAI,MACR,GAAG,WAAW,KAAK,+DAA+D,WAAW,KAAK,iBAAiB,WAAW,KAAK,uCACrI;CAIF,OAAO,WAAW,MAAM,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,OAAO;AACpD;AAOA,eAAsB,gBACpB,YACA,QACiB;CACjB,MAAM,QAAQ,WAAW,MAAM;CAE/B,IAAI,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,GACzC,MAAM,MAAM,eAAe,MAAM,CAAC;CAGpC,OAAO,MAAM,UAAU;AACzB"}
1
+ {"version":3,"file":"delete-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/delete-methods.ts"],"sourcesContent":["import { DatabaseRemover } from \"../../remover/database-remover\";\nimport type { DeleteStrategy } from \"../../types\";\nimport type { RemoverResult } from \"../../contracts\";\nimport { sanitizeFilter } from \"../../utils/sanitize-filter\";\nimport type { ChildModel, Model } from \"../model\";\n\nexport async function destroyModel(\n model: Model,\n options?: { strategy?: DeleteStrategy; skipEvents?: boolean },\n): Promise<RemoverResult> {\n const remover = new DatabaseRemover(model);\n return remover.destroy(options);\n}\n\nexport async function deleteRecords(\n ModelClass: ChildModel<any>,\n filter?: Record<string, unknown>,\n): Promise<number> {\n const sanitized = filter ? sanitizeFilter(filter) : undefined;\n\n if (!sanitized || Object.keys(sanitized).length === 0) {\n throw new Error(\n `${ModelClass.name}.delete() requires a filter: pass an explicit filter, or use ${ModelClass.name}.deleteAll() / ${ModelClass.name}.query().delete() to delete every row.`,\n );\n }\n\n // Through the query builder so global scopes (tenant, soft delete) apply.\n return ModelClass.query().where(sanitized).delete();\n}\n\n/** Delete every row visible to the model's global scopes. Explicit on purpose. */\nexport async function deleteAllRecords(ModelClass: ChildModel<any>): Promise<number> {\n return ModelClass.query().delete();\n}\n\nexport async function deleteOneRecord(\n ModelClass: ChildModel<any>,\n filter?: Record<string, unknown>,\n): Promise<number> {\n const query = ModelClass.query();\n\n if (filter && Object.keys(filter).length > 0) {\n query.where(sanitizeFilter(filter));\n }\n\n return query.deleteOne();\n}\n"],"mappings":";;;;AAMA,eAAsB,aACpB,OACA,SACwB;CAExB,OAAO,IADa,gBAAgB,KACvB,CAAC,CAAC,QAAQ,OAAO;AAChC;AAEA,eAAsB,cACpB,YACA,QACiB;CACjB,MAAM,YAAY,SAAS,eAAe,MAAM,IAAI;CAEpD,IAAI,CAAC,aAAa,OAAO,KAAK,SAAS,CAAC,CAAC,WAAW,GAClD,MAAM,IAAI,MACR,GAAG,WAAW,KAAK,+DAA+D,WAAW,KAAK,iBAAiB,WAAW,KAAK,uCACrI;CAIF,OAAO,WAAW,MAAM,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,OAAO;AACpD;AAOA,eAAsB,gBACpB,YACA,QACiB;CACjB,MAAM,QAAQ,WAAW,MAAM;CAE/B,IAAI,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,GACzC,MAAM,MAAM,eAAe,MAAM,CAAC;CAGpC,OAAO,MAAM,UAAU;AACzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"meta-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/meta-methods.ts"],"sourcesContent":["import { get, set } from \"@mongez/reinforcements\";\r\nimport { DatabaseWriter } from \"../../writer/database-writer\";\r\nimport type { Model } from \"../model\";\r\n\r\n/**\r\n * Whether a subclass (or an intermediate base below `Model`) set the static\r\n * itself. The base `Model` initialises several statics (strictMode,\r\n * autoGenerateId, incrementIdBy, deletedAtColumn), so comparing to\r\n * `undefined` would never let data-source defaults apply.\r\n */\r\nfunction isExplicitStatic(ModelClass: any, key: string): boolean {\r\n let current = ModelClass;\r\n\r\n // The base Model is the class whose parent is `Function.prototype`; its own\r\n // initialisers are framework fallbacks, not explicit choices.\r\n while (current && Object.getPrototypeOf(current) !== Function.prototype) {\r\n if (Object.prototype.hasOwnProperty.call(current, key) && current[key] !== undefined) {\r\n return true;\r\n }\r\n\r\n current = Object.getPrototypeOf(current);\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function applyDefaultsToModel(ModelClass: any, defaults: any): void {\r\n // Only apply defaults if model doesn't have its own value\r\n\r\n // ============================================================================\r\n // ID Generation\r\n // ============================================================================\r\n if (defaults.autoGenerateId !== undefined && !isExplicitStatic(ModelClass, \"autoGenerateId\")) {\r\n ModelClass.autoGenerateId = defaults.autoGenerateId;\r\n }\r\n if (defaults.initialId !== undefined && !isExplicitStatic(ModelClass, \"initialId\")) {\r\n ModelClass.initialId = defaults.initialId;\r\n }\r\n if (defaults.randomInitialId !== undefined && !isExplicitStatic(ModelClass, \"randomInitialId\")) {\r\n ModelClass.randomInitialId = defaults.randomInitialId;\r\n }\r\n if (defaults.incrementIdBy !== undefined && !isExplicitStatic(ModelClass, \"incrementIdBy\")) {\r\n ModelClass.incrementIdBy = defaults.incrementIdBy;\r\n }\r\n if (defaults.randomIncrement !== undefined && !isExplicitStatic(ModelClass, \"randomIncrement\")) {\r\n ModelClass.randomIncrement = defaults.randomIncrement;\r\n }\r\n\r\n // ============================================================================\r\n // Timestamps\r\n // ============================================================================\r\n if (defaults.createdAtColumn !== undefined && !isExplicitStatic(ModelClass, \"createdAtColumn\")) {\r\n ModelClass.createdAtColumn = defaults.createdAtColumn;\r\n }\r\n\r\n if (defaults.updatedAtColumn !== undefined && !isExplicitStatic(ModelClass, \"updatedAtColumn\")) {\r\n ModelClass.updatedAtColumn = defaults.updatedAtColumn;\r\n }\r\n\r\n // ============================================================================\r\n // Deletion\r\n // ============================================================================\r\n if (defaults.deleteStrategy !== undefined && !isExplicitStatic(ModelClass, \"deleteStrategy\")) {\r\n ModelClass.deleteStrategy = defaults.deleteStrategy;\r\n }\r\n if (defaults.deletedAtColumn !== undefined && !isExplicitStatic(ModelClass, \"deletedAtColumn\")) {\r\n ModelClass.deletedAtColumn = defaults.deletedAtColumn;\r\n }\r\n if (defaults.trashTable !== undefined && !isExplicitStatic(ModelClass, \"trashTable\")) {\r\n // Handle function-based trash table\r\n if (typeof defaults.trashTable === \"function\") {\r\n ModelClass.trashTable = defaults.trashTable(ModelClass.table);\r\n } else {\r\n ModelClass.trashTable = defaults.trashTable;\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // Validation\r\n // ============================================================================\r\n if (defaults.strictMode !== undefined && !isExplicitStatic(ModelClass, \"strictMode\")) {\r\n ModelClass.strictMode = defaults.strictMode;\r\n }\r\n}\r\n\r\nexport async function generateModelNextId(model: Model): Promise<number | string> {\r\n const writer = new DatabaseWriter(model);\r\n await writer.generateNextId();\r\n return model.id!;\r\n}\r\n\r\nexport async function performAtomicUpdate(\r\n model: Model,\r\n operations: Record<string, unknown>,\r\n): Promise<number> {\r\n return model.self().atomic({ [model.self().primaryKey]: model.trustedPrimaryKey }, operations);\r\n}\r\n\r\n/**\r\n * Apply an atomic delta to the local value without marking the field dirty.\r\n * The database already holds the change, so a later `save()` must not send a\r\n * stale `$set` for it. Other pending changes stay dirty.\r\n */\r\nfunction applyLocalDelta(model: Model, field: string, delta: number): void {\r\n const tracker = model.dirtyTracker;\r\n const fieldWasDirty = tracker.isDirty(field);\r\n const value = (get(model.data, field, 0) as number) + delta;\r\n\r\n set(model.data, field, value);\r\n\r\n // A removed column can't be replayed after a baseline reset, so fall back to\r\n // plain dirty tracking for that rare case.\r\n if (fieldWasDirty || tracker.getRemovedColumns().length > 0) {\r\n tracker.setAtPath(field, value);\r\n return;\r\n }\r\n\r\n const pending = tracker.getDirtyColumnsWithValues();\r\n const baseline = structuredClone(model.data) as Record<string, unknown>;\r\n\r\n for (const [column, values] of Object.entries(pending)) {\r\n set(baseline, column, values.oldValue);\r\n }\r\n\r\n tracker.reset(baseline);\r\n\r\n for (const [column, values] of Object.entries(pending)) {\r\n tracker.setAtPath(column, values.newValue);\r\n }\r\n}\r\n\r\nexport async function performAtomicIncrement<T extends string>(\r\n model: Model,\r\n field: T,\r\n amount = 1,\r\n): Promise<number> {\r\n const result = await performAtomicUpdate(model, { $inc: { [field]: amount } });\r\n applyLocalDelta(model, field, amount);\r\n return result;\r\n}\r\n\r\nexport async function performAtomicDecrement<T extends string>(\r\n model: Model,\r\n field: T,\r\n amount = 1,\r\n): Promise<number> {\r\n const result = await performAtomicUpdate(model, { $inc: { [field]: -amount } });\r\n applyLocalDelta(model, field, -amount);\r\n return result;\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"meta-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/meta-methods.ts"],"sourcesContent":["import { get, set } from \"@mongez/reinforcements\";\nimport { DatabaseWriter } from \"../../writer/database-writer\";\nimport type { Model } from \"../model\";\n\n/**\n * Whether a subclass (or an intermediate base below `Model`) set the static\n * itself. The base `Model` initialises several statics (strictMode,\n * autoGenerateId, incrementIdBy, deletedAtColumn), so comparing to\n * `undefined` would never let data-source defaults apply.\n */\nfunction isExplicitStatic(ModelClass: any, key: string): boolean {\n let current = ModelClass;\n\n // The base Model is the class whose parent is `Function.prototype`; its own\n // initialisers are framework fallbacks, not explicit choices.\n while (current && Object.getPrototypeOf(current) !== Function.prototype) {\n if (Object.prototype.hasOwnProperty.call(current, key) && current[key] !== undefined) {\n return true;\n }\n\n current = Object.getPrototypeOf(current);\n }\n\n return false;\n}\n\nexport function applyDefaultsToModel(ModelClass: any, defaults: any): void {\n // Only apply defaults if model doesn't have its own value\n\n // ============================================================================\n // ID Generation\n // ============================================================================\n if (defaults.autoGenerateId !== undefined && !isExplicitStatic(ModelClass, \"autoGenerateId\")) {\n ModelClass.autoGenerateId = defaults.autoGenerateId;\n }\n if (defaults.initialId !== undefined && !isExplicitStatic(ModelClass, \"initialId\")) {\n ModelClass.initialId = defaults.initialId;\n }\n if (defaults.randomInitialId !== undefined && !isExplicitStatic(ModelClass, \"randomInitialId\")) {\n ModelClass.randomInitialId = defaults.randomInitialId;\n }\n if (defaults.incrementIdBy !== undefined && !isExplicitStatic(ModelClass, \"incrementIdBy\")) {\n ModelClass.incrementIdBy = defaults.incrementIdBy;\n }\n if (defaults.randomIncrement !== undefined && !isExplicitStatic(ModelClass, \"randomIncrement\")) {\n ModelClass.randomIncrement = defaults.randomIncrement;\n }\n\n // ============================================================================\n // Timestamps\n // ============================================================================\n if (defaults.createdAtColumn !== undefined && !isExplicitStatic(ModelClass, \"createdAtColumn\")) {\n ModelClass.createdAtColumn = defaults.createdAtColumn;\n }\n\n if (defaults.updatedAtColumn !== undefined && !isExplicitStatic(ModelClass, \"updatedAtColumn\")) {\n ModelClass.updatedAtColumn = defaults.updatedAtColumn;\n }\n\n // ============================================================================\n // Deletion\n // ============================================================================\n if (defaults.deleteStrategy !== undefined && !isExplicitStatic(ModelClass, \"deleteStrategy\")) {\n ModelClass.deleteStrategy = defaults.deleteStrategy;\n }\n if (defaults.deletedAtColumn !== undefined && !isExplicitStatic(ModelClass, \"deletedAtColumn\")) {\n ModelClass.deletedAtColumn = defaults.deletedAtColumn;\n }\n if (defaults.trashTable !== undefined && !isExplicitStatic(ModelClass, \"trashTable\")) {\n // Handle function-based trash table\n if (typeof defaults.trashTable === \"function\") {\n ModelClass.trashTable = defaults.trashTable(ModelClass.table);\n } else {\n ModelClass.trashTable = defaults.trashTable;\n }\n }\n\n // ============================================================================\n // Validation\n // ============================================================================\n if (defaults.strictMode !== undefined && !isExplicitStatic(ModelClass, \"strictMode\")) {\n ModelClass.strictMode = defaults.strictMode;\n }\n}\n\nexport async function generateModelNextId(model: Model): Promise<number | string> {\n const writer = new DatabaseWriter(model);\n await writer.generateNextId();\n return model.id!;\n}\n\nexport async function performAtomicUpdate(\n model: Model,\n operations: Record<string, unknown>,\n): Promise<number> {\n return model.self().atomic({ [model.self().primaryKey]: model.trustedPrimaryKey }, operations);\n}\n\n/**\n * Apply an atomic delta to the local value without marking the field dirty.\n * The database already holds the change, so a later `save()` must not send a\n * stale `$set` for it. Other pending changes stay dirty.\n */\nfunction applyLocalDelta(model: Model, field: string, delta: number): void {\n const tracker = model.dirtyTracker;\n const fieldWasDirty = tracker.isDirty(field);\n const value = (get(model.data, field, 0) as number) + delta;\n\n set(model.data, field, value);\n\n // A removed column can't be replayed after a baseline reset, so fall back to\n // plain dirty tracking for that rare case.\n if (fieldWasDirty || tracker.getRemovedColumns().length > 0) {\n tracker.setAtPath(field, value);\n return;\n }\n\n const pending = tracker.getDirtyColumnsWithValues();\n const baseline = structuredClone(model.data) as Record<string, unknown>;\n\n for (const [column, values] of Object.entries(pending)) {\n set(baseline, column, values.oldValue);\n }\n\n tracker.reset(baseline);\n\n for (const [column, values] of Object.entries(pending)) {\n tracker.setAtPath(column, values.newValue);\n }\n}\n\nexport async function performAtomicIncrement<T extends string>(\n model: Model,\n field: T,\n amount = 1,\n): Promise<number> {\n const result = await performAtomicUpdate(model, { $inc: { [field]: amount } });\n applyLocalDelta(model, field, amount);\n return result;\n}\n\nexport async function performAtomicDecrement<T extends string>(\n model: Model,\n field: T,\n amount = 1,\n): Promise<number> {\n const result = await performAtomicUpdate(model, { $inc: { [field]: -amount } });\n applyLocalDelta(model, field, -amount);\n return result;\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { dataSourceRegistry } from "../../data-source/data-source-registry.mjs";
2
2
  import { sanitizeFilter } from "../../utils/sanitize-filter.mjs";
3
3
  import { emitStaticEvent } from "./static-event-methods.mjs";
4
+ import { generateModelId } from "../generate-model-id.mjs";
4
5
  import { warnUndeclaredSensitiveFields } from "./serialization-methods.mjs";
5
6
 
6
7
  //#region ../cascade/src/model/methods/query-methods.ts
@@ -95,15 +96,39 @@ function toDriverOptions(options) {
95
96
  const { trustedFilter: _trustedFilter, ...rest } = options;
96
97
  return rest;
97
98
  }
99
+ function applyWriteFilter(query, filter, trustedFilter) {
100
+ if (trustedFilter && typeof query.whereTrusted === "function") return query.whereTrusted(filter);
101
+ return query.where(filter);
102
+ }
103
+ /**
104
+ * Add the same generated `id` that normal Mongo inserts receive to an upsert's
105
+ * insert branch. `$setOnInsert` keeps an existing document's id immutable.
106
+ */
107
+ async function withAutoGeneratedUpsertId(ModelClass, filter, operations, options) {
108
+ if (!options?.upsert || !ModelClass.autoGenerateId || ModelClass.getDriver().name !== "mongodb" || Array.isArray(operations)) return operations;
109
+ const filterId = filter.id;
110
+ const filterConstrainsId = Object.hasOwn(filter, "id") && (filterId === null || typeof filterId !== "object" || !Array.isArray(filterId) && Object.hasOwn(filterId, "$eq"));
111
+ const updateSuppliesId = Object.hasOwn(operations.$set ?? {}, "id") || Object.hasOwn(operations.$setOnInsert ?? {}, "id");
112
+ if (filterConstrainsId || updateSuppliesId) return operations;
113
+ const id = await generateModelId(ModelClass);
114
+ if (id === void 0) return operations;
115
+ return {
116
+ ...operations,
117
+ $setOnInsert: {
118
+ ...operations.$setOnInsert,
119
+ id
120
+ }
121
+ };
122
+ }
98
123
  /**
99
124
  * Pin a driver-level write to the rows the model's global scopes (tenant, soft
100
125
  * delete) allow. The driver write APIs take a raw filter and never see scopes,
101
126
  * so the target ids are resolved through the scoped query builder and added to
102
127
  * the filter. `null` means no visible row matches: the write must be a no-op.
103
128
  */
104
- async function scopeWriteFilter(ModelClass, filter, single) {
129
+ async function scopeWriteFilter(ModelClass, filter, single, trustedFilter = false) {
105
130
  const primaryKey = ModelClass.primaryKey;
106
- const ids = await ModelClass.query().where(filter).pluck(primaryKey);
131
+ const ids = await applyWriteFilter(ModelClass.query(), filter, trustedFilter).pluck(primaryKey);
107
132
  if (ids.length === 0) return null;
108
133
  return {
109
134
  ...filter,
@@ -115,10 +140,10 @@ async function scopeWriteFilter(ModelClass, filter, single) {
115
140
  * the driver would insert or, worse, update a row a scope hides (another
116
141
  * tenant's, a soft-deleted one), so a hidden match is refused.
117
142
  */
118
- async function scopeUpsertFilter(ModelClass, filter) {
119
- const scoped = await scopeWriteFilter(ModelClass, filter, true);
143
+ async function scopeUpsertFilter(ModelClass, filter, trustedFilter = false) {
144
+ const scoped = await scopeWriteFilter(ModelClass, filter, true, trustedFilter);
120
145
  if (scoped) return scoped;
121
- if (await ModelClass.query().withoutGlobalScopes().where(filter).exists()) throw new Error(`${ModelClass.name}: upsert matches a row hidden by a global scope (tenant or soft delete); refusing to touch it.`);
146
+ if (await applyWriteFilter(ModelClass.query().withoutGlobalScopes(), filter, trustedFilter).exists()) throw new Error(`${ModelClass.name}: upsert matches a row hidden by a global scope (tenant or soft delete); refusing to touch it.`);
122
147
  return filter;
123
148
  }
124
149
  /**
@@ -127,9 +152,10 @@ async function scopeUpsertFilter(ModelClass, filter) {
127
152
  */
128
153
  async function performAtomic(ModelClass, filter, operations, options) {
129
154
  const resolved = resolveFilter(filter, options);
130
- const scoped = options?.upsert ? await scopeUpsertFilter(ModelClass, resolved) : await scopeWriteFilter(ModelClass, resolved, false);
155
+ const scoped = options?.upsert ? await scopeUpsertFilter(ModelClass, resolved, options?.trustedFilter) : await scopeWriteFilter(ModelClass, resolved, false, options?.trustedFilter);
131
156
  if (!scoped) return 0;
132
- const result = await ModelClass.getDriver().atomic(ModelClass.table, scoped, operations, toDriverOptions(options));
157
+ const upsertOperations = await withAutoGeneratedUpsertId(ModelClass, scoped, operations, options);
158
+ const result = await ModelClass.getDriver().atomic(ModelClass.table, scoped, upsertOperations, toDriverOptions(options));
133
159
  return result.modifiedCount + (result.upsertedCount ?? 0);
134
160
  }
135
161
  /**
@@ -146,8 +172,8 @@ async function updateById(ModelClass, id, data) {
146
172
  }
147
173
  async function findAndUpdateRecords(ModelClass, filter, update, options) {
148
174
  const primaryKey = ModelClass.primaryKey;
149
- const safeFilter = sanitizeFilter(filter);
150
- const ids = await ModelClass.query().where(safeFilter).pluck(primaryKey);
175
+ const safeFilter = resolveFilter(filter, options);
176
+ const ids = await applyWriteFilter(ModelClass.query(), safeFilter, options?.trustedFilter ?? false).pluck(primaryKey);
151
177
  if (ids.length === 0) {
152
178
  if (!options?.upsert) return [];
153
179
  await performAtomic(ModelClass, safeFilter, update, {
@@ -164,9 +190,10 @@ async function findAndUpdateRecords(ModelClass, filter, update, options) {
164
190
  }
165
191
  async function findOneAndUpdateRecord(ModelClass, filter, update, options) {
166
192
  const resolved = resolveFilter(filter, options);
167
- const scoped = options?.upsert ? await scopeUpsertFilter(ModelClass, resolved) : await scopeWriteFilter(ModelClass, resolved, true);
193
+ const scoped = options?.upsert ? await scopeUpsertFilter(ModelClass, resolved, options?.trustedFilter) : await scopeWriteFilter(ModelClass, resolved, true, options?.trustedFilter);
168
194
  if (!scoped) return null;
169
- const result = await ModelClass.getDriver().findOneAndUpdate(ModelClass.table, scoped, update, toDriverOptions(options));
195
+ const upsertUpdate = await withAutoGeneratedUpsertId(ModelClass, scoped, update, options);
196
+ const result = await ModelClass.getDriver().findOneAndUpdate(ModelClass.table, scoped, upsertUpdate, toDriverOptions(options));
170
197
  if (!result) return null;
171
198
  return ModelClass.hydrate(result);
172
199
  }
@@ -1 +1 @@
1
- {"version":3,"file":"query-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/query-methods.ts"],"sourcesContent":["import type {\n AtomicUpdate,\n AtomicUpdateOptions,\n FindOneAndUpdateOptions,\n PaginationOptions,\n PaginationResult,\n QueryBuilderContract,\n} from \"../../contracts\";\nimport type { DataSource } from \"../../data-source/data-source\";\nimport { dataSourceRegistry } from \"../../data-source/data-source-registry\";\nimport { sanitizeFilter } from \"../../utils/sanitize-filter\";\nimport type { ChildModel, GlobalScopeDefinition, Model } from \"../model\";\nimport { emitStaticEvent } from \"./static-event-methods\";\nimport { warnUndeclaredSensitiveFields } from \"./serialization-methods\";\n\nexport function buildQuery<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n BaseModel: typeof Model,\n): QueryBuilderContract<TModel> {\n const queryBuilder = ModelClass.newQueryBuilder<TModel>();\n const qb = queryBuilder;\n\n // Collect global scopes from base Model and child model\n const allGlobalScopes = new Map<string, GlobalScopeDefinition>([\n ...BaseModel.globalScopes,\n ...ModelClass.globalScopes,\n ]);\n\n queryBuilder.pendingGlobalScopes = allGlobalScopes;\n queryBuilder.availableLocalScopes = ModelClass.localScopes;\n queryBuilder.disabledGlobalScopes = new Set();\n queryBuilder.relationDefinitions = ModelClass.relations;\n queryBuilder.modelClass = ModelClass;\n\n let fetchStartedAt = Date.now();\n\n // Emitted from the builder's execute path (awaited), not at construction, so\n // listener changes apply before the query runs and a throwing listener fails\n // the query instead of becoming an unhandled rejection.\n queryBuilder.onFetching(async () => {\n fetchStartedAt = Date.now();\n\n await emitStaticEvent(ModelClass, \"fetching\", queryBuilder, {\n table: ModelClass.table,\n modelClass: ModelClass,\n });\n });\n\n queryBuilder.onHydrating(async (records: any[], context: any) => {\n await emitStaticEvent(ModelClass, \"hydrating\", records as any, {\n query: queryBuilder,\n hydrateCallback: context?.hydrateCallback,\n });\n });\n\n queryBuilder.hydrate((data: any) => {\n return ModelClass.hydrate(data);\n });\n\n // Eager-loading runs inside the driver's `get()` so it works for any\n // builder construction path (Model.query, Model.newQueryBuilder, custom\n // subclassed builders). This hook only handles the model-level `fetched`\n // event emission.\n queryBuilder.onFetched(async (models: any[], context: any) => {\n await emitStaticEvent(ModelClass, \"fetched\", models as any, {\n query: queryBuilder,\n rawRecords: context?.rawRecords ?? [],\n duration: context?.duration ?? Date.now() - fetchStartedAt,\n });\n });\n\n return queryBuilder;\n}\n\nexport function buildNewQueryBuilder<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n): QueryBuilderContract<TModel> {\n const dataSource = ModelClass.getDataSource();\n\n if (ModelClass.builder) {\n const BuilderClass = ModelClass.builder;\n return new BuilderClass(ModelClass.table, dataSource) as QueryBuilderContract<TModel>;\n }\n\n const queryBuilder = dataSource.driver.queryBuilder<TModel>(ModelClass.table);\n return queryBuilder;\n}\n\nexport async function findFirst<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel | null> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return query.first();\n}\n\nexport async function findLast<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel | null> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n\n return query.last();\n}\n\nexport async function findAll<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel[]> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return query.get();\n}\n\nexport function countRecords<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<number> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return query.count();\n}\n\nexport async function findById<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n id: string | number,\n): Promise<TModel | null> {\n const query = ModelClass.query();\n return query.where(ModelClass.primaryKey, id).first();\n}\n\nexport async function paginateRecords<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n options: PaginationOptions & { filter?: Record<string, unknown> } = {},\n): Promise<PaginationResult<TModel>> {\n const query = ModelClass.query();\n if (options.filter) {\n query.where(options.filter);\n }\n\n return query.paginate({\n limit: options.limit,\n page: options.page,\n });\n}\n\nexport async function findLatest<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel[]> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return (await query.latest()) as unknown as TModel[];\n}\n\nexport function increaseField<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n field: string,\n amount: number,\n): Promise<number> {\n const query = ModelClass.query().where(filter);\n return query.increment(field, amount);\n}\n\nexport function decreaseField<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n field: string,\n amount: number,\n): Promise<number> {\n const query = ModelClass.query().where(filter);\n return query.decrement(field, amount);\n}\n\n// The atomic/find-and-modify statics below forward their filter straight to\n// the driver — they never pass through where(), so they must run the same\n// operator-injection check themselves. Only the FILTER is sanitized; update\n// operators ($set/$inc/…) are the point of these APIs and stay untouched.\n//\n// `trustedFilter` is the explicit, code-authored opt-out: it lets a conditional\n// filter such as `{ used: { $lt: 10 } }` through. It is stripped before the\n// options reach the driver.\nfunction resolveFilter(\n filter: Record<string, unknown>,\n options: AtomicUpdateOptions | undefined,\n): Record<string, unknown> {\n return options?.trustedFilter ? filter : sanitizeFilter(filter);\n}\n\nfunction toDriverOptions<TOptions extends AtomicUpdateOptions>(\n options: TOptions | undefined,\n): Omit<TOptions, \"trustedFilter\"> | undefined {\n if (!options) {\n return undefined;\n }\n\n const { trustedFilter: _trustedFilter, ...rest } = options;\n\n return rest;\n}\n\n/**\n * Pin a driver-level write to the rows the model's global scopes (tenant, soft\n * delete) allow. The driver write APIs take a raw filter and never see scopes,\n * so the target ids are resolved through the scoped query builder and added to\n * the filter. `null` means no visible row matches: the write must be a no-op.\n */\nexport async function scopeWriteFilter(\n ModelClass: ChildModel<any>,\n filter: Record<string, unknown>,\n single: boolean,\n): Promise<Record<string, unknown> | null> {\n const primaryKey = ModelClass.primaryKey;\n const ids = await ModelClass.query().where(filter).pluck(primaryKey);\n\n if (ids.length === 0) {\n return null;\n }\n\n return { ...filter, [primaryKey]: single ? ids[0] : { $in: ids } };\n}\n\n/**\n * Scoped filter for a write that may insert (`upsert`). With no visible match\n * the driver would insert or, worse, update a row a scope hides (another\n * tenant's, a soft-deleted one), so a hidden match is refused.\n */\nexport async function scopeUpsertFilter(\n ModelClass: ChildModel<any>,\n filter: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const scoped = await scopeWriteFilter(ModelClass, filter, true);\n\n if (scoped) {\n return scoped;\n }\n\n const hidden = await ModelClass.query().withoutGlobalScopes().where(filter).exists();\n\n if (hidden) {\n throw new Error(\n `${ModelClass.name}: upsert matches a row hidden by a global scope (tenant or soft delete); refusing to touch it.`,\n );\n }\n\n return filter;\n}\n\n/**\n * Run an atomic update and return the number of documents modified plus the\n * number inserted by an `upsert`.\n */\nexport async function performAtomic<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n operations: AtomicUpdate,\n options?: AtomicUpdateOptions,\n): Promise<number> {\n const resolved = resolveFilter(filter, options);\n const scoped = options?.upsert\n ? await scopeUpsertFilter(ModelClass, resolved)\n : await scopeWriteFilter(ModelClass, resolved, false);\n\n if (!scoped) {\n return 0;\n }\n\n const result = await ModelClass.getDriver().atomic(\n ModelClass.table,\n scoped,\n operations,\n toDriverOptions(options),\n );\n\n return result.modifiedCount + (result.upsertedCount ?? 0);\n}\n\n/**\n * Update a row by id through the model writer: the row is loaded (scopes\n * apply), merged, and saved, so the schema, strictMode, casting, `updatedAt`\n * and events all apply. Returns 1 when a row was saved, 0 when none is visible.\n */\nexport async function updateById<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n id: string | number,\n data: Record<string, unknown>,\n): Promise<number> {\n const model = await ModelClass.query().where(ModelClass.primaryKey, id).first();\n\n if (!model) {\n return 0;\n }\n\n model.merge(data);\n await model.save();\n\n return 1;\n}\n\nexport async function findAndUpdateRecords<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n update: AtomicUpdate,\n options?: Omit<AtomicUpdateOptions, \"trustedFilter\">,\n): Promise<TModel[]> {\n const primaryKey = ModelClass.primaryKey;\n const safeFilter = sanitizeFilter(filter);\n\n // Capture the matching ids first: the update usually changes the very field\n // the filter matches on, so re-querying with the filter would find nothing.\n const ids = await ModelClass.query().where(safeFilter).pluck(primaryKey);\n\n if (ids.length === 0) {\n if (!options?.upsert) {\n return [];\n }\n\n await performAtomic(ModelClass, safeFilter, update, { ...options, trustedFilter: true });\n return await ModelClass.query().where(safeFilter).get();\n }\n\n await performAtomic(\n ModelClass,\n { [primaryKey]: { $in: ids } },\n update,\n { ...options, trustedFilter: true },\n );\n\n return await ModelClass.query().whereIn(primaryKey, ids).get();\n}\n\nexport async function findOneAndUpdateRecord<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n update: AtomicUpdate,\n options?: FindOneAndUpdateOptions,\n): Promise<TModel | null> {\n const resolved = resolveFilter(filter, options);\n const scoped = options?.upsert\n ? await scopeUpsertFilter(ModelClass, resolved)\n : await scopeWriteFilter(ModelClass, resolved, true);\n\n if (!scoped) return null;\n\n const result = await ModelClass.getDriver().findOneAndUpdate(\n ModelClass.table,\n scoped,\n update,\n toDriverOptions(options),\n );\n if (!result) return null;\n return ModelClass.hydrate(result as Record<string, unknown>) as TModel;\n}\n\nexport async function findAndReplaceRecord<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n document: Record<string, unknown>,\n): Promise<TModel | null> {\n const scoped = await scopeWriteFilter(ModelClass, sanitizeFilter(filter), true);\n\n if (!scoped) return null;\n\n const result = await ModelClass.getDriver().replace(ModelClass.table, scoped, document);\n if (!result) return null;\n return ModelClass.hydrate(result as Record<string, unknown>) as TModel;\n}\n\nexport async function findOneAndDeleteRecord<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n options?: Record<string, unknown>,\n): Promise<TModel | null> {\n const scoped = await scopeWriteFilter(ModelClass, sanitizeFilter(filter), true);\n\n if (!scoped) {\n return null;\n }\n\n const result = await ModelClass.getDriver().findOneAndDelete(ModelClass.table, scoped, options);\n\n if (!result) {\n return null;\n }\n\n const model = ModelClass.hydrate(result as Record<string, unknown>);\n model.dirtyTracker.reset();\n return model;\n}\n\nexport function resolveDataSource<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n): DataSource {\n const ref = ModelClass.dataSource;\n let dataSource: DataSource;\n\n if (typeof ref === \"string\") {\n dataSource = dataSourceRegistry.get(ref);\n } else if (ref) {\n dataSource = ref;\n } else {\n dataSource = dataSourceRegistry.get();\n }\n\n if (!ModelClass.hasOwnProperty(\"_defaultsApplied\")) {\n const driverDefaults = dataSource.driver.modelDefaults || {};\n const dataSourceDefaults = dataSource.modelDefaults || {};\n\n const mergedDefaults = {\n ...driverDefaults,\n ...dataSourceDefaults,\n };\n\n if (Object.keys(mergedDefaults).length > 0) {\n (ModelClass as any).applyModelDefaults(mergedDefaults);\n }\n\n (ModelClass as any)._defaultsApplied = true;\n }\n\n // First data-source resolution is the earliest per-class hook every model\n // passes through — warn here (once) if the schema carries credential-shaped\n // fields that toJSON() would expose.\n warnUndeclaredSensitiveFields(ModelClass);\n\n return dataSource;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"query-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/query-methods.ts"],"sourcesContent":["import type {\n AtomicUpdate,\n AtomicUpdateOptions,\n FindOneAndUpdateOptions,\n PaginationOptions,\n PaginationResult,\n QueryBuilderContract,\n} from \"../../contracts\";\nimport type { DataSource } from \"../../data-source/data-source\";\nimport { dataSourceRegistry } from \"../../data-source/data-source-registry\";\nimport { sanitizeFilter } from \"../../utils/sanitize-filter\";\nimport { generateModelId } from \"../generate-model-id\";\nimport type { ChildModel, GlobalScopeDefinition, Model } from \"../model\";\nimport { emitStaticEvent } from \"./static-event-methods\";\nimport { warnUndeclaredSensitiveFields } from \"./serialization-methods\";\n\nexport function buildQuery<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n BaseModel: typeof Model,\n): QueryBuilderContract<TModel> {\n const queryBuilder = ModelClass.newQueryBuilder<TModel>();\n const qb = queryBuilder;\n\n // Collect global scopes from base Model and child model\n const allGlobalScopes = new Map<string, GlobalScopeDefinition>([\n ...BaseModel.globalScopes,\n ...ModelClass.globalScopes,\n ]);\n\n queryBuilder.pendingGlobalScopes = allGlobalScopes;\n queryBuilder.availableLocalScopes = ModelClass.localScopes;\n queryBuilder.disabledGlobalScopes = new Set();\n queryBuilder.relationDefinitions = ModelClass.relations;\n queryBuilder.modelClass = ModelClass;\n\n let fetchStartedAt = Date.now();\n\n // Emitted from the builder's execute path (awaited), not at construction, so\n // listener changes apply before the query runs and a throwing listener fails\n // the query instead of becoming an unhandled rejection.\n queryBuilder.onFetching(async () => {\n fetchStartedAt = Date.now();\n\n await emitStaticEvent(ModelClass, \"fetching\", queryBuilder, {\n table: ModelClass.table,\n modelClass: ModelClass,\n });\n });\n\n queryBuilder.onHydrating(async (records: any[], context: any) => {\n await emitStaticEvent(ModelClass, \"hydrating\", records as any, {\n query: queryBuilder,\n hydrateCallback: context?.hydrateCallback,\n });\n });\n\n queryBuilder.hydrate((data: any) => {\n return ModelClass.hydrate(data);\n });\n\n // Eager-loading runs inside the driver's `get()` so it works for any\n // builder construction path (Model.query, Model.newQueryBuilder, custom\n // subclassed builders). This hook only handles the model-level `fetched`\n // event emission.\n queryBuilder.onFetched(async (models: any[], context: any) => {\n await emitStaticEvent(ModelClass, \"fetched\", models as any, {\n query: queryBuilder,\n rawRecords: context?.rawRecords ?? [],\n duration: context?.duration ?? Date.now() - fetchStartedAt,\n });\n });\n\n return queryBuilder;\n}\n\nexport function buildNewQueryBuilder<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n): QueryBuilderContract<TModel> {\n const dataSource = ModelClass.getDataSource();\n\n if (ModelClass.builder) {\n const BuilderClass = ModelClass.builder;\n return new BuilderClass(ModelClass.table, dataSource) as QueryBuilderContract<TModel>;\n }\n\n const queryBuilder = dataSource.driver.queryBuilder<TModel>(ModelClass.table);\n return queryBuilder;\n}\n\nexport async function findFirst<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel | null> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return query.first();\n}\n\nexport async function findLast<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel | null> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n\n return query.last();\n}\n\nexport async function findAll<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel[]> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return query.get();\n}\n\nexport function countRecords<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<number> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return query.count();\n}\n\nexport async function findById<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n id: string | number,\n): Promise<TModel | null> {\n const query = ModelClass.query();\n return query.where(ModelClass.primaryKey, id).first();\n}\n\nexport async function paginateRecords<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n options: PaginationOptions & { filter?: Record<string, unknown> } = {},\n): Promise<PaginationResult<TModel>> {\n const query = ModelClass.query();\n if (options.filter) {\n query.where(options.filter);\n }\n\n return query.paginate({\n limit: options.limit,\n page: options.page,\n });\n}\n\nexport async function findLatest<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n): Promise<TModel[]> {\n const query = ModelClass.query();\n if (filter) {\n query.where(filter);\n }\n return (await query.latest()) as unknown as TModel[];\n}\n\nexport function increaseField<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n field: string,\n amount: number,\n): Promise<number> {\n const query = ModelClass.query().where(filter);\n return query.increment(field, amount);\n}\n\nexport function decreaseField<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n field: string,\n amount: number,\n): Promise<number> {\n const query = ModelClass.query().where(filter);\n return query.decrement(field, amount);\n}\n\n// The atomic/find-and-modify statics below forward their filter straight to\n// the driver — they never pass through where(), so they must run the same\n// operator-injection check themselves. Only the FILTER is sanitized; update\n// operators ($set/$inc/…) are the point of these APIs and stay untouched.\n//\n// `trustedFilter` is the explicit, code-authored opt-out: it lets a conditional\n// filter such as `{ used: { $lt: 10 } }` through. It is stripped before the\n// options reach the driver.\nfunction resolveFilter(\n filter: Record<string, unknown>,\n options: AtomicUpdateOptions | undefined,\n): Record<string, unknown> {\n return options?.trustedFilter ? filter : sanitizeFilter(filter);\n}\n\nfunction toDriverOptions<TOptions extends AtomicUpdateOptions>(\n options: TOptions | undefined,\n): Omit<TOptions, \"trustedFilter\"> | undefined {\n if (!options) {\n return undefined;\n }\n\n const { trustedFilter: _trustedFilter, ...rest } = options;\n\n return rest;\n}\n\nfunction applyWriteFilter<TModel extends Model>(\n query: QueryBuilderContract<TModel>,\n filter: Record<string, unknown>,\n trustedFilter: boolean,\n): QueryBuilderContract<TModel> {\n // Query builders supplied by integrations predating `whereTrusted` can\n // still apply a code-authored filter through their regular `where` method.\n // Concrete Cascade builders implement `whereTrusted`, which is required for\n // MongoDB operator filters; retain the fallback for compatible custom\n // builders and test doubles.\n if (trustedFilter && typeof query.whereTrusted === \"function\") {\n return query.whereTrusted(filter);\n }\n\n return query.where(filter);\n}\n\n/**\n * Add the same generated `id` that normal Mongo inserts receive to an upsert's\n * insert branch. `$setOnInsert` keeps an existing document's id immutable.\n */\nasync function withAutoGeneratedUpsertId<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n operations: AtomicUpdate,\n options: AtomicUpdateOptions | undefined,\n): Promise<AtomicUpdate> {\n if (\n !options?.upsert ||\n !ModelClass.autoGenerateId ||\n ModelClass.getDriver().name !== \"mongodb\" ||\n Array.isArray(operations)\n ) {\n return operations;\n }\n\n const filterId = filter.id;\n const filterConstrainsId =\n Object.hasOwn(filter, \"id\") &&\n (filterId === null ||\n typeof filterId !== \"object\" ||\n (!Array.isArray(filterId) && Object.hasOwn(filterId, \"$eq\")));\n const updateSuppliesId =\n Object.hasOwn(operations.$set ?? {}, \"id\") ||\n Object.hasOwn(operations.$setOnInsert ?? {}, \"id\");\n\n if (filterConstrainsId || updateSuppliesId) {\n return operations;\n }\n\n const id = await generateModelId(ModelClass);\n\n if (id === undefined) {\n return operations;\n }\n\n return {\n ...operations,\n $setOnInsert: { ...operations.$setOnInsert, id },\n };\n}\n\n/**\n * Pin a driver-level write to the rows the model's global scopes (tenant, soft\n * delete) allow. The driver write APIs take a raw filter and never see scopes,\n * so the target ids are resolved through the scoped query builder and added to\n * the filter. `null` means no visible row matches: the write must be a no-op.\n */\nexport async function scopeWriteFilter(\n ModelClass: ChildModel<any>,\n filter: Record<string, unknown>,\n single: boolean,\n trustedFilter = false,\n): Promise<Record<string, unknown> | null> {\n const primaryKey = ModelClass.primaryKey;\n const query = ModelClass.query();\n const ids = await applyWriteFilter(query, filter, trustedFilter).pluck(primaryKey);\n\n if (ids.length === 0) {\n return null;\n }\n\n return { ...filter, [primaryKey]: single ? ids[0] : { $in: ids } };\n}\n\n/**\n * Scoped filter for a write that may insert (`upsert`). With no visible match\n * the driver would insert or, worse, update a row a scope hides (another\n * tenant's, a soft-deleted one), so a hidden match is refused.\n */\nexport async function scopeUpsertFilter(\n ModelClass: ChildModel<any>,\n filter: Record<string, unknown>,\n trustedFilter = false,\n): Promise<Record<string, unknown>> {\n const scoped = await scopeWriteFilter(ModelClass, filter, true, trustedFilter);\n\n if (scoped) {\n return scoped;\n }\n\n const query = ModelClass.query().withoutGlobalScopes();\n const hidden = await applyWriteFilter(query, filter, trustedFilter).exists();\n\n if (hidden) {\n throw new Error(\n `${ModelClass.name}: upsert matches a row hidden by a global scope (tenant or soft delete); refusing to touch it.`,\n );\n }\n\n return filter;\n}\n\n/**\n * Run an atomic update and return the number of documents modified plus the\n * number inserted by an `upsert`.\n */\nexport async function performAtomic<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n operations: AtomicUpdate,\n options?: AtomicUpdateOptions,\n): Promise<number> {\n const resolved = resolveFilter(filter, options);\n const scoped = options?.upsert\n ? await scopeUpsertFilter(ModelClass, resolved, options?.trustedFilter)\n : await scopeWriteFilter(ModelClass, resolved, false, options?.trustedFilter);\n\n if (!scoped) {\n return 0;\n }\n\n const upsertOperations = await withAutoGeneratedUpsertId(ModelClass, scoped, operations, options);\n\n const result = await ModelClass.getDriver().atomic(\n ModelClass.table,\n scoped,\n upsertOperations,\n toDriverOptions(options),\n );\n\n return result.modifiedCount + (result.upsertedCount ?? 0);\n}\n\n/**\n * Update a row by id through the model writer: the row is loaded (scopes\n * apply), merged, and saved, so the schema, strictMode, casting, `updatedAt`\n * and events all apply. Returns 1 when a row was saved, 0 when none is visible.\n */\nexport async function updateById<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n id: string | number,\n data: Record<string, unknown>,\n): Promise<number> {\n const model = await ModelClass.query().where(ModelClass.primaryKey, id).first();\n\n if (!model) {\n return 0;\n }\n\n model.merge(data);\n await model.save();\n\n return 1;\n}\n\nexport async function findAndUpdateRecords<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n update: AtomicUpdate,\n options?: AtomicUpdateOptions,\n): Promise<TModel[]> {\n const primaryKey = ModelClass.primaryKey;\n const safeFilter = resolveFilter(filter, options);\n\n // Capture the matching ids first: the update usually changes the very field\n // the filter matches on, so re-querying with the filter would find nothing.\n const query = ModelClass.query();\n const ids = await applyWriteFilter(query, safeFilter, options?.trustedFilter ?? false).pluck(\n primaryKey,\n );\n\n if (ids.length === 0) {\n if (!options?.upsert) {\n return [];\n }\n\n await performAtomic(ModelClass, safeFilter, update, { ...options, trustedFilter: true });\n return await ModelClass.query().where(safeFilter).get();\n }\n\n await performAtomic(ModelClass, { [primaryKey]: { $in: ids } }, update, {\n ...options,\n trustedFilter: true,\n });\n\n return await ModelClass.query().whereIn(primaryKey, ids).get();\n}\n\nexport async function findOneAndUpdateRecord<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n update: AtomicUpdate,\n options?: FindOneAndUpdateOptions,\n): Promise<TModel | null> {\n const resolved = resolveFilter(filter, options);\n const scoped = options?.upsert\n ? await scopeUpsertFilter(ModelClass, resolved, options?.trustedFilter)\n : await scopeWriteFilter(ModelClass, resolved, true, options?.trustedFilter);\n\n if (!scoped) return null;\n\n const upsertUpdate = await withAutoGeneratedUpsertId(ModelClass, scoped, update, options);\n\n const result = await ModelClass.getDriver().findOneAndUpdate(\n ModelClass.table,\n scoped,\n upsertUpdate,\n toDriverOptions(options),\n );\n if (!result) return null;\n return ModelClass.hydrate(result as Record<string, unknown>) as TModel;\n}\n\nexport async function findAndReplaceRecord<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n document: Record<string, unknown>,\n): Promise<TModel | null> {\n const scoped = await scopeWriteFilter(ModelClass, sanitizeFilter(filter), true);\n\n if (!scoped) return null;\n\n const result = await ModelClass.getDriver().replace(ModelClass.table, scoped, document);\n if (!result) return null;\n return ModelClass.hydrate(result as Record<string, unknown>) as TModel;\n}\n\nexport async function findOneAndDeleteRecord<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n filter: Record<string, unknown>,\n options?: Record<string, unknown>,\n): Promise<TModel | null> {\n const scoped = await scopeWriteFilter(ModelClass, sanitizeFilter(filter), true);\n\n if (!scoped) {\n return null;\n }\n\n const result = await ModelClass.getDriver().findOneAndDelete(ModelClass.table, scoped, options);\n\n if (!result) {\n return null;\n }\n\n const model = ModelClass.hydrate(result as Record<string, unknown>);\n model.dirtyTracker.reset();\n return model;\n}\n\nexport function resolveDataSource<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n): DataSource {\n const ref = ModelClass.dataSource;\n let dataSource: DataSource;\n\n if (typeof ref === \"string\") {\n dataSource = dataSourceRegistry.get(ref);\n } else if (ref) {\n dataSource = ref;\n } else {\n dataSource = dataSourceRegistry.get();\n }\n\n if (!ModelClass.hasOwnProperty(\"_defaultsApplied\")) {\n const driverDefaults = dataSource.driver.modelDefaults || {};\n const dataSourceDefaults = dataSource.modelDefaults || {};\n\n const mergedDefaults = {\n ...driverDefaults,\n ...dataSourceDefaults,\n };\n\n if (Object.keys(mergedDefaults).length > 0) {\n (ModelClass as any).applyModelDefaults(mergedDefaults);\n }\n\n (ModelClass as any)._defaultsApplied = true;\n }\n\n // First data-source resolution is the earliest per-class hook every model\n // passes through — warn here (once) if the schema carries credential-shaped\n // fields that toJSON() would expose.\n warnUndeclaredSensitiveFields(ModelClass);\n\n return dataSource;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"write-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/write-methods.ts"],"sourcesContent":["import { DatabaseWriter } from \"../../writer/database-writer\";\r\nimport type { InsertResult, WriterOptions } from \"../../contracts\";\r\nimport type { ChildModel, Model, ModelSchema } from \"../model\";\r\nimport { mergeDriverFields } from \"./accessor-methods\";\r\nimport { sanitizeFilter } from \"../../utils/sanitize-filter\";\r\nimport { emitModelEvent } from \"./instance-event-methods\";\r\n\r\n/**\r\n * Default number of rows processed per chunk by {@link createManyRecords}.\r\n *\r\n * Chunking keeps a single huge `createMany` call from flooding the driver:\r\n * the default path runs each chunk's `save()` calls under one `Promise.all`,\r\n * and the bulk path emits one multi-row `insertMany` per chunk so the\r\n * generated `INSERT ... VALUES (...),(...)` stays under the database's bind\r\n * parameter ceiling.\r\n */\r\nexport const DEFAULT_CREATE_MANY_BATCH_SIZE = 500;\r\n\r\n/**\r\n * Options for {@link createManyRecords} (and `Model.createMany`).\r\n */\r\nexport type CreateManyOptions = {\r\n /**\r\n * Number of rows processed per chunk.\r\n *\r\n * @default 500 ({@link DEFAULT_CREATE_MANY_BATCH_SIZE})\r\n */\r\n batchSize?: number;\r\n\r\n /**\r\n * Route each chunk through the driver's native multi-row insert\r\n * (`insertMany`) instead of per-row `save()`.\r\n *\r\n * **Tradeoff:** the bulk path is 10–100× faster for large arrays but\r\n * SKIPS the per-row lifecycle: `saving` / `creating` / `created` / `saved`\r\n * events, instance hooks, and sync operations are NOT emitted. Casts,\r\n * timestamps, defaults and id-generation that the writer normally applies\r\n * ARE still applied (the rows are prepped through the same writer pipeline),\r\n * so persisted columns match the default path.\r\n *\r\n * @default false\r\n */\r\n bulk?: boolean;\r\n};\r\n\r\nexport async function saveModel<TModel extends Model>(\r\n model: TModel,\r\n options?: WriterOptions & { merge?: Partial<ModelSchema> },\r\n): Promise<TModel> {\r\n if (options?.merge) {\r\n model.merge(options.merge);\r\n }\r\n const writer = new DatabaseWriter(model);\r\n await writer.save(options);\r\n return model;\r\n}\r\n\r\nexport async function createRecord<\r\n TModel extends Model,\r\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\r\n>(ModelClass: ChildModel<TModel>, data: Partial<TSchema>): Promise<TModel> {\r\n const model = new ModelClass(data);\r\n await model.save();\r\n return model;\r\n}\r\n\r\n/**\r\n * Split an array into sequential chunks of at most `size` elements.\r\n *\r\n * @param items - The array to split.\r\n * @param size - Maximum chunk length (callers pass a value `>= 1`).\r\n * @returns An array of chunks preserving the original order.\r\n */\r\nfunction chunkArray<TItem>(items: TItem[], size: number): TItem[][] {\r\n const chunks: TItem[][] = [];\r\n\r\n for (let index = 0; index < items.length; index += size) {\r\n chunks.push(items.slice(index, index + size));\r\n }\r\n\r\n return chunks;\r\n}\r\n\r\n/**\r\n * Create many records, chunking the work so a huge array can't overwhelm the\r\n * driver.\r\n *\r\n * Two strategies are available via `options.bulk`:\r\n *\r\n * - **Default (`bulk` falsy):** each row is persisted through `save()`, so\r\n * model hooks, lifecycle events, casts and generated ids are all preserved.\r\n * Rows are processed in sequential chunks of `batchSize`, each chunk running\r\n * under a single `Promise.all`, so an array of millions of rows can't open\r\n * millions of concurrent inserts at once.\r\n *\r\n * - **Bulk (`bulk: true`):** each chunk is routed to the driver's native\r\n * multi-row insert (`insertMany`) for 10–100× throughput. This SKIPS the\r\n * per-row save lifecycle (no `saving` / `creating` / `created` / `saved`\r\n * events, hooks, or sync). Rows are still prepped through the writer\r\n * pipeline (validation, casting, timestamps, defaults, id-generation) so the\r\n * persisted columns match the default path, and the values returned by the\r\n * driver (generated `_id`, timestamps, SQL `RETURNING *`) are merged back\r\n * onto the returned models.\r\n *\r\n * Both strategies return the created model instances (an empty array is a\r\n * no-op that never touches the driver).\r\n *\r\n * @param ModelClass - The model class to create records for.\r\n * @param data - The rows to insert.\r\n * @param options - Chunking / bulk options.\r\n * @returns The created model instances.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Default: per-row save(), chunked in batches of 500\r\n * const users = await User.createMany(rows);\r\n *\r\n * // Bulk: one multi-row INSERT per 1000-row chunk (skips per-row hooks)\r\n * const users = await User.createMany(rows, { bulk: true, batchSize: 1000 });\r\n * ```\r\n */\r\nexport async function createManyRecords<\r\n TModel extends Model,\r\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\r\n>(\r\n ModelClass: ChildModel<TModel>,\r\n data: Partial<TSchema>[],\r\n options: CreateManyOptions = {},\r\n): Promise<TModel[]> {\r\n if (data.length === 0) {\r\n return [];\r\n }\r\n\r\n const batchSize =\r\n options.batchSize && options.batchSize > 0\r\n ? options.batchSize\r\n : DEFAULT_CREATE_MANY_BATCH_SIZE;\r\n\r\n const chunks = chunkArray(data, batchSize);\r\n\r\n if (options.bulk === true) {\r\n return await createManyBulk(ModelClass, chunks);\r\n }\r\n\r\n const created: TModel[] = [];\r\n\r\n for (const chunk of chunks) {\r\n const models = chunk.map((item) => new ModelClass(item)) as TModel[];\r\n\r\n // Reserve one contiguous id block for the whole chunk (1 counter op instead\r\n // of N), pre-seeding each id-less model so its per-row save() no-ops id-gen.\r\n await assignIdBlock(ModelClass, models);\r\n\r\n const chunkModels = await Promise.all(\r\n models.map(async (model) => {\r\n await model.save();\r\n return model;\r\n }),\r\n );\r\n\r\n created.push(...chunkModels);\r\n }\r\n\r\n return created;\r\n}\r\n\r\n/**\r\n * Reserve a single contiguous id block for one chunk and pre-assign the ids to\r\n * the models that don't already carry one, so the per-row writer's id\r\n * generation no-ops (its `model.get(\"id\")` guard short-circuits). This turns N\r\n * per-row counter round-trips into ONE per chunk.\r\n *\r\n * Falls back to per-row generation (a no-op here) when:\r\n * - the model disables auto-generation (`autoGenerateId === false`) — e.g. SQL,\r\n * which uses native `SERIAL`;\r\n * - the data source's id generator has no batch API (`generateNextIds`) — the\r\n * optional contract member is feature-detected;\r\n * - the model uses a random initial id / increment — a random stride can't form\r\n * a contiguous block, so those models keep per-row generation.\r\n *\r\n * Only models WITHOUT a caller-supplied id consume a block slot, so a chunk\r\n * mixing supplied and auto ids allocates exactly the right number (no gaps).\r\n *\r\n * @param ModelClass - The model class being inserted.\r\n * @param models - The freshly-constructed (unsaved) models for one chunk.\r\n */\r\nasync function assignIdBlock<TModel extends Model>(\r\n ModelClass: ChildModel<TModel>,\r\n models: TModel[],\r\n): Promise<void> {\r\n if (!ModelClass.autoGenerateId || ModelClass.randomInitialId || ModelClass.randomIncrement) {\r\n return;\r\n }\r\n\r\n const idGenerator = ModelClass.getDataSource().idGenerator;\r\n\r\n if (!idGenerator || typeof idGenerator.generateNextIds !== \"function\") {\r\n return;\r\n }\r\n\r\n const idLessModels = models.filter((model) => !model.get(\"id\"));\r\n\r\n if (idLessModels.length === 0) {\r\n return;\r\n }\r\n\r\n const ids = await idGenerator.generateNextIds({\r\n table: ModelClass.table,\r\n initialId: ModelClass.initialId || 1,\r\n incrementIdBy: ModelClass.incrementIdBy || 1,\r\n count: idLessModels.length,\r\n });\r\n\r\n // Enforce the contract at this pluggable, feature-detected boundary: a\r\n // non-conforming generator returning the wrong count would otherwise set\r\n // `id = undefined` on the unmatched rows, the per-row writer would silently\r\n // re-generate single ids, and the reserved block would no longer match what\r\n // is persisted. Fail loud instead of corrupting the sequence.\r\n if (ids.length !== idLessModels.length) {\r\n throw new Error(\r\n `generateNextIds returned ${ids.length} id(s) for ${idLessModels.length} row(s) on ` +\r\n `\"${ModelClass.table}\" — a batch id generator must return exactly the requested count.`,\r\n );\r\n }\r\n\r\n idLessModels.forEach((model, index) => {\r\n model.set(\"id\", ids[index]);\r\n });\r\n}\r\n\r\n/**\r\n * Bulk variant of {@link createManyRecords}: prep each row through the writer\r\n * pipeline (validation, casting, timestamps, defaults, id-generation) without\r\n * touching the database, then flush each chunk with a single\r\n * `driver.insertMany` call.\r\n *\r\n * The writer reuse goes through `DatabaseWriter.prepareForInsert()`, the same\r\n * pipeline `save()` uses for an insert, so the shared driver is never mutated\r\n * and concurrent `save()` calls are unaffected.\r\n *\r\n * @param ModelClass - The model class to create records for.\r\n * @param chunks - Pre-chunked rows.\r\n * @returns The created model instances with driver-returned values merged in.\r\n */\r\nasync function createManyBulk<\r\n TModel extends Model,\r\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\r\n>(ModelClass: ChildModel<TModel>, chunks: Partial<TSchema>[][]): Promise<TModel[]> {\r\n const dataSource = ModelClass.getDataSource();\r\n const driver = dataSource.driver;\r\n const table = ModelClass.table;\r\n\r\n const created: TModel[] = [];\r\n\r\n {\r\n for (const chunk of chunks) {\r\n const models = chunk.map((item) => new ModelClass(item)) as TModel[];\r\n\r\n // Reserve one contiguous id block for the whole chunk (1 counter op\r\n // instead of N), pre-seeding each id-less model so the per-row writer's\r\n // id generation no-ops.\r\n await assignIdBlock(ModelClass, models);\r\n\r\n // Prep every model through the real writer pipeline. The captured\r\n // `insert` keeps this off the wire while still mutating each model's\r\n // data with casts/timestamps/defaults/generated ids.\r\n const preparedDocuments = await Promise.all(\r\n models.map(async (model) => {\r\n const document = await new DatabaseWriter(model).prepareForInsert({\r\n skipEvents: true,\r\n skipSync: true,\r\n });\r\n return { ...document } as Record<string, unknown>;\r\n }),\r\n );\r\n\r\n const results = await driver.insertMany(table, preparedDocuments);\r\n\r\n // Merge driver-returned values (generated _id, timestamps, RETURNING *)\r\n // back onto each model so the returned instances reflect persisted state.\r\n models.forEach((model, index) => {\r\n const result = results[index] as InsertResult | Record<string, unknown> | undefined;\r\n\r\n if (result) {\r\n const returnedDocument =\r\n \"document\" in (result as Record<string, unknown>)\r\n ? (result as InsertResult).document\r\n : result;\r\n\r\n // Driver-returned identity (generated _id / RETURNING *) — merged\r\n // through the framework-internal path so it is not treated as mass\r\n // assignment on a model the writer has already marked persisted.\r\n mergeDriverFields(model, returnedDocument as Record<string, unknown>);\r\n }\r\n\r\n model.dirtyTracker.reset();\r\n model.isNew = false;\r\n });\r\n\r\n created.push(...models);\r\n }\r\n }\r\n\r\n return created;\r\n}\r\n\r\nexport async function findOrCreateRecord<\r\n TModel extends Model,\r\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\r\n>(\r\n ModelClass: ChildModel<TModel>,\r\n filter: Partial<TSchema>,\r\n data: Partial<TSchema>,\r\n): Promise<TModel> {\r\n const existing = await ModelClass.first(filter as Record<string, unknown>);\r\n\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n return await createRecord(ModelClass, { ...filter, ...data } as Partial<TSchema>);\r\n}\r\n\r\nexport async function upsertRecord<\r\n TModel extends Model,\r\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\r\n>(\r\n ModelClass: ChildModel<TModel>,\r\n filter: Partial<TSchema>,\r\n data: Partial<TSchema>,\r\n options?: Record<string, unknown>,\r\n): Promise<TModel> {\r\n const driver = ModelClass.getDriver();\r\n const safeFilter = sanitizeFilter(filter as Record<string, unknown>);\r\n const mergedData = { ...safeFilter, ...data } as Record<string, unknown>;\r\n\r\n const tempModel = new ModelClass(mergedData as Partial<TSchema>);\r\n tempModel.isNew = true;\r\n\r\n // One `saving` run against the model itself, so listener changes (slug,\r\n // createdBy, ...) land in the data that is written.\r\n await emitModelEvent(tempModel, \"saving\", {\r\n isInsert: true,\r\n options,\r\n mode: \"upsert\",\r\n });\r\n\r\n // Validation, casting and Mongo id generation, same as `create()`.\r\n await new DatabaseWriter(tempModel).prepareForUpsert();\r\n\r\n const setData: Record<string, unknown> = { ...tempModel.data };\r\n const setOnInsert: Record<string, unknown> = {};\r\n const now = new Date();\r\n\r\n // Identity and creation time belong to the insert only; an existing row\r\n // keeps its own.\r\n for (const key of new Set([\"id\", \"_id\", ModelClass.primaryKey])) {\r\n if (key in setData) {\r\n setOnInsert[key] = setData[key];\r\n delete setData[key];\r\n }\r\n }\r\n\r\n const createdAtColumn = ModelClass.createdAtColumn;\r\n if (createdAtColumn) {\r\n setOnInsert[createdAtColumn] = setData[createdAtColumn] ?? now;\r\n delete setData[createdAtColumn];\r\n }\r\n\r\n const updatedAtColumn = ModelClass.updatedAtColumn;\r\n if (updatedAtColumn) {\r\n setData[updatedAtColumn] = now;\r\n }\r\n\r\n const result = await driver.findOneAndUpdate(\r\n ModelClass.table,\r\n safeFilter,\r\n { $set: setData, $setOnInsert: setOnInsert },\r\n { ...options, upsert: true, returnDocument: \"after\" },\r\n );\r\n\r\n const model = ModelClass.hydrate(result as Record<string, unknown>) as TModel;\r\n model.dirtyTracker.reset();\r\n\r\n await emitModelEvent(model, \"saved\", { filter: safeFilter, data: result, options, mode: \"upsert\" });\r\n\r\n return model;\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"write-methods.mjs","names":[],"sources":["../../../../../../../../cascade/src/model/methods/write-methods.ts"],"sourcesContent":["import { DatabaseWriter } from \"../../writer/database-writer\";\nimport type { InsertResult, WriterOptions } from \"../../contracts\";\nimport type { ChildModel, Model, ModelSchema } from \"../model\";\nimport { mergeDriverFields } from \"./accessor-methods\";\nimport { sanitizeFilter } from \"../../utils/sanitize-filter\";\nimport { emitModelEvent } from \"./instance-event-methods\";\n\n/**\n * Default number of rows processed per chunk by {@link createManyRecords}.\n *\n * Chunking keeps a single huge `createMany` call from flooding the driver:\n * the default path runs each chunk's `save()` calls under one `Promise.all`,\n * and the bulk path emits one multi-row `insertMany` per chunk so the\n * generated `INSERT ... VALUES (...),(...)` stays under the database's bind\n * parameter ceiling.\n */\nexport const DEFAULT_CREATE_MANY_BATCH_SIZE = 500;\n\n/**\n * Options for {@link createManyRecords} (and `Model.createMany`).\n */\nexport type CreateManyOptions = {\n /**\n * Number of rows processed per chunk.\n *\n * @default 500 ({@link DEFAULT_CREATE_MANY_BATCH_SIZE})\n */\n batchSize?: number;\n\n /**\n * Route each chunk through the driver's native multi-row insert\n * (`insertMany`) instead of per-row `save()`.\n *\n * **Tradeoff:** the bulk path is 10–100× faster for large arrays but\n * SKIPS the per-row lifecycle: `saving` / `creating` / `created` / `saved`\n * events, instance hooks, and sync operations are NOT emitted. Casts,\n * timestamps, defaults and id-generation that the writer normally applies\n * ARE still applied (the rows are prepped through the same writer pipeline),\n * so persisted columns match the default path.\n *\n * @default false\n */\n bulk?: boolean;\n};\n\nexport async function saveModel<TModel extends Model>(\n model: TModel,\n options?: WriterOptions & { merge?: Partial<ModelSchema> },\n): Promise<TModel> {\n if (options?.merge) {\n model.merge(options.merge);\n }\n const writer = new DatabaseWriter(model);\n await writer.save(options);\n return model;\n}\n\nexport async function createRecord<\n TModel extends Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n>(ModelClass: ChildModel<TModel>, data: Partial<TSchema>): Promise<TModel> {\n const model = new ModelClass(data);\n await model.save();\n return model;\n}\n\n/**\n * Split an array into sequential chunks of at most `size` elements.\n *\n * @param items - The array to split.\n * @param size - Maximum chunk length (callers pass a value `>= 1`).\n * @returns An array of chunks preserving the original order.\n */\nfunction chunkArray<TItem>(items: TItem[], size: number): TItem[][] {\n const chunks: TItem[][] = [];\n\n for (let index = 0; index < items.length; index += size) {\n chunks.push(items.slice(index, index + size));\n }\n\n return chunks;\n}\n\n/**\n * Create many records, chunking the work so a huge array can't overwhelm the\n * driver.\n *\n * Two strategies are available via `options.bulk`:\n *\n * - **Default (`bulk` falsy):** each row is persisted through `save()`, so\n * model hooks, lifecycle events, casts and generated ids are all preserved.\n * Rows are processed in sequential chunks of `batchSize`, each chunk running\n * under a single `Promise.all`, so an array of millions of rows can't open\n * millions of concurrent inserts at once.\n *\n * - **Bulk (`bulk: true`):** each chunk is routed to the driver's native\n * multi-row insert (`insertMany`) for 10–100× throughput. This SKIPS the\n * per-row save lifecycle (no `saving` / `creating` / `created` / `saved`\n * events, hooks, or sync). Rows are still prepped through the writer\n * pipeline (validation, casting, timestamps, defaults, id-generation) so the\n * persisted columns match the default path, and the values returned by the\n * driver (generated `_id`, timestamps, SQL `RETURNING *`) are merged back\n * onto the returned models.\n *\n * Both strategies return the created model instances (an empty array is a\n * no-op that never touches the driver).\n *\n * @param ModelClass - The model class to create records for.\n * @param data - The rows to insert.\n * @param options - Chunking / bulk options.\n * @returns The created model instances.\n *\n * @example\n * ```typescript\n * // Default: per-row save(), chunked in batches of 500\n * const users = await User.createMany(rows);\n *\n * // Bulk: one multi-row INSERT per 1000-row chunk (skips per-row hooks)\n * const users = await User.createMany(rows, { bulk: true, batchSize: 1000 });\n * ```\n */\nexport async function createManyRecords<\n TModel extends Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n>(\n ModelClass: ChildModel<TModel>,\n data: Partial<TSchema>[],\n options: CreateManyOptions = {},\n): Promise<TModel[]> {\n if (data.length === 0) {\n return [];\n }\n\n const batchSize =\n options.batchSize && options.batchSize > 0\n ? options.batchSize\n : DEFAULT_CREATE_MANY_BATCH_SIZE;\n\n const chunks = chunkArray(data, batchSize);\n\n if (options.bulk === true) {\n return await createManyBulk(ModelClass, chunks);\n }\n\n const created: TModel[] = [];\n\n for (const chunk of chunks) {\n const models = chunk.map((item) => new ModelClass(item)) as TModel[];\n\n // Reserve one contiguous id block for the whole chunk (1 counter op instead\n // of N), pre-seeding each id-less model so its per-row save() no-ops id-gen.\n await assignIdBlock(ModelClass, models);\n\n const chunkModels = await Promise.all(\n models.map(async (model) => {\n await model.save();\n return model;\n }),\n );\n\n created.push(...chunkModels);\n }\n\n return created;\n}\n\n/**\n * Reserve a single contiguous id block for one chunk and pre-assign the ids to\n * the models that don't already carry one, so the per-row writer's id\n * generation no-ops (its `model.get(\"id\")` guard short-circuits). This turns N\n * per-row counter round-trips into ONE per chunk.\n *\n * Falls back to per-row generation (a no-op here) when:\n * - the model disables auto-generation (`autoGenerateId === false`) — e.g. SQL,\n * which uses native `SERIAL`;\n * - the data source's id generator has no batch API (`generateNextIds`) — the\n * optional contract member is feature-detected;\n * - the model uses a random initial id / increment — a random stride can't form\n * a contiguous block, so those models keep per-row generation.\n *\n * Only models WITHOUT a caller-supplied id consume a block slot, so a chunk\n * mixing supplied and auto ids allocates exactly the right number (no gaps).\n *\n * @param ModelClass - The model class being inserted.\n * @param models - The freshly-constructed (unsaved) models for one chunk.\n */\nasync function assignIdBlock<TModel extends Model>(\n ModelClass: ChildModel<TModel>,\n models: TModel[],\n): Promise<void> {\n if (!ModelClass.autoGenerateId || ModelClass.randomInitialId || ModelClass.randomIncrement) {\n return;\n }\n\n const idGenerator = ModelClass.getDataSource().idGenerator;\n\n if (!idGenerator || typeof idGenerator.generateNextIds !== \"function\") {\n return;\n }\n\n const idLessModels = models.filter((model) => !model.get(\"id\"));\n\n if (idLessModels.length === 0) {\n return;\n }\n\n const ids = await idGenerator.generateNextIds({\n table: ModelClass.table,\n initialId: ModelClass.initialId || 1,\n incrementIdBy: ModelClass.incrementIdBy || 1,\n count: idLessModels.length,\n });\n\n // Enforce the contract at this pluggable, feature-detected boundary: a\n // non-conforming generator returning the wrong count would otherwise set\n // `id = undefined` on the unmatched rows, the per-row writer would silently\n // re-generate single ids, and the reserved block would no longer match what\n // is persisted. Fail loud instead of corrupting the sequence.\n if (ids.length !== idLessModels.length) {\n throw new Error(\n `generateNextIds returned ${ids.length} id(s) for ${idLessModels.length} row(s) on ` +\n `\"${ModelClass.table}\" — a batch id generator must return exactly the requested count.`,\n );\n }\n\n idLessModels.forEach((model, index) => {\n model.set(\"id\", ids[index]);\n });\n}\n\n/**\n * Bulk variant of {@link createManyRecords}: prep each row through the writer\n * pipeline (validation, casting, timestamps, defaults, id-generation) without\n * touching the database, then flush each chunk with a single\n * `driver.insertMany` call.\n *\n * The writer reuse goes through `DatabaseWriter.prepareForInsert()`, the same\n * pipeline `save()` uses for an insert, so the shared driver is never mutated\n * and concurrent `save()` calls are unaffected.\n *\n * @param ModelClass - The model class to create records for.\n * @param chunks - Pre-chunked rows.\n * @returns The created model instances with driver-returned values merged in.\n */\nasync function createManyBulk<\n TModel extends Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n>(ModelClass: ChildModel<TModel>, chunks: Partial<TSchema>[][]): Promise<TModel[]> {\n const dataSource = ModelClass.getDataSource();\n const driver = dataSource.driver;\n const table = ModelClass.table;\n\n const created: TModel[] = [];\n\n {\n for (const chunk of chunks) {\n const models = chunk.map((item) => new ModelClass(item)) as TModel[];\n\n // Reserve one contiguous id block for the whole chunk (1 counter op\n // instead of N), pre-seeding each id-less model so the per-row writer's\n // id generation no-ops.\n await assignIdBlock(ModelClass, models);\n\n // Prep every model through the real writer pipeline. The captured\n // `insert` keeps this off the wire while still mutating each model's\n // data with casts/timestamps/defaults/generated ids.\n const preparedDocuments = await Promise.all(\n models.map(async (model) => {\n const document = await new DatabaseWriter(model).prepareForInsert({\n skipEvents: true,\n skipSync: true,\n });\n return { ...document } as Record<string, unknown>;\n }),\n );\n\n const results = await driver.insertMany(table, preparedDocuments);\n\n // Merge driver-returned values (generated _id, timestamps, RETURNING *)\n // back onto each model so the returned instances reflect persisted state.\n models.forEach((model, index) => {\n const result = results[index] as InsertResult | Record<string, unknown> | undefined;\n\n if (result) {\n const returnedDocument =\n \"document\" in (result as Record<string, unknown>)\n ? (result as InsertResult).document\n : result;\n\n // Driver-returned identity (generated _id / RETURNING *) — merged\n // through the framework-internal path so it is not treated as mass\n // assignment on a model the writer has already marked persisted.\n mergeDriverFields(model, returnedDocument as Record<string, unknown>);\n }\n\n model.dirtyTracker.reset();\n model.isNew = false;\n });\n\n created.push(...models);\n }\n }\n\n return created;\n}\n\nexport async function findOrCreateRecord<\n TModel extends Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n>(\n ModelClass: ChildModel<TModel>,\n filter: Partial<TSchema>,\n data: Partial<TSchema>,\n): Promise<TModel> {\n const existing = await ModelClass.first(filter as Record<string, unknown>);\n\n if (existing) {\n return existing;\n }\n\n return await createRecord(ModelClass, { ...filter, ...data } as Partial<TSchema>);\n}\n\nexport async function upsertRecord<\n TModel extends Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n>(\n ModelClass: ChildModel<TModel>,\n filter: Partial<TSchema>,\n data: Partial<TSchema>,\n options?: Record<string, unknown>,\n): Promise<TModel> {\n const driver = ModelClass.getDriver();\n const safeFilter = sanitizeFilter(filter as Record<string, unknown>);\n const mergedData = { ...safeFilter, ...data } as Record<string, unknown>;\n\n const tempModel = new ModelClass(mergedData as Partial<TSchema>);\n tempModel.isNew = true;\n\n // One `saving` run against the model itself, so listener changes (slug,\n // createdBy, ...) land in the data that is written.\n await emitModelEvent(tempModel, \"saving\", {\n isInsert: true,\n options,\n mode: \"upsert\",\n });\n\n // Validation, casting and Mongo id generation, same as `create()`.\n await new DatabaseWriter(tempModel).prepareForUpsert();\n\n const setData: Record<string, unknown> = { ...tempModel.data };\n const setOnInsert: Record<string, unknown> = {};\n const now = new Date();\n\n // Identity and creation time belong to the insert only; an existing row\n // keeps its own.\n for (const key of new Set([\"id\", \"_id\", ModelClass.primaryKey])) {\n if (key in setData) {\n setOnInsert[key] = setData[key];\n delete setData[key];\n }\n }\n\n const createdAtColumn = ModelClass.createdAtColumn;\n if (createdAtColumn) {\n setOnInsert[createdAtColumn] = setData[createdAtColumn] ?? now;\n delete setData[createdAtColumn];\n }\n\n const updatedAtColumn = ModelClass.updatedAtColumn;\n if (updatedAtColumn) {\n setData[updatedAtColumn] = now;\n }\n\n const result = await driver.findOneAndUpdate(\n ModelClass.table,\n safeFilter,\n { $set: setData, $setOnInsert: setOnInsert },\n { ...options, upsert: true, returnDocument: \"after\" },\n );\n\n const model = ModelClass.hydrate(result as Record<string, unknown>) as TModel;\n model.dirtyTracker.reset();\n\n await emitModelEvent(model, \"saved\", { filter: safeFilter, data: result, options, mode: \"upsert\" });\n\n return model;\n}\n"],"mappings":"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"}
@@ -1313,10 +1313,10 @@ declare abstract class Model<TSchema extends ModelSchema = ModelSchema> {
1313
1313
  * Find one and update multiple records that matches the provided filter and return the updated record
1314
1314
  * @param filter - Filter conditions
1315
1315
  * @param update - Update operators, or an aggregation pipeline (MongoDB only)
1316
- * @param options - `upsert`, `arrayFilters` (MongoDB only)
1316
+ * @param options - `upsert`, `arrayFilters` (MongoDB only), `trustedFilter`
1317
1317
  * @returns The updated records
1318
1318
  */
1319
- static findAndUpdate<TModel extends Model = Model>(this: ChildModel<TModel>, filter: Record<string, unknown>, update: AtomicUpdate, options?: Omit<AtomicUpdateOptions, "trustedFilter">): Promise<TModel[]>;
1319
+ static findAndUpdate<TModel extends Model = Model>(this: ChildModel<TModel>, filter: Record<string, unknown>, update: AtomicUpdate, options?: AtomicUpdateOptions): Promise<TModel[]>;
1320
1320
  /**
1321
1321
  * Find one and update a single record that matches the provided filter and return the updated record
1322
1322
  * @param filter - Filter conditions
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.mts","names":[],"sources":["../../../../../../../cascade/src/model/model.ts"],"mappings":"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"}
1
+ {"version":3,"file":"model.d.mts","names":[],"sources":["../../../../../../../cascade/src/model/model.ts"],"mappings":"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"}
@@ -1262,7 +1262,7 @@ var Model = class Model {
1262
1262
  * Find one and update multiple records that matches the provided filter and return the updated record
1263
1263
  * @param filter - Filter conditions
1264
1264
  * @param update - Update operators, or an aggregation pipeline (MongoDB only)
1265
- * @param options - `upsert`, `arrayFilters` (MongoDB only)
1265
+ * @param options - `upsert`, `arrayFilters` (MongoDB only), `trustedFilter`
1266
1266
  * @returns The updated records
1267
1267
  */
1268
1268
  static async findAndUpdate(filter, update, options) {