@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,215 +1,213 @@
1
- /**
2
- * Audit Table Runner
3
- *
4
- * Mengeksekusi DDL audit table ke database yang dituju.
5
- * Bersifat idempotent (table existing tidak menyebabkan error).
6
- *
7
- * Failure mode:
8
- * - Connection gagal (timeout/auth) → warning + dry-run mode (return status,
9
- * tidak throw). Generator boleh lanjut karena migration bisa dijalankan
10
- * manual via file SQL yang ditulis.
11
- * - DDL gagal setelah connection sukses → throw, generator abort.
12
- *
13
- * Reference: docs/todo/todo-fieldprotection-concurrency-by-design.md (Bagian 3, 6.4)
14
- *
15
- * @module lib/migration/audit-table-runner
16
- */
17
-
18
- const fs = require('fs');
19
- const path = require('path');
20
- const { generateAuditTableMigration } = require('./audit-table-generator');
21
-
22
- /**
23
- * Jalankan migration audit table.
24
- *
25
- * @param {string} tableName - Nama tabel sumber
26
- * @param {string} dialect - 'postgres' | 'mysql' | 'oracle'
27
- * @param {Object|null} connectionInfo - Connection info { host, port, user, password, database, connectString? }.
28
- * Jika null dry-run mode (file SQL tetap ditulis).
29
- * @param {Object} [options]
30
- * @param {string} [options.projectRoot=process.cwd()] - Root project untuk menulis migrations/audit/
31
- * @param {Object} [options.logger=console] - Logger dengan method info/warn/error
32
- * @returns {Promise<{status: string, sqlPath: string, auditTable: string}>}
33
- * status: 'created' | 'exists' | 'dry-run' | 'connection-failed'
34
- */
35
- async function runAuditMigration(tableName, dialect, connectionInfo, options = {}) {
36
- const projectRoot = options.projectRoot || process.cwd();
37
- const logger = options.logger || console;
38
- const auditTable = `${tableName}_audit`;
39
- const sql = generateAuditTableMigration(tableName, dialect);
40
-
41
- const sqlPath = writeMigrationFile(projectRoot, auditTable, sql);
42
- logger.info(`[restforge] audit migration written: ${path.relative(projectRoot, sqlPath)}`);
43
-
44
- if (!connectionInfo) {
45
- logger.warn(`[restforge] audit migration skipped — database connection not configured`);
46
- return { status: 'dry-run', sqlPath, auditTable };
47
- }
48
-
49
- let connection;
50
- try {
51
- connection = await connectToDatabase(dialect, connectionInfo);
52
- } catch (err) {
53
- logger.warn(`[restforge] audit migration skipped — connection failed: ${err.message}`);
54
- return { status: 'connection-failed', sqlPath, auditTable };
55
- }
56
-
57
- try {
58
- const existed = await auditTableExists(connection, dialect, auditTable, connectionInfo);
59
- await executeMigration(connection, dialect, sql);
60
- logger.info(existed
61
- ? `[restforge] audit table exists: ${auditTable}`
62
- : `[restforge] audit table created: ${auditTable}`);
63
- return { status: existed ? 'exists' : 'created', sqlPath, auditTable };
64
- } catch (err) {
65
- logger.error(`[restforge] audit migration failed: ${err.message}`);
66
- throw err;
67
- } finally {
68
- await closeConnection(connection, dialect);
69
- }
70
- }
71
-
72
- function writeMigrationFile(projectRoot, auditTable, sql) {
73
- const migrationsDir = path.join(projectRoot, 'migrations', 'audit');
74
- fs.mkdirSync(migrationsDir, { recursive: true });
75
- const sqlPath = path.join(migrationsDir, `${auditTable}.sql`);
76
- fs.writeFileSync(sqlPath, sql + '\n', 'utf8');
77
- return sqlPath;
78
- }
79
-
80
- async function connectToDatabase(dialect, connectionInfo) {
81
- if (dialect === 'postgres') {
82
- const { Client } = require('pg');
83
- const client = new Client({
84
- host: connectionInfo.host,
85
- port: connectionInfo.port,
86
- user: connectionInfo.user,
87
- password: connectionInfo.password,
88
- database: connectionInfo.database
89
- });
90
- await client.connect();
91
- return client;
92
- }
93
-
94
- if (dialect === 'mysql') {
95
- const mysql = require('mysql2/promise');
96
- return await mysql.createConnection({
97
- host: connectionInfo.host,
98
- port: connectionInfo.port,
99
- user: connectionInfo.user,
100
- password: connectionInfo.password,
101
- database: connectionInfo.database,
102
- multipleStatements: true
103
- });
104
- }
105
-
106
- if (dialect === 'oracle') {
107
- const oracledb = require('oracledb');
108
- return await oracledb.getConnection({
109
- user: connectionInfo.user,
110
- password: connectionInfo.password,
111
- connectString: connectionInfo.connectString
112
- || `${connectionInfo.host}:${connectionInfo.port}/${connectionInfo.database}`
113
- });
114
- }
115
-
116
- throw new Error(`connectToDatabase: unsupported dialect '${dialect}'`);
117
- }
118
-
119
- async function closeConnection(connection, dialect) {
120
- if (!connection) return;
121
- try {
122
- if (dialect === 'oracle') {
123
- await connection.close();
124
- } else {
125
- await connection.end();
126
- }
127
- } catch (_err) {
128
- // ignore close error — primary action sudah selesai
129
- }
130
- }
131
-
132
- async function auditTableExists(connection, dialect, auditTable, connectionInfo) {
133
- if (dialect === 'postgres') {
134
- const { rows } = await connection.query(
135
- `SELECT 1 FROM information_schema.tables
136
- WHERE table_schema = current_schema() AND table_name = $1
137
- LIMIT 1`,
138
- [auditTable]
139
- );
140
- return rows.length > 0;
141
- }
142
-
143
- if (dialect === 'mysql') {
144
- const [rows] = await connection.query(
145
- `SELECT 1 FROM information_schema.tables
146
- WHERE table_schema = ? AND table_name = ?
147
- LIMIT 1`,
148
- [connectionInfo.database, auditTable]
149
- );
150
- return rows.length > 0;
151
- }
152
-
153
- if (dialect === 'oracle') {
154
- const result = await connection.execute(
155
- `SELECT 1 FROM user_tables WHERE table_name = :name`,
156
- { name: auditTable.toUpperCase() }
157
- );
158
- return result.rows && result.rows.length > 0;
159
- }
160
-
161
- return false;
162
- }
163
-
164
- async function executeMigration(connection, dialect, sql) {
165
- if (dialect === 'postgres') {
166
- // pg client mendukung multiple statement dalam satu query() tanpa params
167
- await connection.query(sql);
168
- return;
169
- }
170
-
171
- if (dialect === 'mysql') {
172
- // mysql2 dengan multipleStatements: true
173
- await connection.query(sql);
174
- return;
175
- }
176
-
177
- if (dialect === 'oracle') {
178
- // Oracle PL/SQL anonim dipisahkan oleh '/' di line tersendiri.
179
- // oracledb.execute() menerima satu statement per call.
180
- const blocks = splitOraclePlsqlBlocks(sql);
181
- for (const block of blocks) {
182
- const trimmed = block.trim();
183
- if (trimmed === '') continue;
184
- await connection.execute(trimmed);
185
- }
186
- return;
187
- }
188
-
189
- throw new Error(`executeMigration: unsupported dialect '${dialect}'`);
190
- }
191
-
192
- function splitOraclePlsqlBlocks(sql) {
193
- // Pisahkan blok PL/SQL berdasarkan baris yang isinya hanya '/'
194
- const lines = sql.split(/\r?\n/);
195
- const blocks = [];
196
- let current = [];
197
- for (const line of lines) {
198
- if (line.trim() === '/') {
199
- if (current.length > 0) {
200
- blocks.push(current.join('\n'));
201
- current = [];
202
- }
203
- } else {
204
- current.push(line);
205
- }
206
- }
207
- if (current.length > 0 && current.join('').trim() !== '') {
208
- blocks.push(current.join('\n'));
209
- }
210
- return blocks;
211
- }
212
-
213
- module.exports = {
214
- runAuditMigration
215
- };
1
+ /**
2
+ * Audit Table Runner
3
+ *
4
+ * Mengeksekusi DDL audit table ke database yang dituju.
5
+ * Bersifat idempotent (table existing tidak menyebabkan error).
6
+ *
7
+ * Failure mode:
8
+ * - Connection gagal (timeout/auth) → warning + dry-run mode (return status,
9
+ * tidak throw). Generator boleh lanjut karena migration bisa dijalankan
10
+ * manual via file SQL yang ditulis.
11
+ * - DDL gagal setelah connection sukses → throw, generator abort.
12
+ *
13
+ * @module lib/migration/audit-table-runner
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const { generateAuditTableMigration } = require('./audit-table-generator');
19
+
20
+ /**
21
+ * Jalankan migration audit table.
22
+ *
23
+ * @param {string} tableName - Nama tabel sumber
24
+ * @param {string} dialect - 'postgres' | 'mysql' | 'oracle'
25
+ * @param {Object|null} connectionInfo - Connection info { host, port, user, password, database, connectString? }.
26
+ * Jika null dry-run mode (file SQL tetap ditulis).
27
+ * @param {Object} [options]
28
+ * @param {string} [options.projectRoot=process.cwd()] - Root project untuk menulis migrations/audit/
29
+ * @param {Object} [options.logger=console] - Logger dengan method info/warn/error
30
+ * @returns {Promise<{status: string, sqlPath: string, auditTable: string}>}
31
+ * status: 'created' | 'exists' | 'dry-run' | 'connection-failed'
32
+ */
33
+ async function runAuditMigration(tableName, dialect, connectionInfo, options = {}) {
34
+ const projectRoot = options.projectRoot || process.cwd();
35
+ const logger = options.logger || console;
36
+ const auditTable = `${tableName}_audit`;
37
+ const sql = generateAuditTableMigration(tableName, dialect);
38
+
39
+ const sqlPath = writeMigrationFile(projectRoot, auditTable, sql);
40
+ logger.info(`[restforge] audit migration written: ${path.relative(projectRoot, sqlPath)}`);
41
+
42
+ if (!connectionInfo) {
43
+ logger.warn(`[restforge] audit migration skipped — database connection not configured`);
44
+ return { status: 'dry-run', sqlPath, auditTable };
45
+ }
46
+
47
+ let connection;
48
+ try {
49
+ connection = await connectToDatabase(dialect, connectionInfo);
50
+ } catch (err) {
51
+ logger.warn(`[restforge] audit migration skipped — connection failed: ${err.message}`);
52
+ return { status: 'connection-failed', sqlPath, auditTable };
53
+ }
54
+
55
+ try {
56
+ const existed = await auditTableExists(connection, dialect, auditTable, connectionInfo);
57
+ await executeMigration(connection, dialect, sql);
58
+ logger.info(existed
59
+ ? `[restforge] audit table exists: ${auditTable}`
60
+ : `[restforge] audit table created: ${auditTable}`);
61
+ return { status: existed ? 'exists' : 'created', sqlPath, auditTable };
62
+ } catch (err) {
63
+ logger.error(`[restforge] audit migration failed: ${err.message}`);
64
+ throw err;
65
+ } finally {
66
+ await closeConnection(connection, dialect);
67
+ }
68
+ }
69
+
70
+ function writeMigrationFile(projectRoot, auditTable, sql) {
71
+ const migrationsDir = path.join(projectRoot, 'migrations', 'audit');
72
+ fs.mkdirSync(migrationsDir, { recursive: true });
73
+ const sqlPath = path.join(migrationsDir, `${auditTable}.sql`);
74
+ fs.writeFileSync(sqlPath, sql + '\n', 'utf8');
75
+ return sqlPath;
76
+ }
77
+
78
+ async function connectToDatabase(dialect, connectionInfo) {
79
+ if (dialect === 'postgres') {
80
+ const { Client } = require('pg');
81
+ const client = new Client({
82
+ host: connectionInfo.host,
83
+ port: connectionInfo.port,
84
+ user: connectionInfo.user,
85
+ password: connectionInfo.password,
86
+ database: connectionInfo.database
87
+ });
88
+ await client.connect();
89
+ return client;
90
+ }
91
+
92
+ if (dialect === 'mysql') {
93
+ const mysql = require('mysql2/promise');
94
+ return await mysql.createConnection({
95
+ host: connectionInfo.host,
96
+ port: connectionInfo.port,
97
+ user: connectionInfo.user,
98
+ password: connectionInfo.password,
99
+ database: connectionInfo.database,
100
+ multipleStatements: true
101
+ });
102
+ }
103
+
104
+ if (dialect === 'oracle') {
105
+ const oracledb = require('oracledb');
106
+ return await oracledb.getConnection({
107
+ user: connectionInfo.user,
108
+ password: connectionInfo.password,
109
+ connectString: connectionInfo.connectString
110
+ || `${connectionInfo.host}:${connectionInfo.port}/${connectionInfo.database}`
111
+ });
112
+ }
113
+
114
+ throw new Error(`connectToDatabase: unsupported dialect '${dialect}'`);
115
+ }
116
+
117
+ async function closeConnection(connection, dialect) {
118
+ if (!connection) return;
119
+ try {
120
+ if (dialect === 'oracle') {
121
+ await connection.close();
122
+ } else {
123
+ await connection.end();
124
+ }
125
+ } catch (_err) {
126
+ // ignore close error — primary action sudah selesai
127
+ }
128
+ }
129
+
130
+ async function auditTableExists(connection, dialect, auditTable, connectionInfo) {
131
+ if (dialect === 'postgres') {
132
+ const { rows } = await connection.query(
133
+ `SELECT 1 FROM information_schema.tables
134
+ WHERE table_schema = current_schema() AND table_name = $1
135
+ LIMIT 1`,
136
+ [auditTable]
137
+ );
138
+ return rows.length > 0;
139
+ }
140
+
141
+ if (dialect === 'mysql') {
142
+ const [rows] = await connection.query(
143
+ `SELECT 1 FROM information_schema.tables
144
+ WHERE table_schema = ? AND table_name = ?
145
+ LIMIT 1`,
146
+ [connectionInfo.database, auditTable]
147
+ );
148
+ return rows.length > 0;
149
+ }
150
+
151
+ if (dialect === 'oracle') {
152
+ const result = await connection.execute(
153
+ `SELECT 1 FROM user_tables WHERE table_name = :name`,
154
+ { name: auditTable.toUpperCase() }
155
+ );
156
+ return result.rows && result.rows.length > 0;
157
+ }
158
+
159
+ return false;
160
+ }
161
+
162
+ async function executeMigration(connection, dialect, sql) {
163
+ if (dialect === 'postgres') {
164
+ // pg client mendukung multiple statement dalam satu query() tanpa params
165
+ await connection.query(sql);
166
+ return;
167
+ }
168
+
169
+ if (dialect === 'mysql') {
170
+ // mysql2 dengan multipleStatements: true
171
+ await connection.query(sql);
172
+ return;
173
+ }
174
+
175
+ if (dialect === 'oracle') {
176
+ // Oracle PL/SQL anonim dipisahkan oleh '/' di line tersendiri.
177
+ // oracledb.execute() menerima satu statement per call.
178
+ const blocks = splitOraclePlsqlBlocks(sql);
179
+ for (const block of blocks) {
180
+ const trimmed = block.trim();
181
+ if (trimmed === '') continue;
182
+ await connection.execute(trimmed);
183
+ }
184
+ return;
185
+ }
186
+
187
+ throw new Error(`executeMigration: unsupported dialect '${dialect}'`);
188
+ }
189
+
190
+ function splitOraclePlsqlBlocks(sql) {
191
+ // Pisahkan blok PL/SQL berdasarkan baris yang isinya hanya '/'
192
+ const lines = sql.split(/\r?\n/);
193
+ const blocks = [];
194
+ let current = [];
195
+ for (const line of lines) {
196
+ if (line.trim() === '/') {
197
+ if (current.length > 0) {
198
+ blocks.push(current.join('\n'));
199
+ current = [];
200
+ }
201
+ } else {
202
+ current.push(line);
203
+ }
204
+ }
205
+ if (current.length > 0 && current.join('').trim() !== '') {
206
+ blocks.push(current.join('\n'));
207
+ }
208
+ return blocks;
209
+ }
210
+
211
+ module.exports = {
212
+ runAuditMigration
213
+ };
@@ -0,0 +1,171 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Endpoint Schema Validator
5
+ *
6
+ * Orchestrator untuk validasi schema database saat `endpoint create` dijalankan.
7
+ * Module ini:
8
+ * 1. Resolve --config file (via config-resolver)
9
+ * 2. Load config + connect ke database (via DatabaseIntrospector)
10
+ * 3. Compare payload-vs-database menggunakan compareSchemaStrict
11
+ * 4. Map hasil ke exit-code semantics:
12
+ * - clean schema -> return { status: 'ok' }
13
+ * - drift detected -> throw error dengan exitCode=1 + formatted report
14
+ * - connection fail -> throw error dengan exitCode=3
15
+ * - usage error -> throw error dengan exitCode=2 (di-handle caller via validateContract)
16
+ *
17
+ * Module ini sengaja decoupled dari PayloadGenerator agar tidak ikut menjalankan
18
+ * payload regenerate/sync flow.
19
+ *
20
+ * @module lib/payload/endpoint-schema-validator
21
+ */
22
+
23
+ const { DatabaseIntrospector } = require('../utils/database-introspector');
24
+ const { resolveConfig, printDefaultConfigWarning } = require('../utils/config-resolver');
25
+ const { compareSchemaStrict, formatDriftReport } = require('./schema-diff');
26
+
27
+ /**
28
+ * Buat Error object dengan property `exitCode` agar cli-entry dapat
29
+ * forward exit code spesifik.
30
+ *
31
+ * @param {string} message
32
+ * @param {number} exitCode
33
+ * @returns {Error}
34
+ */
35
+ function createExitError(message, exitCode) {
36
+ const err = new Error(message);
37
+ err.exitCode = exitCode;
38
+ err.isSchemaValidationError = true;
39
+ return err;
40
+ }
41
+
42
+ /**
43
+ * Jalankan validasi schema untuk satu payload + table sebelum codegen.
44
+ *
45
+ * @param {Object} options
46
+ * @param {Object} options.payload - Processed payload object (harus punya tableName)
47
+ * @param {string} options.payloadFileName - Nama file payload untuk pesan error
48
+ * @param {string} options.configArg - Nilai flag --config dari CLI
49
+ * @param {boolean} options.skipSchemaCheck - true bila --skip-schema-check di-set
50
+ * @param {string} [options.workingDir] - cwd, default process.cwd()
51
+ * @param {Function} [options.IntrospectorClass] - Override untuk testing
52
+ * @returns {Promise<{
53
+ * status: 'ok' | 'skipped',
54
+ * reason?: string,
55
+ * columnsChecked?: number
56
+ * }>}
57
+ * @throws {Error} Dengan property exitCode (1=drift, 2=usage, 3=connection)
58
+ */
59
+ async function validateEndpointSchema(options) {
60
+ const {
61
+ payload,
62
+ payloadFileName,
63
+ configArg,
64
+ skipSchemaCheck,
65
+ workingDir,
66
+ IntrospectorClass
67
+ } = options;
68
+
69
+ if (!payload || !payload.tableName) {
70
+ throw createExitError('Payload missing tableName — cannot run schema validation', 2);
71
+ }
72
+
73
+ if (skipSchemaCheck) {
74
+ return { status: 'skipped', reason: '--skip-schema-check active' };
75
+ }
76
+
77
+ const resolved = resolveConfig(configArg, workingDir || process.cwd());
78
+ if (!resolved) {
79
+ const lines = [
80
+ 'Error: --config is required for schema validation',
81
+ 'Usage: npx restforge endpoint create --project=<P> --name=<N> --payload=<F> --config=<ENV> [--force=true] [--skip-schema-check]'
82
+ ];
83
+ throw createExitError(lines.join('\n'), 2);
84
+ }
85
+
86
+ if (resolved.source === 'default') {
87
+ printDefaultConfigWarning(resolved.defaultName);
88
+ }
89
+
90
+ const IntroCtor = IntrospectorClass || DatabaseIntrospector;
91
+ const db = new IntroCtor({ quiet: true });
92
+
93
+ const loaded = db.loadConfig(resolved.path);
94
+ if (!loaded) {
95
+ throw createExitError(
96
+ buildConnectionErrorMessage(`Cannot load config file: ${resolved.path}`),
97
+ 3
98
+ );
99
+ }
100
+
101
+ let connected = false;
102
+ try {
103
+ connected = await db.connect();
104
+ } catch (e) {
105
+ try { await db.close(); } catch (_e) { /* ignore */ }
106
+ throw createExitError(
107
+ buildConnectionErrorMessage(e.message || String(e)),
108
+ 3
109
+ );
110
+ }
111
+
112
+ if (!connected) {
113
+ try { await db.close(); } catch (_e) { /* ignore */ }
114
+ throw createExitError(
115
+ buildConnectionErrorMessage('database not reachable'),
116
+ 3
117
+ );
118
+ }
119
+
120
+ let comparison;
121
+ try {
122
+ comparison = await compareSchemaStrict(payload, db);
123
+ } finally {
124
+ try { await db.close(); } catch (_e) { /* ignore */ }
125
+ }
126
+
127
+ if (comparison.status === 'error') {
128
+ const lines = [
129
+ 'Schema Validation:',
130
+ ` [ERROR] ${comparison.summary}`,
131
+ ' Endpoint generation blocked.',
132
+ '',
133
+ ' Workarounds:',
134
+ ' 1. Verify the table exists in the database',
135
+ ' 2. Use --skip-schema-check to bypass validation (NOT recommended for production)'
136
+ ];
137
+ throw createExitError(lines.join('\n'), 3);
138
+ }
139
+
140
+ if (comparison.status === 'drift') {
141
+ const driftLines = formatDriftReport(comparison, {
142
+ payloadFileName,
143
+ tableName: payload.tableName
144
+ });
145
+ const lines = ['Schema Validation:', ...driftLines, '', 'Endpoint generation blocked due to schema drift'];
146
+ throw createExitError(lines.join('\n'), 1);
147
+ }
148
+
149
+ return {
150
+ status: 'ok',
151
+ columnsChecked: comparison.totalColumnsChecked || 0
152
+ };
153
+ }
154
+
155
+ function buildConnectionErrorMessage(reason) {
156
+ const lines = [
157
+ 'Schema Validation:',
158
+ ` [ERROR] Cannot connect to database: ${reason}`,
159
+ ' Endpoint generation blocked.',
160
+ '',
161
+ ' Workarounds:',
162
+ ' 1. Verify db-connection.env is correct and database is reachable',
163
+ ' 2. Use --skip-schema-check to bypass validation (NOT recommended for production)'
164
+ ];
165
+ return lines.join('\n');
166
+ }
167
+
168
+ module.exports = {
169
+ validateEndpointSchema,
170
+ createExitError
171
+ };