@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
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contract: schema diff
|
|
5
|
+
*
|
|
6
|
+
* Drift detection antara Schema Definition File (SDF) dan struktur tabel
|
|
7
|
+
* actual di database. Read-only. Tidak melakukan modifikasi pada filesystem
|
|
8
|
+
* maupun database.
|
|
9
|
+
*
|
|
10
|
+
* Algoritma bidirectional: tampilkan delta dari kedua sisi (only-in-SDF,
|
|
11
|
+
* only-in-DB, mismatched) di level IR (Intermediate Representation),
|
|
12
|
+
* bypass formatting noise.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const os = require('os');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
const { loadSchemaPath } = require('../../lib/dbschema-kit/loader');
|
|
20
|
+
const { mapTableMetaToIR } = require('../../lib/dbschema-kit/introspect-mapper');
|
|
21
|
+
const { loadConfig } = require('../../lib/dbschema-kit/connection');
|
|
22
|
+
const { diffModels } = require('../../lib/dbschema-kit/diff-engine');
|
|
23
|
+
const { reportHuman, reportJson, getExitCode } = require('../../lib/dbschema-kit/diff-reporter');
|
|
24
|
+
const { resolveConfig, printDefaultConfigWarning } = require('../../lib/utils/config-resolver');
|
|
25
|
+
|
|
26
|
+
function loadIntrospector() {
|
|
27
|
+
const stubPath = process.env.DBSCHEMA_KIT_TEST_INTROSPECT_STUB;
|
|
28
|
+
if (stubPath) {
|
|
29
|
+
return require(path.resolve(stubPath));
|
|
30
|
+
}
|
|
31
|
+
return defaultIntrospector;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function mapDialectToDbType(dialect) {
|
|
35
|
+
switch (dialect) {
|
|
36
|
+
case 'postgres': return 'postgresql';
|
|
37
|
+
case 'mysql': return 'mysql';
|
|
38
|
+
case 'oracle': return 'oracle';
|
|
39
|
+
case 'sqlite': return 'sqlite';
|
|
40
|
+
default: return dialect;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildEphemeralEnvFile(config, dbType) {
|
|
45
|
+
const lines = [`DB_TYPE=${dbType}`];
|
|
46
|
+
if (config.host !== undefined) lines.push(`DB_HOST=${config.host}`);
|
|
47
|
+
if (config.port !== undefined) lines.push(`DB_PORT=${config.port}`);
|
|
48
|
+
if (dbType === 'oracle') {
|
|
49
|
+
lines.push(`DB_NAME=${config.serviceName || ''}`);
|
|
50
|
+
} else if (config.database !== undefined) {
|
|
51
|
+
lines.push(`DB_NAME=${config.database}`);
|
|
52
|
+
}
|
|
53
|
+
if (config.user !== undefined) lines.push(`DB_USER=${config.user}`);
|
|
54
|
+
if (config.password !== undefined) lines.push(`DB_PASSWORD=${config.password}`);
|
|
55
|
+
return lines.join('\n') + '\n';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createTmpEnvFile(content) {
|
|
59
|
+
const tmpDir = os.tmpdir();
|
|
60
|
+
const tmpName = `restforge-diff-${process.pid}-${Date.now()}.env`;
|
|
61
|
+
const fullPath = path.join(tmpDir, tmpName);
|
|
62
|
+
fs.writeFileSync(fullPath, content, 'utf8');
|
|
63
|
+
return fullPath;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function collectTableMeta(introspector, target) {
|
|
67
|
+
const ref = target.schemaName ? `${target.schemaName}.${target.tableName}` : target.tableName;
|
|
68
|
+
const detailedColumns = await introspector.getDetailedColumnInfo(ref);
|
|
69
|
+
const constraints = await introspector.getConstraints(ref);
|
|
70
|
+
const foreignKeys = await introspector.getForeignKeys(ref);
|
|
71
|
+
const indexes = await introspector.getIndexes(ref);
|
|
72
|
+
|
|
73
|
+
const pkConstraint = constraints.find((c) => c.type === 'PRIMARY KEY');
|
|
74
|
+
const uniqueConstraints = constraints
|
|
75
|
+
.filter((c) => c.type === 'UNIQUE')
|
|
76
|
+
.map((c) => ({ name: c.name, columns: c.columns }));
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
tableName: target.tableName,
|
|
80
|
+
schemaName: target.schemaName || null,
|
|
81
|
+
columns: detailedColumns,
|
|
82
|
+
primaryKey: pkConstraint ? pkConstraint.columns : [],
|
|
83
|
+
uniques: uniqueConstraints,
|
|
84
|
+
foreignKeys,
|
|
85
|
+
indexes,
|
|
86
|
+
checks: []
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const defaultIntrospector = {
|
|
91
|
+
introspect: async ({ config, tables }) => {
|
|
92
|
+
const dbType = mapDialectToDbType(config.dialect);
|
|
93
|
+
if (dbType === 'sqlite') {
|
|
94
|
+
throw new Error('schema:diff does not yet support sqlite. Use postgres, mysql, or oracle.');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { DatabaseIntrospector } = require('../../lib/utils/database-introspector');
|
|
98
|
+
const introspector = new DatabaseIntrospector({ quiet: true });
|
|
99
|
+
|
|
100
|
+
const ephemeralEnv = buildEphemeralEnvFile(config, dbType);
|
|
101
|
+
const tmpPath = createTmpEnvFile(ephemeralEnv);
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const ok = introspector.loadConfig(tmpPath);
|
|
105
|
+
if (!ok) throw new Error('Failed to load config into DatabaseIntrospector');
|
|
106
|
+
const connected = await introspector.connect();
|
|
107
|
+
if (!connected) throw new Error('Failed to connect to database');
|
|
108
|
+
|
|
109
|
+
const out = [];
|
|
110
|
+
for (const target of tables) {
|
|
111
|
+
try {
|
|
112
|
+
out.push(await collectTableMeta(introspector, target));
|
|
113
|
+
} catch (err) {
|
|
114
|
+
// Tabel tidak ada di DB: catat dengan struktur kosong agar
|
|
115
|
+
// diff engine memperlakukannya sebagai "only-in-SDF" di sisi DB.
|
|
116
|
+
out.push({
|
|
117
|
+
tableName: target.tableName,
|
|
118
|
+
schemaName: target.schemaName || null,
|
|
119
|
+
columns: [],
|
|
120
|
+
primaryKey: [],
|
|
121
|
+
uniques: [],
|
|
122
|
+
foreignKeys: [],
|
|
123
|
+
indexes: [],
|
|
124
|
+
checks: [],
|
|
125
|
+
_missing: true,
|
|
126
|
+
_error: err && err.message ? err.message : String(err)
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { tables: out };
|
|
131
|
+
} finally {
|
|
132
|
+
try { await introspector.disconnect(); } catch (e) { /* ignore */ }
|
|
133
|
+
try { fs.unlinkSync(tmpPath); } catch (e) { /* ignore */ }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
resource: 'schema',
|
|
140
|
+
verb: 'diff',
|
|
141
|
+
description: 'Drift detection antara SDF dan struktur tabel database (read-only, bidirectional)',
|
|
142
|
+
category: 'introspection',
|
|
143
|
+
flags: {
|
|
144
|
+
path: {
|
|
145
|
+
type: 'string',
|
|
146
|
+
required: true,
|
|
147
|
+
description: 'Path file atau folder schema (mis. ./schema atau ./schema/users.js)'
|
|
148
|
+
},
|
|
149
|
+
config: {
|
|
150
|
+
type: 'string',
|
|
151
|
+
required: false,
|
|
152
|
+
default: null,
|
|
153
|
+
description: 'File config database (.env). Fallback ke `.restforge/defaults.json` bila tidak disediakan eksplisit (set via `config set-default`)'
|
|
154
|
+
},
|
|
155
|
+
table: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
required: false,
|
|
158
|
+
default: null,
|
|
159
|
+
description: 'Diff hanya satu tabel spesifik (default: semua model di SDF)'
|
|
160
|
+
},
|
|
161
|
+
json: {
|
|
162
|
+
type: 'boolean',
|
|
163
|
+
required: false,
|
|
164
|
+
default: false,
|
|
165
|
+
description: 'Output format JSON (default: human-readable plain)'
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
examples: [
|
|
169
|
+
'npx restforge schema diff --path=./schema --config=db.env',
|
|
170
|
+
'npx restforge schema diff --path=./schema/visitors.js --config=db.env --table=visitors',
|
|
171
|
+
'npx restforge schema diff --path=./schema --config=db.env --json'
|
|
172
|
+
],
|
|
173
|
+
async handler(args) {
|
|
174
|
+
// 1. Resolve config
|
|
175
|
+
const resolvedConfigResult = resolveConfig(args.config, process.cwd());
|
|
176
|
+
if (!resolvedConfigResult) {
|
|
177
|
+
console.error('Error: --config=<file> is required.');
|
|
178
|
+
console.error("Tip: set a default with 'npx restforge config set-default --config=<file>' to omit --config in future runs");
|
|
179
|
+
const err = new Error('--config=<file> is required');
|
|
180
|
+
err.exitCode = 2;
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (resolvedConfigResult.source === 'default') {
|
|
185
|
+
printDefaultConfigWarning(resolvedConfigResult.defaultName);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let config;
|
|
189
|
+
try {
|
|
190
|
+
config = loadConfig(resolvedConfigResult.path);
|
|
191
|
+
} catch (err) {
|
|
192
|
+
console.error(`Error: ${err.message}`);
|
|
193
|
+
const e = new Error(err.message);
|
|
194
|
+
e.exitCode = 2;
|
|
195
|
+
throw e;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 2. Load SDF
|
|
199
|
+
const schemaPath = args.path;
|
|
200
|
+
const absPath = path.resolve(process.cwd(), schemaPath);
|
|
201
|
+
|
|
202
|
+
let sdfModels;
|
|
203
|
+
try {
|
|
204
|
+
sdfModels = loadSchemaPath(absPath);
|
|
205
|
+
} catch (err) {
|
|
206
|
+
console.error(`Error: ${err.message}`);
|
|
207
|
+
const e = new Error(err.message);
|
|
208
|
+
e.exitCode = 2;
|
|
209
|
+
throw e;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (sdfModels.size === 0) {
|
|
213
|
+
console.error(`Error: No schema models found at '${schemaPath}'.`);
|
|
214
|
+
const e = new Error(`No schema models found at '${schemaPath}'`);
|
|
215
|
+
e.exitCode = 2;
|
|
216
|
+
throw e;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 3. Resolve target tables
|
|
220
|
+
let targetEntries = Array.from(sdfModels.entries());
|
|
221
|
+
if (args.table) {
|
|
222
|
+
targetEntries = targetEntries.filter(([qualified, ir]) => {
|
|
223
|
+
return ir.tableName === args.table || qualified === args.table;
|
|
224
|
+
});
|
|
225
|
+
if (targetEntries.length === 0) {
|
|
226
|
+
console.error(`Error: Table '${args.table}' not found in SDF.`);
|
|
227
|
+
const e = new Error(`Table '${args.table}' not found in SDF`);
|
|
228
|
+
e.exitCode = 2;
|
|
229
|
+
throw e;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const targetsForDb = targetEntries.map(([_, ir]) => ({
|
|
234
|
+
tableName: ir.tableName,
|
|
235
|
+
schemaName: ir.schemaName || null
|
|
236
|
+
}));
|
|
237
|
+
|
|
238
|
+
// 4. Connect database, introspect setiap tabel
|
|
239
|
+
let introspector;
|
|
240
|
+
try {
|
|
241
|
+
introspector = loadIntrospector();
|
|
242
|
+
} catch (err) {
|
|
243
|
+
console.error(`Error: Failed to load introspector: ${err.message}`);
|
|
244
|
+
const e = new Error(err.message);
|
|
245
|
+
e.exitCode = 2;
|
|
246
|
+
throw e;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
let result;
|
|
250
|
+
try {
|
|
251
|
+
result = await introspector.introspect({ config, tables: targetsForDb });
|
|
252
|
+
} catch (err) {
|
|
253
|
+
const message = err && err.message ? err.message : String(err);
|
|
254
|
+
console.error(`Error: ${message}`);
|
|
255
|
+
const e = new Error(message);
|
|
256
|
+
e.exitCode = 2;
|
|
257
|
+
throw e;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (!result || !Array.isArray(result.tables)) {
|
|
261
|
+
console.error('Error: Introspector did not return a tables array.');
|
|
262
|
+
const e = new Error('Introspector did not return a tables array');
|
|
263
|
+
e.exitCode = 2;
|
|
264
|
+
throw e;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// 5. Map DB results to IR (keyed by tableName supaya match dengan SDF)
|
|
268
|
+
const dialect = config.dialect;
|
|
269
|
+
const dbModels = new Map();
|
|
270
|
+
for (const tableMeta of result.tables) {
|
|
271
|
+
if (tableMeta._missing) {
|
|
272
|
+
// Tabel hilang di DB: register empty IR agar diff engine
|
|
273
|
+
// memperlakukan sebagai onlyInSdf untuk seluruh content.
|
|
274
|
+
const qualified = tableMeta.schemaName
|
|
275
|
+
? `${tableMeta.schemaName}.${tableMeta.tableName}`
|
|
276
|
+
: tableMeta.tableName;
|
|
277
|
+
dbModels.set(qualified, {
|
|
278
|
+
tableName: tableMeta.tableName,
|
|
279
|
+
schemaName: tableMeta.schemaName || null,
|
|
280
|
+
qualifiedName: qualified,
|
|
281
|
+
fields: {},
|
|
282
|
+
primaryKey: [],
|
|
283
|
+
indexes: [],
|
|
284
|
+
uniques: [],
|
|
285
|
+
relations: {},
|
|
286
|
+
checks: []
|
|
287
|
+
});
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const ir = mapTableMetaToIR(tableMeta, dialect);
|
|
291
|
+
dbModels.set(ir.qualifiedName || ir.tableName, ir);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 6. Build SDF map matching same key convention as dbModels
|
|
295
|
+
const sdfMap = new Map();
|
|
296
|
+
for (const [_, ir] of targetEntries) {
|
|
297
|
+
sdfMap.set(ir.qualifiedName || ir.tableName, ir);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// 7. Compute diff
|
|
301
|
+
const deltas = diffModels(sdfMap, dbModels);
|
|
302
|
+
|
|
303
|
+
// 8. Report
|
|
304
|
+
if (args.json) {
|
|
305
|
+
const obj = reportJson(deltas);
|
|
306
|
+
process.stdout.write(JSON.stringify(obj, null, 2));
|
|
307
|
+
process.stdout.write('\n');
|
|
308
|
+
} else {
|
|
309
|
+
const text = reportHuman(deltas);
|
|
310
|
+
process.stdout.write(text);
|
|
311
|
+
process.stdout.write('\n');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// 9. Exit code
|
|
315
|
+
const exitCode = getExitCode(deltas);
|
|
316
|
+
if (exitCode !== 0) {
|
|
317
|
+
const err = new Error(`schema diff detected drift in ${deltas.filter((d) => d.hasDrift).length} table(s)`);
|
|
318
|
+
err.exitCode = exitCode;
|
|
319
|
+
throw err;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
};
|
|
@@ -27,6 +27,11 @@ module.exports = {
|
|
|
27
27
|
description: 'Generate DDL SQL (CREATE TABLE, CREATE INDEX, opsional DROP) untuk seluruh schema models',
|
|
28
28
|
category: 'generation',
|
|
29
29
|
flags: {
|
|
30
|
+
path: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
required: true,
|
|
33
|
+
description: 'Path file atau folder schema (mis. ./schema atau ./schema/users.js)'
|
|
34
|
+
},
|
|
30
35
|
dialect: {
|
|
31
36
|
type: 'string',
|
|
32
37
|
required: true,
|
|
@@ -45,17 +50,9 @@ module.exports = {
|
|
|
45
50
|
description: 'Sertakan statement DROP TABLE sebelum CREATE'
|
|
46
51
|
}
|
|
47
52
|
},
|
|
48
|
-
positional: [
|
|
49
|
-
{
|
|
50
|
-
name: 'path',
|
|
51
|
-
type: 'string',
|
|
52
|
-
required: true,
|
|
53
|
-
description: 'Path file atau folder schema'
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
53
|
examples: [
|
|
57
|
-
'npx restforge schema generate-ddl
|
|
58
|
-
'npx restforge schema generate-ddl
|
|
54
|
+
'npx restforge schema generate-ddl --path=./schema --dialect=postgres --out=migration.sql',
|
|
55
|
+
'npx restforge schema generate-ddl --path=./schema --dialect=mysql --drop=true'
|
|
59
56
|
],
|
|
60
57
|
async handler(args) {
|
|
61
58
|
if (!args.dialect) {
|
|
@@ -1,172 +1,95 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Contract: schema init
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
],
|
|
97
|
-
|
|
98
|
-
// CHECK constraints (operators: in, gt, gte, lt, lte, eq, neq)
|
|
99
|
-
checks: [
|
|
100
|
-
{ field: 'status', in: ['active', 'inactive', 'suspended'] },
|
|
101
|
-
{ field: 'credit_limit', gte: 0 }
|
|
102
|
-
]${relationsBlock}
|
|
103
|
-
});
|
|
104
|
-
`;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
module.exports = {
|
|
108
|
-
resource: 'schema',
|
|
109
|
-
verb: 'init',
|
|
110
|
-
description: 'Membuat skeleton file schema definition (fields, indexes, uniques, relations)',
|
|
111
|
-
category: 'utility',
|
|
112
|
-
flags: {},
|
|
113
|
-
positional: [
|
|
114
|
-
{
|
|
115
|
-
name: 'path',
|
|
116
|
-
type: 'string',
|
|
117
|
-
required: true,
|
|
118
|
-
description: 'Path file schema yang akan dibuat (mis. schema/users.js)'
|
|
119
|
-
}
|
|
120
|
-
],
|
|
121
|
-
examples: [
|
|
122
|
-
'npx restforge schema init schema/users.js',
|
|
123
|
-
'npx restforge schema init ./schema/item_product.js'
|
|
124
|
-
],
|
|
125
|
-
async handler(args) {
|
|
126
|
-
if (!args.path) {
|
|
127
|
-
console.error('Error: Target file path is required.');
|
|
128
|
-
console.error("Run 'npx restforge schema init --help' for usage information");
|
|
129
|
-
throw new Error('Target file path is required');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const absPath = path.resolve(process.cwd(), args.path);
|
|
133
|
-
|
|
134
|
-
if (path.extname(absPath) !== '.js') {
|
|
135
|
-
console.error(`Error: Schema file must have .js extension: ${absPath}`);
|
|
136
|
-
throw new Error(`Schema file must have .js extension: ${absPath}`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (fs.existsSync(absPath)) {
|
|
140
|
-
console.error(`Error: File already exists: ${absPath}`);
|
|
141
|
-
throw new Error(`File already exists: ${absPath}`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const tableName = path.basename(absPath, '.js');
|
|
145
|
-
if (!/^[a-z][a-z0-9_]*$/i.test(tableName)) {
|
|
146
|
-
console.error(
|
|
147
|
-
`Error: Invalid table name '${tableName}' (derived from filename). ` +
|
|
148
|
-
`Must start with a letter and contain only letters, digits, or underscore.`
|
|
149
|
-
);
|
|
150
|
-
throw new Error(`Invalid table name '${tableName}' (derived from filename)`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const parentDir = path.dirname(absPath);
|
|
154
|
-
try {
|
|
155
|
-
fs.mkdirSync(parentDir, { recursive: true });
|
|
156
|
-
} catch (err) {
|
|
157
|
-
console.error(`Error: Failed to create directory '${parentDir}': ${err.message}`);
|
|
158
|
-
throw new Error(`Failed to create directory '${parentDir}': ${err.message}`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
fs.writeFileSync(absPath, buildSkeleton(tableName), 'utf8');
|
|
163
|
-
} catch (err) {
|
|
164
|
-
console.error(`Error: Failed to write file '${absPath}': ${err.message}`);
|
|
165
|
-
throw new Error(`Failed to write file '${absPath}': ${err.message}`);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
console.log(`✓ Created schema skeleton: ${absPath}`);
|
|
169
|
-
console.log(` Table name: ${tableName}`);
|
|
170
|
-
console.log(' Edit fields, indexes, uniques, and relations to match the actual table.');
|
|
171
|
-
}
|
|
172
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contract: schema init
|
|
5
|
+
*
|
|
6
|
+
* Thin wrapper untuk scaffold file schema definition. Implementasi sekarang
|
|
7
|
+
* mendelegasikan ke binary native sdf-tools.exe dengan template `dummy`,
|
|
8
|
+
* menggantikan generator skeleton custom yang sebelumnya inline.
|
|
9
|
+
*
|
|
10
|
+
* Setara dengan: sdf-tools.exe --table=dummy --generate --lang=sdf --path=<USER_PATH>
|
|
11
|
+
*
|
|
12
|
+
* Kontrak CLI dipertahankan (verb, category, flag --path) agar workflow user
|
|
13
|
+
* tidak breaking. File yang dihasilkan berisi struktur template `dummy` dari
|
|
14
|
+
* koleksi RestForge Schema Reference, yang dapat di-rename dan diadaptasi
|
|
15
|
+
* sesuai kebutuhan.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const os = require('os');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const { spawnSync } = require('child_process');
|
|
22
|
+
|
|
23
|
+
function resolveBinaryPath() {
|
|
24
|
+
if (os.platform() !== 'win32') return null;
|
|
25
|
+
return path.resolve(__dirname, '..', '..', '..', 'bin', 'sdf-tools.exe');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
resource: 'schema',
|
|
30
|
+
verb: 'init',
|
|
31
|
+
description: 'Membuat skeleton file schema definition (delegate ke sdf-tools dengan template dummy)',
|
|
32
|
+
category: 'utility',
|
|
33
|
+
flags: {
|
|
34
|
+
path: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
required: true,
|
|
37
|
+
description: 'Path file schema yang akan dibuat (mis. schema/users.js)'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
examples: [
|
|
41
|
+
'npx restforge schema init --path=schema/users.js',
|
|
42
|
+
'npx restforge schema init --path=./schema/item_product.js'
|
|
43
|
+
],
|
|
44
|
+
async handler(args) {
|
|
45
|
+
if (!args.path) {
|
|
46
|
+
console.error('Error: Target file path is required.');
|
|
47
|
+
console.error("Run 'npx restforge schema init --help' for usage information");
|
|
48
|
+
throw new Error('Target file path is required');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const binaryPath = resolveBinaryPath();
|
|
52
|
+
if (!binaryPath) {
|
|
53
|
+
const err = new Error(
|
|
54
|
+
`schema init hanya tersedia di Windows (sdf-tools.exe). Platform saat ini: ${os.platform()}`
|
|
55
|
+
);
|
|
56
|
+
err.exitCode = 3;
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(binaryPath)) {
|
|
61
|
+
const err = new Error(
|
|
62
|
+
`sdf-tools.exe tidak ditemukan di ${binaryPath}. ` +
|
|
63
|
+
'Pastikan binary sudah di-build dan tersedia di folder bin/ package.'
|
|
64
|
+
);
|
|
65
|
+
err.exitCode = 3;
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const binaryArgs = [
|
|
70
|
+
'--table=dummy',
|
|
71
|
+
'--generate',
|
|
72
|
+
'--lang=sdf',
|
|
73
|
+
`--path=${args.path}`
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
const result = spawnSync(binaryPath, binaryArgs, {
|
|
77
|
+
stdio: 'inherit',
|
|
78
|
+
windowsHide: true
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (result.error) {
|
|
82
|
+
const err = new Error(`Gagal menjalankan sdf-tools.exe: ${result.error.message}`);
|
|
83
|
+
err.exitCode = 1;
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const status = typeof result.status === 'number' ? result.status : 1;
|
|
88
|
+
if (status !== 0) {
|
|
89
|
+
const err = new Error(`sdf-tools.exe exit code ${status}`);
|
|
90
|
+
err.exitCode = status;
|
|
91
|
+
err.silent = true;
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
@@ -238,8 +238,9 @@ module.exports = {
|
|
|
238
238
|
flags: {
|
|
239
239
|
config: {
|
|
240
240
|
type: 'string',
|
|
241
|
-
required:
|
|
242
|
-
|
|
241
|
+
required: false,
|
|
242
|
+
default: null,
|
|
243
|
+
description: 'File config database (.env). Fallback ke `.restforge/defaults.json` bila tidak disediakan eksplisit (set via `config set-default`)'
|
|
243
244
|
},
|
|
244
245
|
output: {
|
|
245
246
|
type: 'string',
|
|
@@ -23,8 +23,9 @@ module.exports = {
|
|
|
23
23
|
flags: {
|
|
24
24
|
config: {
|
|
25
25
|
type: 'string',
|
|
26
|
-
required:
|
|
27
|
-
|
|
26
|
+
required: false,
|
|
27
|
+
default: null,
|
|
28
|
+
description: 'File config database (.env). Fallback ke `.restforge/defaults.json` bila tidak disediakan eksplisit (set via `config set-default`)'
|
|
28
29
|
},
|
|
29
30
|
schema: {
|
|
30
31
|
type: 'string',
|