@restforgejs/platform 4.1.1 → 4.3.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/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 +43 -4
- 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 +526 -0
- package/generators/cli/schema/describe.js +3 -2
- package/generators/cli/schema/diff.js +322 -0
- package/generators/cli/schema/generate-ddl.js +7 -10
- package/generators/cli/schema/init.js +95 -172
- package/generators/cli/schema/introspect.js +3 -2
- package/generators/cli/schema/list.js +3 -2
- package/generators/cli/schema/migrate.js +13 -18
- package/generators/cli/schema/models.js +8 -12
- package/generators/cli/schema/template.js +222 -0
- package/generators/cli/schema/validate.js +8 -12
- package/generators/cli-entry.js +17 -2
- package/generators/lib/dbschema-kit/apply-engine.js +582 -0
- package/generators/lib/dbschema-kit/diff-engine.js +703 -0
- package/generators/lib/dbschema-kit/diff-reporter.js +272 -0
- package/generators/lib/dbschema-kit/emitters/alter-table.js +275 -0
- package/generators/lib/migration/audit-table-runner.js +213 -215
- package/generators/lib/payload/endpoint-schema-validator.js +171 -0
- package/generators/lib/payload/payload-runner.js +137 -220
- package/generators/lib/payload/schema-diff.js +277 -0
- 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/audit-columns.js +181 -0
- package/generators/lib/utils/cli-output.js +17 -0
- package/generators/lib/utils/database-introspector.js +16 -13
- 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,237 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert');
|
|
5
|
-
|
|
6
|
-
const { parseFieldShorthand } = require('../../../../../lib/dbschema-kit/parser/shorthand-parser');
|
|
7
|
-
|
|
8
|
-
test('parser: type sederhana tanpa constraint (integer)', () => {
|
|
9
|
-
const result = parseFieldShorthand('integer', 'qty');
|
|
10
|
-
assert.deepStrictEqual(result, { type: 'integer' });
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('parser: type text tanpa constraint', () => {
|
|
14
|
-
const result = parseFieldShorthand('text', 'description');
|
|
15
|
-
assert.deepStrictEqual(result, { type: 'text' });
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('parser: string dengan length modifier', () => {
|
|
19
|
-
const result = parseFieldShorthand('string:20', 'code');
|
|
20
|
-
assert.deepStrictEqual(result, { type: 'string', length: 20 });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('parser: decimal dengan precision dan scale', () => {
|
|
24
|
-
const result = parseFieldShorthand('decimal:15,2', 'amount');
|
|
25
|
-
assert.deepStrictEqual(result, { type: 'decimal', precision: 15, scale: 2 });
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test('parser: decimal dengan scale nol', () => {
|
|
29
|
-
const result = parseFieldShorthand('decimal:15,0', 'stock');
|
|
30
|
-
assert.deepStrictEqual(result, { type: 'decimal', precision: 15, scale: 0 });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('parser: uuid dengan primary key constraint', () => {
|
|
34
|
-
const result = parseFieldShorthand('uuid pk', 'category_id');
|
|
35
|
-
assert.deepStrictEqual(result, { type: 'uuid', pk: true });
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('parser: multiple constraint pada string field', () => {
|
|
39
|
-
const result = parseFieldShorthand('string:20 unique notnull', 'category_code');
|
|
40
|
-
assert.deepStrictEqual(result, {
|
|
41
|
-
type: 'string',
|
|
42
|
-
length: 20,
|
|
43
|
-
unique: true,
|
|
44
|
-
notnull: true
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('parser: default value boolean true', () => {
|
|
49
|
-
const result = parseFieldShorthand('boolean default:true', 'is_active');
|
|
50
|
-
assert.deepStrictEqual(result, {
|
|
51
|
-
type: 'boolean',
|
|
52
|
-
default: { kind: 'literal', value: true }
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test('parser: default value boolean false', () => {
|
|
57
|
-
const result = parseFieldShorthand('boolean default:false', 'is_deleted');
|
|
58
|
-
assert.deepStrictEqual(result, {
|
|
59
|
-
type: 'boolean',
|
|
60
|
-
default: { kind: 'literal', value: false }
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test('parser: default value integer nol', () => {
|
|
65
|
-
const result = parseFieldShorthand('integer default:0', 'qty');
|
|
66
|
-
assert.deepStrictEqual(result, {
|
|
67
|
-
type: 'integer',
|
|
68
|
-
default: { kind: 'literal', value: 0 }
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('parser: default value integer negatif', () => {
|
|
73
|
-
const result = parseFieldShorthand('integer default:-5', 'offset');
|
|
74
|
-
assert.deepStrictEqual(result, {
|
|
75
|
-
type: 'integer',
|
|
76
|
-
default: { kind: 'literal', value: -5 }
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('parser: default value string literal dengan single quote', () => {
|
|
81
|
-
const result = parseFieldShorthand("string:100 default:'INDONESIA'", 'country');
|
|
82
|
-
assert.deepStrictEqual(result, {
|
|
83
|
-
type: 'string',
|
|
84
|
-
length: 100,
|
|
85
|
-
default: { kind: 'literal', value: 'INDONESIA' }
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test('parser: default value function call now()', () => {
|
|
90
|
-
const result = parseFieldShorthand('timestamp default:now()', 'created_at');
|
|
91
|
-
assert.deepStrictEqual(result, {
|
|
92
|
-
type: 'timestamp',
|
|
93
|
-
default: { kind: 'function', name: 'now', args: [] }
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('parser: default value constant identifier', () => {
|
|
98
|
-
const result = parseFieldShorthand('date default:current_date', 'inbound_date');
|
|
99
|
-
assert.deepStrictEqual(result, {
|
|
100
|
-
type: 'date',
|
|
101
|
-
default: { kind: 'constant', value: 'current_date' }
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('parser: foreign key shorthand dengan constraint tambahan', () => {
|
|
106
|
-
const result = parseFieldShorthand('uuid fk:category.category_id notnull', 'category_id');
|
|
107
|
-
assert.deepStrictEqual(result, {
|
|
108
|
-
type: 'uuid',
|
|
109
|
-
fk: { table: 'category', column: 'category_id' },
|
|
110
|
-
notnull: true
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test('parser: index shorthand pada field date', () => {
|
|
115
|
-
const result = parseFieldShorthand('date index', 'inbound_date');
|
|
116
|
-
assert.deepStrictEqual(result, { type: 'date', index: true });
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('parser: urutan constraint tidak signifikan', () => {
|
|
120
|
-
const a = parseFieldShorthand('string:20 notnull unique', 'code');
|
|
121
|
-
const b = parseFieldShorthand('string:20 unique notnull', 'code');
|
|
122
|
-
assert.deepStrictEqual(a, b);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test('parser: default string literal yang mengandung spasi', () => {
|
|
126
|
-
const result = parseFieldShorthand("string:100 default:'HELLO WORLD'", 'greeting');
|
|
127
|
-
assert.deepStrictEqual(result, {
|
|
128
|
-
type: 'string',
|
|
129
|
-
length: 100,
|
|
130
|
-
default: { kind: 'literal', value: 'HELLO WORLD' }
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test('parser: error untuk input string kosong', () => {
|
|
135
|
-
assert.throws(
|
|
136
|
-
() => parseFieldShorthand('', 'foo'),
|
|
137
|
-
/Field 'foo': shorthand must be a non-empty string/
|
|
138
|
-
);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test('parser: error untuk input bukan string', () => {
|
|
142
|
-
assert.throws(
|
|
143
|
-
() => parseFieldShorthand(null, 'foo'),
|
|
144
|
-
/Field 'foo': shorthand must be a non-empty string/
|
|
145
|
-
);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test('parser: error untuk type yang tidak dikenali', () => {
|
|
149
|
-
assert.throws(
|
|
150
|
-
() => parseFieldShorthand('foobar', 'mystery'),
|
|
151
|
-
/Field 'mystery': unknown type 'foobar'/
|
|
152
|
-
);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test('parser: error untuk string tanpa length modifier', () => {
|
|
156
|
-
assert.throws(
|
|
157
|
-
() => parseFieldShorthand('string', 'name'),
|
|
158
|
-
/Field 'name': type 'string' requires length modifier/
|
|
159
|
-
);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test('parser: error untuk string length bukan positive integer', () => {
|
|
163
|
-
assert.throws(
|
|
164
|
-
() => parseFieldShorthand('string:abc', 'name'),
|
|
165
|
-
/Field 'name': string length must be a positive integer/
|
|
166
|
-
);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test('parser: error untuk decimal tanpa scale', () => {
|
|
170
|
-
assert.throws(
|
|
171
|
-
() => parseFieldShorthand('decimal:15', 'amount'),
|
|
172
|
-
/Field 'amount': decimal modifier must be 'precision,scale'/
|
|
173
|
-
);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
test('parser: error untuk decimal tanpa modifier sama sekali', () => {
|
|
177
|
-
assert.throws(
|
|
178
|
-
() => parseFieldShorthand('decimal', 'amount'),
|
|
179
|
-
/Field 'amount': type 'decimal' requires precision and scale/
|
|
180
|
-
);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test('parser: error untuk decimal dengan scale lebih besar dari precision', () => {
|
|
184
|
-
assert.throws(
|
|
185
|
-
() => parseFieldShorthand('decimal:5,10', 'amount'),
|
|
186
|
-
/Field 'amount': decimal scale \(10\) cannot exceed precision \(5\)/
|
|
187
|
-
);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test('parser: error untuk type non-modifier yang diberi modifier', () => {
|
|
191
|
-
assert.throws(
|
|
192
|
-
() => parseFieldShorthand('integer:5', 'qty'),
|
|
193
|
-
/Field 'qty': type 'integer' does not accept modifier/
|
|
194
|
-
);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test('parser: error untuk constraint typo unknown', () => {
|
|
198
|
-
assert.throws(
|
|
199
|
-
() => parseFieldShorthand('string:20 uniqe', 'code'),
|
|
200
|
-
/Field 'code': unknown constraint 'uniqe'/
|
|
201
|
-
);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
test('parser: error untuk foreign key tanpa dot separator', () => {
|
|
205
|
-
assert.throws(
|
|
206
|
-
() => parseFieldShorthand('uuid fk:nodot notnull', 'parent_id'),
|
|
207
|
-
/Field 'parent_id': invalid foreign key format 'nodot'/
|
|
208
|
-
);
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
test('parser: error untuk foreign key dengan kolom kosong', () => {
|
|
212
|
-
assert.throws(
|
|
213
|
-
() => parseFieldShorthand('uuid fk:table.', 'parent_id'),
|
|
214
|
-
/Field 'parent_id': invalid foreign key format 'table\.'/
|
|
215
|
-
);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
test('parser: error untuk constraint duplikat', () => {
|
|
219
|
-
assert.throws(
|
|
220
|
-
() => parseFieldShorthand('string:20 notnull notnull', 'code'),
|
|
221
|
-
/Field 'code': duplicate constraint 'notnull'/
|
|
222
|
-
);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test('parser: error untuk string literal yang tidak ditutup', () => {
|
|
226
|
-
assert.throws(
|
|
227
|
-
() => parseFieldShorthand("string:100 default:'OPEN", 'code'),
|
|
228
|
-
/Field 'code': unterminated string literal/
|
|
229
|
-
);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test('parser: error untuk default value yang tidak bisa di-parse', () => {
|
|
233
|
-
assert.throws(
|
|
234
|
-
() => parseFieldShorthand('integer default:!@#', 'qty'),
|
|
235
|
-
/Field 'qty': invalid default value '!@#'/
|
|
236
|
-
);
|
|
237
|
-
});
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert');
|
|
5
|
-
const path = require('node:path');
|
|
6
|
-
const fs = require('node:fs');
|
|
7
|
-
const os = require('node:os');
|
|
8
|
-
|
|
9
|
-
const { serialize } = require('../../../../lib/dbschema-kit/schema-printer');
|
|
10
|
-
const { loadSchemaPath } = require('../../../../lib/dbschema-kit/loader');
|
|
11
|
-
const { defineModel } = require('../../../../lib/dbschema-kit/define-model');
|
|
12
|
-
|
|
13
|
-
const FIXED_TIMESTAMP = '2026-05-10T00:00:00.000Z';
|
|
14
|
-
|
|
15
|
-
function buildIRViaDefineModel(tableName, options) {
|
|
16
|
-
return defineModel(tableName, options);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function withTmpFile(content, fn) {
|
|
20
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dbsk-printer-'));
|
|
21
|
-
const file = path.join(tmpDir, `${Date.now()}.js`);
|
|
22
|
-
fs.writeFileSync(file, content, 'utf8');
|
|
23
|
-
try {
|
|
24
|
-
return fn(file);
|
|
25
|
-
} finally {
|
|
26
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
test('printer: IR sederhana (PK + 2 field) menghasilkan factory function valid', () => {
|
|
31
|
-
const ir = buildIRViaDefineModel('category', {
|
|
32
|
-
fields: {
|
|
33
|
-
category_id: 'string:36 pk',
|
|
34
|
-
name: 'string:100 notnull'
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
38
|
-
assert.match(out, /^'use strict';/);
|
|
39
|
-
assert.match(out, /module\.exports = \(\{ defineModel \}\) => defineModel\('category'/);
|
|
40
|
-
assert.match(out, /category_id: 'string:36 pk'/);
|
|
41
|
-
assert.match(out, /name: 'string:100 notnull'/);
|
|
42
|
-
assert.match(out, /\}\);\n$/);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('printer: output dapat di-load oleh loadSchemaPath (round-trip parse)', () => {
|
|
46
|
-
const ir = buildIRViaDefineModel('supplier', {
|
|
47
|
-
fields: {
|
|
48
|
-
supplier_id: 'string:36 pk',
|
|
49
|
-
code: 'string:20 unique notnull',
|
|
50
|
-
name: 'string:100 notnull'
|
|
51
|
-
},
|
|
52
|
-
indexes: [['code', 'name']]
|
|
53
|
-
});
|
|
54
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
55
|
-
withTmpFile(out, (file) => {
|
|
56
|
-
const models = loadSchemaPath(file);
|
|
57
|
-
assert.strictEqual(models.size, 1);
|
|
58
|
-
const reloaded = models.get('supplier');
|
|
59
|
-
assert.strictEqual(reloaded.tableName, 'supplier');
|
|
60
|
-
assert.deepStrictEqual(reloaded.primaryKey, ['supplier_id']);
|
|
61
|
-
assert.strictEqual(reloaded.fields.code.unique, true);
|
|
62
|
-
assert.strictEqual(reloaded.fields.code.notnull, true);
|
|
63
|
-
const compositeIdx = reloaded.indexes.find((i) => i.composite);
|
|
64
|
-
assert.ok(compositeIdx, 'composite index harus terjaga setelah round-trip');
|
|
65
|
-
assert.deepStrictEqual(compositeIdx.columns, ['code', 'name']);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('printer: section kosong (no uniques, no relations) tidak di-emit', () => {
|
|
70
|
-
const ir = buildIRViaDefineModel('thing', {
|
|
71
|
-
fields: {
|
|
72
|
-
thing_id: 'string:36 pk',
|
|
73
|
-
name: 'string:50 notnull'
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
77
|
-
assert.doesNotMatch(out, /uniques:/);
|
|
78
|
-
assert.doesNotMatch(out, /relations:/);
|
|
79
|
-
assert.doesNotMatch(out, /checks:/);
|
|
80
|
-
assert.doesNotMatch(out, /primaryKey:/); // single PK uses shorthand on field
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test('printer: single quote dalam value pakai wrapper double quote', () => {
|
|
84
|
-
const ir = buildIRViaDefineModel('order', {
|
|
85
|
-
fields: {
|
|
86
|
-
order_id: 'string:36 pk',
|
|
87
|
-
status: "string:20 notnull default:'active'"
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
91
|
-
assert.match(out, /status: "string:20 notnull default:'active'"/);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('printer: composite uniques dirender sebagai array nested', () => {
|
|
95
|
-
const ir = buildIRViaDefineModel('item_warehouse', {
|
|
96
|
-
fields: {
|
|
97
|
-
item_warehouse_id: 'string:36 pk',
|
|
98
|
-
item_id: 'string:36 notnull',
|
|
99
|
-
warehouse_id: 'string:36 notnull'
|
|
100
|
-
},
|
|
101
|
-
uniques: [['item_id', 'warehouse_id']]
|
|
102
|
-
});
|
|
103
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
104
|
-
assert.match(out, /uniques: \[\s*\['item_id', 'warehouse_id'\]\s*\]/m);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('printer: CHECK in dengan multiple values dirender benar', () => {
|
|
108
|
-
const ir = buildIRViaDefineModel('order', {
|
|
109
|
-
fields: {
|
|
110
|
-
order_id: 'string:36 pk',
|
|
111
|
-
status: "string:20 notnull default:'active'"
|
|
112
|
-
},
|
|
113
|
-
checks: [
|
|
114
|
-
{ field: 'status', in: ['active', 'inactive', 'cancelled'] }
|
|
115
|
-
]
|
|
116
|
-
});
|
|
117
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
118
|
-
assert.match(out, /checks:\s*\[/);
|
|
119
|
-
assert.match(out, /field: 'status', in: \['active', 'inactive', 'cancelled'\]/);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test('printer: relations multi-line dengan onDelete', () => {
|
|
123
|
-
const ir = buildIRViaDefineModel('stock_inbound', {
|
|
124
|
-
fields: {
|
|
125
|
-
stock_inbound_id: 'string:36 pk',
|
|
126
|
-
warehouse_id: 'string:36 notnull'
|
|
127
|
-
},
|
|
128
|
-
relations: {
|
|
129
|
-
warehouse: {
|
|
130
|
-
type: 'belongsTo',
|
|
131
|
-
target: 'warehouse',
|
|
132
|
-
localKey: 'warehouse_id',
|
|
133
|
-
references: 'warehouse_id',
|
|
134
|
-
onDelete: 'restrict'
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
139
|
-
assert.match(out, /relations:\s*\{/);
|
|
140
|
-
assert.match(out, /warehouse:\s*\{/);
|
|
141
|
-
assert.match(out, /type: 'belongsTo'/);
|
|
142
|
-
assert.match(out, /target: 'warehouse'/);
|
|
143
|
-
assert.match(out, /localKey: 'warehouse_id'/);
|
|
144
|
-
assert.match(out, /references: 'warehouse_id'/);
|
|
145
|
-
assert.match(out, /onDelete: 'restrict'/);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test('printer: header comment include timestamp valid', () => {
|
|
149
|
-
const ir = buildIRViaDefineModel('thing', {
|
|
150
|
-
fields: { thing_id: 'string:36 pk' }
|
|
151
|
-
});
|
|
152
|
-
const customStamp = '2026-05-10T12:34:56.000Z';
|
|
153
|
-
const out = serialize(ir, { timestamp: customStamp });
|
|
154
|
-
assert.match(out, new RegExp(`Generated at: ${customStamp.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`));
|
|
155
|
-
assert.match(out, /Schema definition for `thing`/);
|
|
156
|
-
assert.match(out, /Generated by: npx restforge schema introspect/);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
test('printer: composite primaryKey dirender sebagai opsi terpisah', () => {
|
|
160
|
-
const ir = buildIRViaDefineModel('user_role', {
|
|
161
|
-
fields: {
|
|
162
|
-
user_id: 'string:36',
|
|
163
|
-
role_id: 'string:36'
|
|
164
|
-
},
|
|
165
|
-
primaryKey: ['user_id', 'role_id']
|
|
166
|
-
});
|
|
167
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
168
|
-
assert.match(out, /primaryKey:\s*\['user_id',\s*'role_id'\]/);
|
|
169
|
-
assert.doesNotMatch(out, /string:36 pk/);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
test('printer: indexes single-col yang merupakan FK dilewati saat emit', () => {
|
|
173
|
-
const ir = buildIRViaDefineModel('item_product', {
|
|
174
|
-
fields: {
|
|
175
|
-
item_product_id: 'string:36 pk',
|
|
176
|
-
category_id: 'string:36 fk:category.category_id notnull'
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
// FK auto-generates an index entry, but printer should skip emitting it.
|
|
180
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
181
|
-
assert.doesNotMatch(out, /indexes:\s*\[\s*'category_id'/);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// =====================================================
|
|
185
|
-
// Phase 14: schema-aware printer
|
|
186
|
-
// =====================================================
|
|
187
|
-
|
|
188
|
-
test('printer (Phase 14): IR dengan schemaName → output emit baris schema: di body factory', () => {
|
|
189
|
-
const ir = buildIRViaDefineModel('products', {
|
|
190
|
-
schema: 'inventory',
|
|
191
|
-
fields: {
|
|
192
|
-
product_id: 'string:36 pk',
|
|
193
|
-
name: 'string:100 notnull'
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
197
|
-
assert.match(out, /defineModel\('products', \{/);
|
|
198
|
-
assert.match(out, /^\s{2}schema: 'inventory',$/m);
|
|
199
|
-
assert.match(out, /^\s{2}fields: \{/m);
|
|
200
|
-
// schema must appear before fields
|
|
201
|
-
const schemaIdx = out.indexOf("schema: 'inventory'");
|
|
202
|
-
const fieldsIdx = out.indexOf('fields: {');
|
|
203
|
-
assert.ok(schemaIdx < fieldsIdx && schemaIdx > 0, 'schema: must appear before fields:');
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
test('printer (Phase 14): IR tanpa schemaName → output tidak emit baris schema: (backward compat)', () => {
|
|
207
|
-
const ir = buildIRViaDefineModel('category', {
|
|
208
|
-
fields: {
|
|
209
|
-
category_id: 'string:36 pk',
|
|
210
|
-
name: 'string:50 notnull'
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
214
|
-
assert.doesNotMatch(out, /^\s*schema:/m);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
test('printer (Phase 14): output dengan schemaName dapat di-load oleh loadSchemaPath (round-trip)', () => {
|
|
218
|
-
const ir = buildIRViaDefineModel('events', {
|
|
219
|
-
schema: 'audit',
|
|
220
|
-
fields: {
|
|
221
|
-
event_id: 'string:36 pk',
|
|
222
|
-
action: 'string:50 notnull'
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
226
|
-
withTmpFile(out, (file) => {
|
|
227
|
-
const models = loadSchemaPath(file);
|
|
228
|
-
assert.strictEqual(models.size, 1);
|
|
229
|
-
const reloaded = models.get('audit.events');
|
|
230
|
-
assert.ok(reloaded, 'model harus terindex via qualifiedName');
|
|
231
|
-
assert.strictEqual(reloaded.schemaName, 'audit');
|
|
232
|
-
assert.strictEqual(reloaded.tableName, 'events');
|
|
233
|
-
assert.strictEqual(reloaded.qualifiedName, 'audit.events');
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
test('printer: check unparsable diemit sebagai komentar TODO', () => {
|
|
238
|
-
const ir = {
|
|
239
|
-
tableName: 'item',
|
|
240
|
-
fields: { item_id: { type: 'string', length: 36, pk: true, notnull: true } },
|
|
241
|
-
primaryKey: ['item_id'],
|
|
242
|
-
indexes: [],
|
|
243
|
-
uniques: [],
|
|
244
|
-
relations: {},
|
|
245
|
-
checks: [{ _unparsable: true, expression: 'col1 LIKE \'%foo%\'' }],
|
|
246
|
-
_meta: { hasSinglePkShorthand: true, hasCompositePrimaryKey: false, autoGeneratedRelations: [] }
|
|
247
|
-
};
|
|
248
|
-
const out = serialize(ir, { timestamp: FIXED_TIMESTAMP });
|
|
249
|
-
assert.match(out, /TODO: CHECK constraints below are not parsable/);
|
|
250
|
-
assert.match(out, /col1 LIKE '%foo%'/);
|
|
251
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert');
|
|
5
|
-
|
|
6
|
-
const { applyIfNotExistsModifier } = require('../../../../lib/dbschema-kit/statement-modifier');
|
|
7
|
-
|
|
8
|
-
test('modifier: Postgres CREATE TABLE → tambah IF NOT EXISTS', () => {
|
|
9
|
-
const stmt = 'CREATE TABLE foo (id UUID NOT NULL)';
|
|
10
|
-
const out = applyIfNotExistsModifier(stmt, 'postgres');
|
|
11
|
-
assert.strictEqual(out, 'CREATE TABLE IF NOT EXISTS foo (id UUID NOT NULL)');
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test('modifier: Postgres CREATE INDEX → tambah IF NOT EXISTS', () => {
|
|
15
|
-
const stmt = 'CREATE INDEX idx_foo ON foo (col_a)';
|
|
16
|
-
const out = applyIfNotExistsModifier(stmt, 'postgres');
|
|
17
|
-
assert.strictEqual(out, 'CREATE INDEX IF NOT EXISTS idx_foo ON foo (col_a)');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test('modifier: MySQL CREATE TABLE → tambah IF NOT EXISTS', () => {
|
|
21
|
-
const stmt = 'CREATE TABLE category (id BIGINT)';
|
|
22
|
-
const out = applyIfNotExistsModifier(stmt, 'mysql');
|
|
23
|
-
assert.strictEqual(out, 'CREATE TABLE IF NOT EXISTS category (id BIGINT)');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('modifier: SQLite CREATE TABLE → tambah IF NOT EXISTS', () => {
|
|
27
|
-
const stmt = 'CREATE TABLE foo (id INTEGER PRIMARY KEY)';
|
|
28
|
-
const out = applyIfNotExistsModifier(stmt, 'sqlite');
|
|
29
|
-
assert.strictEqual(out, 'CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY)');
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('modifier: Oracle CREATE TABLE → wrap dalam BEGIN ... EXCEPTION ... END dengan SQLCODE -955', () => {
|
|
33
|
-
const stmt = 'CREATE TABLE category (category_id VARCHAR2(36) NOT NULL)';
|
|
34
|
-
const out = applyIfNotExistsModifier(stmt, 'oracle');
|
|
35
|
-
assert.match(out, /^BEGIN\n/);
|
|
36
|
-
assert.match(out, /EXECUTE IMMEDIATE '/);
|
|
37
|
-
assert.match(out, /CREATE TABLE category/);
|
|
38
|
-
assert.match(out, /EXCEPTION/);
|
|
39
|
-
assert.match(out, /WHEN OTHERS THEN/);
|
|
40
|
-
assert.match(out, /IF SQLCODE != -955 THEN RAISE; END IF;/);
|
|
41
|
-
assert.match(out, /END;$/);
|
|
42
|
-
// Tidak ada terminator / di output (statement-splitter tidak suka)
|
|
43
|
-
assert.ok(!out.endsWith('/'));
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('modifier: Oracle CREATE TABLE dengan apostrophe DEFAULT → escape jadi double quote', () => {
|
|
47
|
-
const stmt = "CREATE TABLE category (is_active VARCHAR2(5) DEFAULT 'true')";
|
|
48
|
-
const out = applyIfNotExistsModifier(stmt, 'oracle');
|
|
49
|
-
// Original ' harus jadi '' di dalam EXECUTE IMMEDIATE string literal
|
|
50
|
-
assert.match(out, /EXECUTE IMMEDIATE 'CREATE TABLE category \(is_active VARCHAR2\(5\) DEFAULT ''true''\)';/);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('modifier: Oracle CREATE INDEX → wrap dalam PL/SQL block (SQLCODE -955)', () => {
|
|
54
|
-
const stmt = 'CREATE INDEX idx_foo ON foo (col_a)';
|
|
55
|
-
const out = applyIfNotExistsModifier(stmt, 'oracle');
|
|
56
|
-
assert.match(out, /^BEGIN/);
|
|
57
|
-
assert.match(out, /EXECUTE IMMEDIATE 'CREATE INDEX idx_foo ON foo \(col_a\)';/);
|
|
58
|
-
assert.match(out, /IF SQLCODE != -955 THEN RAISE; END IF;/);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('modifier: DROP statement → return as-is (semua dialect)', () => {
|
|
62
|
-
const stmt = 'DROP TABLE IF EXISTS foo CASCADE';
|
|
63
|
-
assert.strictEqual(applyIfNotExistsModifier(stmt, 'postgres'), stmt);
|
|
64
|
-
assert.strictEqual(applyIfNotExistsModifier(stmt, 'mysql'), stmt);
|
|
65
|
-
assert.strictEqual(applyIfNotExistsModifier(stmt, 'sqlite'), stmt);
|
|
66
|
-
assert.strictEqual(applyIfNotExistsModifier(stmt, 'oracle'), stmt);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('modifier: statement sudah ada IF NOT EXISTS → idempotent (no double insert)', () => {
|
|
70
|
-
const stmt = 'CREATE TABLE IF NOT EXISTS foo (id UUID)';
|
|
71
|
-
assert.strictEqual(applyIfNotExistsModifier(stmt, 'postgres'), stmt);
|
|
72
|
-
assert.strictEqual(applyIfNotExistsModifier(stmt, 'mysql'), stmt);
|
|
73
|
-
|
|
74
|
-
const idxStmt = 'CREATE INDEX IF NOT EXISTS idx_foo ON foo (col_a)';
|
|
75
|
-
assert.strictEqual(applyIfNotExistsModifier(idxStmt, 'postgres'), idxStmt);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('modifier: CREATE UNIQUE INDEX → tambah IF NOT EXISTS sambil pertahankan UNIQUE', () => {
|
|
79
|
-
const stmt = 'CREATE UNIQUE INDEX idx_foo ON foo (col_a)';
|
|
80
|
-
const out = applyIfNotExistsModifier(stmt, 'postgres');
|
|
81
|
-
assert.strictEqual(out, 'CREATE UNIQUE INDEX IF NOT EXISTS idx_foo ON foo (col_a)');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('modifier: Postgres multi-line CREATE TABLE → IF NOT EXISTS hanya di header', () => {
|
|
85
|
-
const stmt = [
|
|
86
|
-
'CREATE TABLE foo (',
|
|
87
|
-
' id UUID NOT NULL,',
|
|
88
|
-
' PRIMARY KEY (id)',
|
|
89
|
-
')'
|
|
90
|
-
].join('\n');
|
|
91
|
-
const out = applyIfNotExistsModifier(stmt, 'postgres');
|
|
92
|
-
assert.match(out, /^CREATE TABLE IF NOT EXISTS foo \(\n/);
|
|
93
|
-
assert.match(out, /PRIMARY KEY \(id\)/);
|
|
94
|
-
// Hanya satu kemunculan IF NOT EXISTS
|
|
95
|
-
const occurrences = (out.match(/IF NOT EXISTS/g) || []).length;
|
|
96
|
-
assert.strictEqual(occurrences, 1);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test('modifier: invalid dialect → throw error', () => {
|
|
100
|
-
assert.throws(() => applyIfNotExistsModifier('CREATE TABLE foo (id INT)', 'mssql'), /invalid dialect/);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test('modifier: statement bukan string → throw error', () => {
|
|
104
|
-
assert.throws(() => applyIfNotExistsModifier(null, 'postgres'), /must be a string/);
|
|
105
|
-
});
|