@warlock.js/cascade 4.8.2 → 4.9.1
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.
- package/CHANGELOG.md +13 -0
- package/cjs/index.cjs +172 -127
- package/cjs/index.cjs.map +1 -1
- package/esm/context/database-data-source-context.d.mts +1 -1
- package/esm/context/database-data-source-context.d.mts.map +1 -1
- package/esm/context/database-data-source-context.mjs +1 -1
- package/esm/context/database-data-source-context.mjs.map +1 -1
- package/esm/context/database-transaction-context.d.mts +1 -1
- package/esm/context/database-transaction-context.d.mts.map +1 -1
- package/esm/context/database-transaction-context.mjs +1 -1
- package/esm/context/database-transaction-context.mjs.map +1 -1
- package/esm/contracts/database-driver.contract.d.mts +1 -1
- package/esm/contracts/database-driver.contract.d.mts.map +1 -1
- package/esm/contracts/database-id-generator.contract.d.mts +1 -1
- package/esm/contracts/database-id-generator.contract.d.mts.map +1 -1
- package/esm/contracts/database-remover.contract.d.mts +1 -1
- package/esm/contracts/database-remover.contract.d.mts.map +1 -1
- package/esm/contracts/database-restorer.contract.d.mts +1 -1
- package/esm/contracts/database-restorer.contract.d.mts.map +1 -1
- package/esm/contracts/database-writer.contract.d.mts +1 -1
- package/esm/contracts/database-writer.contract.d.mts.map +1 -1
- package/esm/contracts/driver-blueprint.contract.d.mts +1 -1
- package/esm/contracts/driver-blueprint.contract.d.mts.map +1 -1
- package/esm/contracts/migration-driver.contract.d.mts +1 -1
- package/esm/contracts/migration-driver.contract.d.mts.map +1 -1
- package/esm/contracts/query-builder.contract.d.mts +1 -1
- package/esm/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/contracts/sync-adapter.contract.d.mts +1 -1
- package/esm/contracts/sync-adapter.contract.d.mts.map +1 -1
- package/esm/data-source/data-source-registry.d.mts +1 -1
- package/esm/data-source/data-source-registry.d.mts.map +1 -1
- package/esm/data-source/data-source-registry.mjs +1 -1
- package/esm/data-source/data-source-registry.mjs.map +1 -1
- package/esm/data-source/data-source.d.mts +1 -1
- package/esm/data-source/data-source.d.mts.map +1 -1
- package/esm/data-source/data-source.mjs +1 -1
- package/esm/data-source/data-source.mjs.map +1 -1
- package/esm/database-dirty-tracker.d.mts +12 -3
- package/esm/database-dirty-tracker.d.mts.map +1 -1
- package/esm/database-dirty-tracker.mjs +13 -4
- package/esm/database-dirty-tracker.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-blueprint.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-blueprint.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-operations.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-query-operations.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-operations.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-query-operations.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-sync-adapter.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-sync-adapter.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-sync-adapter.mjs +1 -1
- package/esm/drivers/mongodb/mongodb-sync-adapter.mjs.map +1 -1
- package/esm/drivers/mongodb/types.d.mts +1 -1
- package/esm/drivers/mongodb/types.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-blueprint.d.mts +1 -1
- package/esm/drivers/postgres/postgres-blueprint.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-blueprint.mjs +1 -1
- package/esm/drivers/postgres/postgres-blueprint.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-dialect.d.mts +1 -1
- package/esm/drivers/postgres/postgres-dialect.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-dialect.mjs +1 -1
- package/esm/drivers/postgres/postgres-dialect.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-driver.d.mts +1 -1
- package/esm/drivers/postgres/postgres-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.d.mts +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.mjs +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-builder.d.mts +1 -1
- package/esm/drivers/postgres/postgres-query-builder.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-builder.mjs +1 -1
- package/esm/drivers/postgres/postgres-query-builder.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts +1 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.mjs +1 -1
- package/esm/drivers/postgres/postgres-query-parser.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-sql-serializer.mjs +1 -1
- package/esm/drivers/postgres/postgres-sql-serializer.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-sync-adapter.d.mts +1 -1
- package/esm/drivers/postgres/postgres-sync-adapter.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-sync-adapter.mjs +1 -1
- package/esm/drivers/postgres/postgres-sync-adapter.mjs.map +1 -1
- package/esm/drivers/postgres/types.d.mts +1 -1
- package/esm/drivers/postgres/types.d.mts.map +1 -1
- package/esm/drivers/sql/sql-dialect.contract.d.mts +1 -1
- package/esm/drivers/sql/sql-dialect.contract.d.mts.map +1 -1
- package/esm/drivers/sql/sql-types.d.mts +1 -1
- package/esm/drivers/sql/sql-types.d.mts.map +1 -1
- package/esm/errors/missing-data-source.error.d.mts +1 -1
- package/esm/errors/missing-data-source.error.d.mts.map +1 -1
- package/esm/errors/missing-data-source.error.mjs +1 -1
- package/esm/errors/missing-data-source.error.mjs.map +1 -1
- package/esm/errors/transaction-rollback.error.d.mts +1 -1
- package/esm/errors/transaction-rollback.error.d.mts.map +1 -1
- package/esm/errors/transaction-rollback.error.mjs +1 -1
- package/esm/errors/transaction-rollback.error.mjs.map +1 -1
- package/esm/events/model-events.d.mts +1 -1
- package/esm/events/model-events.d.mts.map +1 -1
- package/esm/events/model-events.mjs +1 -1
- package/esm/events/model-events.mjs.map +1 -1
- package/esm/expressions/aggregate-expressions.d.mts +1 -1
- package/esm/expressions/aggregate-expressions.d.mts.map +1 -1
- package/esm/expressions/aggregate-expressions.mjs +1 -1
- package/esm/expressions/aggregate-expressions.mjs.map +1 -1
- package/esm/expressions/column-expressions.d.mts +1 -1
- package/esm/expressions/column-expressions.d.mts.map +1 -1
- package/esm/expressions/column-expressions.mjs +1 -1
- package/esm/expressions/column-expressions.mjs.map +1 -1
- package/esm/migration/column-builder.d.mts +1 -1
- package/esm/migration/column-builder.d.mts.map +1 -1
- package/esm/migration/column-builder.mjs +1 -1
- package/esm/migration/column-builder.mjs.map +1 -1
- package/esm/migration/column-helpers.d.mts +1 -1
- package/esm/migration/column-helpers.d.mts.map +1 -1
- package/esm/migration/column-helpers.mjs +1 -1
- package/esm/migration/column-helpers.mjs.map +1 -1
- package/esm/migration/foreign-key-builder.d.mts +1 -1
- package/esm/migration/foreign-key-builder.d.mts.map +1 -1
- package/esm/migration/foreign-key-builder.mjs +1 -1
- package/esm/migration/foreign-key-builder.mjs.map +1 -1
- package/esm/migration/migration-runner.d.mts +1 -1
- package/esm/migration/migration-runner.d.mts.map +1 -1
- package/esm/migration/migration-runner.mjs +4 -40
- package/esm/migration/migration-runner.mjs.map +1 -1
- package/esm/migration/migration.d.mts +1 -1
- package/esm/migration/migration.d.mts.map +1 -1
- package/esm/migration/migration.mjs +1 -1
- package/esm/migration/migration.mjs.map +1 -1
- package/esm/migration/parse-created-at.mjs +67 -0
- package/esm/migration/parse-created-at.mjs.map +1 -0
- package/esm/migration/sql-grammar.mjs +16 -6
- package/esm/migration/sql-grammar.mjs.map +1 -1
- package/esm/migration/sql-serializer.d.mts +1 -1
- package/esm/migration/sql-serializer.d.mts.map +1 -1
- package/esm/migration/sql-serializer.mjs +1 -1
- package/esm/migration/sql-serializer.mjs.map +1 -1
- package/esm/migration/types.d.mts +1 -1
- package/esm/migration/types.d.mts.map +1 -1
- package/esm/model/methods/accessor-methods.mjs +1 -1
- package/esm/model/methods/accessor-methods.mjs.map +1 -1
- package/esm/model/methods/delete-methods.mjs +1 -1
- package/esm/model/methods/delete-methods.mjs.map +1 -1
- package/esm/model/methods/dirty-methods.mjs +1 -1
- package/esm/model/methods/dirty-methods.mjs.map +1 -1
- package/esm/model/methods/hydration-methods.mjs +1 -1
- package/esm/model/methods/hydration-methods.mjs.map +1 -1
- package/esm/model/methods/instance-event-methods.mjs +1 -1
- package/esm/model/methods/instance-event-methods.mjs.map +1 -1
- package/esm/model/methods/meta-methods.mjs +1 -1
- package/esm/model/methods/meta-methods.mjs.map +1 -1
- package/esm/model/methods/pivot-methods.mjs +1 -1
- package/esm/model/methods/pivot-methods.mjs.map +1 -1
- package/esm/model/methods/query-methods.mjs +1 -1
- package/esm/model/methods/query-methods.mjs.map +1 -1
- package/esm/model/methods/restore-methods.mjs +1 -1
- package/esm/model/methods/restore-methods.mjs.map +1 -1
- package/esm/model/methods/scope-methods.mjs +1 -1
- package/esm/model/methods/scope-methods.mjs.map +1 -1
- package/esm/model/methods/serialization-methods.mjs +1 -1
- package/esm/model/methods/serialization-methods.mjs.map +1 -1
- package/esm/model/methods/static-event-methods.mjs +1 -1
- package/esm/model/methods/static-event-methods.mjs.map +1 -1
- package/esm/model/methods/write-methods.d.mts +1 -1
- package/esm/model/methods/write-methods.d.mts.map +1 -1
- package/esm/model/methods/write-methods.mjs +1 -1
- package/esm/model/methods/write-methods.mjs.map +1 -1
- package/esm/model/model.d.mts +1 -1
- package/esm/model/model.d.mts.map +1 -1
- package/esm/model/model.mjs +1 -1
- package/esm/model/model.mjs.map +1 -1
- package/esm/model/model.types.d.mts +1 -1
- package/esm/model/model.types.d.mts.map +1 -1
- package/esm/model/register-model.d.mts +1 -1
- package/esm/model/register-model.d.mts.map +1 -1
- package/esm/model/register-model.mjs +1 -1
- package/esm/model/register-model.mjs.map +1 -1
- package/esm/model/relation-decorators.d.mts +1 -1
- package/esm/model/relation-decorators.d.mts.map +1 -1
- package/esm/model/relation-decorators.mjs +1 -1
- package/esm/model/relation-decorators.mjs.map +1 -1
- package/esm/operations/database.d.mts +1 -1
- package/esm/operations/database.d.mts.map +1 -1
- package/esm/operations/database.mjs +1 -1
- package/esm/operations/database.mjs.map +1 -1
- package/esm/operations/migrations.d.mts +1 -1
- package/esm/operations/migrations.d.mts.map +1 -1
- package/esm/operations/migrations.mjs +1 -1
- package/esm/operations/migrations.mjs.map +1 -1
- package/esm/query-builder/query-builder.d.mts +1 -1
- package/esm/query-builder/query-builder.d.mts.map +1 -1
- package/esm/query-builder/query-builder.mjs +1 -1
- package/esm/query-builder/query-builder.mjs.map +1 -1
- package/esm/relations/key-conventions.mjs +1 -1
- package/esm/relations/key-conventions.mjs.map +1 -1
- package/esm/relations/pivot-operations.d.mts +1 -1
- package/esm/relations/pivot-operations.d.mts.map +1 -1
- package/esm/relations/pivot-operations.mjs +1 -1
- package/esm/relations/pivot-operations.mjs.map +1 -1
- package/esm/relations/relation-hydrator.d.mts +1 -1
- package/esm/relations/relation-hydrator.d.mts.map +1 -1
- package/esm/relations/relation-hydrator.mjs +1 -1
- package/esm/relations/relation-hydrator.mjs.map +1 -1
- package/esm/relations/relation-loader.d.mts +1 -1
- package/esm/relations/relation-loader.d.mts.map +1 -1
- package/esm/relations/relation-loader.mjs +1 -1
- package/esm/relations/relation-loader.mjs.map +1 -1
- package/esm/relations/types.d.mts +1 -1
- package/esm/relations/types.d.mts.map +1 -1
- package/esm/remover/database-remover.d.mts +1 -1
- package/esm/remover/database-remover.d.mts.map +1 -1
- package/esm/remover/database-remover.mjs +1 -1
- package/esm/remover/database-remover.mjs.map +1 -1
- package/esm/restorer/database-restorer.d.mts +1 -1
- package/esm/restorer/database-restorer.d.mts.map +1 -1
- package/esm/restorer/database-restorer.mjs +1 -1
- package/esm/restorer/database-restorer.mjs.map +1 -1
- package/esm/sql-database-dirty-tracker.d.mts +1 -1
- package/esm/sql-database-dirty-tracker.d.mts.map +1 -1
- package/esm/sql-database-dirty-tracker.mjs +1 -1
- package/esm/sql-database-dirty-tracker.mjs.map +1 -1
- package/esm/sync/model-events.mjs +1 -1
- package/esm/sync/model-events.mjs.map +1 -1
- package/esm/sync/model-sync-operation.d.mts +1 -1
- package/esm/sync/model-sync-operation.d.mts.map +1 -1
- package/esm/sync/model-sync-operation.mjs +1 -1
- package/esm/sync/model-sync-operation.mjs.map +1 -1
- package/esm/sync/model-sync.d.mts +1 -1
- package/esm/sync/model-sync.d.mts.map +1 -1
- package/esm/sync/model-sync.mjs +1 -1
- package/esm/sync/model-sync.mjs.map +1 -1
- package/esm/sync/sync-context.d.mts +1 -1
- package/esm/sync/sync-context.d.mts.map +1 -1
- package/esm/sync/sync-context.mjs +1 -1
- package/esm/sync/sync-context.mjs.map +1 -1
- package/esm/sync/sync-manager.d.mts +1 -1
- package/esm/sync/sync-manager.d.mts.map +1 -1
- package/esm/sync/sync-manager.mjs +1 -1
- package/esm/sync/sync-manager.mjs.map +1 -1
- package/esm/sync/types.d.mts +1 -1
- package/esm/sync/types.d.mts.map +1 -1
- package/esm/types.d.mts +1 -1
- package/esm/types.d.mts.map +1 -1
- package/esm/utils/connect-to-database.d.mts +1 -1
- package/esm/utils/connect-to-database.d.mts.map +1 -1
- package/esm/utils/connect-to-database.mjs +1 -1
- package/esm/utils/connect-to-database.mjs.map +1 -1
- package/esm/utils/database-writer.utils.d.mts +1 -1
- package/esm/utils/database-writer.utils.d.mts.map +1 -1
- package/esm/utils/database-writer.utils.mjs +1 -1
- package/esm/utils/database-writer.utils.mjs.map +1 -1
- package/esm/utils/define-model.d.mts +1 -1
- package/esm/utils/define-model.d.mts.map +1 -1
- package/esm/utils/define-model.mjs +1 -1
- package/esm/utils/define-model.mjs.map +1 -1
- package/esm/utils/is-valid-date-value.mjs +1 -1
- package/esm/utils/is-valid-date-value.mjs.map +1 -1
- package/esm/utils/once-connected.d.mts +1 -1
- package/esm/utils/once-connected.d.mts.map +1 -1
- package/esm/utils/once-connected.mjs +1 -1
- package/esm/utils/once-connected.mjs.map +1 -1
- package/esm/validation/database-seal-plugins.mjs +1 -1
- package/esm/validation/database-seal-plugins.mjs.map +1 -1
- package/esm/validation/database-writer-validation-error.d.mts +1 -1
- package/esm/validation/database-writer-validation-error.d.mts.map +1 -1
- package/esm/validation/database-writer-validation-error.mjs +1 -1
- package/esm/validation/database-writer-validation-error.mjs.map +1 -1
- package/esm/validation/mutators/embed-mutator.mjs +1 -1
- package/esm/validation/mutators/embed-mutator.mjs.map +1 -1
- package/esm/validation/plugins/database-rules-plugin.d.mts +1 -1
- package/esm/validation/plugins/database-rules-plugin.d.mts.map +1 -1
- package/esm/validation/plugins/database-rules-plugin.mjs +1 -1
- package/esm/validation/plugins/database-rules-plugin.mjs.map +1 -1
- package/esm/validation/plugins/embed-validator-plugin.d.mts +1 -1
- package/esm/validation/plugins/embed-validator-plugin.d.mts.map +1 -1
- package/esm/validation/plugins/embed-validator-plugin.mjs +1 -1
- package/esm/validation/plugins/embed-validator-plugin.mjs.map +1 -1
- package/esm/validation/rules/database-model-rule.mjs +1 -1
- package/esm/validation/rules/database-model-rule.mjs.map +1 -1
- package/esm/validation/rules/exists-rule.mjs +1 -1
- package/esm/validation/rules/exists-rule.mjs.map +1 -1
- package/esm/validation/rules/unique-rule.mjs +1 -1
- package/esm/validation/rules/unique-rule.mjs.map +1 -1
- package/esm/validation/transformers/embed-model-transformer.mjs +1 -1
- package/esm/validation/transformers/embed-model-transformer.mjs.map +1 -1
- package/esm/validation/types.d.mts +1 -1
- package/esm/validation/types.d.mts.map +1 -1
- package/esm/validation/validators/embed-validator.d.mts +1 -1
- package/esm/validation/validators/embed-validator.d.mts.map +1 -1
- package/esm/validation/validators/embed-validator.mjs +1 -1
- package/esm/validation/validators/embed-validator.mjs.map +1 -1
- package/esm/writer/database-writer.d.mts +1 -1
- package/esm/writer/database-writer.d.mts.map +1 -1
- package/esm/writer/database-writer.mjs +1 -1
- package/esm/writer/database-writer.mjs.map +1 -1
- package/llms-full.txt +32 -0
- package/package.json +4 -4
- package/skills/track-changes/SKILL.md +18 -0
- package/skills/write-migration/SKILL.md +14 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"missing-data-source.error.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"missing-data-source.error.mjs","names":[],"sources":["../../../../../../../cascade/src/errors/missing-data-source.error.ts"],"sourcesContent":["/**\n * Error thrown when a requested data source is not found in the registry.\n *\n * This can occur when:\n * - Attempting to retrieve a non-existent named data source\n * - Trying to get the default data source before any have been registered\n * - Context override references an unregistered data source name\n */\nexport class MissingDataSourceError extends Error {\n /**\n * The name of the data source that was not found (if applicable).\n */\n public readonly dataSourceName?: string;\n\n /**\n * Creates a new MissingDataSourceError.\n *\n * @param message - Descriptive error message\n * @param dataSourceName - Optional data source name that was not found\n */\n public constructor(message: string, dataSourceName?: string) {\n super(message);\n this.name = \"MissingDataSourceError\";\n this.dataSourceName = dataSourceName;\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, MissingDataSourceError);\n }\n }\n}\n"],"mappings":";;;;;;;;;AAQA,IAAa,yBAAb,MAAa,+BAA+B,MAAM;;;;CAIhD,AAAgB;;;;;;;CAQhB,AAAO,YAAY,SAAiB,gBAAyB;EAC3D,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,iBAAiB;EAGtB,IAAI,MAAM,mBACR,MAAM,kBAAkB,MAAM,sBAAsB;CAExD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-rollback.error.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"transaction-rollback.error.d.mts","names":[],"sources":["../../../../../../../cascade/src/errors/transaction-rollback.error.ts"],"mappings":";;AAOA;;;;;;cAAa,wBAAA,SAAiC,KAAK;EAW9B;;AAAe;EAAf,SAPH,MAAA;;;;;;cAOG,MAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-rollback.error.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"transaction-rollback.error.mjs","names":[],"sources":["../../../../../../../cascade/src/errors/transaction-rollback.error.ts"],"sourcesContent":["/**\n * Error thrown when a transaction is explicitly rolled back via ctx.rollback().\n *\n * This error is used to signal transaction rollback without representing\n * an application error. It's caught by the transaction wrapper to perform\n * cleanup and then re-thrown.\n */\nexport class TransactionRollbackError extends Error {\n /**\n * The reason for the rollback (if provided).\n */\n public readonly reason?: string;\n\n /**\n * Creates a new TransactionRollbackError.\n *\n * @param reason - Optional reason for rollback (for logging/debugging)\n */\n public constructor(reason?: string) {\n super(reason || \"Transaction rolled back\");\n this.name = \"TransactionRollbackError\";\n this.reason = reason;\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TransactionRollbackError);\n }\n }\n}\n"],"mappings":";;;;;;;;AAOA,IAAa,2BAAb,MAAa,iCAAiC,MAAM;;;;CAIlD,AAAgB;;;;;;CAOhB,AAAO,YAAY,QAAiB;EAClC,MAAM,UAAU,yBAAyB;EACzC,KAAK,OAAO;EACZ,KAAK,SAAS;EAGd,IAAI,MAAM,mBACR,MAAM,kBAAkB,MAAM,wBAAwB;CAE1D;AACF"}
|
|
@@ -2,7 +2,7 @@ import { DeleteStrategy } from "../types.mjs";
|
|
|
2
2
|
import { ModelSchema } from "../model/model.types.mjs";
|
|
3
3
|
import { Model } from "../model/model.mjs";
|
|
4
4
|
import { QueryBuilderContract } from "../contracts/query-builder.contract.mjs";
|
|
5
|
-
//#region
|
|
5
|
+
//#region ../cascade/src/events/model-events.d.ts
|
|
6
6
|
type OnValidatingEventContext = {
|
|
7
7
|
isInsert: boolean;
|
|
8
8
|
mode: "insert" | "update";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-events.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"model-events.d.mts","names":[],"sources":["../../../../../../../cascade/src/events/model-events.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-events.mjs","names":[],"sources":["../../../../../../../@warlock.js/cascade/src/events/model-events.ts"],"sourcesContent":["import { QueryBuilderContract } from \"../contracts\";\r\nimport type { Model } from \"../model/model\";\r\nimport { DeleteStrategy } from \"../types\";\r\n\r\ntype OnValidatingEventContext = {\r\n isInsert: boolean;\r\n mode: \"insert\" | \"update\";\r\n};\r\n\r\ntype OnSavingEventContext = {\r\n isInsert: boolean;\r\n mode: \"insert\" | \"update\";\r\n};\r\n\r\ntype OnDeletingEventContext = {\r\n strategy: DeleteStrategy;\r\n primaryKeyValue: string | number;\r\n primaryKey: string;\r\n};\r\n\r\nexport type OnDeletedEventContext = OnDeletingEventContext & {\r\n deletedCount: number;\r\n trashRecord?: Record<string, unknown>;\r\n};\r\n\r\ntype OnFetchingEventContext = {\r\n table: string;\r\n modelClass: any;\r\n};\r\n\r\ntype OnHydratingEventContext = {\r\n query: QueryBuilderContract;\r\n hydrateCallback?: (data: any, index: number) => any;\r\n};\r\n\r\ntype OnFetchedEventContext = {\r\n query: QueryBuilderContract;\r\n rawRecords: any[];\r\n duration: number;\r\n};\r\n\r\n/**\r\n * Lifecycle events understood by Cascade models.\r\n *\r\n * The list mirrors the hooks in the legacy ORM so downstream code can subscribe\r\n * with consistent semantics.\r\n */\r\nexport type ModelEventName =\r\n | \"initializing\"\r\n | \"fetching\"\r\n | \"hydrating\"\r\n | \"fetched\"\r\n | \"validating\"\r\n | \"validated\"\r\n | \"saving\"\r\n | \"saved\"\r\n | \"creating\"\r\n | \"created\"\r\n | \"updating\"\r\n | \"updated\"\r\n | \"deleting\"\r\n | \"deleted\"\r\n | \"restoring\"\r\n | \"restored\";\r\n\r\n/** Signature of an event listener registered against a model lifecycle hook. */\r\nexport type ModelEventListener<TModel, TContext = unknown> = (\r\n model: TModel,\r\n context: TContext,\r\n) => void | Promise<void>;\r\n\r\n/**\r\n * Light-weight async event emitter used to power model lifecycle hooks.\r\n *\r\n * The implementation intentionally avoids any external dependency so we can\r\n * re-use it in drivers, writers, and other core services without pulling in\r\n * heavier event libraries.\r\n */\r\nexport class ModelEvents<TModel> {\r\n public readonly listeners = new Map<ModelEventName, Set<ModelEventListener<TModel>>>();\r\n\r\n /**\r\n * Register a listener for the given event.\r\n * Returns an unsubscribe function for convenience.\r\n */\r\n public on<TContext = unknown>(\r\n event: ModelEventName,\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n const listeners = this.ensureListenerSet(event);\r\n listeners.add(listener as ModelEventListener<TModel>);\r\n return () => this.off(event, listener);\r\n }\r\n\r\n /**\r\n * Register a listener that automatically unsubscribes after the first call.\r\n */\r\n public once<TContext = unknown>(\r\n event: ModelEventName,\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n const wrapper: ModelEventListener<TModel, TContext> = async (model, context) => {\r\n try {\r\n await listener(model, context);\r\n } finally {\r\n this.off(event, wrapper);\r\n }\r\n };\r\n return this.on(event, wrapper);\r\n }\r\n\r\n /**\r\n * Deregister a listener for the given event.\r\n */\r\n public off<TContext = unknown>(\r\n event: ModelEventName,\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): void {\r\n const listeners = this.listeners.get(event);\r\n if (!listeners) {\r\n return;\r\n }\r\n listeners.delete(listener as ModelEventListener<TModel>);\r\n if (listeners.size === 0) {\r\n this.listeners.delete(event);\r\n }\r\n }\r\n\r\n /**\r\n * Emit an event to all registered listeners.\r\n */\r\n public async emit<TContext = unknown>(\r\n event: ModelEventName,\r\n model: TModel,\r\n context: TContext,\r\n ): Promise<void> {\r\n const listeners = this.listeners.get(event);\r\n if (!listeners || listeners.size === 0) {\r\n return;\r\n }\r\n for (const listener of Array.from(listeners)) {\r\n await listener(model, context);\r\n }\r\n }\r\n\r\n /**\r\n * Emit events for fetching\r\n */\r\n public async emitFetching<TContext = unknown>(\r\n query: QueryBuilderContract,\r\n context?: TContext,\r\n ): Promise<void> {\r\n await this.emit(\"fetching\", query as any, context);\r\n }\r\n\r\n /**\r\n * Remove all registered listeners.\r\n */\r\n public clear(): void {\r\n this.listeners.clear();\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"saving\" event.\r\n *\r\n * Fired before a model is persisted (both insert and update), and before validation.\r\n * Use this hook for data enrichment and preparation (e.g., setting createdBy, updatedBy).\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onSaving<TContext = OnSavingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"saving\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"saved\" event.\r\n *\r\n * Fired after a model has been successfully persisted.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onSaved<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\r\n return this.on(\"saved\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"creating\" event.\r\n *\r\n * Fired before a new model is inserted into the database.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onCreating<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"creating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"created\" event.\r\n *\r\n * Fired after a new model has been successfully inserted.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onCreated<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\r\n return this.on(\"created\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"updating\" event.\r\n *\r\n * Fired before an existing model is updated in the database.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onUpdating<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"updating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"updated\" event.\r\n *\r\n * Fired after an existing model has been successfully updated.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onUpdated<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\r\n return this.on(\"updated\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"deleting\" event.\r\n *\r\n * Fired before a model is deleted from the database.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onDeleting<TContext = OnDeletingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"deleting\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"deleted\" event.\r\n *\r\n * Fired after a model has been successfully deleted.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onDeleted<TContext = OnDeletedEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"deleted\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"validating\" event.\r\n *\r\n * Fired before model validation is performed.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onValidating<TContext = OnValidatingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"validating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"validated\" event.\r\n *\r\n * Fired after model validation has completed.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onValidated<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"validated\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"fetching\" event.\r\n *\r\n * Fired before a query is executed to fetch models.\r\n * Receives the query builder instance, allowing modification before execution.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onFetching<TContext = OnFetchingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"fetching\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"hydrating\" event.\r\n *\r\n * Fired after raw records are fetched but before they are hydrated into model instances.\r\n * Allows modification of raw data before hydration.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onHydrating<TContext = OnHydratingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"hydrating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"fetched\" event.\r\n *\r\n * Fired after models have been fetched and hydrated.\r\n * Receives hydrated model instances and query context.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onFetched<TContext = OnFetchedEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"fetched\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"restoring\" event.\r\n *\r\n * Fired before a soft-deleted model is restored.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onRestoring<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"restoring\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"restored\" event.\r\n *\r\n * Fired after a soft-deleted model has been successfully restored.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onRestored<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"restored\", listener);\r\n }\r\n\r\n /**\r\n * Ensures a listener set exists for the given event.\r\n *\r\n * @param event - The event name\r\n * @returns The listener set for the event\r\n * @private\r\n */\r\n private ensureListenerSet(event: ModelEventName): Set<ModelEventListener<TModel>> {\r\n let listeners = this.listeners.get(event);\r\n if (!listeners) {\r\n listeners = new Set();\r\n this.listeners.set(event, listeners);\r\n }\r\n return listeners;\r\n }\r\n}\r\n\r\n/**\r\n * Global event emitter invoked for every model instance, regardless of type.\r\n * Useful for cross-cutting concerns like auditing or request-scoped enrichment.\r\n */\r\nexport const globalModelEvents = new ModelEvents<Model>();\r\n"],"mappings":";;;;;;;;AA8EA,IAAa,cAAb,MAAiC;CAC/B,AAAgB,4BAAY,IAAI,IAAqD;;;;;CAMrF,AAAO,GACL,OACA,UACY;EAEZ,AADkB,KAAK,kBAAkB,KACjC,CAAC,CAAC,IAAI,QAAsC;EACpD,aAAa,KAAK,IAAI,OAAO,QAAQ;CACvC;;;;CAKA,AAAO,KACL,OACA,UACY;EACZ,MAAM,UAAgD,OAAO,OAAO,YAAY;GAC9E,IAAI;IACF,MAAM,SAAS,OAAO,OAAO;GAC/B,UAAU;IACR,KAAK,IAAI,OAAO,OAAO;GACzB;EACF;EACA,OAAO,KAAK,GAAG,OAAO,OAAO;CAC/B;;;;CAKA,AAAO,IACL,OACA,UACM;EACN,MAAM,YAAY,KAAK,UAAU,IAAI,KAAK;EAC1C,IAAI,CAAC,WACH;EAEF,UAAU,OAAO,QAAsC;EACvD,IAAI,UAAU,SAAS,GACrB,KAAK,UAAU,OAAO,KAAK;CAE/B;;;;CAKA,MAAa,KACX,OACA,OACA,SACe;EACf,MAAM,YAAY,KAAK,UAAU,IAAI,KAAK;EAC1C,IAAI,CAAC,aAAa,UAAU,SAAS,GACnC;EAEF,KAAK,MAAM,YAAY,MAAM,KAAK,SAAS,GACzC,MAAM,SAAS,OAAO,OAAO;CAEjC;;;;CAKA,MAAa,aACX,OACA,SACe;EACf,MAAM,KAAK,KAAK,YAAY,OAAc,OAAO;CACnD;;;;CAKA,AAAO,QAAc;EACnB,KAAK,UAAU,MAAM;CACvB;;;;;;;;;;CAWA,AAAO,SACL,UACY;EACZ,OAAO,KAAK,GAAG,UAAU,QAAQ;CACnC;;;;;;;;;CAUA,AAAO,QAA4B,UAA4D;EAC7F,OAAO,KAAK,GAAG,SAAS,QAAQ;CAClC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;CAUA,AAAO,UAA8B,UAA4D;EAC/F,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;CAUA,AAAO,UAA8B,UAA4D;EAC/F,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;CAUA,AAAO,UACL,UACY;EACZ,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,aACL,UACY;EACZ,OAAO,KAAK,GAAG,cAAc,QAAQ;CACvC;;;;;;;;;CAUA,AAAO,YACL,UACY;EACZ,OAAO,KAAK,GAAG,aAAa,QAAQ;CACtC;;;;;;;;;;CAWA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;;CAWA,AAAO,YACL,UACY;EACZ,OAAO,KAAK,GAAG,aAAa,QAAQ;CACtC;;;;;;;;;;CAWA,AAAO,UACL,UACY;EACZ,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,YACL,UACY;EACZ,OAAO,KAAK,GAAG,aAAa,QAAQ;CACtC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;CASA,AAAQ,kBAAkB,OAAwD;EAChF,IAAI,YAAY,KAAK,UAAU,IAAI,KAAK;EACxC,IAAI,CAAC,WAAW;GACd,4BAAY,IAAI,IAAI;GACpB,KAAK,UAAU,IAAI,OAAO,SAAS;EACrC;EACA,OAAO;CACT;AACF;;;;;AAMA,MAAa,oBAAoB,IAAI,YAAmB"}
|
|
1
|
+
{"version":3,"file":"model-events.mjs","names":[],"sources":["../../../../../../../cascade/src/events/model-events.ts"],"sourcesContent":["import { QueryBuilderContract } from \"../contracts\";\r\nimport type { Model } from \"../model/model\";\r\nimport { DeleteStrategy } from \"../types\";\r\n\r\ntype OnValidatingEventContext = {\r\n isInsert: boolean;\r\n mode: \"insert\" | \"update\";\r\n};\r\n\r\ntype OnSavingEventContext = {\r\n isInsert: boolean;\r\n mode: \"insert\" | \"update\";\r\n};\r\n\r\ntype OnDeletingEventContext = {\r\n strategy: DeleteStrategy;\r\n primaryKeyValue: string | number;\r\n primaryKey: string;\r\n};\r\n\r\nexport type OnDeletedEventContext = OnDeletingEventContext & {\r\n deletedCount: number;\r\n trashRecord?: Record<string, unknown>;\r\n};\r\n\r\ntype OnFetchingEventContext = {\r\n table: string;\r\n modelClass: any;\r\n};\r\n\r\ntype OnHydratingEventContext = {\r\n query: QueryBuilderContract;\r\n hydrateCallback?: (data: any, index: number) => any;\r\n};\r\n\r\ntype OnFetchedEventContext = {\r\n query: QueryBuilderContract;\r\n rawRecords: any[];\r\n duration: number;\r\n};\r\n\r\n/**\r\n * Lifecycle events understood by Cascade models.\r\n *\r\n * The list mirrors the hooks in the legacy ORM so downstream code can subscribe\r\n * with consistent semantics.\r\n */\r\nexport type ModelEventName =\r\n | \"initializing\"\r\n | \"fetching\"\r\n | \"hydrating\"\r\n | \"fetched\"\r\n | \"validating\"\r\n | \"validated\"\r\n | \"saving\"\r\n | \"saved\"\r\n | \"creating\"\r\n | \"created\"\r\n | \"updating\"\r\n | \"updated\"\r\n | \"deleting\"\r\n | \"deleted\"\r\n | \"restoring\"\r\n | \"restored\";\r\n\r\n/** Signature of an event listener registered against a model lifecycle hook. */\r\nexport type ModelEventListener<TModel, TContext = unknown> = (\r\n model: TModel,\r\n context: TContext,\r\n) => void | Promise<void>;\r\n\r\n/**\r\n * Light-weight async event emitter used to power model lifecycle hooks.\r\n *\r\n * The implementation intentionally avoids any external dependency so we can\r\n * re-use it in drivers, writers, and other core services without pulling in\r\n * heavier event libraries.\r\n */\r\nexport class ModelEvents<TModel> {\r\n public readonly listeners = new Map<ModelEventName, Set<ModelEventListener<TModel>>>();\r\n\r\n /**\r\n * Register a listener for the given event.\r\n * Returns an unsubscribe function for convenience.\r\n */\r\n public on<TContext = unknown>(\r\n event: ModelEventName,\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n const listeners = this.ensureListenerSet(event);\r\n listeners.add(listener as ModelEventListener<TModel>);\r\n return () => this.off(event, listener);\r\n }\r\n\r\n /**\r\n * Register a listener that automatically unsubscribes after the first call.\r\n */\r\n public once<TContext = unknown>(\r\n event: ModelEventName,\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n const wrapper: ModelEventListener<TModel, TContext> = async (model, context) => {\r\n try {\r\n await listener(model, context);\r\n } finally {\r\n this.off(event, wrapper);\r\n }\r\n };\r\n return this.on(event, wrapper);\r\n }\r\n\r\n /**\r\n * Deregister a listener for the given event.\r\n */\r\n public off<TContext = unknown>(\r\n event: ModelEventName,\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): void {\r\n const listeners = this.listeners.get(event);\r\n if (!listeners) {\r\n return;\r\n }\r\n listeners.delete(listener as ModelEventListener<TModel>);\r\n if (listeners.size === 0) {\r\n this.listeners.delete(event);\r\n }\r\n }\r\n\r\n /**\r\n * Emit an event to all registered listeners.\r\n */\r\n public async emit<TContext = unknown>(\r\n event: ModelEventName,\r\n model: TModel,\r\n context: TContext,\r\n ): Promise<void> {\r\n const listeners = this.listeners.get(event);\r\n if (!listeners || listeners.size === 0) {\r\n return;\r\n }\r\n for (const listener of Array.from(listeners)) {\r\n await listener(model, context);\r\n }\r\n }\r\n\r\n /**\r\n * Emit events for fetching\r\n */\r\n public async emitFetching<TContext = unknown>(\r\n query: QueryBuilderContract,\r\n context?: TContext,\r\n ): Promise<void> {\r\n await this.emit(\"fetching\", query as any, context);\r\n }\r\n\r\n /**\r\n * Remove all registered listeners.\r\n */\r\n public clear(): void {\r\n this.listeners.clear();\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"saving\" event.\r\n *\r\n * Fired before a model is persisted (both insert and update), and before validation.\r\n * Use this hook for data enrichment and preparation (e.g., setting createdBy, updatedBy).\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onSaving<TContext = OnSavingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"saving\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"saved\" event.\r\n *\r\n * Fired after a model has been successfully persisted.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onSaved<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\r\n return this.on(\"saved\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"creating\" event.\r\n *\r\n * Fired before a new model is inserted into the database.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onCreating<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"creating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"created\" event.\r\n *\r\n * Fired after a new model has been successfully inserted.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onCreated<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\r\n return this.on(\"created\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"updating\" event.\r\n *\r\n * Fired before an existing model is updated in the database.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onUpdating<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"updating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"updated\" event.\r\n *\r\n * Fired after an existing model has been successfully updated.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onUpdated<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\r\n return this.on(\"updated\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"deleting\" event.\r\n *\r\n * Fired before a model is deleted from the database.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onDeleting<TContext = OnDeletingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"deleting\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"deleted\" event.\r\n *\r\n * Fired after a model has been successfully deleted.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onDeleted<TContext = OnDeletedEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"deleted\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"validating\" event.\r\n *\r\n * Fired before model validation is performed.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onValidating<TContext = OnValidatingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"validating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"validated\" event.\r\n *\r\n * Fired after model validation has completed.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onValidated<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"validated\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"fetching\" event.\r\n *\r\n * Fired before a query is executed to fetch models.\r\n * Receives the query builder instance, allowing modification before execution.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onFetching<TContext = OnFetchingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"fetching\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"hydrating\" event.\r\n *\r\n * Fired after raw records are fetched but before they are hydrated into model instances.\r\n * Allows modification of raw data before hydration.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onHydrating<TContext = OnHydratingEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"hydrating\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"fetched\" event.\r\n *\r\n * Fired after models have been fetched and hydrated.\r\n * Receives hydrated model instances and query context.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onFetched<TContext = OnFetchedEventContext>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"fetched\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"restoring\" event.\r\n *\r\n * Fired before a soft-deleted model is restored.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onRestoring<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"restoring\", listener);\r\n }\r\n\r\n /**\r\n * Registers a listener for the \"restored\" event.\r\n *\r\n * Fired after a soft-deleted model has been successfully restored.\r\n *\r\n * @param listener - The callback to invoke\r\n * @returns An unsubscribe function\r\n */\r\n public onRestored<TContext = unknown>(\r\n listener: ModelEventListener<TModel, TContext>,\r\n ): () => void {\r\n return this.on(\"restored\", listener);\r\n }\r\n\r\n /**\r\n * Ensures a listener set exists for the given event.\r\n *\r\n * @param event - The event name\r\n * @returns The listener set for the event\r\n * @private\r\n */\r\n private ensureListenerSet(event: ModelEventName): Set<ModelEventListener<TModel>> {\r\n let listeners = this.listeners.get(event);\r\n if (!listeners) {\r\n listeners = new Set();\r\n this.listeners.set(event, listeners);\r\n }\r\n return listeners;\r\n }\r\n}\r\n\r\n/**\r\n * Global event emitter invoked for every model instance, regardless of type.\r\n * Useful for cross-cutting concerns like auditing or request-scoped enrichment.\r\n */\r\nexport const globalModelEvents = new ModelEvents<Model>();\r\n"],"mappings":";;;;;;;;AA8EA,IAAa,cAAb,MAAiC;CAC/B,AAAgB,4BAAY,IAAI,IAAqD;;;;;CAMrF,AAAO,GACL,OACA,UACY;EAEZ,AADkB,KAAK,kBAAkB,KACjC,CAAC,CAAC,IAAI,QAAsC;EACpD,aAAa,KAAK,IAAI,OAAO,QAAQ;CACvC;;;;CAKA,AAAO,KACL,OACA,UACY;EACZ,MAAM,UAAgD,OAAO,OAAO,YAAY;GAC9E,IAAI;IACF,MAAM,SAAS,OAAO,OAAO;GAC/B,UAAU;IACR,KAAK,IAAI,OAAO,OAAO;GACzB;EACF;EACA,OAAO,KAAK,GAAG,OAAO,OAAO;CAC/B;;;;CAKA,AAAO,IACL,OACA,UACM;EACN,MAAM,YAAY,KAAK,UAAU,IAAI,KAAK;EAC1C,IAAI,CAAC,WACH;EAEF,UAAU,OAAO,QAAsC;EACvD,IAAI,UAAU,SAAS,GACrB,KAAK,UAAU,OAAO,KAAK;CAE/B;;;;CAKA,MAAa,KACX,OACA,OACA,SACe;EACf,MAAM,YAAY,KAAK,UAAU,IAAI,KAAK;EAC1C,IAAI,CAAC,aAAa,UAAU,SAAS,GACnC;EAEF,KAAK,MAAM,YAAY,MAAM,KAAK,SAAS,GACzC,MAAM,SAAS,OAAO,OAAO;CAEjC;;;;CAKA,MAAa,aACX,OACA,SACe;EACf,MAAM,KAAK,KAAK,YAAY,OAAc,OAAO;CACnD;;;;CAKA,AAAO,QAAc;EACnB,KAAK,UAAU,MAAM;CACvB;;;;;;;;;;CAWA,AAAO,SACL,UACY;EACZ,OAAO,KAAK,GAAG,UAAU,QAAQ;CACnC;;;;;;;;;CAUA,AAAO,QAA4B,UAA4D;EAC7F,OAAO,KAAK,GAAG,SAAS,QAAQ;CAClC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;CAUA,AAAO,UAA8B,UAA4D;EAC/F,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;CAUA,AAAO,UAA8B,UAA4D;EAC/F,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;CAUA,AAAO,UACL,UACY;EACZ,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,aACL,UACY;EACZ,OAAO,KAAK,GAAG,cAAc,QAAQ;CACvC;;;;;;;;;CAUA,AAAO,YACL,UACY;EACZ,OAAO,KAAK,GAAG,aAAa,QAAQ;CACtC;;;;;;;;;;CAWA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;;;CAWA,AAAO,YACL,UACY;EACZ,OAAO,KAAK,GAAG,aAAa,QAAQ;CACtC;;;;;;;;;;CAWA,AAAO,UACL,UACY;EACZ,OAAO,KAAK,GAAG,WAAW,QAAQ;CACpC;;;;;;;;;CAUA,AAAO,YACL,UACY;EACZ,OAAO,KAAK,GAAG,aAAa,QAAQ;CACtC;;;;;;;;;CAUA,AAAO,WACL,UACY;EACZ,OAAO,KAAK,GAAG,YAAY,QAAQ;CACrC;;;;;;;;CASA,AAAQ,kBAAkB,OAAwD;EAChF,IAAI,YAAY,KAAK,UAAU,IAAI,KAAK;EACxC,IAAI,CAAC,WAAW;GACd,4BAAY,IAAI,IAAI;GACpB,KAAK,UAAU,IAAI,OAAO,SAAS;EACrC;EACA,OAAO;CACT;AACF;;;;;AAMA,MAAa,oBAAoB,IAAI,YAAmB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColumnExpression, ColumnExpressionInput } from "./column-expressions.mjs";
|
|
2
2
|
|
|
3
|
-
//#region
|
|
3
|
+
//#region ../cascade/src/expressions/aggregate-expressions.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Abstract aggregate expression format.
|
|
6
6
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate-expressions.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"aggregate-expressions.d.mts","names":[],"sources":["../../../../../../../cascade/src/expressions/aggregate-expressions.ts"],"mappings":";;;AAmFA;;;;;;AAAA,KA/CY,mBAAA;EAqJkB,kCAnJ5B,KAAA,EAAO,iBAAA,EAiMa;EA/LpB,OAAA;EA2OyB;;;;;;EApOzB,MAAA,GAAS,gBAAgB;AAAA;;;;KAMf,iBAAA;;;;iBAeI,qBAAA,CAAsB,KAAA,YAAiB,KAAA,IAAS,mBAAmB;;;;;;;cAetE,IAAA;EAoJS;;;;;;;;;;;;;;;;WAnIX,mBAAA;EAmP+B;;;;;;;;;;;;;;;;;;;;gCA3NV,mBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;aA8BnB,qBAAA,GAAwB,mBAAA;;;;;;;;;;;;;;;;;;;;;;;;8BA+BP,mBAAA;;;;;;;;;;;;;;;;;;sBAyBR,mBAAA;;;;;;;;;;;;;;;;;;sBAqBA,mBAAA;;;;;;;;;;;;;;;;;;sBAqBA,mBAAA;;;;;;;;;;;;;;;;;;;;2BAuBK,mBAAA;;;;;;;;;;;;;;;;;;;wBAsBH,mBAAA;;;;;;;;;;;;;;;;;;;;wBAuBA,mBAAA;;;;;;;;;;;;;;;;;;;;uBAuBD,mBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate-expressions.mjs","names":[],"sources":["../../../../../../../@warlock.js/cascade/src/expressions/aggregate-expressions.ts"],"sourcesContent":["/**\n * Database-agnostic aggregation expressions.\n *\n * `count` / `countDistinct` / `sum` / `avg` / `min` / `max` are **cross-driver**\n * — the same call compiles to the native shape on every supported database\n * (MongoDB `{ $sum: \"$field\" }`, SQL `SUM(field)`, ...). `countDistinct` uses\n * MongoDB's `$addToSet` + `$size` per-group pattern and SQL `COUNT(DISTINCT …)`.\n *\n * `distinct` / `floor` / `first` / `last` are **MongoDB-only**. They have no\n * single-scalar `GROUP BY` equivalent in SQL, so on Postgres they throw a\n * fail-fast error at the `.groupBy()` call (naming the `selectRaw` /\n * `havingRaw` escape hatch) rather than emit a silently-different query.\n *\n * @example\n * ```typescript\n * import { $agg } from '@warlock.js/cascade';\n *\n * // Works for both MongoDB and SQL\n * Lesson.query()\n * .groupBy(\"type\", {\n * count: $agg.count(),\n * total: $agg.sum(\"duration\"),\n * avg: $agg.avg(\"rating\")\n * })\n * .get();\n * ```\n */\n\nimport type { ColumnExpression, ColumnExpressionInput } from \"./column-expressions\";\n\n/**\n * Abstract aggregate expression format.\n *\n * This format is database-agnostic and will be translated by each driver\n * to their native syntax.\n */\nexport type AggregateExpression = {\n /** The aggregate function type */\n __agg: AggregateFunction;\n /** The field to aggregate (null for count, or when `__expr` carries a composed expression) */\n __field: string | null;\n /**\n * A typed column expression to aggregate over, when the aggregate operates\n * on more than a bare column (e.g. `price * quantity`). When present, drivers\n * compile this instead of `__field`. Absent for the simple bare-column form\n * so existing `$agg.sum(\"col\")` payloads stay byte-for-byte identical.\n */\n __expr?: ColumnExpression;\n};\n\n/**\n * Supported aggregate functions.\n */\nexport type AggregateFunction =\n | \"count\"\n | \"countDistinct\"\n | \"sum\"\n | \"avg\"\n | \"min\"\n | \"max\"\n | \"first\"\n | \"last\"\n | \"distinct\"\n | \"floor\";\n\n/**\n * Checks if a value is an abstract aggregate expression.\n */\nexport function isAggregateExpression(value: unknown): value is AggregateExpression {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__field\" in value &&\n typeof (value as AggregateExpression).__agg === \"string\"\n );\n}\n\n/**\n * Database-agnostic aggregation expression helpers.\n *\n * These helpers create abstract expressions that each driver translates\n * to their native format.\n */\nexport const $agg = {\n /**\n * Count documents in each group.\n *\n * @returns Abstract count expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * count: $agg.count()\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $sum: 1 }`\n * - SQL: `COUNT(*)`\n */\n count(): AggregateExpression {\n return { __agg: \"count\", __field: null };\n },\n\n /**\n * Count the number of distinct values of a field in each group.\n *\n * @param field - The field name to count distinct values of\n * @returns Abstract count-distinct expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"country\", {\n * uniqueCities: $agg.countDistinct(\"city\")\n * });\n * ```\n *\n * **Cross-driver.** Translates to:\n * - SQL: `COUNT(DISTINCT city)`\n * - MongoDB: `{ $addToSet: \"$city\" }` in the `$group` stage, finalized with\n * `{ $size: \"$uniqueCities\" }` in the renaming `$project` (the standard\n * distinct-count-per-group pattern, since `$size` is not a `$group`\n * accumulator).\n */\n countDistinct(field: string): AggregateExpression {\n return { __agg: \"countDistinct\", __field: field };\n },\n\n /**\n * Sum a numeric field — or a composed arithmetic expression — across\n * documents in each group.\n *\n * Pass a bare column name to sum a single field (unchanged from v1), or a\n * typed `$expr` node (`$expr.mul` / `$expr.add` / `$expr.sub` / `$expr.div` /\n * `$expr.col` / `$expr.lit`) to sum a computed value such as `price * quantity`.\n *\n * @param input - A field name or a typed `ColumnExpression`\n * @returns Abstract sum expression\n *\n * @example\n * ```typescript\n * import { $agg, $expr } from \"@warlock.js/cascade\";\n *\n * // Bare column\n * query.groupBy(\"type\", { totalDuration: $agg.sum(\"duration\") });\n *\n * // Composed expression: SUM(price * quantity)\n * query.groupBy(\"type\", { revenue: $agg.sum($expr.mul(\"price\", \"quantity\")) });\n * ```\n *\n * Translates to:\n * - SQL: `SUM(\"duration\")` / `SUM((\"price\" * \"quantity\"))`\n * - MongoDB: `{ $sum: \"$duration\" }` / `{ $sum: { $multiply: [\"$price\", \"$quantity\"] } }`\n */\n sum(input: ColumnExpressionInput): AggregateExpression {\n if (typeof input === \"string\") {\n return { __agg: \"sum\", __field: input };\n }\n\n return { __agg: \"sum\", __field: null, __expr: input };\n },\n\n /**\n * Sum a raw, driver-native expression escape hatch.\n *\n * Equivalent to `$agg.sum($expr.raw(expression))`. The raw string is emitted\n * verbatim into the generated query — never build it from untrusted input.\n * Reach for the typed {@link sum} form first; this exists only for fragments\n * the typed combinators can't express.\n *\n * @param expression - A raw expression fragment (e.g. `\"price * quantity\"`)\n * @returns Abstract sum expression wrapping the raw fragment\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * net: $agg.sumRaw(\"price * quantity * (1 - discount)\"),\n * });\n * ```\n *\n * Translates to:\n * - SQL: `SUM(price * quantity * (1 - discount))`\n * - MongoDB: throws — raw SQL fragments are not portable to a pipeline; use\n * the typed {@link sum} form (or `groupByRaw`) on MongoDB instead.\n */\n sumRaw(expression: string): AggregateExpression {\n return {\n __agg: \"sum\",\n __field: null,\n __expr: { __expr: \"raw\", expression },\n };\n },\n\n /**\n * Calculate the average value of a field across documents in each group.\n *\n * @param field - The field name to average\n * @returns Abstract average expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * avgRating: $agg.avg(\"rating\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $avg: \"$rating\" }`\n * - SQL: `AVG(rating)`\n */\n avg(field: string): AggregateExpression {\n return { __agg: \"avg\", __field: field };\n },\n\n /**\n * Get the minimum value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract min expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * minPrice: $agg.min(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $min: \"$price\" }`\n * - SQL: `MIN(price)`\n */\n min(field: string): AggregateExpression {\n return { __agg: \"min\", __field: field };\n },\n\n /**\n * Get the maximum value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract max expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * maxPrice: $agg.max(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $max: \"$price\" }`\n * - SQL: `MAX(price)`\n */\n max(field: string): AggregateExpression {\n return { __agg: \"max\", __field: field };\n },\n\n /**\n * Get the distinct values of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract distinct expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * distinctColors: $agg.distinct(\"color\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $distinct: \"$color\" }` (returns the array\n * of distinct values). On Postgres this throws — SQL `DISTINCT` is a set\n * quantifier, not a scalar aggregate, so there is no equivalent single\n * value to put in a `GROUP BY` projection. Use `selectRaw` if you need a\n * Postgres-specific shape (e.g. `array_agg(DISTINCT color)`).\n */\n distinct(field: string): AggregateExpression {\n return { __agg: \"distinct\", __field: field };\n },\n\n /**\n * Get the floor value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract floor expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * floorPrice: $agg.floor(\"price\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $floor: \"$price\" }`. On Postgres this\n * throws — `FLOOR` is a scalar function, not an aggregate, so it is\n * meaningless inside a bare `$group` / `GROUP BY`. Use `selectRaw` with\n * `FLOOR(...)` over the aggregated value if you need it on Postgres.\n */\n floor(field: string): AggregateExpression {\n return { __agg: \"floor\", __field: field };\n },\n\n /**\n * Get the first value of a field in each group (order-dependent).\n *\n * @param field - The field name\n * @returns Abstract first expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * firstName: $agg.first(\"name\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $first: \"$name\" }` (group-order\n * dependent). On Postgres this throws — the SQL equivalent is\n * `FIRST_VALUE(name) OVER (ORDER BY ...)`, a window function needing an\n * ordering context the `$agg` API doesn't carry. Use `selectRaw` with an\n * explicit window function if you need it on Postgres.\n */\n first(field: string): AggregateExpression {\n return { __agg: \"first\", __field: field };\n },\n\n /**\n * Get the last value of a field in each group (order-dependent).\n *\n * @param field - The field name\n * @returns Abstract last expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * lastName: $agg.last(\"name\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $last: \"$name\" }` (group-order\n * dependent). On Postgres this throws — the SQL equivalent is\n * `LAST_VALUE(name) OVER (ORDER BY ...)`, a window function needing an\n * ordering context the `$agg` API doesn't carry. Use `selectRaw` with an\n * explicit window function if you need it on Postgres.\n */\n last(field: string): AggregateExpression {\n return { __agg: \"last\", __field: field };\n },\n};\n"],"mappings":";;;;AAoEA,SAAgB,sBAAsB,OAA8C;CAClF,OACE,OAAO,UAAU,YACjB,UAAU,QACV,aAAa,SACb,OAAQ,MAA8B,UAAU;AAEpD;;;;;;;AAQA,MAAa,OAAO;;;;;;;;;;;;;;;;;CAiBlB,QAA6B;EAC3B,OAAO;GAAE,OAAO;GAAS,SAAS;EAAK;CACzC;;;;;;;;;;;;;;;;;;;;;CAsBA,cAAc,OAAoC;EAChD,OAAO;GAAE,OAAO;GAAiB,SAAS;EAAM;CAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BA,IAAI,OAAmD;EACrD,IAAI,OAAO,UAAU,UACnB,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;EAGxC,OAAO;GAAE,OAAO;GAAO,SAAS;GAAM,QAAQ;EAAM;CACtD;;;;;;;;;;;;;;;;;;;;;;;;CAyBA,OAAO,YAAyC;EAC9C,OAAO;GACL,OAAO;GACP,SAAS;GACT,QAAQ;IAAE,QAAQ;IAAO;GAAW;EACtC;CACF;;;;;;;;;;;;;;;;;;CAmBA,IAAI,OAAoC;EACtC,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;CACxC;;;;;;;;;;;;;;;;;;CAmBA,IAAI,OAAoC;EACtC,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;CACxC;;;;;;;;;;;;;;;;;;CAmBA,IAAI,OAAoC;EACtC,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;CACxC;;;;;;;;;;;;;;;;;;;;CAqBA,SAAS,OAAoC;EAC3C,OAAO;GAAE,OAAO;GAAY,SAAS;EAAM;CAC7C;;;;;;;;;;;;;;;;;;;CAoBA,MAAM,OAAoC;EACxC,OAAO;GAAE,OAAO;GAAS,SAAS;EAAM;CAC1C;;;;;;;;;;;;;;;;;;;;CAqBA,MAAM,OAAoC;EACxC,OAAO;GAAE,OAAO;GAAS,SAAS;EAAM;CAC1C;;;;;;;;;;;;;;;;;;;;CAqBA,KAAK,OAAoC;EACvC,OAAO;GAAE,OAAO;GAAQ,SAAS;EAAM;CACzC;AACF"}
|
|
1
|
+
{"version":3,"file":"aggregate-expressions.mjs","names":[],"sources":["../../../../../../../cascade/src/expressions/aggregate-expressions.ts"],"sourcesContent":["/**\n * Database-agnostic aggregation expressions.\n *\n * `count` / `countDistinct` / `sum` / `avg` / `min` / `max` are **cross-driver**\n * — the same call compiles to the native shape on every supported database\n * (MongoDB `{ $sum: \"$field\" }`, SQL `SUM(field)`, ...). `countDistinct` uses\n * MongoDB's `$addToSet` + `$size` per-group pattern and SQL `COUNT(DISTINCT …)`.\n *\n * `distinct` / `floor` / `first` / `last` are **MongoDB-only**. They have no\n * single-scalar `GROUP BY` equivalent in SQL, so on Postgres they throw a\n * fail-fast error at the `.groupBy()` call (naming the `selectRaw` /\n * `havingRaw` escape hatch) rather than emit a silently-different query.\n *\n * @example\n * ```typescript\n * import { $agg } from '@warlock.js/cascade';\n *\n * // Works for both MongoDB and SQL\n * Lesson.query()\n * .groupBy(\"type\", {\n * count: $agg.count(),\n * total: $agg.sum(\"duration\"),\n * avg: $agg.avg(\"rating\")\n * })\n * .get();\n * ```\n */\n\nimport type { ColumnExpression, ColumnExpressionInput } from \"./column-expressions\";\n\n/**\n * Abstract aggregate expression format.\n *\n * This format is database-agnostic and will be translated by each driver\n * to their native syntax.\n */\nexport type AggregateExpression = {\n /** The aggregate function type */\n __agg: AggregateFunction;\n /** The field to aggregate (null for count, or when `__expr` carries a composed expression) */\n __field: string | null;\n /**\n * A typed column expression to aggregate over, when the aggregate operates\n * on more than a bare column (e.g. `price * quantity`). When present, drivers\n * compile this instead of `__field`. Absent for the simple bare-column form\n * so existing `$agg.sum(\"col\")` payloads stay byte-for-byte identical.\n */\n __expr?: ColumnExpression;\n};\n\n/**\n * Supported aggregate functions.\n */\nexport type AggregateFunction =\n | \"count\"\n | \"countDistinct\"\n | \"sum\"\n | \"avg\"\n | \"min\"\n | \"max\"\n | \"first\"\n | \"last\"\n | \"distinct\"\n | \"floor\";\n\n/**\n * Checks if a value is an abstract aggregate expression.\n */\nexport function isAggregateExpression(value: unknown): value is AggregateExpression {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__field\" in value &&\n typeof (value as AggregateExpression).__agg === \"string\"\n );\n}\n\n/**\n * Database-agnostic aggregation expression helpers.\n *\n * These helpers create abstract expressions that each driver translates\n * to their native format.\n */\nexport const $agg = {\n /**\n * Count documents in each group.\n *\n * @returns Abstract count expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * count: $agg.count()\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $sum: 1 }`\n * - SQL: `COUNT(*)`\n */\n count(): AggregateExpression {\n return { __agg: \"count\", __field: null };\n },\n\n /**\n * Count the number of distinct values of a field in each group.\n *\n * @param field - The field name to count distinct values of\n * @returns Abstract count-distinct expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"country\", {\n * uniqueCities: $agg.countDistinct(\"city\")\n * });\n * ```\n *\n * **Cross-driver.** Translates to:\n * - SQL: `COUNT(DISTINCT city)`\n * - MongoDB: `{ $addToSet: \"$city\" }` in the `$group` stage, finalized with\n * `{ $size: \"$uniqueCities\" }` in the renaming `$project` (the standard\n * distinct-count-per-group pattern, since `$size` is not a `$group`\n * accumulator).\n */\n countDistinct(field: string): AggregateExpression {\n return { __agg: \"countDistinct\", __field: field };\n },\n\n /**\n * Sum a numeric field — or a composed arithmetic expression — across\n * documents in each group.\n *\n * Pass a bare column name to sum a single field (unchanged from v1), or a\n * typed `$expr` node (`$expr.mul` / `$expr.add` / `$expr.sub` / `$expr.div` /\n * `$expr.col` / `$expr.lit`) to sum a computed value such as `price * quantity`.\n *\n * @param input - A field name or a typed `ColumnExpression`\n * @returns Abstract sum expression\n *\n * @example\n * ```typescript\n * import { $agg, $expr } from \"@warlock.js/cascade\";\n *\n * // Bare column\n * query.groupBy(\"type\", { totalDuration: $agg.sum(\"duration\") });\n *\n * // Composed expression: SUM(price * quantity)\n * query.groupBy(\"type\", { revenue: $agg.sum($expr.mul(\"price\", \"quantity\")) });\n * ```\n *\n * Translates to:\n * - SQL: `SUM(\"duration\")` / `SUM((\"price\" * \"quantity\"))`\n * - MongoDB: `{ $sum: \"$duration\" }` / `{ $sum: { $multiply: [\"$price\", \"$quantity\"] } }`\n */\n sum(input: ColumnExpressionInput): AggregateExpression {\n if (typeof input === \"string\") {\n return { __agg: \"sum\", __field: input };\n }\n\n return { __agg: \"sum\", __field: null, __expr: input };\n },\n\n /**\n * Sum a raw, driver-native expression escape hatch.\n *\n * Equivalent to `$agg.sum($expr.raw(expression))`. The raw string is emitted\n * verbatim into the generated query — never build it from untrusted input.\n * Reach for the typed {@link sum} form first; this exists only for fragments\n * the typed combinators can't express.\n *\n * @param expression - A raw expression fragment (e.g. `\"price * quantity\"`)\n * @returns Abstract sum expression wrapping the raw fragment\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * net: $agg.sumRaw(\"price * quantity * (1 - discount)\"),\n * });\n * ```\n *\n * Translates to:\n * - SQL: `SUM(price * quantity * (1 - discount))`\n * - MongoDB: throws — raw SQL fragments are not portable to a pipeline; use\n * the typed {@link sum} form (or `groupByRaw`) on MongoDB instead.\n */\n sumRaw(expression: string): AggregateExpression {\n return {\n __agg: \"sum\",\n __field: null,\n __expr: { __expr: \"raw\", expression },\n };\n },\n\n /**\n * Calculate the average value of a field across documents in each group.\n *\n * @param field - The field name to average\n * @returns Abstract average expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * avgRating: $agg.avg(\"rating\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $avg: \"$rating\" }`\n * - SQL: `AVG(rating)`\n */\n avg(field: string): AggregateExpression {\n return { __agg: \"avg\", __field: field };\n },\n\n /**\n * Get the minimum value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract min expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * minPrice: $agg.min(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $min: \"$price\" }`\n * - SQL: `MIN(price)`\n */\n min(field: string): AggregateExpression {\n return { __agg: \"min\", __field: field };\n },\n\n /**\n * Get the maximum value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract max expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * maxPrice: $agg.max(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $max: \"$price\" }`\n * - SQL: `MAX(price)`\n */\n max(field: string): AggregateExpression {\n return { __agg: \"max\", __field: field };\n },\n\n /**\n * Get the distinct values of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract distinct expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * distinctColors: $agg.distinct(\"color\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $distinct: \"$color\" }` (returns the array\n * of distinct values). On Postgres this throws — SQL `DISTINCT` is a set\n * quantifier, not a scalar aggregate, so there is no equivalent single\n * value to put in a `GROUP BY` projection. Use `selectRaw` if you need a\n * Postgres-specific shape (e.g. `array_agg(DISTINCT color)`).\n */\n distinct(field: string): AggregateExpression {\n return { __agg: \"distinct\", __field: field };\n },\n\n /**\n * Get the floor value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract floor expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * floorPrice: $agg.floor(\"price\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $floor: \"$price\" }`. On Postgres this\n * throws — `FLOOR` is a scalar function, not an aggregate, so it is\n * meaningless inside a bare `$group` / `GROUP BY`. Use `selectRaw` with\n * `FLOOR(...)` over the aggregated value if you need it on Postgres.\n */\n floor(field: string): AggregateExpression {\n return { __agg: \"floor\", __field: field };\n },\n\n /**\n * Get the first value of a field in each group (order-dependent).\n *\n * @param field - The field name\n * @returns Abstract first expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * firstName: $agg.first(\"name\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $first: \"$name\" }` (group-order\n * dependent). On Postgres this throws — the SQL equivalent is\n * `FIRST_VALUE(name) OVER (ORDER BY ...)`, a window function needing an\n * ordering context the `$agg` API doesn't carry. Use `selectRaw` with an\n * explicit window function if you need it on Postgres.\n */\n first(field: string): AggregateExpression {\n return { __agg: \"first\", __field: field };\n },\n\n /**\n * Get the last value of a field in each group (order-dependent).\n *\n * @param field - The field name\n * @returns Abstract last expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * lastName: $agg.last(\"name\")\n * });\n * ```\n *\n * **MongoDB-only.** MongoDB: `{ $last: \"$name\" }` (group-order\n * dependent). On Postgres this throws — the SQL equivalent is\n * `LAST_VALUE(name) OVER (ORDER BY ...)`, a window function needing an\n * ordering context the `$agg` API doesn't carry. Use `selectRaw` with an\n * explicit window function if you need it on Postgres.\n */\n last(field: string): AggregateExpression {\n return { __agg: \"last\", __field: field };\n },\n};\n"],"mappings":";;;;AAoEA,SAAgB,sBAAsB,OAA8C;CAClF,OACE,OAAO,UAAU,YACjB,UAAU,QACV,aAAa,SACb,OAAQ,MAA8B,UAAU;AAEpD;;;;;;;AAQA,MAAa,OAAO;;;;;;;;;;;;;;;;;CAiBlB,QAA6B;EAC3B,OAAO;GAAE,OAAO;GAAS,SAAS;EAAK;CACzC;;;;;;;;;;;;;;;;;;;;;CAsBA,cAAc,OAAoC;EAChD,OAAO;GAAE,OAAO;GAAiB,SAAS;EAAM;CAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BA,IAAI,OAAmD;EACrD,IAAI,OAAO,UAAU,UACnB,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;EAGxC,OAAO;GAAE,OAAO;GAAO,SAAS;GAAM,QAAQ;EAAM;CACtD;;;;;;;;;;;;;;;;;;;;;;;;CAyBA,OAAO,YAAyC;EAC9C,OAAO;GACL,OAAO;GACP,SAAS;GACT,QAAQ;IAAE,QAAQ;IAAO;GAAW;EACtC;CACF;;;;;;;;;;;;;;;;;;CAmBA,IAAI,OAAoC;EACtC,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;CACxC;;;;;;;;;;;;;;;;;;CAmBA,IAAI,OAAoC;EACtC,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;CACxC;;;;;;;;;;;;;;;;;;CAmBA,IAAI,OAAoC;EACtC,OAAO;GAAE,OAAO;GAAO,SAAS;EAAM;CACxC;;;;;;;;;;;;;;;;;;;;CAqBA,SAAS,OAAoC;EAC3C,OAAO;GAAE,OAAO;GAAY,SAAS;EAAM;CAC7C;;;;;;;;;;;;;;;;;;;CAoBA,MAAM,OAAoC;EACxC,OAAO;GAAE,OAAO;GAAS,SAAS;EAAM;CAC1C;;;;;;;;;;;;;;;;;;;;CAqBA,MAAM,OAAoC;EACxC,OAAO;GAAE,OAAO;GAAS,SAAS;EAAM;CAC1C;;;;;;;;;;;;;;;;;;;;CAqBA,KAAK,OAAoC;EACvC,OAAO;GAAE,OAAO;GAAQ,SAAS;EAAM;CACzC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-expressions.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"column-expressions.d.mts","names":[],"sources":["../../../../../../../cascade/src/expressions/column-expressions.ts"],"mappings":";;AAyCA;;;;AAAgC;AAahC;;;;AAEiB;AAIjB;;;;AAEgB;AAShB;;;;;;;;AAEqC;AAQrC;;;;AAEqB;AAQrB;;;;;;;;;;KAlDY,oBAAA;;;;AAsDW;KAzCX,mBAAA;EAAA,SACD,MAAA;EAAA,SACA,MAAM;AAAA;AA0CmC;AAAA,KAtCxC,iBAAA;EAAA,SACD,MAAA;EAAA,SACA,KAAK;AAAA;;;;;AA4C6D;AAM5E;KAzCW,oBAAA;EAAA,SACD,MAAA;EAAA,SACA,QAAA,EAAU,gBAAgB;AAAA;AA+CY;;;;AAUO;AAVP,KAvCrC,mBAAA;EAAA,SACD,MAAA;EAAA,SACA,UAAU;AAAA;;;;;AAyDmD;KAjD5D,gBAAA,GACR,mBAAA,GACA,iBAAA,GACA,oBAAA,GACA,mBAAA;;KAGQ,qBAAA,GAAwB,gBAAgB;;;;;;AAoDoB;iBA5CxD,kBAAA,CAAmB,KAAA,YAAiB,KAAA,IAAS,gBAAgB;;;;;;;iBAcpE,GAAA,CAAI,MAAA,WAAiB,mBAAmB;;;;;;;iBAUxC,GAAA,CAAI,KAAA,qBAA0B,iBAAiB;AAkCjC;;;;;;AAAA,iBAxBd,GAAA,IAAO,QAAA,EAAU,qBAAA,KAA0B,oBAAoB;;;;;;;iBAU/D,GAAA,IAAO,QAAA,EAAU,qBAAA,KAA0B,oBAAoB;AA+BjD;AAAA;;;;AAkB8B;AAYrD;AA9BuB,iBApBd,GAAA,CACP,IAAA,EAAM,qBAAA,EACN,KAAA,EAAO,qBAAA,GACN,oBAAA;;;;;;;AA+C+E;iBAjCzE,GAAA,CACP,IAAA,EAAM,qBAAA,EACN,KAAA,EAAO,qBAAA,GACN,oBAAA;;;;;;;;;;;;iBAkBM,GAAA,CAAI,UAAA,WAAqB,mBAAmB;;;;;;;;;iBAYrC,kBAAA,CAAmB,KAAA,EAAO,qBAAA,GAAwB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+BrE,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-expressions.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"column-expressions.mjs","names":[],"sources":["../../../../../../../cascade/src/expressions/column-expressions.ts"],"sourcesContent":["/**\n * Database-agnostic, **typed** column expressions for aggregate inputs.\n *\n * These let `$agg.sum(...)` (and any future expression-accepting aggregate)\n * operate on a composed arithmetic expression — e.g. `price * quantity` — not\n * just a bare column, while staying portable across drivers.\n *\n * The builders are grouped under a single `$expr` object (mirroring `$agg`),\n * so the package root exposes exactly two expression namespaces — `$agg` for\n * aggregates and `$expr` for the scalar arithmetic that feeds them — rather\n * than a handful of collision-prone bare verbs (`mul`, `add`, `col`, …).\n *\n * The expression tree is a small, closed union of safe nodes:\n *\n * - `$expr.col(\"price\")` — a column reference (driver quotes/escapes it)\n * - `$expr.lit(2)` — a numeric/boolean literal\n * - `$expr.mul(a, b, …)` / `$expr.add(…)` / `$expr.sub(a, b)` / `$expr.div(a, b)` — arithmetic\n * - `$expr.raw(\"price * 1.2\")` — an explicit escape hatch for a raw SQL fragment\n *\n * Only `$expr.raw` ever embeds an uninterpreted string, and it is opt-in by\n * name. Everything else is composed from typed nodes, so user-supplied column\n * names flow through the driver's identifier-quoting path rather than being\n * string-interpolated into SQL. This is the boundary the S2 task calls out: a\n * tiny typed DSL for the common safe ops, plus a clearly-named raw escape\n * hatch for everything beyond it.\n *\n * Bare strings are still accepted everywhere a `ColumnExpression` is — a plain\n * string is treated as a column reference (`\"price\"` === `$expr.col(\"price\")`),\n * so the existing `$agg.sum(\"amount\")` call site keeps working unchanged.\n *\n * @example\n * ```typescript\n * import { $agg, $expr } from \"@warlock.js/cascade\";\n *\n * query.groupByDate(\"created_at\", \"month\", {\n * revenue: $agg.sum($expr.mul(\"price\", \"quantity\")),\n * });\n * ```\n */\n\n/** Discriminator tag identifying a node in the column-expression tree. */\nexport type ColumnExpressionType =\n | \"column\"\n | \"literal\"\n | \"add\"\n | \"subtract\"\n | \"multiply\"\n | \"divide\"\n | \"raw\";\n\n/**\n * A reference to a column/field. The driver is responsible for quoting the\n * name (SQL) or prefixing it with `$` (Mongo) — it is never interpolated raw.\n */\nexport type ColumnRefExpression = {\n readonly __expr: \"column\";\n readonly column: string;\n};\n\n/** A scalar literal value embedded directly in the expression. */\nexport type LiteralExpression = {\n readonly __expr: \"literal\";\n readonly value: number | boolean;\n};\n\n/**\n * An arithmetic operation over one or more operands.\n *\n * `add` / `multiply` are variadic; `subtract` / `divide` take exactly two\n * operands (left, right) since they are not associative.\n */\nexport type ArithmeticExpression = {\n readonly __expr: \"add\" | \"subtract\" | \"multiply\" | \"divide\";\n readonly operands: ColumnExpression[];\n};\n\n/**\n * A raw expression escape hatch. The string is emitted verbatim into the\n * generated SQL — callers MUST NOT build it from untrusted input. This is the\n * documented boundary for anything the typed nodes above don't cover.\n */\nexport type RawColumnExpression = {\n readonly __expr: \"raw\";\n readonly expression: string;\n};\n\n/**\n * Any node in the typed column-expression tree. A bare `string` is also a\n * valid expression input wherever this type is accepted — it is interpreted as\n * a column reference.\n */\nexport type ColumnExpression =\n | ColumnRefExpression\n | LiteralExpression\n | ArithmeticExpression\n | RawColumnExpression;\n\n/** Input accepted by expression-aware helpers: a typed node or a column-name string. */\nexport type ColumnExpressionInput = ColumnExpression | string;\n\n/**\n * Type guard: is `value` one of the typed column-expression nodes?\n *\n * @param value - The value to test\n * @returns `true` when `value` is a `ColumnExpression` node\n */\nexport function isColumnExpression(value: unknown): value is ColumnExpression {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as ColumnExpression).__expr === \"string\"\n );\n}\n\n/**\n * Reference a column/field by name.\n *\n * @param column - The column/field name\n * @returns A column-reference expression node\n */\nfunction col(column: string): ColumnRefExpression {\n return { __expr: \"column\", column };\n}\n\n/**\n * A scalar literal (number or boolean) operand.\n *\n * @param value - The literal value\n * @returns A literal expression node\n */\nfunction lit(value: number | boolean): LiteralExpression {\n return { __expr: \"literal\", value };\n}\n\n/**\n * Multiply two or more operands.\n *\n * @param operands - Column names, literals, or nested expression nodes\n * @returns A multiply expression node\n */\nfunction mul(...operands: ColumnExpressionInput[]): ArithmeticExpression {\n return { __expr: \"multiply\", operands: operands.map(toColumnExpression) };\n}\n\n/**\n * Add two or more operands.\n *\n * @param operands - Column names, literals, or nested expression nodes\n * @returns An add expression node\n */\nfunction add(...operands: ColumnExpressionInput[]): ArithmeticExpression {\n return { __expr: \"add\", operands: operands.map(toColumnExpression) };\n}\n\n/**\n * Subtract `right` from `left`.\n *\n * @param left - The minuend\n * @param right - The subtrahend\n * @returns A subtract expression node\n */\nfunction sub(\n left: ColumnExpressionInput,\n right: ColumnExpressionInput,\n): ArithmeticExpression {\n return {\n __expr: \"subtract\",\n operands: [toColumnExpression(left), toColumnExpression(right)],\n };\n}\n\n/**\n * Divide `left` by `right`.\n *\n * @param left - The dividend\n * @param right - The divisor\n * @returns A divide expression node\n */\nfunction div(\n left: ColumnExpressionInput,\n right: ColumnExpressionInput,\n): ArithmeticExpression {\n return {\n __expr: \"divide\",\n operands: [toColumnExpression(left), toColumnExpression(right)],\n };\n}\n\n/**\n * Wrap a raw expression string as an escape hatch.\n *\n * The string is emitted verbatim — never build it from untrusted input. Use\n * this only when the typed `$expr.mul` / `$expr.add` / `$expr.sub` /\n * `$expr.div` / `$expr.col` / `$expr.lit` combinators can't express what you\n * need.\n *\n * @param expression - A raw, driver-native expression fragment\n * @returns A raw expression node\n */\nfunction raw(expression: string): RawColumnExpression {\n return { __expr: \"raw\", expression };\n}\n\n/**\n * Normalize an expression input to a `ColumnExpression` node. A bare string\n * becomes a `$expr.col(...)` reference; an existing node passes through\n * unchanged.\n *\n * @param input - A typed expression node or a bare column-name string\n * @returns The corresponding `ColumnExpression` node\n */\nexport function toColumnExpression(input: ColumnExpressionInput): ColumnExpression {\n return typeof input === \"string\" ? col(input) : input;\n}\n\n/**\n * Typed, database-agnostic column-expression builders.\n *\n * Grouped under one object (like `$agg`) so the scalar arithmetic that feeds\n * an aggregate reads as a single, discoverable namespace: `$agg.sum($expr.mul(\n * \"price\", \"quantity\"))`. Each builder returns a plain, closed `ColumnExpression`\n * node — the driver translates it to native SQL / a Mongo pipeline.\n *\n * @example\n * ```typescript\n * import { $agg, $expr } from \"@warlock.js/cascade\";\n *\n * // SUM(price * quantity)\n * query.groupBy(\"product_id\", { revenue: $agg.sum($expr.mul(\"price\", \"quantity\")) });\n *\n * // SUM((1 - discount) * price)\n * query.groupBy(\"product_id\", {\n * net: $agg.sum($expr.mul($expr.sub($expr.lit(1), \"discount\"), \"price\")),\n * });\n *\n * // price * 1.2 (e.g. tax)\n * $agg.sum($expr.mul(\"price\", $expr.lit(1.2)));\n *\n * // escape hatch (Postgres-only, emitted verbatim — never from user input)\n * $agg.sum($expr.raw(\"price * quantity * (1 - discount)\"));\n * ```\n */\nexport const $expr = {\n col,\n lit,\n mul,\n add,\n sub,\n div,\n raw,\n};\n"],"mappings":";;;;;;;AA0GA,SAAgB,mBAAmB,OAA2C;CAC5E,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA2B,WAAW;AAElD;;;;;;;AAQA,SAAS,IAAI,QAAqC;CAChD,OAAO;EAAE,QAAQ;EAAU;CAAO;AACpC;;;;;;;AAQA,SAAS,IAAI,OAA4C;CACvD,OAAO;EAAE,QAAQ;EAAW;CAAM;AACpC;;;;;;;AAQA,SAAS,IAAI,GAAG,UAAyD;CACvE,OAAO;EAAE,QAAQ;EAAY,UAAU,SAAS,IAAI,kBAAkB;CAAE;AAC1E;;;;;;;AAQA,SAAS,IAAI,GAAG,UAAyD;CACvE,OAAO;EAAE,QAAQ;EAAO,UAAU,SAAS,IAAI,kBAAkB;CAAE;AACrE;;;;;;;;AASA,SAAS,IACP,MACA,OACsB;CACtB,OAAO;EACL,QAAQ;EACR,UAAU,CAAC,mBAAmB,IAAI,GAAG,mBAAmB,KAAK,CAAC;CAChE;AACF;;;;;;;;AASA,SAAS,IACP,MACA,OACsB;CACtB,OAAO;EACL,QAAQ;EACR,UAAU,CAAC,mBAAmB,IAAI,GAAG,mBAAmB,KAAK,CAAC;CAChE;AACF;;;;;;;;;;;;AAaA,SAAS,IAAI,YAAyC;CACpD,OAAO;EAAE,QAAQ;EAAO;CAAW;AACrC;;;;;;;;;AAUA,SAAgB,mBAAmB,OAAgD;CACjF,OAAO,OAAO,UAAU,WAAW,IAAI,KAAK,IAAI;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,QAAQ;CACnB;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColumnDefinition, ColumnType, ForeignKeyDefinition, VectorIndexOptions } from "../contracts/migration-driver.contract.mjs";
|
|
2
2
|
|
|
3
|
-
//#region
|
|
3
|
+
//#region ../cascade/src/migration/column-builder.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Reference to the Migration type to avoid circular imports.
|
|
6
6
|
* The actual type is injected at runtime.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-builder.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"column-builder.d.mts","names":[],"sources":["../../../../../../../cascade/src/migration/column-builder.ts"],"mappings":";;;;;AAKgD;;KAM3C,aAAA;EACH,eAAA,CAAgB,KAAA;IAAS,OAAA;IAAmB,MAAA;EAAA;EAC5C,sBAAA,CAAuB,EAAA,EAAI,oBAAA;EAC3B,qBAAA,EAAuB,MAAA,UAAgB,OAAA,EAAS,IAAA,CAAK,kBAAA;AAAA;;;;;;;;;;;;AAA6B;AAqCpF;;;;;;;;;;cAAa,aAAA;EAAA,iBAmBQ,SAAA;EAklBK;EAAA,iBAnmBP,UAAA;EAmmBuB;EAAA,QAhmBhC,YAAA;EAHS;EAAA,QAMT,mBAAA;EAAA;;;;;;;;cAWW,SAAA,EAAW,aAAA,EAC5B,IAAA,UACA,IAAA,EAAM,UAAA,EACN,OAAA,GAAS,OAAA,CACP,IAAA,CAAK,gBAAA;EAAA;;;;;;;;;;EAyBF,QAAA;EAuIA;;;;;;;EA3HA,WAAA;EAoOA;;;;;;;;;;;;;;;;;EA1MA,OAAA,CAAQ,KAAA;EA0WC;;;;;;;;;;;AAqKwB;;;;EA1fjC,aAAA,CAAc,KAAA;;;;;;;;;;;;;EAkBd,UAAA;;;;;;;;;;;;;EAiBA,kBAAA;;;;;;;;;;;;;EAqBA,MAAA;;;;;;;;;;;;;EAoBA,KAAA;;;;;;;;;;;;;;EAoBA,WAAA,CAAY,OAAA,GAAS,IAAA,CAAK,kBAAA;;;;;;;;;;;EAwB1B,OAAA;;;;;;;;;;;;;;EAkBA,aAAA;;;;;;;;;;;;;EAqBA,QAAA;;;;;;;;;;;;;;EAsBA,OAAA,CAAQ,IAAA;;;;;;;;EAgBR,KAAA,CAAM,UAAA,UAAoB,IAAA;;;;;;;;;;;;;;EAyB1B,KAAA,CAAM,UAAA;;;;;;;;;;;;;EAiBN,KAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCA,UAAA,CAAW,YAAA;IAAyB,KAAA;EAAA;;;;;;;;;;;;;;EA2BpC,EAAA,CAAG,MAAA;;;;;;;;;;;;;;EAoBH,QAAA,CAAS,MAAA,EAAQ,oBAAA;;;;;;;;;;;;;;EAoBjB,QAAA,CAAS,MAAA,EAAQ,oBAAA;;;;;;;;;;;;;EAmBjB,UAAA;;;;;;;;;;;;;;;;;;;;;EAgCA,MAAA;;;;EAkCA,MAAA;;;;;;;;;;;;;;;;;;;;;;;EA8BA,WAAA,CAAY,UAAA;;;;;;;;EAYZ,MAAA;;;;;;;;EAiBA,OAAA;;;;;;;;EAqBA,aAAA,IAAiB,gBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-builder.mjs","names":[],"sources":["../../../../../../../@warlock.js/cascade/src/migration/column-builder.ts"],"sourcesContent":["import type {\n ColumnDefinition,\n ColumnType,\n ForeignKeyDefinition,\n VectorIndexOptions,\n} from \"../contracts/migration-driver.contract\";\n\n/**\n * Reference to the Migration type to avoid circular imports.\n * The actual type is injected at runtime.\n */\ntype MigrationLike = {\n addPendingIndex(index: { columns: string[]; unique?: boolean }): void;\n addForeignKeyOperation(fk: ForeignKeyDefinition): void;\n addPendingVectorIndex?(column: string, options: Omit<VectorIndexOptions, \"column\">): void;\n};\n\n/**\n * Mutable foreign key definition being built via ColumnBuilder.\n */\ninterface MutableForeignKeyDefinition {\n name?: string;\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete: ForeignKeyDefinition[\"onDelete\"];\n onUpdate: ForeignKeyDefinition[\"onUpdate\"];\n}\n\n/**\n * Fluent builder for defining column properties.\n *\n * Allows chaining modifiers like `.nullable()`, `.unique()`, `.default()`.\n * Each column builder is bound to a parent migration and accumulates\n * the column definition through method chains.\n *\n * @example\n * ```typescript\n * this.string(\"email\")\n * .nullable()\n * .unique()\n * .default(\"guest@example.com\");\n * ```\n *\n * @example\n * ```typescript\n * this.integer(\"age\")\n * .unsigned()\n * .comment(\"User's age in years\");\n * ```\n */\nexport class ColumnBuilder {\n /** Mutable column definition being accumulated */\n private readonly definition: ColumnDefinition;\n\n /** Mutable foreign key definition, set when .references() is called */\n private fkDefinition?: MutableForeignKeyDefinition;\n\n /** Temporary storage for generated expression before .stored() or .virtual() is called */\n private generatedExpression?: string;\n\n /**\n * Create a new column builder.\n *\n * @param migration - Parent migration instance for index registration\n * @param name - Column name\n * @param type - Column data type\n * @param options - Optional initial configuration\n */\n public constructor(\n private readonly migration: MigrationLike,\n name: string,\n type: ColumnType,\n options: Partial<\n Pick<ColumnDefinition, \"length\" | \"precision\" | \"scale\" | \"dimensions\" | \"values\">\n > = {},\n ) {\n this.definition = {\n name,\n type,\n nullable: false,\n ...options,\n };\n }\n\n // ============================================================================\n // NULLABILITY\n // ============================================================================\n\n /**\n * Mark column as nullable (allows NULL values).\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"middleName\").nullable();\n * ```\n */\n public nullable(): this {\n this.definition.nullable = true;\n return this;\n }\n\n /**\n * Mark column as not nullable (disallows NULL values).\n *\n * This is the default, but can be used for clarity.\n *\n * @returns This builder for chaining\n */\n public notNullable(): this {\n this.definition.nullable = false;\n return this;\n }\n\n // ============================================================================\n // DEFAULT VALUES\n // ============================================================================\n\n /**\n * Set default value for the column as a raw SQL expression.\n *\n * The value will be used as-is in the SQL statement without escaping.\n * Use this for database functions and expressions.\n *\n * @param value - Default value (SQL expression, number, or boolean)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.uuid(\"id\").default(\"gen_random_uuid()\");\n * this.timestamp(\"created_at\").default(\"NOW()\");\n * this.integer(\"version\").default(1);\n * this.boolean(\"is_active\").default(true);\n * ```\n */\n public default(value: string | number | boolean): this {\n this.definition.defaultValue = value;\n this.definition.isRawDefault = true;\n return this;\n }\n\n /**\n * Set default value for the column as a literal string.\n *\n * The value will be properly escaped and quoted in the SQL statement.\n * Use this for literal string values, not SQL expressions.\n *\n * @param value - Default string value (will be escaped)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.text(\"status\").defaultString(\"active\");\n * this.text(\"greeting\").defaultString(\"Hello, World!\");\n * ```\n */\n public defaultString(value: string): this {\n this.definition.defaultValue = value;\n this.definition.isRawDefault = false;\n return this;\n }\n\n /**\n * Set default value to the current timestamp.\n *\n * Database-agnostic. Generates NOW() / CURRENT_TIMESTAMP / GETDATE() based on driver.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.timestamp(\"created_at\").useCurrent();\n * ```\n */\n public useCurrent(): this {\n this.definition.defaultValue = { __type: \"CURRENT_TIMESTAMP\" };\n return this;\n }\n\n /**\n * Set column to update to current timestamp on row update.\n *\n * MySQL only. Other databases ignore this.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.timestamp(\"updated_at\").useCurrent().useCurrentOnUpdate();\n * ```\n */\n public useCurrentOnUpdate(): this {\n this.definition.onUpdateCurrent = true;\n return this;\n }\n\n // ============================================================================\n // INDEXES\n // ============================================================================\n\n /**\n * Add unique constraint/index on this column.\n *\n * Registers a pending unique index with the parent migration.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"email\").unique();\n * ```\n */\n public unique(): this {\n this.migration.addPendingIndex({\n columns: [this.definition.name],\n unique: true,\n });\n return this;\n }\n\n /**\n * Add regular index on this column.\n *\n * Registers a pending index with the parent migration.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"email\").index();\n * ```\n */\n public index(): this {\n this.migration.addPendingIndex({\n columns: [this.definition.name],\n });\n return this;\n }\n\n /**\n * Add a vector search index on this column.\n *\n * Registers a pending vector index with the parent migration.\n *\n * @param options - Vector index options\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.vector(1536).vectorIndex({ similarity: \"cosine\" });\n * ```\n */\n public vectorIndex(options: Omit<VectorIndexOptions, \"dimensions\"> = {}): this {\n if (this.migration.addPendingVectorIndex) {\n this.migration.addPendingVectorIndex(this.definition.name, {\n ...options,\n dimensions: this.definition.dimensions || 0,\n });\n }\n return this;\n }\n\n // ============================================================================\n // PRIMARY KEY & AUTO INCREMENT\n // ============================================================================\n\n /**\n * Mark as primary key.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary();\n * ```\n */\n public primary(): this {\n this.definition.primary = true;\n return this;\n }\n\n /**\n * Mark as auto-increment (numeric types only).\n *\n * SQL databases will use native AUTO_INCREMENT/SERIAL.\n * NoSQL databases ignore this.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary().autoIncrement();\n * ```\n */\n public autoIncrement(): this {\n this.definition.autoIncrement = true;\n return this;\n }\n\n // ============================================================================\n // NUMERIC MODIFIERS\n // ============================================================================\n\n /**\n * Mark as unsigned (numeric types only).\n *\n * Disallows negative values and doubles the positive range.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"age\").unsigned();\n * ```\n */\n public unsigned(): this {\n this.definition.unsigned = true;\n return this;\n }\n\n // ============================================================================\n // METADATA\n // ============================================================================\n\n /**\n * Add comment/description to column.\n *\n * Stored as column metadata in the database.\n *\n * @param text - Comment text\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"sku\").comment(\"Stock Keeping Unit code\");\n * ```\n */\n public comment(text: string): this {\n this.definition.comment = text;\n return this;\n }\n\n // ============================================================================\n // CONSTRAINTS\n // ============================================================================\n\n /**\n * Add a CHECK constraint scoped to this column.\n *\n * @param expression - SQL CHECK expression (can reference the column by name)\n * @param name - Constraint name (defaults to `check_<column>`)\n * @returns This builder for chaining\n */\n public check(expression: string, name?: string): this {\n this.definition.checkConstraint = {\n expression,\n name: name ?? `check_${this.definition.name}`,\n };\n return this;\n }\n\n // ============================================================================\n // COLUMN POSITIONING (MySQL/MariaDB only)\n // ============================================================================\n\n /**\n * Position this column after another column.\n *\n * MySQL/MariaDB only. Ignored by PostgreSQL and NoSQL drivers.\n *\n * @param columnName - Column to position after\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"middle_name\").after(\"first_name\");\n * ```\n */\n public after(columnName: string): this {\n this.definition.after = columnName;\n return this;\n }\n\n /**\n * Position this column as the first column in the table.\n *\n * MySQL/MariaDB only. Ignored by PostgreSQL and NoSQL drivers.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary().first();\n * ```\n */\n public first(): this {\n this.definition.first = true;\n return this;\n }\n\n // ============================================================================\n // FOREIGN KEY\n // ============================================================================\n\n /**\n * Declare a foreign key constraint on this column.\n *\n * Accepts either a raw table-name string or a Model class (anything with a\n * static `table` property). Using a Model class is preferred — it is\n * type-safe and automatically tracks table renames.\n *\n * Pushes an `addForeignKey` operation immediately using a mutable reference —\n * subsequent `.on()`, `.onDelete()`, `.onUpdate()` calls mutate the same\n * definition that is already queued, so no `.add()` terminator is needed.\n *\n * Referenced column defaults to `\"id\"` — use `.on()` to override.\n *\n * @param tableOrModel - Referenced table name OR a Model class with a static `table` property\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Preferred — model class reference (type-safe, rename-proof)\n * this.uuid(\"organization_id\").references(Organization).onDelete(\"cascade\");\n *\n * // Also supported — raw table string\n * this.uuid(\"organization_id\").references(\"organizations\").onDelete(\"cascade\");\n * this.uuid(\"organization_id\").references(Organization.table).onDelete(\"cascade\");\n * ```\n */\n public references(tableOrModel: string | { table: string }): this {\n const tableName = typeof tableOrModel === \"string\" ? tableOrModel : tableOrModel.table;\n\n this.fkDefinition = {\n column: this.definition.name,\n referencesTable: tableName,\n referencesColumn: \"id\",\n onDelete: \"restrict\",\n onUpdate: \"restrict\",\n };\n this.migration.addForeignKeyOperation(this.fkDefinition as ForeignKeyDefinition);\n return this;\n }\n\n /**\n * Set the referenced column for the foreign key.\n *\n * Only meaningful after `.references()`. Defaults to `\"id\"` if omitted.\n *\n * @param column - Referenced column name\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").on(\"custom_id\");\n * ```\n */\n public on(column: string): this {\n if (this.fkDefinition) {\n this.fkDefinition.referencesColumn = column;\n }\n return this;\n }\n\n /**\n * Set the ON DELETE action for the foreign key.\n *\n * Only meaningful after `.references()`.\n *\n * @param action - Action when the referenced row is deleted\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").onDelete(\"cascade\");\n * ```\n */\n public onDelete(action: ForeignKeyDefinition[\"onDelete\"]): this {\n if (this.fkDefinition) {\n this.fkDefinition.onDelete = action;\n }\n return this;\n }\n\n /**\n * Set the ON UPDATE action for the foreign key.\n *\n * Only meaningful after `.references()`.\n *\n * @param action - Action when the referenced row's key is updated\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").onUpdate(\"cascade\");\n * ```\n */\n public onUpdate(action: ForeignKeyDefinition[\"onUpdate\"]): this {\n if (this.fkDefinition) {\n this.fkDefinition.onUpdate = action;\n }\n return this;\n }\n\n /**\n * Shorthand for `.onDelete(\"cascade\").onUpdate(\"cascade\")`.\n *\n * Only meaningful after `.references()`.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").cascadeAll();\n * ```\n */\n public cascadeAll(): this {\n if (this.fkDefinition) {\n this.fkDefinition.onDelete = \"cascade\";\n this.fkDefinition.onUpdate = \"cascade\";\n }\n return this;\n }\n\n // ============================================================================\n // COLUMN MODIFICATION\n // ============================================================================\n\n /**\n * Mark this column definition as a modification of an existing column.\n *\n * Pushes a `modifyColumn` operation instead of `addColumn`.\n * This method breaks the builder chain and returns the parent migration.\n *\n * @returns The parent migration instance (breaks builder chain)\n *\n * @example\n * ```typescript\n * // Make email nullable\n * this.string(\"email\").nullable().change();\n *\n * // Increase length\n * this.string(\"name\", 255).change();\n *\n * // Change type\n * this.text(\"description\").change();\n * ```\n */\n public change(): unknown {\n const operations = (this.migration as any).pendingOperations;\n\n // Remove the addColumn pushed by the column type method (e.g. uuid(), string())\n const lastOp = operations[operations.length - 1];\n if (lastOp?.type === \"addColumn\" && lastOp.payload === this.definition) {\n operations.pop();\n }\n\n // If .references() was called before .change(), the addForeignKey op is now\n // last in the queue. We must pop it, push modifyColumn first, then re-push\n // the FK — because SQL requires: ALTER COLUMN (type change) → ADD CONSTRAINT (FK).\n let pendingFkOp: (typeof operations)[number] | undefined;\n if (this.fkDefinition) {\n const tail = operations[operations.length - 1];\n if (tail?.type === \"addForeignKey\" && tail.payload === this.fkDefinition) {\n pendingFkOp = operations.pop();\n }\n }\n\n // Push modifyColumn — it must precede the FK constraint\n operations.push({ type: \"modifyColumn\", payload: this.definition });\n\n // Re-queue the FK after the column modification\n if (pendingFkOp) {\n operations.push(pendingFkOp);\n }\n\n return this.migration;\n }\n\n /**\n * @alias change\n */\n public modify(): unknown {\n return this.change();\n }\n\n // ============================================================================\n // GENERATED COLUMNS\n // ============================================================================\n\n /**\n * Mark this column as a generated column with the given SQL expression.\n *\n * Must be followed by `.stored()` or `.virtual()` to specify storage type.\n *\n * PostgreSQL: GENERATED ALWAYS AS (...) STORED\n * MySQL: GENERATED ALWAYS AS (...) STORED | VIRTUAL\n *\n * @param expression - SQL expression to compute the value\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"full_name\")\n * .generatedAs(\"CONCAT(first_name, ' ', last_name)\")\n * .stored();\n *\n * this.decimal(\"price_with_tax\")\n * .generatedAs(\"price * 1.2\")\n * .virtual();\n * ```\n */\n public generatedAs(expression: string): this {\n this.generatedExpression = expression;\n return this;\n }\n\n /**\n * Mark the generated column as stored (computed and persisted to disk).\n *\n * Must be called after `.generatedAs()`.\n *\n * @returns This builder for chaining\n */\n public stored(): this {\n if (this.generatedExpression) {\n this.definition.generated = {\n expression: this.generatedExpression,\n stored: true,\n };\n }\n return this;\n }\n\n /**\n * Mark the generated column as virtual (computed on read, not stored).\n *\n * Must be called after `.generatedAs()`. Not supported by PostgreSQL.\n *\n * @returns This builder for chaining\n */\n public virtual(): this {\n if (this.generatedExpression) {\n this.definition.generated = {\n expression: this.generatedExpression,\n stored: false,\n };\n }\n return this;\n }\n\n // ============================================================================\n // ACCESSOR\n // ============================================================================\n\n /**\n * Get the built column definition.\n *\n * Called internally by the Migration class to extract the final definition.\n *\n * @returns The accumulated column definition\n */\n public getDefinition(): ColumnDefinition {\n return this.definition;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column-builder.mjs","names":[],"sources":["../../../../../../../cascade/src/migration/column-builder.ts"],"sourcesContent":["import type {\n ColumnDefinition,\n ColumnType,\n ForeignKeyDefinition,\n VectorIndexOptions,\n} from \"../contracts/migration-driver.contract\";\n\n/**\n * Reference to the Migration type to avoid circular imports.\n * The actual type is injected at runtime.\n */\ntype MigrationLike = {\n addPendingIndex(index: { columns: string[]; unique?: boolean }): void;\n addForeignKeyOperation(fk: ForeignKeyDefinition): void;\n addPendingVectorIndex?(column: string, options: Omit<VectorIndexOptions, \"column\">): void;\n};\n\n/**\n * Mutable foreign key definition being built via ColumnBuilder.\n */\ninterface MutableForeignKeyDefinition {\n name?: string;\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete: ForeignKeyDefinition[\"onDelete\"];\n onUpdate: ForeignKeyDefinition[\"onUpdate\"];\n}\n\n/**\n * Fluent builder for defining column properties.\n *\n * Allows chaining modifiers like `.nullable()`, `.unique()`, `.default()`.\n * Each column builder is bound to a parent migration and accumulates\n * the column definition through method chains.\n *\n * @example\n * ```typescript\n * this.string(\"email\")\n * .nullable()\n * .unique()\n * .default(\"guest@example.com\");\n * ```\n *\n * @example\n * ```typescript\n * this.integer(\"age\")\n * .unsigned()\n * .comment(\"User's age in years\");\n * ```\n */\nexport class ColumnBuilder {\n /** Mutable column definition being accumulated */\n private readonly definition: ColumnDefinition;\n\n /** Mutable foreign key definition, set when .references() is called */\n private fkDefinition?: MutableForeignKeyDefinition;\n\n /** Temporary storage for generated expression before .stored() or .virtual() is called */\n private generatedExpression?: string;\n\n /**\n * Create a new column builder.\n *\n * @param migration - Parent migration instance for index registration\n * @param name - Column name\n * @param type - Column data type\n * @param options - Optional initial configuration\n */\n public constructor(\n private readonly migration: MigrationLike,\n name: string,\n type: ColumnType,\n options: Partial<\n Pick<ColumnDefinition, \"length\" | \"precision\" | \"scale\" | \"dimensions\" | \"values\">\n > = {},\n ) {\n this.definition = {\n name,\n type,\n nullable: false,\n ...options,\n };\n }\n\n // ============================================================================\n // NULLABILITY\n // ============================================================================\n\n /**\n * Mark column as nullable (allows NULL values).\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"middleName\").nullable();\n * ```\n */\n public nullable(): this {\n this.definition.nullable = true;\n return this;\n }\n\n /**\n * Mark column as not nullable (disallows NULL values).\n *\n * This is the default, but can be used for clarity.\n *\n * @returns This builder for chaining\n */\n public notNullable(): this {\n this.definition.nullable = false;\n return this;\n }\n\n // ============================================================================\n // DEFAULT VALUES\n // ============================================================================\n\n /**\n * Set default value for the column as a raw SQL expression.\n *\n * The value will be used as-is in the SQL statement without escaping.\n * Use this for database functions and expressions.\n *\n * @param value - Default value (SQL expression, number, or boolean)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.uuid(\"id\").default(\"gen_random_uuid()\");\n * this.timestamp(\"created_at\").default(\"NOW()\");\n * this.integer(\"version\").default(1);\n * this.boolean(\"is_active\").default(true);\n * ```\n */\n public default(value: string | number | boolean): this {\n this.definition.defaultValue = value;\n this.definition.isRawDefault = true;\n return this;\n }\n\n /**\n * Set default value for the column as a literal string.\n *\n * The value will be properly escaped and quoted in the SQL statement.\n * Use this for literal string values, not SQL expressions.\n *\n * @param value - Default string value (will be escaped)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.text(\"status\").defaultString(\"active\");\n * this.text(\"greeting\").defaultString(\"Hello, World!\");\n * ```\n */\n public defaultString(value: string): this {\n this.definition.defaultValue = value;\n this.definition.isRawDefault = false;\n return this;\n }\n\n /**\n * Set default value to the current timestamp.\n *\n * Database-agnostic. Generates NOW() / CURRENT_TIMESTAMP / GETDATE() based on driver.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.timestamp(\"created_at\").useCurrent();\n * ```\n */\n public useCurrent(): this {\n this.definition.defaultValue = { __type: \"CURRENT_TIMESTAMP\" };\n return this;\n }\n\n /**\n * Set column to update to current timestamp on row update.\n *\n * MySQL only. Other databases ignore this.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.timestamp(\"updated_at\").useCurrent().useCurrentOnUpdate();\n * ```\n */\n public useCurrentOnUpdate(): this {\n this.definition.onUpdateCurrent = true;\n return this;\n }\n\n // ============================================================================\n // INDEXES\n // ============================================================================\n\n /**\n * Add unique constraint/index on this column.\n *\n * Registers a pending unique index with the parent migration.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"email\").unique();\n * ```\n */\n public unique(): this {\n this.migration.addPendingIndex({\n columns: [this.definition.name],\n unique: true,\n });\n return this;\n }\n\n /**\n * Add regular index on this column.\n *\n * Registers a pending index with the parent migration.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"email\").index();\n * ```\n */\n public index(): this {\n this.migration.addPendingIndex({\n columns: [this.definition.name],\n });\n return this;\n }\n\n /**\n * Add a vector search index on this column.\n *\n * Registers a pending vector index with the parent migration.\n *\n * @param options - Vector index options\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.vector(1536).vectorIndex({ similarity: \"cosine\" });\n * ```\n */\n public vectorIndex(options: Omit<VectorIndexOptions, \"dimensions\"> = {}): this {\n if (this.migration.addPendingVectorIndex) {\n this.migration.addPendingVectorIndex(this.definition.name, {\n ...options,\n dimensions: this.definition.dimensions || 0,\n });\n }\n return this;\n }\n\n // ============================================================================\n // PRIMARY KEY & AUTO INCREMENT\n // ============================================================================\n\n /**\n * Mark as primary key.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary();\n * ```\n */\n public primary(): this {\n this.definition.primary = true;\n return this;\n }\n\n /**\n * Mark as auto-increment (numeric types only).\n *\n * SQL databases will use native AUTO_INCREMENT/SERIAL.\n * NoSQL databases ignore this.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary().autoIncrement();\n * ```\n */\n public autoIncrement(): this {\n this.definition.autoIncrement = true;\n return this;\n }\n\n // ============================================================================\n // NUMERIC MODIFIERS\n // ============================================================================\n\n /**\n * Mark as unsigned (numeric types only).\n *\n * Disallows negative values and doubles the positive range.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"age\").unsigned();\n * ```\n */\n public unsigned(): this {\n this.definition.unsigned = true;\n return this;\n }\n\n // ============================================================================\n // METADATA\n // ============================================================================\n\n /**\n * Add comment/description to column.\n *\n * Stored as column metadata in the database.\n *\n * @param text - Comment text\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"sku\").comment(\"Stock Keeping Unit code\");\n * ```\n */\n public comment(text: string): this {\n this.definition.comment = text;\n return this;\n }\n\n // ============================================================================\n // CONSTRAINTS\n // ============================================================================\n\n /**\n * Add a CHECK constraint scoped to this column.\n *\n * @param expression - SQL CHECK expression (can reference the column by name)\n * @param name - Constraint name (defaults to `check_<column>`)\n * @returns This builder for chaining\n */\n public check(expression: string, name?: string): this {\n this.definition.checkConstraint = {\n expression,\n name: name ?? `check_${this.definition.name}`,\n };\n return this;\n }\n\n // ============================================================================\n // COLUMN POSITIONING (MySQL/MariaDB only)\n // ============================================================================\n\n /**\n * Position this column after another column.\n *\n * MySQL/MariaDB only. Ignored by PostgreSQL and NoSQL drivers.\n *\n * @param columnName - Column to position after\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"middle_name\").after(\"first_name\");\n * ```\n */\n public after(columnName: string): this {\n this.definition.after = columnName;\n return this;\n }\n\n /**\n * Position this column as the first column in the table.\n *\n * MySQL/MariaDB only. Ignored by PostgreSQL and NoSQL drivers.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary().first();\n * ```\n */\n public first(): this {\n this.definition.first = true;\n return this;\n }\n\n // ============================================================================\n // FOREIGN KEY\n // ============================================================================\n\n /**\n * Declare a foreign key constraint on this column.\n *\n * Accepts either a raw table-name string or a Model class (anything with a\n * static `table` property). Using a Model class is preferred — it is\n * type-safe and automatically tracks table renames.\n *\n * Pushes an `addForeignKey` operation immediately using a mutable reference —\n * subsequent `.on()`, `.onDelete()`, `.onUpdate()` calls mutate the same\n * definition that is already queued, so no `.add()` terminator is needed.\n *\n * Referenced column defaults to `\"id\"` — use `.on()` to override.\n *\n * @param tableOrModel - Referenced table name OR a Model class with a static `table` property\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Preferred — model class reference (type-safe, rename-proof)\n * this.uuid(\"organization_id\").references(Organization).onDelete(\"cascade\");\n *\n * // Also supported — raw table string\n * this.uuid(\"organization_id\").references(\"organizations\").onDelete(\"cascade\");\n * this.uuid(\"organization_id\").references(Organization.table).onDelete(\"cascade\");\n * ```\n */\n public references(tableOrModel: string | { table: string }): this {\n const tableName = typeof tableOrModel === \"string\" ? tableOrModel : tableOrModel.table;\n\n this.fkDefinition = {\n column: this.definition.name,\n referencesTable: tableName,\n referencesColumn: \"id\",\n onDelete: \"restrict\",\n onUpdate: \"restrict\",\n };\n this.migration.addForeignKeyOperation(this.fkDefinition as ForeignKeyDefinition);\n return this;\n }\n\n /**\n * Set the referenced column for the foreign key.\n *\n * Only meaningful after `.references()`. Defaults to `\"id\"` if omitted.\n *\n * @param column - Referenced column name\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").on(\"custom_id\");\n * ```\n */\n public on(column: string): this {\n if (this.fkDefinition) {\n this.fkDefinition.referencesColumn = column;\n }\n return this;\n }\n\n /**\n * Set the ON DELETE action for the foreign key.\n *\n * Only meaningful after `.references()`.\n *\n * @param action - Action when the referenced row is deleted\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").onDelete(\"cascade\");\n * ```\n */\n public onDelete(action: ForeignKeyDefinition[\"onDelete\"]): this {\n if (this.fkDefinition) {\n this.fkDefinition.onDelete = action;\n }\n return this;\n }\n\n /**\n * Set the ON UPDATE action for the foreign key.\n *\n * Only meaningful after `.references()`.\n *\n * @param action - Action when the referenced row's key is updated\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").onUpdate(\"cascade\");\n * ```\n */\n public onUpdate(action: ForeignKeyDefinition[\"onUpdate\"]): this {\n if (this.fkDefinition) {\n this.fkDefinition.onUpdate = action;\n }\n return this;\n }\n\n /**\n * Shorthand for `.onDelete(\"cascade\").onUpdate(\"cascade\")`.\n *\n * Only meaningful after `.references()`.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"user_id\").references(\"users\").cascadeAll();\n * ```\n */\n public cascadeAll(): this {\n if (this.fkDefinition) {\n this.fkDefinition.onDelete = \"cascade\";\n this.fkDefinition.onUpdate = \"cascade\";\n }\n return this;\n }\n\n // ============================================================================\n // COLUMN MODIFICATION\n // ============================================================================\n\n /**\n * Mark this column definition as a modification of an existing column.\n *\n * Pushes a `modifyColumn` operation instead of `addColumn`.\n * This method breaks the builder chain and returns the parent migration.\n *\n * @returns The parent migration instance (breaks builder chain)\n *\n * @example\n * ```typescript\n * // Make email nullable\n * this.string(\"email\").nullable().change();\n *\n * // Increase length\n * this.string(\"name\", 255).change();\n *\n * // Change type\n * this.text(\"description\").change();\n * ```\n */\n public change(): unknown {\n const operations = (this.migration as any).pendingOperations;\n\n // Remove the addColumn pushed by the column type method (e.g. uuid(), string())\n const lastOp = operations[operations.length - 1];\n if (lastOp?.type === \"addColumn\" && lastOp.payload === this.definition) {\n operations.pop();\n }\n\n // If .references() was called before .change(), the addForeignKey op is now\n // last in the queue. We must pop it, push modifyColumn first, then re-push\n // the FK — because SQL requires: ALTER COLUMN (type change) → ADD CONSTRAINT (FK).\n let pendingFkOp: (typeof operations)[number] | undefined;\n if (this.fkDefinition) {\n const tail = operations[operations.length - 1];\n if (tail?.type === \"addForeignKey\" && tail.payload === this.fkDefinition) {\n pendingFkOp = operations.pop();\n }\n }\n\n // Push modifyColumn — it must precede the FK constraint\n operations.push({ type: \"modifyColumn\", payload: this.definition });\n\n // Re-queue the FK after the column modification\n if (pendingFkOp) {\n operations.push(pendingFkOp);\n }\n\n return this.migration;\n }\n\n /**\n * @alias change\n */\n public modify(): unknown {\n return this.change();\n }\n\n // ============================================================================\n // GENERATED COLUMNS\n // ============================================================================\n\n /**\n * Mark this column as a generated column with the given SQL expression.\n *\n * Must be followed by `.stored()` or `.virtual()` to specify storage type.\n *\n * PostgreSQL: GENERATED ALWAYS AS (...) STORED\n * MySQL: GENERATED ALWAYS AS (...) STORED | VIRTUAL\n *\n * @param expression - SQL expression to compute the value\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"full_name\")\n * .generatedAs(\"CONCAT(first_name, ' ', last_name)\")\n * .stored();\n *\n * this.decimal(\"price_with_tax\")\n * .generatedAs(\"price * 1.2\")\n * .virtual();\n * ```\n */\n public generatedAs(expression: string): this {\n this.generatedExpression = expression;\n return this;\n }\n\n /**\n * Mark the generated column as stored (computed and persisted to disk).\n *\n * Must be called after `.generatedAs()`.\n *\n * @returns This builder for chaining\n */\n public stored(): this {\n if (this.generatedExpression) {\n this.definition.generated = {\n expression: this.generatedExpression,\n stored: true,\n };\n }\n return this;\n }\n\n /**\n * Mark the generated column as virtual (computed on read, not stored).\n *\n * Must be called after `.generatedAs()`. Not supported by PostgreSQL.\n *\n * @returns This builder for chaining\n */\n public virtual(): this {\n if (this.generatedExpression) {\n this.definition.generated = {\n expression: this.generatedExpression,\n stored: false,\n };\n }\n return this;\n }\n\n // ============================================================================\n // ACCESSOR\n // ============================================================================\n\n /**\n * Get the built column definition.\n *\n * Called internally by the Migration class to extract the final definition.\n *\n * @returns The accumulated column definition\n */\n public getDefinition(): ColumnDefinition {\n return this.definition;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VectorIndexOptions } from "../contracts/migration-driver.contract.mjs";
|
|
2
2
|
import { ColumnBuilder } from "./column-builder.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../cascade/src/migration/column-helpers.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* A no-op migration sink used by standalone column helpers.
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-helpers.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"column-helpers.d.mts","names":[],"sources":["../../../../../../../cascade/src/migration/column-helpers.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-helpers.mjs","names":[],"sources":["../../../../../../../@warlock.js/cascade/src/migration/column-helpers.ts"],"sourcesContent":["import { ColumnBuilder } from \"./column-builder\";\n\n/**\n * A no-op migration sink used by standalone column helpers.\n *\n * When column helpers are used in `Migration.create()` / `Migration.alter()`,\n * the builder is constructed without a real migration context. The actual\n * operations are dequeued from the ColumnBuilder's definition and replayed\n * onto the real migration instance at execution time.\n *\n * Index and FK operations queued on this sink are collected and transferred\n * to the real migration by the factory methods.\n */\nclass DetachedMigrationSink {\n /** Pending indexes registered via .unique() / .index() on a helper column. */\n public readonly pendingIndexes: { columns: string[]; unique?: boolean }[] = [];\n\n /** Pending FK definitions registered via .references() on a helper column. */\n public readonly pendingForeignKeys: object[] = [];\n\n /** Pending Vector index definitions registered via .vectorIndex() on a helper column. */\n public readonly pendingVectorIndexes: {\n column: string;\n options: import(\"../contracts/migration-driver.contract\").VectorIndexOptions;\n }[] = [];\n\n public addPendingIndex(index: { columns: string[]; unique?: boolean }): void {\n this.pendingIndexes.push(index);\n }\n\n public addForeignKeyOperation(fk: object): void {\n this.pendingForeignKeys.push(fk);\n }\n\n public addPendingVectorIndex(\n column: string,\n options: Omit<import(\"../contracts/migration-driver.contract\").VectorIndexOptions, \"column\">,\n ): void {\n this.pendingVectorIndexes.push({ column, options: options as any });\n }\n}\n\n/**\n * A `ColumnBuilder` that carries its own detached sink so it can be\n * constructed outside of a migration class and later merged in.\n */\nexport class DetachedColumnBuilder extends ColumnBuilder {\n public readonly sink: DetachedMigrationSink;\n\n public constructor(\n type: ConstructorParameters<typeof ColumnBuilder>[2],\n name: string,\n options: ConstructorParameters<typeof ColumnBuilder>[3] = {},\n ) {\n const sink = new DetachedMigrationSink();\n super(sink as any, name, type, options);\n this.sink = sink;\n }\n}\n\n// ============================================================================\n// STRING HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: string / varchar.\n *\n * @example\n * ```typescript\n * import { Migration, string } from \"@warlock.js/cascade\";\n *\n * export default Migration.create(User, {\n * username: string(50).unique(),\n * });\n * ```\n */\nexport function string(length = 255): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"string\", \"__placeholder__\", { length });\n}\n\n/**\n * Standalone column helper: fixed-length CHAR.\n *\n * @example\n * ```typescript\n * code: char(3) // CHAR(3)\n * ```\n */\nexport function char(length: number): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"char\", \"__placeholder__\", { length });\n}\n\n/**\n * Standalone column helper: TEXT (unlimited length).\n *\n * @example\n * ```typescript\n * import { Migration, text } from \"@warlock.js/cascade\";\n *\n * export default Migration.create(User, {\n * bio: text().nullable(),\n * });\n * ```\n */\nexport function text(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"text\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: MEDIUMTEXT.\n */\nexport function mediumText(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"mediumText\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: LONGTEXT.\n */\nexport function longText(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"longText\", \"__placeholder__\");\n}\n\n// ============================================================================\n// NUMERIC HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: INTEGER.\n *\n * @example\n * ```typescript\n * age: integer().unsigned()\n * ```\n */\nexport function integer(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"integer\", \"__placeholder__\");\n}\n\n/** Alias for `integer()`. */\nexport const int = integer;\n\n/**\n * Standalone column helper: SMALLINT.\n */\nexport function smallInteger(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"smallInteger\", \"__placeholder__\");\n}\n\n/** Alias for `smallInteger()`. */\nexport const smallInt = smallInteger;\n\n/**\n * Standalone column helper: TINYINT.\n */\nexport function tinyInteger(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"tinyInteger\", \"__placeholder__\");\n}\n\n/** Alias for `tinyInteger()`. */\nexport const tinyInt = tinyInteger;\n\n/**\n * Standalone column helper: BIGINT.\n */\nexport function bigInteger(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"bigInteger\", \"__placeholder__\");\n}\n\n/** Alias for `bigInteger()`. */\nexport const bigInt = bigInteger;\n\n/**\n * Standalone column helper: FLOAT.\n */\nexport function float(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"float\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: DOUBLE.\n */\nexport function double(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"double\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: DECIMAL.\n *\n * @example\n * ```typescript\n * price: decimal(10, 2) // DECIMAL(10,2)\n * ```\n */\nexport function decimal(precision = 8, scale = 2): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"decimal\", \"__placeholder__\", { precision, scale });\n}\n\n// ============================================================================\n// BOOLEAN HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: BOOLEAN.\n *\n * Named `boolCol` to avoid collision with the TypeScript / JS `boolean` primitive.\n *\n * @example\n * ```typescript\n * is_active: boolCol().default(true)\n * ```\n */\nexport function boolCol(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"boolean\", \"__placeholder__\");\n}\n\n/** Alias for `boolCol()`. */\nexport { boolCol as bool };\n\n// ============================================================================\n// DATE / TIME HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: DATE.\n */\nexport function date(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"date\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: DATETIME.\n */\nexport function dateTime(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"dateTime\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: TIMESTAMP.\n *\n * @example\n * ```typescript\n * started_at: timestamp().default(\"NOW()\")\n * ```\n */\nexport function timestamp(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"timestamp\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: TIME.\n */\nexport function time(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"time\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: YEAR.\n */\nexport function year(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"year\", \"__placeholder__\");\n}\n\n// ============================================================================\n// JSON & BINARY HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: JSON.\n *\n * Named `jsonCol` to avoid collision with the TS/JSON built-in names.\n * Use `json()` is fine for most cases though — this alias exists for clarity.\n *\n * @example\n * ```typescript\n * metadata: json().nullable()\n * ```\n */\nexport function json(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"json\", \"__placeholder__\");\n}\n\n/**\n * Alias for `json()`. Named `objectCol` to avoid collision with TS `object` type.\n */\nexport function objectCol(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"json\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: BINARY / BLOB.\n */\nexport function binary(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"binary\", \"__placeholder__\");\n}\n\n/**\n * Alias for `binary()`. Named `blobCol` to avoid collision with the Web `Blob` API.\n */\nexport function blobCol(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"binary\", \"__placeholder__\");\n}\n\n// ============================================================================\n// IDENTIFIER HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: UUID.\n *\n * @example\n * ```typescript\n * import { Migration, uuid } from \"@warlock.js/cascade\";\n *\n * export default Migration.create(Chat, {\n * organization_id: uuid().references(Organization).onDelete(\"cascade\"),\n * });\n * ```\n */\nexport function uuid(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"uuid\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: ULID.\n */\nexport function ulid(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"ulid\", \"__placeholder__\");\n}\n\n// ============================================================================\n// NETWORK HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: IP address.\n */\nexport function ipAddress(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"ipAddress\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: MAC address.\n */\nexport function macAddress(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"macAddress\", \"__placeholder__\");\n}\n\n// ============================================================================\n// SPATIAL HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: geo point.\n */\nexport function point(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"point\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: polygon.\n */\nexport function polygon(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"polygon\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: line string.\n */\nexport function lineString(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"lineString\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: generic geometry.\n */\nexport function geometry(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"geometry\", \"__placeholder__\");\n}\n\n// ============================================================================\n// AI / ML HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: vector (for AI embeddings).\n *\n * @param dimensions - Embedding size (e.g. 1536 for text-embedding-3-small)\n *\n * @example\n * ```typescript\n * embedding: vector(1536)\n * ```\n */\nexport function vector(dimensions: number): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"vector\", \"__placeholder__\", { dimensions });\n}\n\n// ============================================================================\n// ENUM & SET HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: ENUM.\n *\n * @example\n * ```typescript\n * status: enumCol([\"active\", \"inactive\", \"pending\"])\n * ```\n */\nexport function enumCol(values: string[]): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"enum\", \"__placeholder__\", { values });\n}\n\n/**\n * Standalone column helper: SET (multiple values).\n */\nexport function setCol(values: string[]): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"set\", \"__placeholder__\", { values });\n}\n\n// ============================================================================\n// POSTGRESQL ARRAY HELPERS\n// ============================================================================\n\n/** Standalone helper: INTEGER[] */\nexport function arrayInt(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayInt\", \"__placeholder__\");\n}\n\n/** Standalone helper: BIGINT[] */\nexport function arrayBigInt(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayBigInt\", \"__placeholder__\");\n}\n\n/** Standalone helper: REAL[] */\nexport function arrayFloat(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayFloat\", \"__placeholder__\");\n}\n\n/** Standalone helper: DECIMAL[] */\nexport function arrayDecimal(precision?: number, scale?: number): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayDecimal\", \"__placeholder__\", { precision, scale });\n}\n\n/** Standalone helper: BOOLEAN[] */\nexport function arrayBoolean(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayBoolean\", \"__placeholder__\");\n}\n\n/** Standalone helper: TEXT[] */\nexport function arrayText(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayText\", \"__placeholder__\");\n}\n\n/** Standalone helper: DATE[] */\nexport function arrayDate(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayDate\", \"__placeholder__\");\n}\n\n/** Standalone helper: TIMESTAMPTZ[] */\nexport function arrayTimestamp(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayTimestamp\", \"__placeholder__\");\n}\n\n/** Standalone helper: UUID[] */\nexport function arrayUuid(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayUuid\", \"__placeholder__\");\n}\n\n/** Standalone helper: JSONB[] */\nexport function arrayJson(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayJson\", \"__placeholder__\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column-helpers.mjs","names":[],"sources":["../../../../../../../cascade/src/migration/column-helpers.ts"],"sourcesContent":["import { ColumnBuilder } from \"./column-builder\";\n\n/**\n * A no-op migration sink used by standalone column helpers.\n *\n * When column helpers are used in `Migration.create()` / `Migration.alter()`,\n * the builder is constructed without a real migration context. The actual\n * operations are dequeued from the ColumnBuilder's definition and replayed\n * onto the real migration instance at execution time.\n *\n * Index and FK operations queued on this sink are collected and transferred\n * to the real migration by the factory methods.\n */\nclass DetachedMigrationSink {\n /** Pending indexes registered via .unique() / .index() on a helper column. */\n public readonly pendingIndexes: { columns: string[]; unique?: boolean }[] = [];\n\n /** Pending FK definitions registered via .references() on a helper column. */\n public readonly pendingForeignKeys: object[] = [];\n\n /** Pending Vector index definitions registered via .vectorIndex() on a helper column. */\n public readonly pendingVectorIndexes: {\n column: string;\n options: import(\"../contracts/migration-driver.contract\").VectorIndexOptions;\n }[] = [];\n\n public addPendingIndex(index: { columns: string[]; unique?: boolean }): void {\n this.pendingIndexes.push(index);\n }\n\n public addForeignKeyOperation(fk: object): void {\n this.pendingForeignKeys.push(fk);\n }\n\n public addPendingVectorIndex(\n column: string,\n options: Omit<import(\"../contracts/migration-driver.contract\").VectorIndexOptions, \"column\">,\n ): void {\n this.pendingVectorIndexes.push({ column, options: options as any });\n }\n}\n\n/**\n * A `ColumnBuilder` that carries its own detached sink so it can be\n * constructed outside of a migration class and later merged in.\n */\nexport class DetachedColumnBuilder extends ColumnBuilder {\n public readonly sink: DetachedMigrationSink;\n\n public constructor(\n type: ConstructorParameters<typeof ColumnBuilder>[2],\n name: string,\n options: ConstructorParameters<typeof ColumnBuilder>[3] = {},\n ) {\n const sink = new DetachedMigrationSink();\n super(sink as any, name, type, options);\n this.sink = sink;\n }\n}\n\n// ============================================================================\n// STRING HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: string / varchar.\n *\n * @example\n * ```typescript\n * import { Migration, string } from \"@warlock.js/cascade\";\n *\n * export default Migration.create(User, {\n * username: string(50).unique(),\n * });\n * ```\n */\nexport function string(length = 255): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"string\", \"__placeholder__\", { length });\n}\n\n/**\n * Standalone column helper: fixed-length CHAR.\n *\n * @example\n * ```typescript\n * code: char(3) // CHAR(3)\n * ```\n */\nexport function char(length: number): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"char\", \"__placeholder__\", { length });\n}\n\n/**\n * Standalone column helper: TEXT (unlimited length).\n *\n * @example\n * ```typescript\n * import { Migration, text } from \"@warlock.js/cascade\";\n *\n * export default Migration.create(User, {\n * bio: text().nullable(),\n * });\n * ```\n */\nexport function text(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"text\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: MEDIUMTEXT.\n */\nexport function mediumText(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"mediumText\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: LONGTEXT.\n */\nexport function longText(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"longText\", \"__placeholder__\");\n}\n\n// ============================================================================\n// NUMERIC HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: INTEGER.\n *\n * @example\n * ```typescript\n * age: integer().unsigned()\n * ```\n */\nexport function integer(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"integer\", \"__placeholder__\");\n}\n\n/** Alias for `integer()`. */\nexport const int = integer;\n\n/**\n * Standalone column helper: SMALLINT.\n */\nexport function smallInteger(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"smallInteger\", \"__placeholder__\");\n}\n\n/** Alias for `smallInteger()`. */\nexport const smallInt = smallInteger;\n\n/**\n * Standalone column helper: TINYINT.\n */\nexport function tinyInteger(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"tinyInteger\", \"__placeholder__\");\n}\n\n/** Alias for `tinyInteger()`. */\nexport const tinyInt = tinyInteger;\n\n/**\n * Standalone column helper: BIGINT.\n */\nexport function bigInteger(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"bigInteger\", \"__placeholder__\");\n}\n\n/** Alias for `bigInteger()`. */\nexport const bigInt = bigInteger;\n\n/**\n * Standalone column helper: FLOAT.\n */\nexport function float(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"float\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: DOUBLE.\n */\nexport function double(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"double\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: DECIMAL.\n *\n * @example\n * ```typescript\n * price: decimal(10, 2) // DECIMAL(10,2)\n * ```\n */\nexport function decimal(precision = 8, scale = 2): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"decimal\", \"__placeholder__\", { precision, scale });\n}\n\n// ============================================================================\n// BOOLEAN HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: BOOLEAN.\n *\n * Named `boolCol` to avoid collision with the TypeScript / JS `boolean` primitive.\n *\n * @example\n * ```typescript\n * is_active: boolCol().default(true)\n * ```\n */\nexport function boolCol(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"boolean\", \"__placeholder__\");\n}\n\n/** Alias for `boolCol()`. */\nexport { boolCol as bool };\n\n// ============================================================================\n// DATE / TIME HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: DATE.\n */\nexport function date(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"date\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: DATETIME.\n */\nexport function dateTime(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"dateTime\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: TIMESTAMP.\n *\n * @example\n * ```typescript\n * started_at: timestamp().default(\"NOW()\")\n * ```\n */\nexport function timestamp(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"timestamp\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: TIME.\n */\nexport function time(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"time\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: YEAR.\n */\nexport function year(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"year\", \"__placeholder__\");\n}\n\n// ============================================================================\n// JSON & BINARY HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: JSON.\n *\n * Named `jsonCol` to avoid collision with the TS/JSON built-in names.\n * Use `json()` is fine for most cases though — this alias exists for clarity.\n *\n * @example\n * ```typescript\n * metadata: json().nullable()\n * ```\n */\nexport function json(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"json\", \"__placeholder__\");\n}\n\n/**\n * Alias for `json()`. Named `objectCol` to avoid collision with TS `object` type.\n */\nexport function objectCol(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"json\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: BINARY / BLOB.\n */\nexport function binary(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"binary\", \"__placeholder__\");\n}\n\n/**\n * Alias for `binary()`. Named `blobCol` to avoid collision with the Web `Blob` API.\n */\nexport function blobCol(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"binary\", \"__placeholder__\");\n}\n\n// ============================================================================\n// IDENTIFIER HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: UUID.\n *\n * @example\n * ```typescript\n * import { Migration, uuid } from \"@warlock.js/cascade\";\n *\n * export default Migration.create(Chat, {\n * organization_id: uuid().references(Organization).onDelete(\"cascade\"),\n * });\n * ```\n */\nexport function uuid(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"uuid\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: ULID.\n */\nexport function ulid(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"ulid\", \"__placeholder__\");\n}\n\n// ============================================================================\n// NETWORK HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: IP address.\n */\nexport function ipAddress(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"ipAddress\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: MAC address.\n */\nexport function macAddress(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"macAddress\", \"__placeholder__\");\n}\n\n// ============================================================================\n// SPATIAL HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: geo point.\n */\nexport function point(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"point\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: polygon.\n */\nexport function polygon(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"polygon\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: line string.\n */\nexport function lineString(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"lineString\", \"__placeholder__\");\n}\n\n/**\n * Standalone column helper: generic geometry.\n */\nexport function geometry(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"geometry\", \"__placeholder__\");\n}\n\n// ============================================================================\n// AI / ML HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: vector (for AI embeddings).\n *\n * @param dimensions - Embedding size (e.g. 1536 for text-embedding-3-small)\n *\n * @example\n * ```typescript\n * embedding: vector(1536)\n * ```\n */\nexport function vector(dimensions: number): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"vector\", \"__placeholder__\", { dimensions });\n}\n\n// ============================================================================\n// ENUM & SET HELPERS\n// ============================================================================\n\n/**\n * Standalone column helper: ENUM.\n *\n * @example\n * ```typescript\n * status: enumCol([\"active\", \"inactive\", \"pending\"])\n * ```\n */\nexport function enumCol(values: string[]): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"enum\", \"__placeholder__\", { values });\n}\n\n/**\n * Standalone column helper: SET (multiple values).\n */\nexport function setCol(values: string[]): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"set\", \"__placeholder__\", { values });\n}\n\n// ============================================================================\n// POSTGRESQL ARRAY HELPERS\n// ============================================================================\n\n/** Standalone helper: INTEGER[] */\nexport function arrayInt(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayInt\", \"__placeholder__\");\n}\n\n/** Standalone helper: BIGINT[] */\nexport function arrayBigInt(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayBigInt\", \"__placeholder__\");\n}\n\n/** Standalone helper: REAL[] */\nexport function arrayFloat(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayFloat\", \"__placeholder__\");\n}\n\n/** Standalone helper: DECIMAL[] */\nexport function arrayDecimal(precision?: number, scale?: number): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayDecimal\", \"__placeholder__\", { precision, scale });\n}\n\n/** Standalone helper: BOOLEAN[] */\nexport function arrayBoolean(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayBoolean\", \"__placeholder__\");\n}\n\n/** Standalone helper: TEXT[] */\nexport function arrayText(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayText\", \"__placeholder__\");\n}\n\n/** Standalone helper: DATE[] */\nexport function arrayDate(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayDate\", \"__placeholder__\");\n}\n\n/** Standalone helper: TIMESTAMPTZ[] */\nexport function arrayTimestamp(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayTimestamp\", \"__placeholder__\");\n}\n\n/** Standalone helper: UUID[] */\nexport function arrayUuid(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayUuid\", \"__placeholder__\");\n}\n\n/** Standalone helper: JSONB[] */\nexport function arrayJson(): DetachedColumnBuilder {\n return new DetachedColumnBuilder(\"arrayJson\", \"__placeholder__\");\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ForeignKeyDefinition } from "../contracts/migration-driver.contract.mjs";
|
|
2
2
|
|
|
3
|
-
//#region
|
|
3
|
+
//#region ../cascade/src/migration/foreign-key-builder.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Reference to the Migration type to avoid circular imports.
|
|
6
6
|
*/
|