@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
@@ -1,708 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * RESTForge - dbschema-kit Catalog Sync Validator
5
- *
6
- * Cross-check catalog metadata vs parser source code and spec doc
7
- * to detect drift between artifacts:
8
- *
9
- * 1. Catalog data : generators/lib/templates/dbschema-catalog.js
10
- * 2. Parser code : generators/lib/dbschema-kit/parser/shorthand-parser.js
11
- * generators/lib/dbschema-kit/ir-builder.js
12
- * generators/lib/dbschema-kit/validator/schema-validator.js
13
- * generators/lib/dbschema-kit/define-model.js
14
- * 3. Spec doc : <repo-root>/docs/schema-reference/schema-definition.md
15
- *
16
- * Levels of validation:
17
- * Level 1: Catalog structure integrity (required keys, field shape)
18
- * Level 2: Parser source cross-reference (Set membership match)
19
- * Level 3: Smoke test (catalog examples execute through actual parser)
20
- * Level 4: Default value type consistency (parsed type matches field type)
21
- * Level 5: Spec doc references (each entity is mentioned in markdown)
22
- *
23
- * Usage (jalankan dari folder packages/platform):
24
- * node generators/scripts/validate-dbschema-catalog.js [--strict] [--quiet]
25
- *
26
- * Exit codes:
27
- * 0 = no issues, or only warnings (default)
28
- * 1 = errors found, or warnings found in --strict mode
29
- *
30
- * @module scripts/validate-dbschema-catalog
31
- */
32
-
33
- const fs = require('fs');
34
- const path = require('path');
35
-
36
- // ============================================================================
37
- // CONFIG
38
- // ============================================================================
39
-
40
- const CATALOG_PATH = path.join(__dirname, '..', 'lib', 'templates', 'dbschema-catalog.js');
41
- const SHORTHAND_PARSER_PATH = path.join(__dirname, '..', 'lib', 'dbschema-kit', 'parser', 'shorthand-parser.js');
42
- const IR_BUILDER_PATH = path.join(__dirname, '..', 'lib', 'dbschema-kit', 'ir-builder.js');
43
- const SCHEMA_VALIDATOR_PATH = path.join(__dirname, '..', 'lib', 'dbschema-kit', 'validator', 'schema-validator.js');
44
- const DEFINE_MODEL_PATH = path.join(__dirname, '..', 'lib', 'dbschema-kit', 'define-model.js');
45
- // Spec doc lives at <repo-root>/docs/schema-reference/schema-definition.md (v3 layout).
46
- // __dirname = packages/platform/generators/scripts → naik 4 level untuk reach repo root.
47
- const SPEC_DOC_PATH = path.join(__dirname, '..', '..', '..', '..', 'docs', 'schema-reference', 'schema-definition.md');
48
-
49
- // Mirrors ir-builder.js AUTO_UPDATE_TOKEN_RE_G (used to pre-strip autoUpdate before parser)
50
- const AUTO_UPDATE_RE = /(?:^|\s)autoUpdate(?=\s|$)/g;
51
-
52
- // ============================================================================
53
- // REPORTING
54
- // ============================================================================
55
-
56
- const report = {
57
- errors: [],
58
- warnings: [],
59
- info: []
60
- };
61
-
62
- function err(msg) { report.errors.push(msg); }
63
- function warn(msg) { report.warnings.push(msg); }
64
- function info(msg) { report.info.push(msg); }
65
-
66
- // ============================================================================
67
- // PARSE ARGUMENTS
68
- // ============================================================================
69
-
70
- function parseArgs() {
71
- const args = process.argv.slice(2);
72
- return {
73
- strict: args.includes('--strict'),
74
- quiet: args.includes('--quiet')
75
- };
76
- }
77
-
78
- // ============================================================================
79
- // HELPER — extract `new Set([...])` contents from source file text
80
- // ============================================================================
81
-
82
- function extractSetContents(source, varName) {
83
- const re = new RegExp(`const\\s+${varName}\\s*=\\s*new Set\\(\\[([^\\]]+)\\]\\)`);
84
- const m = source.match(re);
85
- if (!m) return null;
86
-
87
- const body = m[1];
88
- const items = [];
89
- const itemRe = /['"]([a-zA-Z_][a-zA-Z0-9_]*)['"]/g;
90
- let im;
91
- while ((im = itemRe.exec(body)) !== null) {
92
- items.push(im[1]);
93
- }
94
- return new Set(items);
95
- }
96
-
97
- function readSource(filePath, label) {
98
- if (!fs.existsSync(filePath)) {
99
- err(`${label} not found: ${filePath}`);
100
- return null;
101
- }
102
- return fs.readFileSync(filePath, 'utf8');
103
- }
104
-
105
- // ============================================================================
106
- // LEVEL 1: CATALOG STRUCTURE INTEGRITY
107
- // ============================================================================
108
-
109
- function checkCatalogStructure(catalog) {
110
- const requiredKeys = [
111
- 'schemaVersion', 'source', 'summary',
112
- 'defineModelOptions', 'fieldTypes', 'constraints',
113
- 'relationTypes', 'referentialActions', 'checkOperations',
114
- 'auditColumns', 'shorthandSyntax', 'namingRules', 'dialectSupport'
115
- ];
116
- for (const key of requiredKeys) {
117
- if (!(key in catalog)) err(`Catalog missing required top-level key: '${key}'`);
118
- }
119
-
120
- if (!Array.isArray(catalog.defineModelOptions)) err('catalog.defineModelOptions must be an array');
121
- if (!Array.isArray(catalog.fieldTypes)) err('catalog.fieldTypes must be an array');
122
- if (!Array.isArray(catalog.constraints)) err('catalog.constraints must be an array');
123
- if (!Array.isArray(catalog.relationTypes)) err('catalog.relationTypes must be an array');
124
- if (!Array.isArray(catalog.referentialActions)) err('catalog.referentialActions must be an array');
125
- if (!Array.isArray(catalog.checkOperations)) err('catalog.checkOperations must be an array');
126
- if (!Array.isArray(catalog.dialectSupport)) err('catalog.dialectSupport must be an array');
127
- }
128
-
129
- function checkFieldTypesIntegrity(fieldTypes) {
130
- const requiredFields = ['name', 'description', 'requiresModifier', 'example'];
131
- const seen = new Set();
132
-
133
- for (const t of fieldTypes) {
134
- for (const f of requiredFields) {
135
- if (!(f in t)) err(`Field type '${t.name || '<unknown>'}' missing field: '${f}'`);
136
- }
137
- if (seen.has(t.name)) err(`Duplicate field type name: '${t.name}'`);
138
- seen.add(t.name);
139
-
140
- if (t.requiresModifier === true && !t.modifierFormat) {
141
- err(`Field type '${t.name}': requiresModifier=true but missing modifierFormat`);
142
- }
143
- }
144
- }
145
-
146
- function checkConstraintsIntegrity(constraints) {
147
- const requiredFields = ['name', 'kind', 'description', 'example'];
148
- const validKinds = ['standalone', 'value'];
149
- const seen = new Set();
150
-
151
- for (const c of constraints) {
152
- for (const f of requiredFields) {
153
- if (!(f in c)) err(`Constraint '${c.name || '<unknown>'}' missing field: '${f}'`);
154
- }
155
- if (!validKinds.includes(c.kind)) {
156
- err(`Constraint '${c.name}': invalid kind '${c.kind}' (must be one of: ${validKinds.join(', ')})`);
157
- }
158
- if (seen.has(c.name)) err(`Duplicate constraint name: '${c.name}'`);
159
- seen.add(c.name);
160
-
161
- if (c.kind === 'value' && !c.valueFormat) {
162
- err(`Constraint '${c.name}': kind='value' but missing 'valueFormat'`);
163
- }
164
- }
165
- }
166
-
167
- function checkRelationTypesIntegrity(relationTypes) {
168
- const requiredFields = ['name', 'description', 'requiredFields', 'optionalFields', 'example'];
169
- const seen = new Set();
170
-
171
- for (const r of relationTypes) {
172
- for (const f of requiredFields) {
173
- if (!(f in r)) err(`Relation type '${r.name || '<unknown>'}' missing field: '${f}'`);
174
- }
175
- if (seen.has(r.name)) err(`Duplicate relation type name: '${r.name}'`);
176
- seen.add(r.name);
177
-
178
- if (!Array.isArray(r.requiredFields)) err(`Relation type '${r.name}': requiredFields must be array`);
179
- if (!Array.isArray(r.optionalFields)) err(`Relation type '${r.name}': optionalFields must be array`);
180
- }
181
- }
182
-
183
- function checkReferentialActionsIntegrity(actions) {
184
- const requiredFields = ['name', 'description', 'appliesTo'];
185
- const seen = new Set();
186
-
187
- for (const a of actions) {
188
- for (const f of requiredFields) {
189
- if (!(f in a)) err(`Referential action '${a.name || '<unknown>'}' missing field: '${f}'`);
190
- }
191
- if (seen.has(a.name)) err(`Duplicate referential action name: '${a.name}'`);
192
- seen.add(a.name);
193
-
194
- if (!Array.isArray(a.appliesTo)) err(`Referential action '${a.name}': appliesTo must be array`);
195
- }
196
- }
197
-
198
- function checkCheckOperationsIntegrity(ops) {
199
- const requiredFields = ['name', 'description', 'valueType', 'example'];
200
- const seen = new Set();
201
-
202
- for (const op of ops) {
203
- for (const f of requiredFields) {
204
- if (!(f in op)) err(`Check operation '${op.name || '<unknown>'}' missing field: '${f}'`);
205
- }
206
- if (seen.has(op.name)) err(`Duplicate check operation name: '${op.name}'`);
207
- seen.add(op.name);
208
- }
209
- }
210
-
211
- function checkAuditColumnsIntegrity(auditColumns) {
212
- if (!auditColumns || typeof auditColumns !== 'object') {
213
- err('catalog.auditColumns must be an object');
214
- return;
215
- }
216
- if (!Array.isArray(auditColumns.columns)) {
217
- err('catalog.auditColumns.columns must be an array');
218
- return;
219
- }
220
-
221
- const required = ['name', 'shorthand', 'nullable', 'purpose'];
222
- for (const col of auditColumns.columns) {
223
- for (const f of required) {
224
- if (!(f in col)) err(`Audit column '${col.name || '<unknown>'}' missing field: '${f}'`);
225
- }
226
- }
227
- }
228
-
229
- function checkDialectSupportIntegrity(dialects) {
230
- const requiredFields = ['name', 'driver', 'booleanStorage'];
231
- const seen = new Set();
232
-
233
- for (const d of dialects) {
234
- for (const f of requiredFields) {
235
- if (!(f in d)) err(`Dialect '${d.name || '<unknown>'}' missing field: '${f}'`);
236
- }
237
- if (seen.has(d.name)) err(`Duplicate dialect name: '${d.name}'`);
238
- seen.add(d.name);
239
- }
240
- }
241
-
242
- // ============================================================================
243
- // LEVEL 2: PARSER SOURCE CROSS-REFERENCE (GROUND TRUTH)
244
- // ============================================================================
245
-
246
- function checkFieldTypesVsParser(catalog) {
247
- const source = readSource(SHORTHAND_PARSER_PATH, 'Shorthand parser');
248
- if (!source) return;
249
-
250
- const parserTypes = extractSetContents(source, 'VALID_TYPES');
251
- if (!parserTypes) {
252
- warn('Could not extract VALID_TYPES from shorthand-parser.js (regex pattern may need update)');
253
- return;
254
- }
255
-
256
- const catalogTypes = new Set(catalog.fieldTypes.map(t => t.name));
257
-
258
- for (const t of parserTypes) {
259
- if (!catalogTypes.has(t)) {
260
- err(`Parser drift: type '${t}' exists in VALID_TYPES but missing from catalog.fieldTypes`);
261
- }
262
- }
263
-
264
- for (const t of catalogTypes) {
265
- if (!parserTypes.has(t)) {
266
- err(`Parser drift: type '${t}' in catalog.fieldTypes but missing from parser VALID_TYPES`);
267
- }
268
- }
269
- }
270
-
271
- function checkConstraintsVsParser(catalog) {
272
- const parserSrc = readSource(SHORTHAND_PARSER_PATH, 'Shorthand parser');
273
- if (!parserSrc) return;
274
-
275
- const standaloneFromParser = extractSetContents(parserSrc, 'STANDALONE_CONSTRAINTS') || new Set();
276
- const valueFromParser = extractSetContents(parserSrc, 'VALUE_CONSTRAINTS') || new Set();
277
-
278
- // autoUpdate is pre-processed in ir-builder.js, also a valid constraint at the API surface
279
- let irHasAutoUpdate = false;
280
- const irSrc = readSource(IR_BUILDER_PATH, 'IR builder');
281
- if (irSrc) irHasAutoUpdate = /AUTO_UPDATE_TOKEN_RE/.test(irSrc);
282
-
283
- const parserConstraints = new Set([...standaloneFromParser, ...valueFromParser]);
284
- if (irHasAutoUpdate) parserConstraints.add('autoUpdate');
285
-
286
- const catalogConstraintNames = new Set(catalog.constraints.map(c => c.name));
287
-
288
- for (const c of parserConstraints) {
289
- if (!catalogConstraintNames.has(c)) {
290
- err(`Parser drift: constraint '${c}' valid in parser but missing from catalog.constraints`);
291
- }
292
- }
293
-
294
- for (const c of catalogConstraintNames) {
295
- if (!parserConstraints.has(c)) {
296
- err(`Parser drift: constraint '${c}' in catalog but not recognized by parser or ir-builder`);
297
- }
298
- }
299
-
300
- // Verify kind matches parser STANDALONE_CONSTRAINTS / VALUE_CONSTRAINTS partitioning
301
- for (const c of catalog.constraints) {
302
- if (standaloneFromParser.has(c.name) && c.kind !== 'standalone') {
303
- err(`Constraint '${c.name}': kind='${c.kind}' in catalog but is STANDALONE in parser`);
304
- }
305
- if (valueFromParser.has(c.name) && c.kind !== 'value') {
306
- err(`Constraint '${c.name}': kind='${c.kind}' in catalog but is VALUE in parser`);
307
- }
308
- }
309
- }
310
-
311
- function checkRelationTypesVsValidator(catalog) {
312
- const source = readSource(SCHEMA_VALIDATOR_PATH, 'Schema validator');
313
- if (!source) return;
314
-
315
- const validatorTypes = extractSetContents(source, 'VALID_RELATION_TYPES');
316
- if (!validatorTypes) {
317
- warn('Could not extract VALID_RELATION_TYPES from schema-validator.js');
318
- } else {
319
- const catalogTypes = new Set(catalog.relationTypes.map(r => r.name));
320
-
321
- for (const t of validatorTypes) {
322
- if (!catalogTypes.has(t)) {
323
- err(`Validator drift: relation type '${t}' valid in VALID_RELATION_TYPES but missing from catalog.relationTypes`);
324
- }
325
- }
326
- for (const t of catalogTypes) {
327
- if (!validatorTypes.has(t)) {
328
- err(`Validator drift: relation type '${t}' in catalog but not in VALID_RELATION_TYPES`);
329
- }
330
- }
331
- }
332
-
333
- // Validator throws if localKey is missing — so it must be in requiredFields, not optional
334
- const requiresLocalKey = /missing\s+'localKey'/.test(source);
335
- if (requiresLocalKey) {
336
- for (const r of catalog.relationTypes) {
337
- if (r.optionalFields.includes('localKey')) {
338
- err(`Relation type '${r.name}': validator throws on missing 'localKey' but catalog marks it as OPTIONAL`);
339
- }
340
- if (!r.requiredFields.includes('localKey')) {
341
- err(`Relation type '${r.name}': validator requires 'localKey' but catalog does not list it in requiredFields`);
342
- }
343
- }
344
- }
345
-
346
- // The validator only checks typeof rel.references === 'string', so it expects a bare column name
347
- // Catalog examples that show 'references: "table(column)"' would mislead consumers
348
- for (const r of catalog.relationTypes) {
349
- if (typeof r.example !== 'string') continue;
350
- const refMatch = r.example.match(/references:\s*["']([^"']+)["']/);
351
- if (refMatch && /\(.*\)/.test(refMatch[1])) {
352
- err(`Relation type '${r.name}': example shows 'references: "${refMatch[1]}"' (table(column) form) but validator expects a bare column name`);
353
- }
354
- }
355
- }
356
-
357
- function checkReferentialActionsVsValidator(catalog) {
358
- const source = readSource(SCHEMA_VALIDATOR_PATH, 'Schema validator');
359
- if (!source) return;
360
-
361
- const validatorActions = extractSetContents(source, 'VALID_REFERENTIAL_ACTIONS');
362
- if (!validatorActions) {
363
- warn('Could not extract VALID_REFERENTIAL_ACTIONS from schema-validator.js');
364
- return;
365
- }
366
-
367
- const catalogActions = new Set(catalog.referentialActions.map(a => a.name));
368
-
369
- for (const a of validatorActions) {
370
- if (!catalogActions.has(a)) {
371
- err(`Validator drift: referential action '${a}' valid in validator but missing from catalog`);
372
- }
373
- }
374
- for (const a of catalogActions) {
375
- if (!validatorActions.has(a)) {
376
- err(`Validator drift: referential action '${a}' in catalog but not in VALID_REFERENTIAL_ACTIONS`);
377
- }
378
- }
379
- }
380
-
381
- function checkCheckOperationsVsIrBuilder(catalog) {
382
- const source = readSource(IR_BUILDER_PATH, 'IR builder');
383
- if (!source) return;
384
-
385
- const irOps = extractSetContents(source, 'VALID_CHECK_OPS');
386
- if (!irOps) {
387
- warn('Could not extract VALID_CHECK_OPS from ir-builder.js');
388
- } else {
389
- const catalogOps = new Set(catalog.checkOperations.map(o => o.name));
390
-
391
- for (const o of irOps) {
392
- if (!catalogOps.has(o)) {
393
- err(`IR drift: check op '${o}' valid in VALID_CHECK_OPS but missing from catalog`);
394
- }
395
- }
396
- for (const o of catalogOps) {
397
- if (!irOps.has(o)) {
398
- err(`IR drift: check op '${o}' in catalog but not in VALID_CHECK_OPS`);
399
- }
400
- }
401
- }
402
-
403
- // User-facing format is `{ field, <op>: value }` (operator as key).
404
- // The `{ op, field, value }` shape is the IR output, not the user input.
405
- for (const op of catalog.checkOperations) {
406
- if (typeof op.example === 'string' && /\bop\s*:\s*['"]/.test(op.example)) {
407
- err(`Check op '${op.name}': example uses IR output shape '{ op: ... }' instead of user input shape '{ field, ${op.name}: ... }'`);
408
- }
409
- }
410
- }
411
-
412
- // Scan ALL catalog sections for IR check anti-pattern. Catches cases where
413
- // description or example anywhere in the catalog (not just checkOperations)
414
- // uses the internal IR shape `{ op, field, value }` instead of user input
415
- // shape `{ field, <op>: value }`. This complements checkCheckOperationsVsIrBuilder
416
- // which only scans the checkOperations section itself.
417
- function checkAllCatalogForIrCheckPattern(catalog) {
418
- const opValueRe = /\bop\s*:\s*['"](?:in|eq|neq|gt|gte|lt|lte)['"]/;
419
- const descShapeRe = /\{[^}]*\bop\b[^}]*\bfield\b[^}]*\bvalue\b[^}]*\}/;
420
-
421
- const arraySections = [
422
- 'defineModelOptions', 'fieldTypes', 'constraints',
423
- 'relationTypes', 'referentialActions', 'dialectSupport'
424
- // Skip checkOperations — already covered by checkCheckOperationsVsIrBuilder
425
- ];
426
-
427
- for (const sectionName of arraySections) {
428
- const items = catalog[sectionName];
429
- if (!Array.isArray(items)) continue;
430
-
431
- for (const item of items) {
432
- const label = item.name ? `${sectionName}.${item.name}` : sectionName;
433
-
434
- if (typeof item.example === 'string' && opValueRe.test(item.example)) {
435
- err(`${label}.example uses IR check shape '{ op: "...", field, value }'. Use user input shape '{ field, <op>: <value> }' instead.`);
436
- }
437
- if (typeof item.description === 'string' && descShapeRe.test(item.description)) {
438
- err(`${label}.description describes IR check shape '{ ..., op, field, value, ... }'. User input shape uses operator-as-key.`);
439
- }
440
- }
441
- }
442
-
443
- // Also scan shorthandSyntax.examples meaning strings
444
- if (catalog.shorthandSyntax && Array.isArray(catalog.shorthandSyntax.examples)) {
445
- for (const ex of catalog.shorthandSyntax.examples) {
446
- if (typeof ex.meaning === 'string' && opValueRe.test(ex.meaning)) {
447
- err(`shorthandSyntax.examples meaning uses IR check shape: '${ex.meaning}'`);
448
- }
449
- }
450
- }
451
- }
452
-
453
- function checkDefineModelSignature(catalog) {
454
- const source = readSource(DEFINE_MODEL_PATH, 'define-model');
455
- if (!source) return;
456
-
457
- const isPositional = /function\s+defineModel\s*\(\s*tableName\s*,\s*options\s*\)/.test(source);
458
- if (!isPositional) {
459
- warn('Could not verify defineModel signature in define-model.js (regex pattern may need update)');
460
- return;
461
- }
462
-
463
- const tableNameOption = catalog.defineModelOptions.find(o => o.name === 'tableName');
464
- if (tableNameOption) {
465
- err(`Signature drift: 'tableName' is a positional argument in defineModel(tableName, options) but catalog.defineModelOptions lists it as an options property`);
466
- }
467
- }
468
-
469
- // ============================================================================
470
- // LEVEL 3: SMOKE TEST — execute catalog examples through actual parser
471
- // ============================================================================
472
-
473
- function collectShorthandExamples(catalog) {
474
- const examples = [];
475
-
476
- for (const t of catalog.fieldTypes) {
477
- if (typeof t.example === 'string') {
478
- examples.push({ source: `fieldTypes.${t.name}.example`, input: t.example });
479
- }
480
- }
481
- for (const c of catalog.constraints) {
482
- if (typeof c.example === 'string') {
483
- examples.push({ source: `constraints.${c.name}.example`, input: c.example });
484
- }
485
- }
486
- if (catalog.shorthandSyntax && Array.isArray(catalog.shorthandSyntax.examples)) {
487
- for (const ex of catalog.shorthandSyntax.examples) {
488
- if (typeof ex.input === 'string') {
489
- examples.push({ source: `shorthandSyntax.examples[${JSON.stringify(ex.input)}]`, input: ex.input });
490
- }
491
- }
492
- }
493
- if (catalog.auditColumns && Array.isArray(catalog.auditColumns.columns)) {
494
- for (const col of catalog.auditColumns.columns) {
495
- if (typeof col.shorthand === 'string') {
496
- examples.push({ source: `auditColumns.${col.name}.shorthand`, input: col.shorthand });
497
- }
498
- }
499
- }
500
-
501
- return examples;
502
- }
503
-
504
- function loadParser() {
505
- try {
506
- const mod = require(SHORTHAND_PARSER_PATH);
507
- if (typeof mod.parseFieldShorthand !== 'function') {
508
- err('shorthand-parser.js does not export parseFieldShorthand');
509
- return null;
510
- }
511
- return mod.parseFieldShorthand;
512
- } catch (e) {
513
- err(`Could not load shorthand-parser.js: ${e.message}`);
514
- return null;
515
- }
516
- }
517
-
518
- function checkExamplesParseable(catalog, parseFieldShorthand) {
519
- if (!parseFieldShorthand) return;
520
- const examples = collectShorthandExamples(catalog);
521
-
522
- for (const { source, input } of examples) {
523
- const cleaned = input.replace(AUTO_UPDATE_RE, ' ').trim();
524
- if (cleaned === '') continue;
525
-
526
- try {
527
- parseFieldShorthand(cleaned, '_smoke_test_');
528
- } catch (e) {
529
- err(`Smoke test FAIL: ${source} — input '${input}' threw: ${e.message}`);
530
- }
531
- }
532
- }
533
-
534
- // ============================================================================
535
- // LEVEL 4: DEFAULT VALUE TYPE CONSISTENCY
536
- // ============================================================================
537
-
538
- function checkDefaultValueTypeConsistency(catalog, parseFieldShorthand) {
539
- if (!parseFieldShorthand) return;
540
-
541
- const examples = collectShorthandExamples(catalog).filter(e => e.input.includes('default:'));
542
-
543
- for (const { source, input } of examples) {
544
- let parsed;
545
- try {
546
- const cleaned = input.replace(AUTO_UPDATE_RE, ' ').trim();
547
- parsed = parseFieldShorthand(cleaned, '_type_test_');
548
- } catch {
549
- continue; // caught by smoke test
550
- }
551
-
552
- if (!parsed || !parsed.default || parsed.default.kind !== 'literal') continue;
553
- const valueType = typeof parsed.default.value;
554
-
555
- if (parsed.type === 'boolean' && valueType !== 'boolean') {
556
- warn(`${source}: type 'boolean' with default '${input}' parses default as ${valueType}, expected boolean. Use 'default:true' (raw, no quote) instead.`);
557
- }
558
- if ((parsed.type === 'integer' || parsed.type === 'bigint' || parsed.type === 'decimal') && valueType !== 'number') {
559
- warn(`${source}: type '${parsed.type}' with default '${input}' parses default as ${valueType}, expected number. Use raw form like 'default:0' (no quote) instead.`);
560
- }
561
- if ((parsed.type === 'string' || parsed.type === 'text') && valueType !== 'string') {
562
- warn(`${source}: type '${parsed.type}' with default '${input}' parses default as ${valueType}, expected string. Use quoted form like 'default:\\'value\\'' instead.`);
563
- }
564
- }
565
- }
566
-
567
- // ============================================================================
568
- // LEVEL 5: SPEC DOC REFERENCE
569
- // ============================================================================
570
-
571
- function checkSpecDocReferences(catalog) {
572
- if (!fs.existsSync(SPEC_DOC_PATH)) {
573
- warn(`Spec doc not found: ${SPEC_DOC_PATH}`);
574
- return;
575
- }
576
-
577
- const doc = fs.readFileSync(SPEC_DOC_PATH, 'utf8');
578
-
579
- const checks = [
580
- { items: catalog.fieldTypes, label: 'field type' },
581
- { items: catalog.constraints, label: 'constraint' },
582
- { items: catalog.relationTypes, label: 'relation type' },
583
- { items: catalog.referentialActions, label: 'referential action' },
584
- { items: catalog.checkOperations, label: 'check op' },
585
- { items: catalog.dialectSupport, label: 'dialect' }
586
- ];
587
-
588
- for (const { items, label } of checks) {
589
- for (const it of items) {
590
- const re = new RegExp(`\\b${it.name}\\b`, 'i');
591
- if (!re.test(doc)) warn(`Spec doc: ${label} '${it.name}' not referenced in schema-definition.md`);
592
- }
593
- }
594
- }
595
-
596
- // ============================================================================
597
- // MAIN
598
- // ============================================================================
599
-
600
- function printReport(quiet) {
601
- const lines = [];
602
-
603
- lines.push('');
604
- lines.push('================================================================');
605
- lines.push(' dbschema-kit Catalog Sync Validator');
606
- lines.push('================================================================');
607
- lines.push('');
608
-
609
- if (report.errors.length > 0) {
610
- lines.push(`ERRORS (${report.errors.length}):`);
611
- for (const e of report.errors) lines.push(` [X] ${e}`);
612
- lines.push('');
613
- }
614
-
615
- if (report.warnings.length > 0) {
616
- lines.push(`WARNINGS (${report.warnings.length}):`);
617
- for (const w of report.warnings) lines.push(` [!] ${w}`);
618
- lines.push('');
619
- }
620
-
621
- if (!quiet && report.info.length > 0) {
622
- lines.push(`INFO (${report.info.length}):`);
623
- for (const i of report.info) lines.push(` [i] ${i}`);
624
- lines.push('');
625
- }
626
-
627
- lines.push('----------------------------------------------------------------');
628
- lines.push(' Summary');
629
- lines.push('----------------------------------------------------------------');
630
- lines.push(` Errors : ${report.errors.length}`);
631
- lines.push(` Warnings: ${report.warnings.length}`);
632
- lines.push(` Info : ${report.info.length}`);
633
- lines.push('');
634
-
635
- if (report.errors.length === 0 && report.warnings.length === 0) {
636
- lines.push(' Status: PASS — catalog is in sync with parser source and spec doc.');
637
- } else if (report.errors.length === 0) {
638
- lines.push(' Status: PASS WITH WARNINGS — review warnings above.');
639
- } else {
640
- lines.push(' Status: FAIL — fix errors before commit.');
641
- }
642
- lines.push('');
643
-
644
- console.log(lines.join('\n'));
645
- }
646
-
647
- function main() {
648
- const opts = parseArgs();
649
-
650
- let catalog;
651
- try {
652
- ({ DBSCHEMA_CATALOG: catalog } = require(CATALOG_PATH));
653
- } catch (e) {
654
- console.error(`Failed to load catalog from ${CATALOG_PATH}`);
655
- console.error(e.message);
656
- process.exit(1);
657
- }
658
-
659
- info(`Catalog loaded from: ${path.relative(process.cwd(), CATALOG_PATH)}`);
660
- info(`Schema version: ${catalog.schemaVersion}`);
661
- info(
662
- `Field types: ${catalog.fieldTypes ? catalog.fieldTypes.length : 0}, ` +
663
- `Constraints: ${catalog.constraints ? catalog.constraints.length : 0}, ` +
664
- `Relation types: ${catalog.relationTypes ? catalog.relationTypes.length : 0}, ` +
665
- `Check ops: ${catalog.checkOperations ? catalog.checkOperations.length : 0}`
666
- );
667
-
668
- // Level 1: catalog structural integrity
669
- checkCatalogStructure(catalog);
670
- if (Array.isArray(catalog.fieldTypes)) checkFieldTypesIntegrity(catalog.fieldTypes);
671
- if (Array.isArray(catalog.constraints)) checkConstraintsIntegrity(catalog.constraints);
672
- if (Array.isArray(catalog.relationTypes)) checkRelationTypesIntegrity(catalog.relationTypes);
673
- if (Array.isArray(catalog.referentialActions)) checkReferentialActionsIntegrity(catalog.referentialActions);
674
- if (Array.isArray(catalog.checkOperations)) checkCheckOperationsIntegrity(catalog.checkOperations);
675
- if (catalog.auditColumns) checkAuditColumnsIntegrity(catalog.auditColumns);
676
- if (Array.isArray(catalog.dialectSupport)) checkDialectSupportIntegrity(catalog.dialectSupport);
677
-
678
- // Stop early on structural failure — downstream checks would be misleading
679
- if (report.errors.length > 0) {
680
- printReport(opts.quiet);
681
- process.exit(1);
682
- }
683
-
684
- // Level 2: parser source cross-reference
685
- checkFieldTypesVsParser(catalog);
686
- checkConstraintsVsParser(catalog);
687
- checkRelationTypesVsValidator(catalog);
688
- checkReferentialActionsVsValidator(catalog);
689
- checkCheckOperationsVsIrBuilder(catalog);
690
- checkAllCatalogForIrCheckPattern(catalog);
691
- checkDefineModelSignature(catalog);
692
-
693
- // Level 3 + 4: parser smoke test + default value type consistency
694
- const parseFieldShorthand = loadParser();
695
- checkExamplesParseable(catalog, parseFieldShorthand);
696
- checkDefaultValueTypeConsistency(catalog, parseFieldShorthand);
697
-
698
- // Level 5: spec doc references
699
- checkSpecDocReferences(catalog);
700
-
701
- printReport(opts.quiet);
702
-
703
- if (report.errors.length > 0) process.exit(1);
704
- if (opts.strict && report.warnings.length > 0) process.exit(1);
705
- process.exit(0);
706
- }
707
-
708
- main();