@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.
Files changed (340) hide show
  1. package/SECURITY.md +83 -4
  2. package/bin/sdf-tools.exe +0 -0
  3. package/build-info.json +2 -2
  4. package/cli/consumer-deploy.js +1 -1
  5. package/cli/consumer.js +1 -1
  6. package/generators/cli/dashboard/create.js +4 -1
  7. package/generators/cli/endpoint/create.js +43 -4
  8. package/generators/cli/key/generate.js +2 -1
  9. package/generators/cli/key/revoke.js +2 -1
  10. package/generators/cli/payload/diff.js +3 -2
  11. package/generators/cli/payload/generate.js +3 -2
  12. package/generators/cli/payload/sync.js +3 -2
  13. package/generators/cli/payload/validate.js +3 -2
  14. package/generators/cli/processor/create.js +14 -3
  15. package/generators/cli/project/delete.js +2 -1
  16. package/generators/cli/query/validate.js +3 -2
  17. package/generators/cli/schema/apply.js +526 -0
  18. package/generators/cli/schema/describe.js +3 -2
  19. package/generators/cli/schema/diff.js +322 -0
  20. package/generators/cli/schema/generate-ddl.js +7 -10
  21. package/generators/cli/schema/init.js +95 -172
  22. package/generators/cli/schema/introspect.js +3 -2
  23. package/generators/cli/schema/list.js +3 -2
  24. package/generators/cli/schema/migrate.js +13 -18
  25. package/generators/cli/schema/models.js +8 -12
  26. package/generators/cli/schema/template.js +222 -0
  27. package/generators/cli/schema/validate.js +8 -12
  28. package/generators/cli-entry.js +17 -2
  29. package/generators/lib/dbschema-kit/apply-engine.js +582 -0
  30. package/generators/lib/dbschema-kit/diff-engine.js +703 -0
  31. package/generators/lib/dbschema-kit/diff-reporter.js +272 -0
  32. package/generators/lib/dbschema-kit/emitters/alter-table.js +275 -0
  33. package/generators/lib/migration/audit-table-runner.js +213 -215
  34. package/generators/lib/payload/endpoint-schema-validator.js +171 -0
  35. package/generators/lib/payload/payload-runner.js +137 -220
  36. package/generators/lib/payload/schema-diff.js +277 -0
  37. package/generators/lib/templates/dashboard-catalog.js +1 -437
  38. package/generators/lib/templates/db-connection-env.js +1 -212
  39. package/generators/lib/templates/dbschema-catalog.js +1 -489
  40. package/generators/lib/templates/field-validation-catalog.js +1 -531
  41. package/generators/lib/templates/mysql-template.js +1 -3863
  42. package/generators/lib/templates/oracle-template.js +1 -3915
  43. package/generators/lib/templates/postgres-template.js +1 -5838
  44. package/generators/lib/templates/query-declarative-catalog.js +1 -199
  45. package/generators/lib/templates/sqlite-template.js +1 -3440
  46. package/generators/lib/utils/audit-columns.js +181 -0
  47. package/generators/lib/utils/cli-output.js +17 -0
  48. package/generators/lib/utils/database-introspector.js +16 -13
  49. package/generators/lib/utils/env-manager.js +6 -0
  50. package/generators/lib/utils/path-validator.js +71 -0
  51. package/generators/lib/validators/payload-validator.js +1 -2
  52. package/integrity-manifest.json +28 -10
  53. package/package.json +11 -3
  54. package/scripts/verify-integrity.js +1 -1
  55. package/server.js +1 -1
  56. package/src/components/handlers/adjust_handler.js +1 -1
  57. package/src/components/handlers/audit_handler.js +1 -1
  58. package/src/components/handlers/delete_handler.js +1 -1
  59. package/src/components/handlers/export_handler.js +1 -1
  60. package/src/components/handlers/import_handler.js +1 -1
  61. package/src/components/handlers/insert_handler.js +1 -1
  62. package/src/components/handlers/update_handler.js +1 -1
  63. package/src/components/handlers/upload_handler.js +1 -1
  64. package/src/components/handlers/workflow_handler.js +1 -1
  65. package/src/components/integrations/webhook.js +1 -1
  66. package/src/consumers/baseConsumer.js +1 -1
  67. package/src/consumers/declarativeMapper.js +1 -1
  68. package/src/consumers/handlers/apiHandler.js +1 -1
  69. package/src/consumers/handlers/consoleHandler.js +1 -1
  70. package/src/consumers/handlers/databaseHandler.js +1 -1
  71. package/src/consumers/handlers/index.js +1 -1
  72. package/src/consumers/handlers/kafkaHandler.js +1 -1
  73. package/src/consumers/index.js +1 -1
  74. package/src/consumers/messageTransformer.js +1 -1
  75. package/src/consumers/validator.js +1 -1
  76. package/src/core/db/dialect/base-dialect.js +1 -1
  77. package/src/core/db/dialect/index.js +1 -1
  78. package/src/core/db/dialect/mysql-dialect.js +1 -1
  79. package/src/core/db/dialect/oracle-dialect.js +1 -1
  80. package/src/core/db/dialect/postgres-dialect.js +1 -1
  81. package/src/core/db/dialect/sqlite-dialect.js +1 -1
  82. package/src/core/db/flatten-helper.js +1 -1
  83. package/src/core/db/query-builder-error.js +1 -1
  84. package/src/core/db/query-builder.js +1 -1
  85. package/src/core/db/relation-helper.js +1 -1
  86. package/src/core/handlers/delete_handler.js +1 -1
  87. package/src/core/handlers/insert_handler.js +1 -1
  88. package/src/core/handlers/update_handler.js +1 -1
  89. package/src/core/models/base-model.js +1 -1
  90. package/src/core/utils/cache-manager.js +1 -1
  91. package/src/core/utils/component-engine.js +1 -1
  92. package/src/core/utils/context-builder.js +1 -1
  93. package/src/core/utils/datetime-formatter.js +1 -1
  94. package/src/core/utils/datetime-parser.js +1 -1
  95. package/src/core/utils/db.js +1 -1
  96. package/src/core/utils/logger.js +1 -1
  97. package/src/core/utils/payload-loader.js +1 -1
  98. package/src/core/utils/security-checks.js +1 -1
  99. package/src/middleware/body-options.js +1 -1
  100. package/src/middleware/cors.js +1 -1
  101. package/src/middleware/idempotency.js +1 -1
  102. package/src/middleware/rate-limiter.js +1 -1
  103. package/src/middleware/request-logger.js +1 -1
  104. package/src/middleware/security-headers.js +1 -1
  105. package/src/models/base-model-mysql.js +1 -1
  106. package/src/models/base-model-oracle.js +1 -1
  107. package/src/models/base-model-sqlite.js +1 -1
  108. package/src/models/base-model.js +1 -1
  109. package/src/pro/caching/redis-client.js +1 -1
  110. package/src/pro/caching/redis-helper.js +1 -1
  111. package/src/pro/consumers/baseConsumer.js +1 -1
  112. package/src/pro/consumers/declarativeMapper.js +1 -1
  113. package/src/pro/consumers/handlers/apiHandler.js +1 -1
  114. package/src/pro/consumers/handlers/consoleHandler.js +1 -1
  115. package/src/pro/consumers/handlers/databaseHandler.js +1 -1
  116. package/src/pro/consumers/handlers/index.js +1 -1
  117. package/src/pro/consumers/handlers/kafkaHandler.js +1 -1
  118. package/src/pro/consumers/index.js +1 -1
  119. package/src/pro/consumers/messageTransformer.js +1 -1
  120. package/src/pro/consumers/validator.js +1 -1
  121. package/src/pro/database/base-model-mysql.js +1 -1
  122. package/src/pro/database/base-model-oracle.js +1 -1
  123. package/src/pro/database/base-model-sqlite.js +1 -1
  124. package/src/pro/database/db-mysql.js +1 -1
  125. package/src/pro/database/db-oracle.js +1 -1
  126. package/src/pro/database/db-sqlite.js +1 -1
  127. package/src/pro/excel/excel-generator.js +1 -1
  128. package/src/pro/excel/excel-parser.js +1 -1
  129. package/src/pro/excel/export-service.js +1 -1
  130. package/src/pro/excel/export_handler.js +1 -1
  131. package/src/pro/excel/import-service.js +1 -1
  132. package/src/pro/excel/import-validator.js +1 -1
  133. package/src/pro/excel/import_handler.js +1 -1
  134. package/src/pro/excel/upsert-builder.js +1 -1
  135. package/src/pro/idgen/idgen-routes.js +1 -1
  136. package/src/pro/integrations/lookup-resolver.js +1 -1
  137. package/src/pro/integrations/upload-handler-v2.js +1 -1
  138. package/src/pro/integrations/upload-handler.js +1 -1
  139. package/src/pro/integrations/webhook.js +1 -1
  140. package/src/pro/locking/lock-routes.js +1 -1
  141. package/src/pro/locking/resource-lock-manager.js +1 -1
  142. package/src/pro/messaging/kafkaConsumerService.js +1 -1
  143. package/src/pro/messaging/kafkaService.js +1 -1
  144. package/src/pro/messaging/messagehubService.js +1 -1
  145. package/src/pro/messaging/rabbitmqService.js +1 -1
  146. package/src/pro/scheduler/job-manager.js +1 -1
  147. package/src/pro/scheduler/job-routes.js +1 -1
  148. package/src/pro/scheduler/job-validator.js +1 -1
  149. package/src/pro/storage/base-storage-provider.js +1 -1
  150. package/src/pro/storage/file-metadata-helper.js +1 -1
  151. package/src/pro/storage/index.js +1 -1
  152. package/src/pro/storage/local-storage-provider.js +1 -1
  153. package/src/pro/storage/s3-storage-provider.js +1 -1
  154. package/src/pro/storage/upload-cleanup-job.js +1 -1
  155. package/src/pro/storage/upload-cleanup-scheduler.js +1 -1
  156. package/src/pro/storage/upload-pending-tracker.js +1 -1
  157. package/src/pro/websocket/broadcast-helper.js +1 -1
  158. package/src/pro/websocket/index.js +1 -1
  159. package/src/pro/websocket/livesync-server.js +1 -1
  160. package/src/pro/websocket/ws-broadcaster.js +1 -1
  161. package/src/services/export-service.js +1 -1
  162. package/src/services/import-service.js +1 -1
  163. package/src/services/kafkaConsumerService.js +1 -1
  164. package/src/services/kafkaService.js +1 -1
  165. package/src/services/messagehubService.js +1 -1
  166. package/src/services/rabbitmqService.js +1 -1
  167. package/src/utils/cache-invalidation-registry.js +1 -1
  168. package/src/utils/cache-manager.js +1 -1
  169. package/src/utils/component-engine.js +1 -1
  170. package/src/utils/config-extractor.js +1 -1
  171. package/src/utils/consumerLogger.js +1 -1
  172. package/src/utils/context-builder.js +1 -1
  173. package/src/utils/dashboard-helpers.js +1 -1
  174. package/src/utils/dateHelper.js +1 -1
  175. package/src/utils/datetime-formatter.js +1 -1
  176. package/src/utils/datetime-parser.js +1 -1
  177. package/src/utils/db-bootstrap.js +1 -1
  178. package/src/utils/db-mysql.js +1 -1
  179. package/src/utils/db-oracle.js +1 -1
  180. package/src/utils/db-sqlite.js +1 -1
  181. package/src/utils/db.js +1 -1
  182. package/src/utils/demo-generator.js +1 -1
  183. package/src/utils/excel-generator.js +1 -1
  184. package/src/utils/excel-parser.js +1 -1
  185. package/src/utils/file-watcher.js +1 -1
  186. package/src/utils/id-generator.js +1 -1
  187. package/src/utils/idempotency-manager.js +1 -1
  188. package/src/utils/import-validator.js +1 -1
  189. package/src/utils/license-client.js +1 -1
  190. package/src/utils/lock-manager.js +1 -1
  191. package/src/utils/logger.js +1 -1
  192. package/src/utils/lookup-resolver.js +1 -1
  193. package/src/utils/payload-loader.js +1 -1
  194. package/src/utils/processor-response.js +1 -1
  195. package/src/utils/rabbitmq.js +1 -1
  196. package/src/utils/redis-client.js +1 -1
  197. package/src/utils/redis-helper.js +1 -1
  198. package/src/utils/request-scope.js +1 -1
  199. package/src/utils/security-checks.js +1 -1
  200. package/src/utils/service-resolver.js +1 -1
  201. package/src/utils/shutdown-coordinator.js +1 -1
  202. package/src/utils/trusted-keys.js +1 -1
  203. package/src/utils/upload-handler.js +1 -1
  204. package/src/utils/upsert-builder.js +1 -1
  205. package/src/utils/workflow-hook-executor.js +1 -1
  206. package/generators/metadata/global.json +0 -58
  207. package/generators/metadata/test-mysql-workbench.json +0 -118
  208. package/generators/metadata/test-mysql.json +0 -56
  209. package/generators/metadata/test-oracle-workbench.json +0 -118
  210. package/generators/metadata/test-oracle.json +0 -56
  211. package/generators/metadata/test-pg-workbench.json +0 -118
  212. package/generators/metadata/test-pg.json +0 -56
  213. package/generators/scripts/obfuscate-source.js +0 -356
  214. package/generators/scripts/validate-catalog.js +0 -430
  215. package/generators/scripts/validate-dbschema-catalog.js +0 -708
  216. package/generators/tests/baseline/mysql/mini_inventory_item/src/models/mini-inventory/item.js +0 -944
  217. package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
  218. package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory.js +0 -336
  219. package/generators/tests/baseline/oracle/mini_inventory_item/src/models/mini-inventory/item.js +0 -1002
  220. package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
  221. package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory.js +0 -336
  222. package/generators/tests/baseline/postgres/mini_inventory_item/src/models/mini-inventory/item.js +0 -1333
  223. package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory/item.js +0 -1173
  224. package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory.js +0 -496
  225. package/generators/tests/fixtures/payloads/custom-sensitive.json +0 -27
  226. package/generators/tests/fixtures/payloads/dynamic-search-optout.json +0 -23
  227. package/generators/tests/fixtures/payloads/login-with-password.json +0 -22
  228. package/generators/tests/fixtures/payloads/order-process.json +0 -52
  229. package/generators/tests/fixtures/payloads/with-inline-sql.json +0 -26
  230. package/generators/tests/integration-tahap4b/README.md +0 -145
  231. package/generators/tests/integration-tahap4b/run-concurrent.js +0 -77
  232. package/generators/tests/integration-tahap4b/seed.sql +0 -53
  233. package/generators/tests/integration-tahap4b/verify.sql +0 -110
  234. package/generators/tests/unit/cli/create-dashboard.test.js +0 -505
  235. package/generators/tests/unit/cli/create-processor.test.js +0 -319
  236. package/generators/tests/unit/cli/dispatch-dashboard.test.js +0 -149
  237. package/generators/tests/unit/lib/dashboard-generator.test.js +0 -895
  238. package/generators/tests/unit/lib/dashboard-validator.test.js +0 -354
  239. package/generators/tests/unit/lib/dbschema-kit/apply-executor.test.js +0 -437
  240. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-introspect.test.js +0 -393
  241. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-generate-ddl.test.js +0 -104
  242. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-init.test.js +0 -119
  243. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-list.test.js +0 -48
  244. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-migrate.test.js +0 -175
  245. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-validate.test.js +0 -102
  246. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-models.test.js +0 -43
  247. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/all-schemas-listing.js +0 -84
  248. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/connection-error.js +0 -13
  249. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/empty.js +0 -12
  250. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/multi-schema.js +0 -124
  251. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/single-schema-inventory.js +0 -64
  252. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/two-tables.js +0 -66
  253. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/connection-error.js +0 -9
  254. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/partial.js +0 -29
  255. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/rollback.js +0 -26
  256. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/success.js +0 -43
  257. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/audit/events.js +0 -18
  258. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/inventory/products.js +0 -9
  259. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/users.js +0 -8
  260. package/generators/tests/unit/lib/dbschema-kit/connection.test.js +0 -112
  261. package/generators/tests/unit/lib/dbschema-kit/ddl-generator.test.js +0 -205
  262. package/generators/tests/unit/lib/dbschema-kit/define-model.test.js +0 -56
  263. package/generators/tests/unit/lib/dbschema-kit/dialect/index.test.js +0 -46
  264. package/generators/tests/unit/lib/dbschema-kit/dialect/mysql.test.js +0 -126
  265. package/generators/tests/unit/lib/dbschema-kit/dialect/oracle.test.js +0 -126
  266. package/generators/tests/unit/lib/dbschema-kit/dialect/postgres.test.js +0 -131
  267. package/generators/tests/unit/lib/dbschema-kit/dialect/sqlite.test.js +0 -126
  268. package/generators/tests/unit/lib/dbschema-kit/driver-loader.test.js +0 -93
  269. package/generators/tests/unit/lib/dbschema-kit/emitters/create-index.test.js +0 -173
  270. package/generators/tests/unit/lib/dbschema-kit/emitters/create-table.test.js +0 -376
  271. package/generators/tests/unit/lib/dbschema-kit/emitters/drop-table.test.js +0 -78
  272. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/invalid-dialect.env +0 -6
  273. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-dialect.env +0 -5
  274. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-host.env +0 -5
  275. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/oracle-valid.env +0 -6
  276. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/postgres-valid.env +0 -7
  277. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/sqlite-valid.env +0 -2
  278. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/category.js +0 -11
  279. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/item_product.js +0 -11
  280. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound.js +0 -24
  281. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound_item.js +0 -28
  282. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/supplier.js +0 -9
  283. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/warehouse.js +0 -9
  284. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-invalid/orphan.js +0 -17
  285. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/category.js +0 -11
  286. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/item_product.js +0 -11
  287. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/supplier.js +0 -9
  288. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/warehouse.js +0 -9
  289. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound.js +0 -24
  290. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound_item.js +0 -28
  291. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/audit/events.js +0 -18
  292. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/inventory/products.js +0 -9
  293. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/public/users.js +0 -9
  294. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/extra/category.js +0 -8
  295. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/master/category.js +0 -8
  296. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/bar.js +0 -8
  297. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/foo.js +0 -8
  298. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/empty-folder/README.md +0 -1
  299. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-export/plain.js +0 -3
  300. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-schema/bad.js +0 -6
  301. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/legacy-pattern/legacy.js +0 -12
  302. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/audit/products.js +0 -9
  303. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/inventory/products.js +0 -9
  304. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/a/products.js +0 -8
  305. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/b/products.js +0 -8
  306. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/nested-deep/a/b/c/deep_table.js +0 -8
  307. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/.hidden/ignored.js +0 -7
  308. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/category.js +0 -8
  309. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/supplier.js +0 -8
  310. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound.js +0 -8
  311. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound_item.js +0 -8
  312. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/category.js +0 -8
  313. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/item_product.js +0 -9
  314. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-single/category.js +0 -8
  315. package/generators/tests/unit/lib/dbschema-kit/integration.test.js +0 -217
  316. package/generators/tests/unit/lib/dbschema-kit/introspect-mapper.test.js +0 -403
  317. package/generators/tests/unit/lib/dbschema-kit/ir-builder.test.js +0 -390
  318. package/generators/tests/unit/lib/dbschema-kit/loader.test.js +0 -128
  319. package/generators/tests/unit/lib/dbschema-kit/naming.test.js +0 -170
  320. package/generators/tests/unit/lib/dbschema-kit/parser/shorthand-parser.test.js +0 -237
  321. package/generators/tests/unit/lib/dbschema-kit/schema-printer.test.js +0 -251
  322. package/generators/tests/unit/lib/dbschema-kit/statement-modifier.test.js +0 -105
  323. package/generators/tests/unit/lib/dbschema-kit/statement-splitter.test.js +0 -165
  324. package/generators/tests/unit/lib/dbschema-kit/topological-sort.test.js +0 -135
  325. package/generators/tests/unit/lib/dbschema-kit/validator/check-compatibility-validator.test.js +0 -373
  326. package/generators/tests/unit/lib/dbschema-kit/validator/circular-relation-validator.test.js +0 -454
  327. package/generators/tests/unit/lib/dbschema-kit/validator/cross-model-validator.test.js +0 -512
  328. package/generators/tests/unit/lib/dbschema-kit/validator/enhanced-validate-integration.test.js +0 -390
  329. package/generators/tests/unit/lib/dbschema-kit/validator/naming-convention-validator.test.js +0 -306
  330. package/generators/tests/unit/lib/dbschema-kit/validator/schema-validator.test.js +0 -443
  331. package/generators/tests/unit/lib/dbschema-kit/validator/type-compatibility-validator.test.js +0 -440
  332. package/generators/tests/unit/lib/dbschema-kit/validator/validator-reporter.test.js +0 -172
  333. package/generators/tests/unit/lib/metadata-manager-dashboard.test.js +0 -256
  334. package/generators/tests/unit/lib/payload-validator-fieldpolicy.test.js +0 -240
  335. package/generators/tests/unit/lib/processor-validation-generator.test.js +0 -300
  336. package/generators/tests/unit/lib/sensitive-field-masker.test.js +0 -170
  337. package/generators/tests/unit/lib/sql-table-extractor.test.js +0 -119
  338. package/scripts/generate-integrity-manifest.js +0 -124
  339. package/scripts/snapshot-cli-contracts.js +0 -194
  340. package/scripts/verify-publish.js +0 -56
