@restforgejs/platform 4.2.8 → 4.3.2
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/SECURITY.md +83 -4
- package/bin/sdf-tools.exe +0 -0
- package/build-info.json +2 -2
- package/cli/consumer-deploy.js +1 -1
- package/cli/consumer.js +1 -1
- package/generators/cli/dashboard/create.js +4 -1
- package/generators/cli/endpoint/create.js +1 -1
- package/generators/cli/key/generate.js +2 -1
- package/generators/cli/key/revoke.js +2 -1
- package/generators/cli/payload/diff.js +3 -2
- package/generators/cli/payload/generate.js +3 -2
- package/generators/cli/payload/sync.js +3 -2
- package/generators/cli/payload/validate.js +3 -2
- package/generators/cli/processor/create.js +14 -3
- package/generators/cli/project/delete.js +2 -1
- package/generators/cli/query/validate.js +3 -2
- package/generators/cli/schema/apply.js +3 -2
- package/generators/cli/schema/describe.js +3 -2
- package/generators/cli/schema/diff.js +3 -2
- package/generators/cli/schema/introspect.js +3 -2
- package/generators/cli/schema/list.js +3 -2
- package/generators/cli/schema/migrate.js +3 -2
- package/generators/lib/migration/audit-table-runner.js +213 -215
- package/generators/lib/payload/payload-runner.js +1 -1
- package/generators/lib/templates/dashboard-catalog.js +1 -437
- package/generators/lib/templates/db-connection-env.js +1 -212
- package/generators/lib/templates/dbschema-catalog.js +1 -489
- package/generators/lib/templates/field-validation-catalog.js +1 -531
- package/generators/lib/templates/mysql-template.js +1 -3863
- package/generators/lib/templates/oracle-template.js +1 -3915
- package/generators/lib/templates/postgres-template.js +1 -5838
- package/generators/lib/templates/query-declarative-catalog.js +1 -199
- package/generators/lib/templates/sqlite-template.js +1 -3440
- package/generators/lib/utils/env-manager.js +6 -0
- package/generators/lib/utils/path-validator.js +71 -0
- package/generators/lib/validators/payload-validator.js +1 -2
- package/integrity-manifest.json +28 -10
- package/package.json +11 -3
- package/scripts/verify-integrity.js +1 -1
- package/server.js +1 -1
- package/src/components/handlers/adjust_handler.js +1 -1
- package/src/components/handlers/audit_handler.js +1 -1
- package/src/components/handlers/delete_handler.js +1 -1
- package/src/components/handlers/export_handler.js +1 -1
- package/src/components/handlers/import_handler.js +1 -1
- package/src/components/handlers/insert_handler.js +1 -1
- package/src/components/handlers/update_handler.js +1 -1
- package/src/components/handlers/upload_handler.js +1 -1
- package/src/components/handlers/workflow_handler.js +1 -1
- package/src/components/integrations/webhook.js +1 -1
- package/src/consumers/baseConsumer.js +1 -1
- package/src/consumers/declarativeMapper.js +1 -1
- package/src/consumers/handlers/apiHandler.js +1 -1
- package/src/consumers/handlers/consoleHandler.js +1 -1
- package/src/consumers/handlers/databaseHandler.js +1 -1
- package/src/consumers/handlers/index.js +1 -1
- package/src/consumers/handlers/kafkaHandler.js +1 -1
- package/src/consumers/index.js +1 -1
- package/src/consumers/messageTransformer.js +1 -1
- package/src/consumers/validator.js +1 -1
- package/src/core/db/dialect/base-dialect.js +1 -1
- package/src/core/db/dialect/index.js +1 -1
- package/src/core/db/dialect/mysql-dialect.js +1 -1
- package/src/core/db/dialect/oracle-dialect.js +1 -1
- package/src/core/db/dialect/postgres-dialect.js +1 -1
- package/src/core/db/dialect/sqlite-dialect.js +1 -1
- package/src/core/db/flatten-helper.js +1 -1
- package/src/core/db/query-builder-error.js +1 -1
- package/src/core/db/query-builder.js +1 -1
- package/src/core/db/relation-helper.js +1 -1
- package/src/core/handlers/delete_handler.js +1 -1
- package/src/core/handlers/insert_handler.js +1 -1
- package/src/core/handlers/update_handler.js +1 -1
- package/src/core/models/base-model.js +1 -1
- package/src/core/utils/cache-manager.js +1 -1
- package/src/core/utils/component-engine.js +1 -1
- package/src/core/utils/context-builder.js +1 -1
- package/src/core/utils/datetime-formatter.js +1 -1
- package/src/core/utils/datetime-parser.js +1 -1
- package/src/core/utils/db.js +1 -1
- package/src/core/utils/logger.js +1 -1
- package/src/core/utils/payload-loader.js +1 -1
- package/src/core/utils/security-checks.js +1 -1
- package/src/middleware/body-options.js +1 -1
- package/src/middleware/cors.js +1 -1
- package/src/middleware/idempotency.js +1 -1
- package/src/middleware/rate-limiter.js +1 -1
- package/src/middleware/request-logger.js +1 -1
- package/src/middleware/security-headers.js +1 -1
- package/src/models/base-model-mysql.js +1 -1
- package/src/models/base-model-oracle.js +1 -1
- package/src/models/base-model-sqlite.js +1 -1
- package/src/models/base-model.js +1 -1
- package/src/pro/caching/redis-client.js +1 -1
- package/src/pro/caching/redis-helper.js +1 -1
- package/src/pro/consumers/baseConsumer.js +1 -1
- package/src/pro/consumers/declarativeMapper.js +1 -1
- package/src/pro/consumers/handlers/apiHandler.js +1 -1
- package/src/pro/consumers/handlers/consoleHandler.js +1 -1
- package/src/pro/consumers/handlers/databaseHandler.js +1 -1
- package/src/pro/consumers/handlers/index.js +1 -1
- package/src/pro/consumers/handlers/kafkaHandler.js +1 -1
- package/src/pro/consumers/index.js +1 -1
- package/src/pro/consumers/messageTransformer.js +1 -1
- package/src/pro/consumers/validator.js +1 -1
- package/src/pro/database/base-model-mysql.js +1 -1
- package/src/pro/database/base-model-oracle.js +1 -1
- package/src/pro/database/base-model-sqlite.js +1 -1
- package/src/pro/database/db-mysql.js +1 -1
- package/src/pro/database/db-oracle.js +1 -1
- package/src/pro/database/db-sqlite.js +1 -1
- package/src/pro/excel/excel-generator.js +1 -1
- package/src/pro/excel/excel-parser.js +1 -1
- package/src/pro/excel/export-service.js +1 -1
- package/src/pro/excel/export_handler.js +1 -1
- package/src/pro/excel/import-service.js +1 -1
- package/src/pro/excel/import-validator.js +1 -1
- package/src/pro/excel/import_handler.js +1 -1
- package/src/pro/excel/upsert-builder.js +1 -1
- package/src/pro/idgen/idgen-routes.js +1 -1
- package/src/pro/integrations/lookup-resolver.js +1 -1
- package/src/pro/integrations/upload-handler-v2.js +1 -1
- package/src/pro/integrations/upload-handler.js +1 -1
- package/src/pro/integrations/webhook.js +1 -1
- package/src/pro/locking/lock-routes.js +1 -1
- package/src/pro/locking/resource-lock-manager.js +1 -1
- package/src/pro/messaging/kafkaConsumerService.js +1 -1
- package/src/pro/messaging/kafkaService.js +1 -1
- package/src/pro/messaging/messagehubService.js +1 -1
- package/src/pro/messaging/rabbitmqService.js +1 -1
- package/src/pro/scheduler/job-manager.js +1 -1
- package/src/pro/scheduler/job-routes.js +1 -1
- package/src/pro/scheduler/job-validator.js +1 -1
- package/src/pro/storage/base-storage-provider.js +1 -1
- package/src/pro/storage/file-metadata-helper.js +1 -1
- package/src/pro/storage/index.js +1 -1
- package/src/pro/storage/local-storage-provider.js +1 -1
- package/src/pro/storage/s3-storage-provider.js +1 -1
- package/src/pro/storage/upload-cleanup-job.js +1 -1
- package/src/pro/storage/upload-cleanup-scheduler.js +1 -1
- package/src/pro/storage/upload-pending-tracker.js +1 -1
- package/src/pro/websocket/broadcast-helper.js +1 -1
- package/src/pro/websocket/index.js +1 -1
- package/src/pro/websocket/livesync-server.js +1 -1
- package/src/pro/websocket/ws-broadcaster.js +1 -1
- package/src/services/export-service.js +1 -1
- package/src/services/import-service.js +1 -1
- package/src/services/kafkaConsumerService.js +1 -1
- package/src/services/kafkaService.js +1 -1
- package/src/services/messagehubService.js +1 -1
- package/src/services/rabbitmqService.js +1 -1
- package/src/utils/cache-invalidation-registry.js +1 -1
- package/src/utils/cache-manager.js +1 -1
- package/src/utils/component-engine.js +1 -1
- package/src/utils/config-extractor.js +1 -1
- package/src/utils/consumerLogger.js +1 -1
- package/src/utils/context-builder.js +1 -1
- package/src/utils/dashboard-helpers.js +1 -1
- package/src/utils/dateHelper.js +1 -1
- package/src/utils/datetime-formatter.js +1 -1
- package/src/utils/datetime-parser.js +1 -1
- package/src/utils/db-bootstrap.js +1 -1
- package/src/utils/db-mysql.js +1 -1
- package/src/utils/db-oracle.js +1 -1
- package/src/utils/db-sqlite.js +1 -1
- package/src/utils/db.js +1 -1
- package/src/utils/demo-generator.js +1 -1
- package/src/utils/excel-generator.js +1 -1
- package/src/utils/excel-parser.js +1 -1
- package/src/utils/file-watcher.js +1 -1
- package/src/utils/id-generator.js +1 -1
- package/src/utils/idempotency-manager.js +1 -1
- package/src/utils/import-validator.js +1 -1
- package/src/utils/license-client.js +1 -1
- package/src/utils/lock-manager.js +1 -1
- package/src/utils/logger.js +1 -1
- package/src/utils/lookup-resolver.js +1 -1
- package/src/utils/payload-loader.js +1 -1
- package/src/utils/processor-response.js +1 -1
- package/src/utils/rabbitmq.js +1 -1
- package/src/utils/redis-client.js +1 -1
- package/src/utils/redis-helper.js +1 -1
- package/src/utils/request-scope.js +1 -1
- package/src/utils/security-checks.js +1 -1
- package/src/utils/service-resolver.js +1 -1
- package/src/utils/shutdown-coordinator.js +1 -1
- package/src/utils/trusted-keys.js +1 -1
- package/src/utils/upload-handler.js +1 -1
- package/src/utils/upsert-builder.js +1 -1
- package/src/utils/workflow-hook-executor.js +1 -1
- package/generators/metadata/global.json +0 -58
- package/generators/metadata/test-mysql-workbench.json +0 -118
- package/generators/metadata/test-mysql.json +0 -56
- package/generators/metadata/test-oracle-workbench.json +0 -118
- package/generators/metadata/test-oracle.json +0 -56
- package/generators/metadata/test-pg-workbench.json +0 -118
- package/generators/metadata/test-pg.json +0 -56
- package/generators/scripts/obfuscate-source.js +0 -356
- package/generators/scripts/validate-catalog.js +0 -430
- package/generators/scripts/validate-dbschema-catalog.js +0 -708
- package/generators/tests/baseline/mysql/mini_inventory_item/src/models/mini-inventory/item.js +0 -944
- package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
- package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory.js +0 -336
- package/generators/tests/baseline/oracle/mini_inventory_item/src/models/mini-inventory/item.js +0 -1002
- package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
- package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory.js +0 -336
- package/generators/tests/baseline/postgres/mini_inventory_item/src/models/mini-inventory/item.js +0 -1333
- package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory/item.js +0 -1173
- package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory.js +0 -496
- package/generators/tests/fixtures/payloads/custom-sensitive.json +0 -27
- package/generators/tests/fixtures/payloads/dynamic-search-optout.json +0 -23
- package/generators/tests/fixtures/payloads/login-with-password.json +0 -22
- package/generators/tests/fixtures/payloads/order-process.json +0 -52
- package/generators/tests/fixtures/payloads/with-inline-sql.json +0 -26
- package/generators/tests/integration-tahap4b/README.md +0 -145
- package/generators/tests/integration-tahap4b/run-concurrent.js +0 -77
- package/generators/tests/integration-tahap4b/seed.sql +0 -53
- package/generators/tests/integration-tahap4b/verify.sql +0 -110
- package/generators/tests/unit/cli/create-dashboard.test.js +0 -505
- package/generators/tests/unit/cli/create-processor.test.js +0 -319
- package/generators/tests/unit/cli/dispatch-dashboard.test.js +0 -149
- package/generators/tests/unit/lib/dashboard-generator.test.js +0 -895
- package/generators/tests/unit/lib/dashboard-validator.test.js +0 -354
- package/generators/tests/unit/lib/dbschema-kit/apply-executor.test.js +0 -437
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-introspect.test.js +0 -393
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-generate-ddl.test.js +0 -104
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-init.test.js +0 -119
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-list.test.js +0 -48
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-migrate.test.js +0 -175
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-validate.test.js +0 -102
- package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-models.test.js +0 -43
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/all-schemas-listing.js +0 -84
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/connection-error.js +0 -13
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/empty.js +0 -12
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/multi-schema.js +0 -124
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/single-schema-inventory.js +0 -64
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/two-tables.js +0 -66
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/connection-error.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/partial.js +0 -29
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/rollback.js +0 -26
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/success.js +0 -43
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/audit/events.js +0 -18
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/inventory/products.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/users.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/connection.test.js +0 -112
- package/generators/tests/unit/lib/dbschema-kit/ddl-generator.test.js +0 -205
- package/generators/tests/unit/lib/dbschema-kit/define-model.test.js +0 -56
- package/generators/tests/unit/lib/dbschema-kit/dialect/index.test.js +0 -46
- package/generators/tests/unit/lib/dbschema-kit/dialect/mysql.test.js +0 -126
- package/generators/tests/unit/lib/dbschema-kit/dialect/oracle.test.js +0 -126
- package/generators/tests/unit/lib/dbschema-kit/dialect/postgres.test.js +0 -131
- package/generators/tests/unit/lib/dbschema-kit/dialect/sqlite.test.js +0 -126
- package/generators/tests/unit/lib/dbschema-kit/driver-loader.test.js +0 -93
- package/generators/tests/unit/lib/dbschema-kit/emitters/create-index.test.js +0 -173
- package/generators/tests/unit/lib/dbschema-kit/emitters/create-table.test.js +0 -376
- package/generators/tests/unit/lib/dbschema-kit/emitters/drop-table.test.js +0 -78
- package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/invalid-dialect.env +0 -6
- package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-dialect.env +0 -5
- package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-host.env +0 -5
- package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/oracle-valid.env +0 -6
- package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/postgres-valid.env +0 -7
- package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/sqlite-valid.env +0 -2
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/category.js +0 -11
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/item_product.js +0 -11
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound.js +0 -24
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound_item.js +0 -28
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/supplier.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/warehouse.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-invalid/orphan.js +0 -17
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/category.js +0 -11
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/item_product.js +0 -11
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/supplier.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/warehouse.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound.js +0 -24
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound_item.js +0 -28
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/audit/events.js +0 -18
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/inventory/products.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/public/users.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/extra/category.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/master/category.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/bar.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/foo.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/empty-folder/README.md +0 -1
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-export/plain.js +0 -3
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-schema/bad.js +0 -6
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/legacy-pattern/legacy.js +0 -12
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/audit/products.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/inventory/products.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/a/products.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/b/products.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/nested-deep/a/b/c/deep_table.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/.hidden/ignored.js +0 -7
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/category.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/supplier.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound_item.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/category.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/item_product.js +0 -9
- package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-single/category.js +0 -8
- package/generators/tests/unit/lib/dbschema-kit/integration.test.js +0 -217
- package/generators/tests/unit/lib/dbschema-kit/introspect-mapper.test.js +0 -403
- package/generators/tests/unit/lib/dbschema-kit/ir-builder.test.js +0 -390
- package/generators/tests/unit/lib/dbschema-kit/loader.test.js +0 -128
- package/generators/tests/unit/lib/dbschema-kit/naming.test.js +0 -170
- package/generators/tests/unit/lib/dbschema-kit/parser/shorthand-parser.test.js +0 -237
- package/generators/tests/unit/lib/dbschema-kit/schema-printer.test.js +0 -251
- package/generators/tests/unit/lib/dbschema-kit/statement-modifier.test.js +0 -105
- package/generators/tests/unit/lib/dbschema-kit/statement-splitter.test.js +0 -165
- package/generators/tests/unit/lib/dbschema-kit/topological-sort.test.js +0 -135
- package/generators/tests/unit/lib/dbschema-kit/validator/check-compatibility-validator.test.js +0 -373
- package/generators/tests/unit/lib/dbschema-kit/validator/circular-relation-validator.test.js +0 -454
- package/generators/tests/unit/lib/dbschema-kit/validator/cross-model-validator.test.js +0 -512
- package/generators/tests/unit/lib/dbschema-kit/validator/enhanced-validate-integration.test.js +0 -390
- package/generators/tests/unit/lib/dbschema-kit/validator/naming-convention-validator.test.js +0 -306
- package/generators/tests/unit/lib/dbschema-kit/validator/schema-validator.test.js +0 -443
- package/generators/tests/unit/lib/dbschema-kit/validator/type-compatibility-validator.test.js +0 -440
- package/generators/tests/unit/lib/dbschema-kit/validator/validator-reporter.test.js +0 -172
- package/generators/tests/unit/lib/metadata-manager-dashboard.test.js +0 -256
- package/generators/tests/unit/lib/payload-validator-fieldpolicy.test.js +0 -240
- package/generators/tests/unit/lib/processor-validation-generator.test.js +0 -300
- package/generators/tests/unit/lib/sensitive-field-masker.test.js +0 -170
- package/generators/tests/unit/lib/sql-table-extractor.test.js +0 -119
- package/scripts/generate-integrity-manifest.js +0 -124
- package/scripts/snapshot-cli-contracts.js +0 -194
- package/scripts/verify-publish.js +0 -56
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert');
|
|
5
|
-
|
|
6
|
-
const { splitStatements } = require('../../../../lib/dbschema-kit/statement-splitter');
|
|
7
|
-
|
|
8
|
-
test('splitter: DDL multi-statement Postgres → array tanpa comment dan blank line', () => {
|
|
9
|
-
const ddl = [
|
|
10
|
-
'-- ============================================================',
|
|
11
|
-
'-- Generated by dbschema:generate-ddl',
|
|
12
|
-
'-- ============================================================',
|
|
13
|
-
'',
|
|
14
|
-
'-- DROP section',
|
|
15
|
-
'DROP TABLE IF EXISTS supplier CASCADE;',
|
|
16
|
-
'DROP TABLE IF EXISTS category CASCADE;',
|
|
17
|
-
'',
|
|
18
|
-
'-- CREATE TABLE section',
|
|
19
|
-
'CREATE TABLE category (',
|
|
20
|
-
' category_id UUID NOT NULL,',
|
|
21
|
-
' PRIMARY KEY (category_id)',
|
|
22
|
-
');'
|
|
23
|
-
].join('\n');
|
|
24
|
-
|
|
25
|
-
const result = splitStatements(ddl, 'postgres');
|
|
26
|
-
assert.strictEqual(result.length, 3);
|
|
27
|
-
assert.strictEqual(result[0], 'DROP TABLE IF EXISTS supplier CASCADE');
|
|
28
|
-
assert.strictEqual(result[1], 'DROP TABLE IF EXISTS category CASCADE');
|
|
29
|
-
assert.match(result[2], /^CREATE TABLE category \(/);
|
|
30
|
-
assert.match(result[2], /PRIMARY KEY \(category_id\)/);
|
|
31
|
-
// tidak boleh berakhir dengan ;
|
|
32
|
-
assert.ok(!result[2].endsWith(';'));
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('splitter: trailing semicolon dihapus dari setiap statement', () => {
|
|
36
|
-
const ddl = 'CREATE INDEX idx_a ON foo (a);\nCREATE INDEX idx_b ON foo (b);\n';
|
|
37
|
-
const result = splitStatements(ddl, 'postgres');
|
|
38
|
-
assert.strictEqual(result.length, 2);
|
|
39
|
-
assert.strictEqual(result[0], 'CREATE INDEX idx_a ON foo (a)');
|
|
40
|
-
assert.strictEqual(result[1], 'CREATE INDEX idx_b ON foo (b)');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('splitter: skip baris comment (-- ...)', () => {
|
|
44
|
-
const ddl = [
|
|
45
|
-
'-- comment line 1',
|
|
46
|
-
'CREATE TABLE foo (id UUID);',
|
|
47
|
-
'-- comment line 2',
|
|
48
|
-
'CREATE TABLE bar (id UUID);'
|
|
49
|
-
].join('\n');
|
|
50
|
-
|
|
51
|
-
const result = splitStatements(ddl, 'postgres');
|
|
52
|
-
assert.strictEqual(result.length, 2);
|
|
53
|
-
assert.strictEqual(result[0], 'CREATE TABLE foo (id UUID)');
|
|
54
|
-
assert.strictEqual(result[1], 'CREATE TABLE bar (id UUID)');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('splitter: skip baris kosong sebagai separator antar statement', () => {
|
|
58
|
-
const ddl = [
|
|
59
|
-
'CREATE TABLE foo (id UUID);',
|
|
60
|
-
'',
|
|
61
|
-
'',
|
|
62
|
-
'CREATE TABLE bar (id UUID);'
|
|
63
|
-
].join('\n');
|
|
64
|
-
|
|
65
|
-
const result = splitStatements(ddl, 'postgres');
|
|
66
|
-
assert.strictEqual(result.length, 2);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('splitter: multi-line CREATE TABLE tetap utuh sebagai satu element', () => {
|
|
70
|
-
const ddl = [
|
|
71
|
-
'CREATE TABLE category (',
|
|
72
|
-
' category_id UUID NOT NULL,',
|
|
73
|
-
' category_name VARCHAR(100) NOT NULL,',
|
|
74
|
-
' CONSTRAINT pk_category PRIMARY KEY (category_id)',
|
|
75
|
-
');'
|
|
76
|
-
].join('\n');
|
|
77
|
-
|
|
78
|
-
const result = splitStatements(ddl, 'postgres');
|
|
79
|
-
assert.strictEqual(result.length, 1);
|
|
80
|
-
assert.match(result[0], /^CREATE TABLE category \(/);
|
|
81
|
-
assert.match(result[0], /category_id UUID NOT NULL,/);
|
|
82
|
-
assert.match(result[0], /CONSTRAINT pk_category PRIMARY KEY \(category_id\)/);
|
|
83
|
-
assert.ok(!result[0].endsWith(';'));
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test('splitter: Oracle PL/SQL block treated as single statement, terminator / di-strip', () => {
|
|
87
|
-
const ddl = [
|
|
88
|
-
'BEGIN',
|
|
89
|
-
" EXECUTE IMMEDIATE 'DROP TABLE category CASCADE CONSTRAINTS';",
|
|
90
|
-
'EXCEPTION',
|
|
91
|
-
' WHEN OTHERS THEN',
|
|
92
|
-
' IF SQLCODE != -942 THEN RAISE; END IF;',
|
|
93
|
-
'END;',
|
|
94
|
-
'/',
|
|
95
|
-
'BEGIN',
|
|
96
|
-
" EXECUTE IMMEDIATE 'DROP TABLE supplier CASCADE CONSTRAINTS';",
|
|
97
|
-
'EXCEPTION',
|
|
98
|
-
' WHEN OTHERS THEN',
|
|
99
|
-
' IF SQLCODE != -942 THEN RAISE; END IF;',
|
|
100
|
-
'END;',
|
|
101
|
-
'/'
|
|
102
|
-
].join('\n');
|
|
103
|
-
|
|
104
|
-
const result = splitStatements(ddl, 'oracle');
|
|
105
|
-
assert.strictEqual(result.length, 2);
|
|
106
|
-
assert.match(result[0], /^BEGIN/);
|
|
107
|
-
assert.match(result[0], /EXECUTE IMMEDIATE 'DROP TABLE category/);
|
|
108
|
-
assert.match(result[0], /END;$/);
|
|
109
|
-
assert.ok(!result[0].includes('\n/'), 'terminator / harus dihapus');
|
|
110
|
-
assert.ok(!result[0].endsWith('/'));
|
|
111
|
-
assert.match(result[1], /EXECUTE IMMEDIATE 'DROP TABLE supplier/);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test('splitter: MySQL identifier dengan backtick tetap intact dalam statement', () => {
|
|
115
|
-
const ddl = [
|
|
116
|
-
'CREATE TABLE `order` (',
|
|
117
|
-
' `id` BIGINT NOT NULL,',
|
|
118
|
-
' PRIMARY KEY (`id`)',
|
|
119
|
-
');'
|
|
120
|
-
].join('\n');
|
|
121
|
-
|
|
122
|
-
const result = splitStatements(ddl, 'mysql');
|
|
123
|
-
assert.strictEqual(result.length, 1);
|
|
124
|
-
assert.match(result[0], /CREATE TABLE `order`/);
|
|
125
|
-
assert.match(result[0], /`id` BIGINT NOT NULL/);
|
|
126
|
-
assert.match(result[0], /PRIMARY KEY \(`id`\)/);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test('splitter: input kosong → array kosong', () => {
|
|
130
|
-
assert.deepStrictEqual(splitStatements('', 'postgres'), []);
|
|
131
|
-
assert.deepStrictEqual(splitStatements(' \n\n\n', 'postgres'), []);
|
|
132
|
-
assert.deepStrictEqual(splitStatements('-- comment only\n\n', 'postgres'), []);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
test('splitter: Oracle mixed PL/SQL + CREATE TABLE statements', () => {
|
|
136
|
-
const ddl = [
|
|
137
|
-
'BEGIN',
|
|
138
|
-
" EXECUTE IMMEDIATE 'DROP TABLE category CASCADE CONSTRAINTS';",
|
|
139
|
-
'EXCEPTION',
|
|
140
|
-
' WHEN OTHERS THEN',
|
|
141
|
-
' IF SQLCODE != -942 THEN RAISE; END IF;',
|
|
142
|
-
'END;',
|
|
143
|
-
'/',
|
|
144
|
-
'',
|
|
145
|
-
'-- CREATE TABLE section',
|
|
146
|
-
'CREATE TABLE category (',
|
|
147
|
-
' category_id VARCHAR2(36) NOT NULL,',
|
|
148
|
-
' CONSTRAINT pk_category PRIMARY KEY (category_id)',
|
|
149
|
-
');'
|
|
150
|
-
].join('\n');
|
|
151
|
-
|
|
152
|
-
const result = splitStatements(ddl, 'oracle');
|
|
153
|
-
assert.strictEqual(result.length, 2);
|
|
154
|
-
assert.match(result[0], /^BEGIN/);
|
|
155
|
-
assert.match(result[1], /^CREATE TABLE category/);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test('splitter: invalid dialect → throw error', () => {
|
|
159
|
-
assert.throws(() => splitStatements('SELECT 1;', 'mssql'), /invalid dialect/);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test('splitter: ddl bukan string → throw error', () => {
|
|
163
|
-
assert.throws(() => splitStatements(null, 'postgres'), /must be a string/);
|
|
164
|
-
assert.throws(() => splitStatements(42, 'postgres'), /must be a string/);
|
|
165
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert');
|
|
5
|
-
|
|
6
|
-
const { topologicalSort } = require('../../../../lib/dbschema-kit/topological-sort');
|
|
7
|
-
|
|
8
|
-
function makeModel(tableName, relations = {}) {
|
|
9
|
-
const rels = {};
|
|
10
|
-
for (const [relName, target] of Object.entries(relations)) {
|
|
11
|
-
rels[relName] = {
|
|
12
|
-
type: 'belongsTo',
|
|
13
|
-
target,
|
|
14
|
-
localKey: `${target}_id`,
|
|
15
|
-
references: `${target}_id`
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
return { tableName, fields: {}, primaryKey: [`${tableName}_id`], indexes: [], uniques: [], relations: rels, checks: [] };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
test('topological-sort: linear dependency A → B → C menghasilkan urutan [A, B, C]', () => {
|
|
22
|
-
const models = new Map();
|
|
23
|
-
models.set('a', makeModel('a'));
|
|
24
|
-
models.set('b', makeModel('b', { parentA: 'a' }));
|
|
25
|
-
models.set('c', makeModel('c', { parentB: 'b' }));
|
|
26
|
-
|
|
27
|
-
const order = topologicalSort(models);
|
|
28
|
-
assert.deepStrictEqual(order, ['a', 'b', 'c']);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('topological-sort: multi-parent A,B → C, A dan B muncul sebelum C dengan urutan deterministik', () => {
|
|
32
|
-
const models = new Map();
|
|
33
|
-
models.set('b', makeModel('b'));
|
|
34
|
-
models.set('a', makeModel('a'));
|
|
35
|
-
models.set('c', makeModel('c', { parentA: 'a', parentB: 'b' }));
|
|
36
|
-
|
|
37
|
-
const order = topologicalSort(models);
|
|
38
|
-
// A dan B muncul lebih dulu (alphabetical), C terakhir
|
|
39
|
-
assert.deepStrictEqual(order, ['a', 'b', 'c']);
|
|
40
|
-
// C muncul setelah A dan B
|
|
41
|
-
const cIdx = order.indexOf('c');
|
|
42
|
-
assert.ok(order.indexOf('a') < cIdx);
|
|
43
|
-
assert.ok(order.indexOf('b') < cIdx);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('topological-sort: tiga tabel tanpa dependency menghasilkan urutan alfabetis', () => {
|
|
47
|
-
const models = new Map();
|
|
48
|
-
models.set('zebra', makeModel('zebra'));
|
|
49
|
-
models.set('apple', makeModel('apple'));
|
|
50
|
-
models.set('mango', makeModel('mango'));
|
|
51
|
-
|
|
52
|
-
const order = topologicalSort(models);
|
|
53
|
-
assert.deepStrictEqual(order, ['apple', 'mango', 'zebra']);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test('topological-sort: diamond A→B, A→C, B→D, C→D menempatkan A pertama dan D terakhir', () => {
|
|
57
|
-
const models = new Map();
|
|
58
|
-
models.set('a', makeModel('a'));
|
|
59
|
-
models.set('b', makeModel('b', { p: 'a' }));
|
|
60
|
-
models.set('c', makeModel('c', { p: 'a' }));
|
|
61
|
-
models.set('d', makeModel('d', { p1: 'b', p2: 'c' }));
|
|
62
|
-
|
|
63
|
-
const order = topologicalSort(models);
|
|
64
|
-
assert.strictEqual(order[0], 'a');
|
|
65
|
-
assert.strictEqual(order[order.length - 1], 'd');
|
|
66
|
-
// B dan C muncul setelah A dan sebelum D
|
|
67
|
-
assert.ok(order.indexOf('b') > order.indexOf('a'));
|
|
68
|
-
assert.ok(order.indexOf('c') > order.indexOf('a'));
|
|
69
|
-
assert.ok(order.indexOf('d') > order.indexOf('b'));
|
|
70
|
-
assert.ok(order.indexOf('d') > order.indexOf('c'));
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test('topological-sort: circular dependency A→B, B→A melempar error dengan nama tabel', () => {
|
|
74
|
-
const models = new Map();
|
|
75
|
-
models.set('a', makeModel('a', { rel: 'b' }));
|
|
76
|
-
models.set('b', makeModel('b', { rel: 'a' }));
|
|
77
|
-
|
|
78
|
-
assert.throws(() => topologicalSort(models), /Circular dependency.*a.*b|Circular dependency.*b.*a/);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('topological-sort: map kosong menghasilkan array kosong', () => {
|
|
82
|
-
const models = new Map();
|
|
83
|
-
const order = topologicalSort(models);
|
|
84
|
-
assert.deepStrictEqual(order, []);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test('topological-sort: self-reference (A→A) melempar circular dependency error', () => {
|
|
88
|
-
const models = new Map();
|
|
89
|
-
models.set('a', makeModel('a', { self: 'a' }));
|
|
90
|
-
|
|
91
|
-
assert.throws(() => topologicalSort(models), /Circular dependency.*a/);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('topological-sort: panggil dua kali dengan input identik menghasilkan output identik (determinisme)', () => {
|
|
95
|
-
const models = new Map();
|
|
96
|
-
models.set('c', makeModel('c', { p: 'a' }));
|
|
97
|
-
models.set('a', makeModel('a'));
|
|
98
|
-
models.set('b', makeModel('b', { p: 'a' }));
|
|
99
|
-
models.set('d', makeModel('d', { p1: 'b', p2: 'c' }));
|
|
100
|
-
|
|
101
|
-
const r1 = topologicalSort(models);
|
|
102
|
-
const r2 = topologicalSort(models);
|
|
103
|
-
assert.deepStrictEqual(r1, r2);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('topological-sort: input bukan Map melempar error', () => {
|
|
107
|
-
assert.throws(() => topologicalSort({}), /must be a Map/);
|
|
108
|
-
assert.throws(() => topologicalSort([]), /must be a Map/);
|
|
109
|
-
assert.throws(() => topologicalSort(null), /must be a Map/);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test('topological-sort: relasi bukan belongsTo (hasOne/hasMany) tidak menambah dependency', () => {
|
|
113
|
-
const models = new Map();
|
|
114
|
-
models.set('a', { tableName: 'a', fields: {}, primaryKey: ['a_id'], indexes: [], uniques: [], relations: {
|
|
115
|
-
children: { type: 'hasMany', target: 'b', localKey: 'a_id', references: 'a_id' }
|
|
116
|
-
}, checks: [] });
|
|
117
|
-
models.set('b', makeModel('b'));
|
|
118
|
-
|
|
119
|
-
const order = topologicalSort(models);
|
|
120
|
-
// A → hasMany → B; A tidak depend pada B (karena hasMany bukan belongsTo)
|
|
121
|
-
// B juga tidak depend pada A; keduanya in-degree 0 → alphabetical
|
|
122
|
-
assert.deepStrictEqual(order, ['a', 'b']);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test('topological-sort: multiple FK ke parent yang sama hanya dihitung satu kali (in-degree)', () => {
|
|
126
|
-
const models = new Map();
|
|
127
|
-
models.set('a', makeModel('a'));
|
|
128
|
-
models.set('b', { tableName: 'b', fields: {}, primaryKey: ['b_id'], indexes: [], uniques: [], relations: {
|
|
129
|
-
rel1: { type: 'belongsTo', target: 'a', localKey: 'a_id_1', references: 'a_id' },
|
|
130
|
-
rel2: { type: 'belongsTo', target: 'a', localKey: 'a_id_2', references: 'a_id' }
|
|
131
|
-
}, checks: [] });
|
|
132
|
-
|
|
133
|
-
const order = topologicalSort(models);
|
|
134
|
-
assert.deepStrictEqual(order, ['a', 'b']);
|
|
135
|
-
});
|
package/generators/tests/unit/lib/dbschema-kit/validator/check-compatibility-validator.test.js
DELETED
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert');
|
|
5
|
-
|
|
6
|
-
const { validateCheckCompatibility } = require('../../../../../lib/dbschema-kit/validator/check-compatibility-validator');
|
|
7
|
-
|
|
8
|
-
function makeModel(tableName, opts = {}) {
|
|
9
|
-
const schemaName = opts.schemaName || null;
|
|
10
|
-
const model = {
|
|
11
|
-
schemaName,
|
|
12
|
-
tableName,
|
|
13
|
-
qualifiedName: schemaName ? `${schemaName}.${tableName}` : tableName,
|
|
14
|
-
fields: opts.fields || {},
|
|
15
|
-
primaryKey: opts.primaryKey || [],
|
|
16
|
-
indexes: [],
|
|
17
|
-
uniques: [],
|
|
18
|
-
relations: opts.relations || {},
|
|
19
|
-
checks: opts.checks || [],
|
|
20
|
-
_meta: {
|
|
21
|
-
hasSinglePkShorthand: false,
|
|
22
|
-
hasCompositePrimaryKey: false,
|
|
23
|
-
autoGeneratedRelations: []
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
if (opts.filePath) {
|
|
27
|
-
Object.defineProperty(model, '_filePath', {
|
|
28
|
-
value: opts.filePath,
|
|
29
|
-
enumerable: false,
|
|
30
|
-
writable: false,
|
|
31
|
-
configurable: false
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
return model;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function mapOf(model) {
|
|
38
|
-
const map = new Map();
|
|
39
|
-
map.set(model.qualifiedName, model);
|
|
40
|
-
return map;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// =====================================================
|
|
44
|
-
// Valid scenarios
|
|
45
|
-
// =====================================================
|
|
46
|
-
|
|
47
|
-
test('check-compat: empty Map → 0 issues', () => {
|
|
48
|
-
assert.deepStrictEqual(validateCheckCompatibility(new Map()), []);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('check-compat: model tanpa checks → 0 issues', () => {
|
|
52
|
-
const models = mapOf(makeModel('product', {
|
|
53
|
-
fields: { product_id: { type: 'uuid', pk: true, notnull: true } }
|
|
54
|
-
}));
|
|
55
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test('check-compat: string field + in dengan string array → 0 issues', () => {
|
|
59
|
-
const models = mapOf(makeModel('product', {
|
|
60
|
-
fields: {
|
|
61
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
62
|
-
status: { type: 'string', length: 20 }
|
|
63
|
-
},
|
|
64
|
-
checks: [
|
|
65
|
-
{ field: 'status', op: 'in', value: ['active', 'inactive', 'archived'] }
|
|
66
|
-
]
|
|
67
|
-
}));
|
|
68
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test('check-compat: integer field + gt numeric → 0 issues', () => {
|
|
72
|
-
const models = mapOf(makeModel('product', {
|
|
73
|
-
fields: {
|
|
74
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
75
|
-
price: { type: 'integer' }
|
|
76
|
-
},
|
|
77
|
-
checks: [
|
|
78
|
-
{ field: 'price', op: 'gt', value: 0 }
|
|
79
|
-
]
|
|
80
|
-
}));
|
|
81
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('check-compat: timestamp field + eq dengan ISO string → 0 issues', () => {
|
|
85
|
-
const models = mapOf(makeModel('audit_log', {
|
|
86
|
-
fields: {
|
|
87
|
-
audit_log_id: { type: 'uuid', pk: true, notnull: true },
|
|
88
|
-
occurred_at: { type: 'timestamp' }
|
|
89
|
-
},
|
|
90
|
-
checks: [
|
|
91
|
-
{ field: 'occurred_at', op: 'eq', value: '2026-01-01T00:00:00Z' }
|
|
92
|
-
]
|
|
93
|
-
}));
|
|
94
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('check-compat: timestamp field + eq dengan epoch number → 0 issues', () => {
|
|
98
|
-
const models = mapOf(makeModel('audit_log', {
|
|
99
|
-
fields: {
|
|
100
|
-
audit_log_id: { type: 'uuid', pk: true, notnull: true },
|
|
101
|
-
occurred_at: { type: 'timestamp' }
|
|
102
|
-
},
|
|
103
|
-
checks: [
|
|
104
|
-
{ field: 'occurred_at', op: 'eq', value: 1735689600000 }
|
|
105
|
-
]
|
|
106
|
-
}));
|
|
107
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('check-compat: decimal field + gte float → 0 issues', () => {
|
|
111
|
-
const models = mapOf(makeModel('product', {
|
|
112
|
-
fields: {
|
|
113
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
114
|
-
weight: { type: 'decimal', precision: 10, scale: 2 }
|
|
115
|
-
},
|
|
116
|
-
checks: [
|
|
117
|
-
{ field: 'weight', op: 'gte', value: 0.5 }
|
|
118
|
-
]
|
|
119
|
-
}));
|
|
120
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test('check-compat: json field + in dengan mixed types → 0 issues (JSON accepts any)', () => {
|
|
124
|
-
const models = mapOf(makeModel('event', {
|
|
125
|
-
fields: {
|
|
126
|
-
event_id: { type: 'uuid', pk: true, notnull: true },
|
|
127
|
-
payload: { type: 'json' }
|
|
128
|
-
},
|
|
129
|
-
checks: [
|
|
130
|
-
{ field: 'payload', op: 'in', value: [1, 'two', { three: 3 }] }
|
|
131
|
-
]
|
|
132
|
-
}));
|
|
133
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// =====================================================
|
|
137
|
-
// Op-type incompatible errors
|
|
138
|
-
// =====================================================
|
|
139
|
-
|
|
140
|
-
test('check-compat: boolean field + gt → check-op-incompatible-with-type error', () => {
|
|
141
|
-
const models = mapOf(makeModel('user', {
|
|
142
|
-
fields: {
|
|
143
|
-
user_id: { type: 'uuid', pk: true, notnull: true },
|
|
144
|
-
is_active: { type: 'boolean' }
|
|
145
|
-
},
|
|
146
|
-
checks: [
|
|
147
|
-
{ field: 'is_active', op: 'gt', value: 0 }
|
|
148
|
-
]
|
|
149
|
-
}));
|
|
150
|
-
const issues = validateCheckCompatibility(models);
|
|
151
|
-
assert.strictEqual(issues.length, 1);
|
|
152
|
-
assert.strictEqual(issues[0].severity, 'error');
|
|
153
|
-
assert.strictEqual(issues[0].code, 'check-op-incompatible-with-type');
|
|
154
|
-
assert.strictEqual(issues[0].field, 'is_active');
|
|
155
|
-
assert.match(issues[0].message, /operator 'gt' is not compatible/);
|
|
156
|
-
assert.match(issues[0].message, /type 'boolean'/);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
test('check-compat: string field + lt → check-op-incompatible-with-type error', () => {
|
|
160
|
-
const models = mapOf(makeModel('product', {
|
|
161
|
-
fields: {
|
|
162
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
163
|
-
name: { type: 'string', length: 100 }
|
|
164
|
-
},
|
|
165
|
-
checks: [
|
|
166
|
-
{ field: 'name', op: 'lt', value: 5 }
|
|
167
|
-
]
|
|
168
|
-
}));
|
|
169
|
-
const issues = validateCheckCompatibility(models);
|
|
170
|
-
assert.strictEqual(issues.length, 1);
|
|
171
|
-
assert.strictEqual(issues[0].code, 'check-op-incompatible-with-type');
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
test('check-compat: uuid field + gte → check-op-incompatible-with-type error', () => {
|
|
175
|
-
const models = mapOf(makeModel('event', {
|
|
176
|
-
fields: {
|
|
177
|
-
event_id: { type: 'uuid', pk: true, notnull: true },
|
|
178
|
-
reference_id: { type: 'uuid' }
|
|
179
|
-
},
|
|
180
|
-
checks: [
|
|
181
|
-
{ field: 'reference_id', op: 'gte', value: 1 }
|
|
182
|
-
]
|
|
183
|
-
}));
|
|
184
|
-
const issues = validateCheckCompatibility(models);
|
|
185
|
-
assert.strictEqual(issues.length, 1);
|
|
186
|
-
assert.strictEqual(issues[0].code, 'check-op-incompatible-with-type');
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test('check-compat: text field + lte → check-op-incompatible-with-type error', () => {
|
|
190
|
-
const models = mapOf(makeModel('article', {
|
|
191
|
-
fields: {
|
|
192
|
-
article_id: { type: 'uuid', pk: true, notnull: true },
|
|
193
|
-
body: { type: 'text' }
|
|
194
|
-
},
|
|
195
|
-
checks: [
|
|
196
|
-
{ field: 'body', op: 'lte', value: 1000 }
|
|
197
|
-
]
|
|
198
|
-
}));
|
|
199
|
-
const issues = validateCheckCompatibility(models);
|
|
200
|
-
assert.strictEqual(issues.length, 1);
|
|
201
|
-
assert.strictEqual(issues[0].code, 'check-op-incompatible-with-type');
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// =====================================================
|
|
205
|
-
// Value-type mismatch errors
|
|
206
|
-
// =====================================================
|
|
207
|
-
|
|
208
|
-
test('check-compat: integer field + in dengan string array → check-value-type-mismatch error untuk setiap item', () => {
|
|
209
|
-
const models = mapOf(makeModel('product', {
|
|
210
|
-
fields: {
|
|
211
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
212
|
-
category_id: { type: 'integer' }
|
|
213
|
-
},
|
|
214
|
-
checks: [
|
|
215
|
-
{ field: 'category_id', op: 'in', value: ['a', 'b'] }
|
|
216
|
-
]
|
|
217
|
-
}));
|
|
218
|
-
const issues = validateCheckCompatibility(models);
|
|
219
|
-
assert.strictEqual(issues.length, 2);
|
|
220
|
-
for (const issue of issues) {
|
|
221
|
-
assert.strictEqual(issue.code, 'check-value-type-mismatch');
|
|
222
|
-
assert.strictEqual(issue.field, 'category_id');
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
test('check-compat: integer field + in dengan mixed array → error hanya untuk item non-integer', () => {
|
|
227
|
-
const models = mapOf(makeModel('product', {
|
|
228
|
-
fields: {
|
|
229
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
230
|
-
category_id: { type: 'integer' }
|
|
231
|
-
},
|
|
232
|
-
checks: [
|
|
233
|
-
{ field: 'category_id', op: 'in', value: [1, 'two', 3, 4.5] }
|
|
234
|
-
]
|
|
235
|
-
}));
|
|
236
|
-
const issues = validateCheckCompatibility(models);
|
|
237
|
-
// Items at positions 1 ('two', wrong type) and 3 (4.5, not integer) → 2 errors
|
|
238
|
-
assert.strictEqual(issues.length, 2);
|
|
239
|
-
assert.match(issues[0].message, /position 1/);
|
|
240
|
-
assert.match(issues[0].message, /string 'two'/);
|
|
241
|
-
assert.match(issues[1].message, /position 3/);
|
|
242
|
-
assert.match(issues[1].message, /number 4\.5/);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test('check-compat: string field + eq dengan number → check-value-type-mismatch error', () => {
|
|
246
|
-
const models = mapOf(makeModel('product', {
|
|
247
|
-
fields: {
|
|
248
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
249
|
-
status: { type: 'string', length: 20 }
|
|
250
|
-
},
|
|
251
|
-
checks: [
|
|
252
|
-
{ field: 'status', op: 'eq', value: 42 }
|
|
253
|
-
]
|
|
254
|
-
}));
|
|
255
|
-
const issues = validateCheckCompatibility(models);
|
|
256
|
-
assert.strictEqual(issues.length, 1);
|
|
257
|
-
assert.strictEqual(issues[0].code, 'check-value-type-mismatch');
|
|
258
|
-
assert.match(issues[0].message, /number 42/);
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
test('check-compat: boolean field + neq dengan string → check-value-type-mismatch error', () => {
|
|
262
|
-
const models = mapOf(makeModel('user', {
|
|
263
|
-
fields: {
|
|
264
|
-
user_id: { type: 'uuid', pk: true, notnull: true },
|
|
265
|
-
is_active: { type: 'boolean' }
|
|
266
|
-
},
|
|
267
|
-
checks: [
|
|
268
|
-
{ field: 'is_active', op: 'neq', value: 'true' }
|
|
269
|
-
]
|
|
270
|
-
}));
|
|
271
|
-
const issues = validateCheckCompatibility(models);
|
|
272
|
-
assert.strictEqual(issues.length, 1);
|
|
273
|
-
assert.strictEqual(issues[0].code, 'check-value-type-mismatch');
|
|
274
|
-
assert.match(issues[0].message, /string 'true'/);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
test('check-compat: integer field + in dengan float value → check-value-type-mismatch (not integer)', () => {
|
|
278
|
-
const models = mapOf(makeModel('product', {
|
|
279
|
-
fields: {
|
|
280
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
281
|
-
category_id: { type: 'integer' }
|
|
282
|
-
},
|
|
283
|
-
checks: [
|
|
284
|
-
{ field: 'category_id', op: 'in', value: [1, 2.5, 3] }
|
|
285
|
-
]
|
|
286
|
-
}));
|
|
287
|
-
const issues = validateCheckCompatibility(models);
|
|
288
|
-
assert.strictEqual(issues.length, 1);
|
|
289
|
-
assert.strictEqual(issues[0].code, 'check-value-type-mismatch');
|
|
290
|
-
assert.match(issues[0].message, /position 1/);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
test('check-compat: decimal field + in dengan integer dan float → 0 issues (decimal accepts both)', () => {
|
|
294
|
-
const models = mapOf(makeModel('product', {
|
|
295
|
-
fields: {
|
|
296
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
297
|
-
weight: { type: 'decimal', precision: 10, scale: 2 }
|
|
298
|
-
},
|
|
299
|
-
checks: [
|
|
300
|
-
{ field: 'weight', op: 'in', value: [1, 2.5, 3] }
|
|
301
|
-
]
|
|
302
|
-
}));
|
|
303
|
-
assert.deepStrictEqual(validateCheckCompatibility(models), []);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
// =====================================================
|
|
307
|
-
// Op-incompat dan value-mismatch tidak double-report
|
|
308
|
-
// =====================================================
|
|
309
|
-
|
|
310
|
-
test('check-compat: boolean + gt + value string → hanya 1 issue (op-incompat saja), value check di-skip', () => {
|
|
311
|
-
const models = mapOf(makeModel('user', {
|
|
312
|
-
fields: {
|
|
313
|
-
user_id: { type: 'uuid', pk: true, notnull: true },
|
|
314
|
-
is_active: { type: 'boolean' }
|
|
315
|
-
},
|
|
316
|
-
checks: [
|
|
317
|
-
// schema-validator would actually reject value:'x' here, but assume it
|
|
318
|
-
// passes through to keep test focus on the op-incompat → no double-report rule.
|
|
319
|
-
{ field: 'is_active', op: 'gt', value: 0 }
|
|
320
|
-
]
|
|
321
|
-
}));
|
|
322
|
-
const issues = validateCheckCompatibility(models);
|
|
323
|
-
assert.strictEqual(issues.length, 1);
|
|
324
|
-
assert.strictEqual(issues[0].code, 'check-op-incompatible-with-type');
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// =====================================================
|
|
328
|
-
// Issue decoration
|
|
329
|
-
// =====================================================
|
|
330
|
-
|
|
331
|
-
test('check-compat: Issue di-decorate dengan file path bila _filePath ada di model', () => {
|
|
332
|
-
const models = mapOf(makeModel('product', {
|
|
333
|
-
filePath: '/abs/schema/product.js',
|
|
334
|
-
fields: {
|
|
335
|
-
product_id: { type: 'uuid', pk: true, notnull: true },
|
|
336
|
-
status: { type: 'string', length: 20 }
|
|
337
|
-
},
|
|
338
|
-
checks: [
|
|
339
|
-
{ field: 'status', op: 'eq', value: 42 }
|
|
340
|
-
]
|
|
341
|
-
}));
|
|
342
|
-
const issues = validateCheckCompatibility(models);
|
|
343
|
-
assert.strictEqual(issues.length, 1);
|
|
344
|
-
assert.strictEqual(issues[0].file, '/abs/schema/product.js');
|
|
345
|
-
assert.strictEqual(issues[0].table, 'product');
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// =====================================================
|
|
349
|
-
// Multi-table
|
|
350
|
-
// =====================================================
|
|
351
|
-
|
|
352
|
-
test('check-compat: 2 tabel masing-masing punya error → semua di-collect', () => {
|
|
353
|
-
const models = new Map();
|
|
354
|
-
models.set('a', makeModel('a', {
|
|
355
|
-
fields: {
|
|
356
|
-
a_id: { type: 'uuid', pk: true, notnull: true },
|
|
357
|
-
flag_a: { type: 'boolean' }
|
|
358
|
-
},
|
|
359
|
-
checks: [{ field: 'flag_a', op: 'gt', value: 0 }]
|
|
360
|
-
}));
|
|
361
|
-
models.set('b', makeModel('b', {
|
|
362
|
-
fields: {
|
|
363
|
-
b_id: { type: 'uuid', pk: true, notnull: true },
|
|
364
|
-
label: { type: 'string', length: 10 }
|
|
365
|
-
},
|
|
366
|
-
checks: [{ field: 'label', op: 'eq', value: 42 }]
|
|
367
|
-
}));
|
|
368
|
-
|
|
369
|
-
const issues = validateCheckCompatibility(models);
|
|
370
|
-
assert.strictEqual(issues.length, 2);
|
|
371
|
-
const codes = issues.map((i) => i.code).sort();
|
|
372
|
-
assert.deepStrictEqual(codes, ['check-op-incompatible-with-type', 'check-value-type-mismatch']);
|
|
373
|
-
});
|