@@ -0,0 +1,526 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Contract: schema apply
5
+ *
6
+ * Apply drift dari SDF ke database via ALTER TABLE incremental.
7
+ * Komplemen schema diff (detect only) dan schema migrate (full create/drop).
8
+ *
9
+ * Default: additive only (ADD COLUMN/INDEX/UNIQUE). Drift onlyInDb atau
10
+ * mismatched di-skip dengan warning kecuali opt-in flag aktif.
11
+ *
12
+ * Exit code:
13
+ * 0 - semua drift applicable ter-apply (atau no drift)
14
+ * 1 - ada drift yang di-skip karena butuh opt-in (--allow-drop / --allow-modify)
15
+ * 2 - error
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const os = require('os');
20
+ const path = require('path');
21
+
22
+ const { loadSchemaPath } = require('../../lib/dbschema-kit/loader');
23
+ const { mapTableMetaToIR } = require('../../lib/dbschema-kit/introspect-mapper');
24
+ const { loadConfig } = require('../../lib/dbschema-kit/connection');
25
+ const { diffModels } = require('../../lib/dbschema-kit/diff-engine');
26
+ const { generateAlterStatements } = require('../../lib/dbschema-kit/apply-engine');
27
+ const { resolveConfig, printDefaultConfigWarning } = require('../../lib/utils/config-resolver');
28
+
29
+ function loadIntrospector() {
30
+ const stubPath = process.env.DBSCHEMA_KIT_TEST_INTROSPECT_STUB;
31
+ if (stubPath) {
32
+ return require(path.resolve(stubPath));
33
+ }
34
+ return defaultIntrospector;
35
+ }
36
+
37
+ function loadApplyExecutor() {
38
+ const stubPath = process.env.DBSCHEMA_KIT_TEST_APPLY_STUB;
39
+ if (stubPath) {
40
+ return require(path.resolve(stubPath));
41
+ }
42
+ return require('../../lib/dbschema-kit/apply-executor');
43
+ }
44
+
45
+ function mapDialectToDbType(dialect) {
46
+ switch (dialect) {
47
+ case 'postgres': return 'postgresql';
48
+ case 'mysql': return 'mysql';
49
+ case 'oracle': return 'oracle';
50
+ case 'sqlite': return 'sqlite';
51
+ default: return dialect;
52
+ }
53
+ }
54
+
55
+ function buildEphemeralEnvFile(config, dbType) {
56
+ const lines = [`DB_TYPE=${dbType}`];
57
+ if (config.host !== undefined) lines.push(`DB_HOST=${config.host}`);
58
+ if (config.port !== undefined) lines.push(`DB_PORT=${config.port}`);
59
+ if (dbType === 'oracle') {
60
+ lines.push(`DB_NAME=${config.serviceName || ''}`);
61
+ } else if (config.database !== undefined) {
62
+ lines.push(`DB_NAME=${config.database}`);
63
+ }
64
+ if (config.user !== undefined) lines.push(`DB_USER=${config.user}`);
65
+ if (config.password !== undefined) lines.push(`DB_PASSWORD=${config.password}`);
66
+ return lines.join('\n') + '\n';
67
+ }
68
+
69
+ function createTmpEnvFile(content) {
70
+ const tmpDir = os.tmpdir();
71
+ const tmpName = `restforge-apply-${process.pid}-${Date.now()}.env`;
72
+ const fullPath = path.join(tmpDir, tmpName);
73
+ fs.writeFileSync(fullPath, content, 'utf8');
74
+ return fullPath;
75
+ }
76
+
77
+ async function collectTableMeta(introspector, target) {
78
+ const ref = target.schemaName ? `${target.schemaName}.${target.tableName}` : target.tableName;
79
+ const detailedColumns = await introspector.getDetailedColumnInfo(ref);
80
+ const constraints = await introspector.getConstraints(ref);
81
+ const foreignKeys = await introspector.getForeignKeys(ref);
82
+ const indexes = await introspector.getIndexes(ref);
83
+
84
+ const pkConstraint = constraints.find((c) => c.type === 'PRIMARY KEY');
85
+ const uniqueConstraints = constraints
86
+ .filter((c) => c.type === 'UNIQUE')
87
+ .map((c) => ({ name: c.name, columns: c.columns }));
88
+
89
+ return {
90
+ tableName: target.tableName,
91
+ schemaName: target.schemaName || null,
92
+ columns: detailedColumns,
93
+ primaryKey: pkConstraint ? pkConstraint.columns : [],
94
+ uniques: uniqueConstraints,
95
+ foreignKeys,
96
+ indexes,
97
+ checks: []
98
+ };
99
+ }
100
+
101
+ const defaultIntrospector = {
102
+ introspect: async ({ config, tables }) => {
103
+ const dbType = mapDialectToDbType(config.dialect);
104
+ if (dbType === 'sqlite') {
105
+ throw new Error('schema:apply does not yet support sqlite. Use postgres, mysql, or oracle.');
106
+ }
107
+
108
+ const { DatabaseIntrospector } = require('../../lib/utils/database-introspector');
109
+ const introspector = new DatabaseIntrospector({ quiet: true });
110
+
111
+ const ephemeralEnv = buildEphemeralEnvFile(config, dbType);
112
+ const tmpPath = createTmpEnvFile(ephemeralEnv);
113
+
114
+ try {
115
+ const ok = introspector.loadConfig(tmpPath);
116
+ if (!ok) throw new Error('Failed to load config into DatabaseIntrospector');
117
+ const connected = await introspector.connect();
118
+ if (!connected) throw new Error('Failed to connect to database');
119
+
120
+ const out = [];
121
+ for (const target of tables) {
122
+ try {
123
+ out.push(await collectTableMeta(introspector, target));
124
+ } catch (err) {
125
+ out.push({
126
+ tableName: target.tableName,
127
+ schemaName: target.schemaName || null,
128
+ columns: [],
129
+ primaryKey: [],
130
+ uniques: [],
131
+ foreignKeys: [],
132
+ indexes: [],
133
+ checks: [],
134
+ _missing: true,
135
+ _error: err && err.message ? err.message : String(err)
136
+ });
137
+ }
138
+ }
139
+ return { tables: out };
140
+ } finally {
141
+ try { await introspector.disconnect(); } catch (e) { /* ignore */ }
142
+ try { fs.unlinkSync(tmpPath); } catch (e) { /* ignore */ }
143
+ }
144
+ }
145
+ };
146
+
147
+ function buildConnectionSummary(config) {
148
+ if (config.dialect === 'sqlite') {
149
+ return `sqlite @ ${config.file}`;
150
+ }
151
+ if (config.dialect === 'oracle') {
152
+ return `oracle @ ${config.host}:${config.port}/${config.serviceName}`;
153
+ }
154
+ return `${config.dialect} @ ${config.host}:${config.port}/${config.database}`;
155
+ }
156
+
157
+ function formatStatementForDisplay(stmt, dialect) {
158
+ if (dialect === 'oracle' && /^\s*BEGIN\b/i.test(stmt)) {
159
+ return stmt + '\n/';
160
+ }
161
+ return stmt + ';';
162
+ }
163
+
164
+ function printDryRun(result, dialect, outStream) {
165
+ const out = outStream || process.stdout;
166
+ out.write('-- DDL Preview (schema apply, dry-run) --\n');
167
+ out.write('\n');
168
+
169
+ const tables = Object.keys(result.statementsByTable);
170
+ for (const table of tables) {
171
+ out.write(`[${table}]\n`);
172
+ for (const stmt of result.statementsByTable[table]) {
173
+ out.write(formatStatementForDisplay(stmt, dialect));
174
+ out.write('\n');
175
+ }
176
+ out.write('\n');
177
+ }
178
+
179
+ if (tables.length === 0) {
180
+ out.write('No applicable ALTER statements.\n');
181
+ out.write('\n');
182
+ }
183
+
184
+ if (result.skipped.length > 0) {
185
+ out.write('Warnings:\n');
186
+ for (const sk of result.skipped) {
187
+ out.write(` ${sk.description} (${sk.reason})\n`);
188
+ }
189
+ out.write('\n');
190
+ }
191
+
192
+ out.write('Summary:\n');
193
+ out.write(` Tables affected: ${result.summary.tablesAffected}\n`);
194
+ out.write(` Additions: ${result.summary.totalAdditions}\n`);
195
+ out.write(` Modifications: ${result.summary.totalModifications}\n`);
196
+ out.write(` Deletions: ${result.summary.totalDeletions}\n`);
197
+ out.write(` Skipped (opt-in): ${result.summary.totalSkipped}\n`);
198
+ out.write('\n');
199
+ out.write('Dry-run complete. No changes applied.\n');
200
+ }
201
+
202
+ function buildExitCode(result) {
203
+ const hasOptInSkip = result.skipped.some((s) =>
204
+ s.reason === 'requires --allow-drop' || s.reason === 'requires --allow-modify'
205
+ );
206
+ return hasOptInSkip ? 1 : 0;
207
+ }
208
+
209
+ module.exports = {
210
+ resource: 'schema',
211
+ verb: 'apply',
212
+ description: 'Apply drift dari SDF ke database via ALTER TABLE incremental (komplemen schema diff)',
213
+ category: 'management',
214
+ flags: {
215
+ path: {
216
+ type: 'string',
217
+ required: true,
218
+ description: 'Path file atau folder schema (mis. ./schema atau ./schema/users.js)'
219
+ },
220
+ config: {
221
+ type: 'string',
222
+ required: false,
223
+ default: null,
224
+ description: 'File config database (.env). Fallback ke `.restforge/defaults.json` bila tidak disediakan eksplisit (set via `config set-default`)'
225
+ },
226
+ table: {
227
+ type: 'string',
228
+ required: false,
229
+ default: null,
230
+ description: 'Apply hanya satu tabel spesifik (default: semua model di SDF)'
231
+ },
232
+ 'dry-run': {
233
+ type: 'boolean',
234
+ required: false,
235
+ default: false,
236
+ description: 'Preview ALTER tanpa apply ke database'
237
+ },
238
+ 'allow-drop': {
239
+ type: 'boolean',
240
+ required: false,
241
+ default: false,
242
+ description: 'Opt-in: izinkan DROP COLUMN/INDEX/UNIQUE constraint (destruktif data)'
243
+ },
244
+ 'allow-modify': {
245
+ type: 'boolean',
246
+ required: false,
247
+ default: false,
248
+ description: 'Opt-in: izinkan ALTER COLUMN length/nullable (potential data loss)'
249
+ }
250
+ },
251
+ examples: [
252
+ 'npx restforge schema apply --path=./schema --config=db.env --dry-run',
253
+ 'npx restforge schema apply --path=./schema --config=db.env',
254
+ 'npx restforge schema apply --path=./schema --config=db.env --allow-drop',
255
+ 'npx restforge schema apply --path=./schema/visitors.js --config=db.env --table=visitors --dry-run'
256
+ ],
257
+ async handler(args) {
258
+ // 1. Resolve config
259
+ const resolvedConfigResult = resolveConfig(args.config, process.cwd());
260
+ if (!resolvedConfigResult) {
261
+ console.error('Error: --config=<file> is required.');
262
+ console.error("Tip: set a default with 'npx restforge config set-default --config=<file>' to omit --config in future runs");
263
+ const err = new Error('--config=<file> is required');
264
+ err.exitCode = 2;
265
+ throw err;
266
+ }
267
+ if (resolvedConfigResult.source === 'default') {
268
+ printDefaultConfigWarning(resolvedConfigResult.defaultName);
269
+ }
270
+
271
+ let config;
272
+ try {
273
+ config = loadConfig(resolvedConfigResult.path);
274
+ } catch (err) {
275
+ console.error(`Error: ${err.message}`);
276
+ const e = new Error(err.message);
277
+ e.exitCode = 2;
278
+ throw e;
279
+ }
280
+
281
+ // 2. Load SDF
282
+ const schemaPath = args.path;
283
+ const absPath = path.resolve(process.cwd(), schemaPath);
284
+
285
+ let sdfModels;
286
+ try {
287
+ sdfModels = loadSchemaPath(absPath);
288
+ } catch (err) {
289
+ console.error(`Error: ${err.message}`);
290
+ const e = new Error(err.message);
291
+ e.exitCode = 2;
292
+ throw e;
293
+ }
294
+
295
+ if (sdfModels.size === 0) {
296
+ console.error(`Error: No schema models found at '${schemaPath}'.`);
297
+ const e = new Error(`No schema models found at '${schemaPath}'`);
298
+ e.exitCode = 2;
299
+ throw e;
300
+ }
301
+
302
+ // 3. Filter target tables
303
+ let targetEntries = Array.from(sdfModels.entries());
304
+ if (args.table) {
305
+ targetEntries = targetEntries.filter(([qualified, ir]) => {
306
+ return ir.tableName === args.table || qualified === args.table;
307
+ });
308
+ if (targetEntries.length === 0) {
309
+ console.error(`Error: Table '${args.table}' not found in SDF.`);
310
+ const e = new Error(`Table '${args.table}' not found in SDF`);
311
+ e.exitCode = 2;
312
+ throw e;
313
+ }
314
+ }
315
+
316
+ const targetsForDb = targetEntries.map(([_, ir]) => ({
317
+ tableName: ir.tableName,
318
+ schemaName: ir.schemaName || null
319
+ }));
320
+
321
+ // 4. Introspect database
322
+ let introspector;
323
+ try {
324
+ introspector = loadIntrospector();
325
+ } catch (err) {
326
+ console.error(`Error: Failed to load introspector: ${err.message}`);
327
+ const e = new Error(err.message);
328
+ e.exitCode = 2;
329
+ throw e;
330
+ }
331
+
332
+ let introspectResult;
333
+ try {
334
+ introspectResult = await introspector.introspect({ config, tables: targetsForDb });
335
+ } catch (err) {
336
+ const message = err && err.message ? err.message : String(err);
337
+ console.error(`Error: ${message}`);
338
+ const e = new Error(message);
339
+ e.exitCode = 2;
340
+ throw e;
341
+ }
342
+
343
+ if (!introspectResult || !Array.isArray(introspectResult.tables)) {
344
+ console.error('Error: Introspector did not return a tables array.');
345
+ const e = new Error('Introspector did not return a tables array');
346
+ e.exitCode = 2;
347
+ throw e;
348
+ }
349
+
350
+ // 5. Map DB meta to IR
351
+ const dialect = config.dialect;
352
+ const dbModels = new Map();
353
+ for (const tableMeta of introspectResult.tables) {
354
+ if (tableMeta._missing) {
355
+ const qualified = tableMeta.schemaName
356
+ ? `${tableMeta.schemaName}.${tableMeta.tableName}`
357
+ : tableMeta.tableName;
358
+ dbModels.set(qualified, {
359
+ tableName: tableMeta.tableName,
360
+ schemaName: tableMeta.schemaName || null,
361
+ qualifiedName: qualified,
362
+ fields: {},
363
+ primaryKey: [],
364
+ indexes: [],
365
+ uniques: [],
366
+ relations: {},
367
+ checks: []
368
+ });
369
+ continue;
370
+ }
371
+ const ir = mapTableMetaToIR(tableMeta, dialect);
372
+ dbModels.set(ir.qualifiedName || ir.tableName, ir);
373
+ }
374
+
375
+ // 6. Build SDF map matching key convention
376
+ const sdfMap = new Map();
377
+ for (const [_, ir] of targetEntries) {
378
+ sdfMap.set(ir.qualifiedName || ir.tableName, ir);
379
+ }
380
+
381
+ // 7. Compute deltas via diff-engine
382
+ const deltas = diffModels(sdfMap, dbModels);
383
+
384
+ // 8. Generate ALTER statements
385
+ let alterResult;
386
+ try {
387
+ alterResult = generateAlterStatements(deltas, {
388
+ dialect,
389
+ allowDrop: args['allow-drop'] === true,
390
+ allowModify: args['allow-modify'] === true,
391
+ sdfModels: sdfMap
392
+ });
393
+ } catch (err) {
394
+ console.error(`Error: ${err.message}`);
395
+ const e = new Error(err.message);
396
+ e.exitCode = 2;
397
+ throw e;
398
+ }
399
+
400
+ // 9. Dry-run path
401
+ if (args['dry-run']) {
402
+ printDryRun(alterResult, dialect);
403
+ const exitCode = buildExitCode(alterResult);
404
+ process.stdout.write(`Exit code: ${exitCode}\n`);
405
+ if (exitCode !== 0) {
406
+ const err = new Error(`schema apply dry-run: ${alterResult.summary.totalSkipped} drift entries require opt-in`);
407
+ err.exitCode = exitCode;
408
+ throw err;
409
+ }
410
+ return;
411
+ }
412
+
413
+ // 10. No-op path
414
+ if (alterResult.statements.length === 0) {
415
+ const exitCode = buildExitCode(alterResult);
416
+ if (alterResult.skipped.length === 0) {
417
+ console.log('No drift to apply.');
418
+ } else {
419
+ console.log('No applicable ALTER statements.');
420
+ console.log('Warnings:');
421
+ for (const sk of alterResult.skipped) {
422
+ console.log(` ${sk.description} (${sk.reason})`);
423
+ }
424
+ }
425
+ if (exitCode !== 0) {
426
+ const err = new Error(`schema apply: ${alterResult.summary.totalSkipped} drift entries require opt-in`);
427
+ err.exitCode = exitCode;
428
+ throw err;
429
+ }
430
+ return;
431
+ }
432
+
433
+ // 11. Apply path
434
+ console.log(`Connecting to database (${buildConnectionSummary(config)})...`);
435
+ console.log(`Applying ${alterResult.statements.length} ALTER statement(s)...`);
436
+ console.log('');
437
+
438
+ const tables = Object.keys(alterResult.statementsByTable);
439
+ const tableHeaderPrinted = new Set();
440
+
441
+ function progressHandler({ index, total, statement, status, error }) {
442
+ if (status === 'running') return;
443
+ const entry = alterResult.statements[index - 1];
444
+ const tableLabel = entry ? entry.table : '?';
445
+ if (!tableHeaderPrinted.has(tableLabel)) {
446
+ console.log(`[${tableLabel}]`);
447
+ tableHeaderPrinted.add(tableLabel);
448
+ }
449
+ if (status === 'success') {
450
+ console.log(` ✓ ${statement};`);
451
+ return;
452
+ }
453
+ if (status === 'error') {
454
+ console.error(` ✗ ${statement};`);
455
+ const message = error && error.message ? error.message : String(error);
456
+ console.error(` Error: ${message}`);
457
+ }
458
+ }
459
+
460
+ let executor;
461
+ try {
462
+ executor = loadApplyExecutor();
463
+ } catch (err) {
464
+ console.error(`Error: Failed to load apply executor: ${err.message}`);
465
+ const e = new Error(err.message);
466
+ e.exitCode = 2;
467
+ throw e;
468
+ }
469
+
470
+ const sqlStatements = alterResult.statements.map((s) => s.sql);
471
+
472
+ let applyResult;
473
+ try {
474
+ applyResult = await executor.applyStatements({
475
+ statements: sqlStatements,
476
+ dialect,
477
+ config,
478
+ onProgress: progressHandler
479
+ });
480
+ } catch (err) {
481
+ if (err && err.status === 'ROLLBACK') {
482
+ console.error('');
483
+ console.error('ROLLBACK applied. Database state unchanged.');
484
+ console.error(` Statements applied before rollback: ${err.applied || 0}`);
485
+ console.error(` Failed statement index: ${err.failedIndex}`);
486
+ const e = new Error(err.message || 'ROLLBACK applied');
487
+ e.exitCode = 2;
488
+ throw e;
489
+ }
490
+ const message = err && err.message ? err.message : String(err);
491
+ console.error(`Error: ${message}`);
492
+ const e = new Error(message);
493
+ e.exitCode = 2;
494
+ throw e;
495
+ }
496
+
497
+ console.log('');
498
+ if (applyResult && applyResult.status === 'SUCCESS') {
499
+ console.log('Summary:');
500
+ console.log(` ${applyResult.applied} statement(s) applied successfully in ${applyResult.durationMs}ms.`);
501
+
502
+ for (const sk of alterResult.skipped) {
503
+ console.log(` ⚠ Skipped: ${sk.target} (${sk.reason})`);
504
+ }
505
+
506
+ const exitCode = buildExitCode(alterResult);
507
+ if (exitCode !== 0) {
508
+ const err = new Error(`schema apply: ${alterResult.summary.totalSkipped} drift entries require opt-in`);
509
+ err.exitCode = exitCode;
510
+ throw err;
511
+ }
512
+ return;
513
+ }
514
+
515
+ if (applyResult && applyResult.status === 'PARTIAL') {
516
+ console.error('Partial apply detected:');
517
+ console.error(` ${applyResult.applied || 0} applied`);
518
+ console.error(` ${applyResult.failed || 1} failed`);
519
+ const err = new Error('Partial apply detected. Manual cleanup may be required.');
520
+ err.exitCode = 2;
521
+ throw err;
522
+ }
523
+
524
+ console.log(`Status: ${applyResult ? applyResult.status : 'UNKNOWN'}`);
525
+ }
526
+ };
@@ -51,8 +51,9 @@ module.exports = {
51
51
  flags: {
52
52
  config: {
53
53
  type: 'string',
54
- required: true,
55
- description: 'File config database (.env)'
54
+ required: false,
55
+ default: null,
56
+ description: 'File config database (.env). Fallback ke `.restforge/defaults.json` bila tidak disediakan eksplisit (set via `config set-default`)'
56
57
  },
57
58
  table: {
58
59
  type: 'string',