@restforgejs/platform 4.2.8 → 4.3.2

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 (325) 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 +1 -1
  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 +3 -2
  18. package/generators/cli/schema/describe.js +3 -2
  19. package/generators/cli/schema/diff.js +3 -2
  20. package/generators/cli/schema/introspect.js +3 -2
  21. package/generators/cli/schema/list.js +3 -2
  22. package/generators/cli/schema/migrate.js +3 -2
  23. package/generators/lib/migration/audit-table-runner.js +213 -215
  24. package/generators/lib/payload/payload-runner.js +1 -1
  25. package/generators/lib/templates/dashboard-catalog.js +1 -437
  26. package/generators/lib/templates/db-connection-env.js +1 -212
  27. package/generators/lib/templates/dbschema-catalog.js +1 -489
  28. package/generators/lib/templates/field-validation-catalog.js +1 -531
  29. package/generators/lib/templates/mysql-template.js +1 -3863
  30. package/generators/lib/templates/oracle-template.js +1 -3915
  31. package/generators/lib/templates/postgres-template.js +1 -5838
  32. package/generators/lib/templates/query-declarative-catalog.js +1 -199
  33. package/generators/lib/templates/sqlite-template.js +1 -3440
  34. package/generators/lib/utils/env-manager.js +6 -0
  35. package/generators/lib/utils/path-validator.js +71 -0
  36. package/generators/lib/validators/payload-validator.js +1 -2
  37. package/integrity-manifest.json +28 -10
  38. package/package.json +11 -3
  39. package/scripts/verify-integrity.js +1 -1
  40. package/server.js +1 -1
  41. package/src/components/handlers/adjust_handler.js +1 -1
  42. package/src/components/handlers/audit_handler.js +1 -1
  43. package/src/components/handlers/delete_handler.js +1 -1
  44. package/src/components/handlers/export_handler.js +1 -1
  45. package/src/components/handlers/import_handler.js +1 -1
  46. package/src/components/handlers/insert_handler.js +1 -1
  47. package/src/components/handlers/update_handler.js +1 -1
  48. package/src/components/handlers/upload_handler.js +1 -1
  49. package/src/components/handlers/workflow_handler.js +1 -1
  50. package/src/components/integrations/webhook.js +1 -1
  51. package/src/consumers/baseConsumer.js +1 -1
  52. package/src/consumers/declarativeMapper.js +1 -1
  53. package/src/consumers/handlers/apiHandler.js +1 -1
  54. package/src/consumers/handlers/consoleHandler.js +1 -1
  55. package/src/consumers/handlers/databaseHandler.js +1 -1
  56. package/src/consumers/handlers/index.js +1 -1
  57. package/src/consumers/handlers/kafkaHandler.js +1 -1
  58. package/src/consumers/index.js +1 -1
  59. package/src/consumers/messageTransformer.js +1 -1
  60. package/src/consumers/validator.js +1 -1
  61. package/src/core/db/dialect/base-dialect.js +1 -1
  62. package/src/core/db/dialect/index.js +1 -1
  63. package/src/core/db/dialect/mysql-dialect.js +1 -1
  64. package/src/core/db/dialect/oracle-dialect.js +1 -1
  65. package/src/core/db/dialect/postgres-dialect.js +1 -1
  66. package/src/core/db/dialect/sqlite-dialect.js +1 -1
  67. package/src/core/db/flatten-helper.js +1 -1
  68. package/src/core/db/query-builder-error.js +1 -1
  69. package/src/core/db/query-builder.js +1 -1
  70. package/src/core/db/relation-helper.js +1 -1
  71. package/src/core/handlers/delete_handler.js +1 -1
  72. package/src/core/handlers/insert_handler.js +1 -1
  73. package/src/core/handlers/update_handler.js +1 -1
  74. package/src/core/models/base-model.js +1 -1
  75. package/src/core/utils/cache-manager.js +1 -1
  76. package/src/core/utils/component-engine.js +1 -1
  77. package/src/core/utils/context-builder.js +1 -1
  78. package/src/core/utils/datetime-formatter.js +1 -1
  79. package/src/core/utils/datetime-parser.js +1 -1
  80. package/src/core/utils/db.js +1 -1
  81. package/src/core/utils/logger.js +1 -1
  82. package/src/core/utils/payload-loader.js +1 -1
  83. package/src/core/utils/security-checks.js +1 -1
  84. package/src/middleware/body-options.js +1 -1
  85. package/src/middleware/cors.js +1 -1
  86. package/src/middleware/idempotency.js +1 -1
  87. package/src/middleware/rate-limiter.js +1 -1
  88. package/src/middleware/request-logger.js +1 -1
  89. package/src/middleware/security-headers.js +1 -1
  90. package/src/models/base-model-mysql.js +1 -1
  91. package/src/models/base-model-oracle.js +1 -1
  92. package/src/models/base-model-sqlite.js +1 -1
  93. package/src/models/base-model.js +1 -1
  94. package/src/pro/caching/redis-client.js +1 -1
  95. package/src/pro/caching/redis-helper.js +1 -1
  96. package/src/pro/consumers/baseConsumer.js +1 -1
  97. package/src/pro/consumers/declarativeMapper.js +1 -1
  98. package/src/pro/consumers/handlers/apiHandler.js +1 -1
  99. package/src/pro/consumers/handlers/consoleHandler.js +1 -1
  100. package/src/pro/consumers/handlers/databaseHandler.js +1 -1
  101. package/src/pro/consumers/handlers/index.js +1 -1
  102. package/src/pro/consumers/handlers/kafkaHandler.js +1 -1
  103. package/src/pro/consumers/index.js +1 -1
  104. package/src/pro/consumers/messageTransformer.js +1 -1
  105. package/src/pro/consumers/validator.js +1 -1
  106. package/src/pro/database/base-model-mysql.js +1 -1
  107. package/src/pro/database/base-model-oracle.js +1 -1
  108. package/src/pro/database/base-model-sqlite.js +1 -1
  109. package/src/pro/database/db-mysql.js +1 -1
  110. package/src/pro/database/db-oracle.js +1 -1
  111. package/src/pro/database/db-sqlite.js +1 -1
  112. package/src/pro/excel/excel-generator.js +1 -1
  113. package/src/pro/excel/excel-parser.js +1 -1
  114. package/src/pro/excel/export-service.js +1 -1
  115. package/src/pro/excel/export_handler.js +1 -1
  116. package/src/pro/excel/import-service.js +1 -1
  117. package/src/pro/excel/import-validator.js +1 -1
  118. package/src/pro/excel/import_handler.js +1 -1
  119. package/src/pro/excel/upsert-builder.js +1 -1
  120. package/src/pro/idgen/idgen-routes.js +1 -1
  121. package/src/pro/integrations/lookup-resolver.js +1 -1
  122. package/src/pro/integrations/upload-handler-v2.js +1 -1
  123. package/src/pro/integrations/upload-handler.js +1 -1
  124. package/src/pro/integrations/webhook.js +1 -1
  125. package/src/pro/locking/lock-routes.js +1 -1
  126. package/src/pro/locking/resource-lock-manager.js +1 -1
  127. package/src/pro/messaging/kafkaConsumerService.js +1 -1
  128. package/src/pro/messaging/kafkaService.js +1 -1
  129. package/src/pro/messaging/messagehubService.js +1 -1
  130. package/src/pro/messaging/rabbitmqService.js +1 -1
  131. package/src/pro/scheduler/job-manager.js +1 -1
  132. package/src/pro/scheduler/job-routes.js +1 -1
  133. package/src/pro/scheduler/job-validator.js +1 -1
  134. package/src/pro/storage/base-storage-provider.js +1 -1
  135. package/src/pro/storage/file-metadata-helper.js +1 -1
  136. package/src/pro/storage/index.js +1 -1
  137. package/src/pro/storage/local-storage-provider.js +1 -1
  138. package/src/pro/storage/s3-storage-provider.js +1 -1
  139. package/src/pro/storage/upload-cleanup-job.js +1 -1
  140. package/src/pro/storage/upload-cleanup-scheduler.js +1 -1
  141. package/src/pro/storage/upload-pending-tracker.js +1 -1
  142. package/src/pro/websocket/broadcast-helper.js +1 -1
  143. package/src/pro/websocket/index.js +1 -1
  144. package/src/pro/websocket/livesync-server.js +1 -1
  145. package/src/pro/websocket/ws-broadcaster.js +1 -1
  146. package/src/services/export-service.js +1 -1
  147. package/src/services/import-service.js +1 -1
  148. package/src/services/kafkaConsumerService.js +1 -1
  149. package/src/services/kafkaService.js +1 -1
  150. package/src/services/messagehubService.js +1 -1
  151. package/src/services/rabbitmqService.js +1 -1
  152. package/src/utils/cache-invalidation-registry.js +1 -1
  153. package/src/utils/cache-manager.js +1 -1
  154. package/src/utils/component-engine.js +1 -1
  155. package/src/utils/config-extractor.js +1 -1
  156. package/src/utils/consumerLogger.js +1 -1
  157. package/src/utils/context-builder.js +1 -1
  158. package/src/utils/dashboard-helpers.js +1 -1
  159. package/src/utils/dateHelper.js +1 -1
  160. package/src/utils/datetime-formatter.js +1 -1
  161. package/src/utils/datetime-parser.js +1 -1
  162. package/src/utils/db-bootstrap.js +1 -1
  163. package/src/utils/db-mysql.js +1 -1
  164. package/src/utils/db-oracle.js +1 -1
  165. package/src/utils/db-sqlite.js +1 -1
  166. package/src/utils/db.js +1 -1
  167. package/src/utils/demo-generator.js +1 -1
  168. package/src/utils/excel-generator.js +1 -1
  169. package/src/utils/excel-parser.js +1 -1
  170. package/src/utils/file-watcher.js +1 -1
  171. package/src/utils/id-generator.js +1 -1
  172. package/src/utils/idempotency-manager.js +1 -1
  173. package/src/utils/import-validator.js +1 -1
  174. package/src/utils/license-client.js +1 -1
  175. package/src/utils/lock-manager.js +1 -1
  176. package/src/utils/logger.js +1 -1
  177. package/src/utils/lookup-resolver.js +1 -1
  178. package/src/utils/payload-loader.js +1 -1
  179. package/src/utils/processor-response.js +1 -1
  180. package/src/utils/rabbitmq.js +1 -1
  181. package/src/utils/redis-client.js +1 -1
  182. package/src/utils/redis-helper.js +1 -1
  183. package/src/utils/request-scope.js +1 -1
  184. package/src/utils/security-checks.js +1 -1
  185. package/src/utils/service-resolver.js +1 -1
  186. package/src/utils/shutdown-coordinator.js +1 -1
  187. package/src/utils/trusted-keys.js +1 -1
  188. package/src/utils/upload-handler.js +1 -1
  189. package/src/utils/upsert-builder.js +1 -1
  190. package/src/utils/workflow-hook-executor.js +1 -1
  191. package/generators/metadata/global.json +0 -58
  192. package/generators/metadata/test-mysql-workbench.json +0 -118
  193. package/generators/metadata/test-mysql.json +0 -56
  194. package/generators/metadata/test-oracle-workbench.json +0 -118
  195. package/generators/metadata/test-oracle.json +0 -56
  196. package/generators/metadata/test-pg-workbench.json +0 -118
  197. package/generators/metadata/test-pg.json +0 -56
  198. package/generators/scripts/obfuscate-source.js +0 -356
  199. package/generators/scripts/validate-catalog.js +0 -430
  200. package/generators/scripts/validate-dbschema-catalog.js +0 -708
  201. package/generators/tests/baseline/mysql/mini_inventory_item/src/models/mini-inventory/item.js +0 -944
  202. package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
  203. package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory.js +0 -336
  204. package/generators/tests/baseline/oracle/mini_inventory_item/src/models/mini-inventory/item.js +0 -1002
  205. package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
  206. package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory.js +0 -336
  207. package/generators/tests/baseline/postgres/mini_inventory_item/src/models/mini-inventory/item.js +0 -1333
  208. package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory/item.js +0 -1173
  209. package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory.js +0 -496
  210. package/generators/tests/fixtures/payloads/custom-sensitive.json +0 -27
  211. package/generators/tests/fixtures/payloads/dynamic-search-optout.json +0 -23
  212. package/generators/tests/fixtures/payloads/login-with-password.json +0 -22
  213. package/generators/tests/fixtures/payloads/order-process.json +0 -52
  214. package/generators/tests/fixtures/payloads/with-inline-sql.json +0 -26
  215. package/generators/tests/integration-tahap4b/README.md +0 -145
  216. package/generators/tests/integration-tahap4b/run-concurrent.js +0 -77
  217. package/generators/tests/integration-tahap4b/seed.sql +0 -53
  218. package/generators/tests/integration-tahap4b/verify.sql +0 -110
  219. package/generators/tests/unit/cli/create-dashboard.test.js +0 -505
  220. package/generators/tests/unit/cli/create-processor.test.js +0 -319
  221. package/generators/tests/unit/cli/dispatch-dashboard.test.js +0 -149
  222. package/generators/tests/unit/lib/dashboard-generator.test.js +0 -895
  223. package/generators/tests/unit/lib/dashboard-validator.test.js +0 -354
  224. package/generators/tests/unit/lib/dbschema-kit/apply-executor.test.js +0 -437
  225. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-introspect.test.js +0 -393
  226. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-generate-ddl.test.js +0 -104
  227. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-init.test.js +0 -119
  228. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-list.test.js +0 -48
  229. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-migrate.test.js +0 -175
  230. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-validate.test.js +0 -102
  231. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-models.test.js +0 -43
  232. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/all-schemas-listing.js +0 -84
  233. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/connection-error.js +0 -13
  234. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/empty.js +0 -12
  235. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/multi-schema.js +0 -124
  236. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/single-schema-inventory.js +0 -64
  237. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/two-tables.js +0 -66
  238. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/connection-error.js +0 -9
  239. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/partial.js +0 -29
  240. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/rollback.js +0 -26
  241. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/success.js +0 -43
  242. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/audit/events.js +0 -18
  243. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/inventory/products.js +0 -9
  244. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/users.js +0 -8
  245. package/generators/tests/unit/lib/dbschema-kit/connection.test.js +0 -112
  246. package/generators/tests/unit/lib/dbschema-kit/ddl-generator.test.js +0 -205
  247. package/generators/tests/unit/lib/dbschema-kit/define-model.test.js +0 -56
  248. package/generators/tests/unit/lib/dbschema-kit/dialect/index.test.js +0 -46
  249. package/generators/tests/unit/lib/dbschema-kit/dialect/mysql.test.js +0 -126
  250. package/generators/tests/unit/lib/dbschema-kit/dialect/oracle.test.js +0 -126
  251. package/generators/tests/unit/lib/dbschema-kit/dialect/postgres.test.js +0 -131
  252. package/generators/tests/unit/lib/dbschema-kit/dialect/sqlite.test.js +0 -126
  253. package/generators/tests/unit/lib/dbschema-kit/driver-loader.test.js +0 -93
  254. package/generators/tests/unit/lib/dbschema-kit/emitters/create-index.test.js +0 -173
  255. package/generators/tests/unit/lib/dbschema-kit/emitters/create-table.test.js +0 -376
  256. package/generators/tests/unit/lib/dbschema-kit/emitters/drop-table.test.js +0 -78
  257. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/invalid-dialect.env +0 -6
  258. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-dialect.env +0 -5
  259. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-host.env +0 -5
  260. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/oracle-valid.env +0 -6
  261. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/postgres-valid.env +0 -7
  262. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/sqlite-valid.env +0 -2
  263. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/category.js +0 -11
  264. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/item_product.js +0 -11
  265. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound.js +0 -24
  266. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound_item.js +0 -28
  267. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/supplier.js +0 -9
  268. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/warehouse.js +0 -9
  269. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-invalid/orphan.js +0 -17
  270. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/category.js +0 -11
  271. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/item_product.js +0 -11
  272. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/supplier.js +0 -9
  273. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/warehouse.js +0 -9
  274. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound.js +0 -24
  275. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound_item.js +0 -28
  276. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/audit/events.js +0 -18
  277. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/inventory/products.js +0 -9
  278. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/public/users.js +0 -9
  279. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/extra/category.js +0 -8
  280. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/master/category.js +0 -8
  281. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/bar.js +0 -8
  282. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/foo.js +0 -8
  283. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/empty-folder/README.md +0 -1
  284. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-export/plain.js +0 -3
  285. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-schema/bad.js +0 -6
  286. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/legacy-pattern/legacy.js +0 -12
  287. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/audit/products.js +0 -9
  288. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/inventory/products.js +0 -9
  289. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/a/products.js +0 -8
  290. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/b/products.js +0 -8
  291. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/nested-deep/a/b/c/deep_table.js +0 -8
  292. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/.hidden/ignored.js +0 -7
  293. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/category.js +0 -8
  294. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/supplier.js +0 -8
  295. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound.js +0 -8
  296. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound_item.js +0 -8
  297. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/category.js +0 -8
  298. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/item_product.js +0 -9
  299. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-single/category.js +0 -8
  300. package/generators/tests/unit/lib/dbschema-kit/integration.test.js +0 -217
  301. package/generators/tests/unit/lib/dbschema-kit/introspect-mapper.test.js +0 -403
  302. package/generators/tests/unit/lib/dbschema-kit/ir-builder.test.js +0 -390
  303. package/generators/tests/unit/lib/dbschema-kit/loader.test.js +0 -128
  304. package/generators/tests/unit/lib/dbschema-kit/naming.test.js +0 -170
  305. package/generators/tests/unit/lib/dbschema-kit/parser/shorthand-parser.test.js +0 -237
  306. package/generators/tests/unit/lib/dbschema-kit/schema-printer.test.js +0 -251
  307. package/generators/tests/unit/lib/dbschema-kit/statement-modifier.test.js +0 -105
  308. package/generators/tests/unit/lib/dbschema-kit/statement-splitter.test.js +0 -165
  309. package/generators/tests/unit/lib/dbschema-kit/topological-sort.test.js +0 -135
  310. package/generators/tests/unit/lib/dbschema-kit/validator/check-compatibility-validator.test.js +0 -373
  311. package/generators/tests/unit/lib/dbschema-kit/validator/circular-relation-validator.test.js +0 -454
  312. package/generators/tests/unit/lib/dbschema-kit/validator/cross-model-validator.test.js +0 -512
  313. package/generators/tests/unit/lib/dbschema-kit/validator/enhanced-validate-integration.test.js +0 -390
  314. package/generators/tests/unit/lib/dbschema-kit/validator/naming-convention-validator.test.js +0 -306
  315. package/generators/tests/unit/lib/dbschema-kit/validator/schema-validator.test.js +0 -443
  316. package/generators/tests/unit/lib/dbschema-kit/validator/type-compatibility-validator.test.js +0 -440
  317. package/generators/tests/unit/lib/dbschema-kit/validator/validator-reporter.test.js +0 -172
  318. package/generators/tests/unit/lib/metadata-manager-dashboard.test.js +0 -256
  319. package/generators/tests/unit/lib/payload-validator-fieldpolicy.test.js +0 -240
  320. package/generators/tests/unit/lib/processor-validation-generator.test.js +0 -300
  321. package/generators/tests/unit/lib/sensitive-field-masker.test.js +0 -170
  322. package/generators/tests/unit/lib/sql-table-extractor.test.js +0 -119
  323. package/scripts/generate-integrity-manifest.js +0 -124
  324. package/scripts/snapshot-cli-contracts.js +0 -194
  325. package/scripts/verify-publish.js +0 -56
@@ -1,496 +0,0 @@
1
- const express = require('express');
2
- const bodyParser = require('body-parser');
3
- const path = require('path');
4
- const fs = require('fs');
5
- const { v4: uuidv4 } = require('uuid');
6
- const { logger, logServerReady, logEndpointRegistered, createRequestLogger, logRequest } = require('restforgejs/src/utils/logger');
7
- const ExportHandler = require('restforgejs/src/components/handlers/export_handler');
8
- const ImportHandler = require('restforgejs/src/components/handlers/import_handler');
9
- const UploadHandler = require('restforgejs/src/components/handlers/upload_handler');
10
- const { extractExportConfigFromEndpoint, extractImportConfigFromEndpoint, extractUploadConfigFromEndpoint } = require('restforgejs/src/utils/config-extractor');
11
- const rateLimiter = require('restforgejs/src/middleware/rate-limiter');
12
- const idempotencyMiddleware = require('restforgejs/src/middleware/idempotency');
13
- const bodyOptionsMiddleware = require('restforgejs/src/middleware/body-options');
14
- const corsMiddleware = require('restforgejs/src/middleware/cors');
15
- const securityHeaders = require('restforgejs/src/middleware/security-headers');
16
-
17
- /**
18
- * MiniInventory Module - Auto-generated on 2026-04-25 07:34:33
19
- *
20
- * Fungsi untuk mengeksekusi modul mini-inventory
21
- * @param {Object} config - Konfigurasi untuk menjalankan modul
22
- * @param {number} config.port - Port untuk server
23
- * @param {string} config.key - API Key (opsional)
24
- * @param {boolean} config.cors - Enable CORS (default: true)
25
- * @param {boolean} config.logging - Enable request logging (default: true)
26
- * @returns {Promise<void>} Promise yang tidak pernah resolve agar server tetap berjalan
27
- */
28
- async function execute(config) {
29
- return new Promise((resolve, reject) => {
30
- try {
31
- const app = express();
32
- const port = config.port || 3000;
33
- const serverAddress = config.serverAddress || '0.0.0.0'; // Default 0.0.0.0 untuk backward compatibility
34
- const moduleNameCapitalized = 'MiniInventory';
35
-
36
- // Configuration options
37
- const loggingEnabled = config.logging !== false;
38
- const apiKeyRequired = !!config.key;
39
-
40
- logger.info({
41
- event: 'module_starting',
42
- module: moduleNameCapitalized,
43
- port,
44
- cors: process.env.CORS_ENABLED !== 'false',
45
- helmet: process.env.HELMET_ENABLED === 'true',
46
- logging: loggingEnabled,
47
- apiKey: apiKeyRequired
48
- }, `Starting ${moduleNameCapitalized} module`);
49
-
50
- // CORS middleware (konfigurasi via CORS_ENABLED dan CORS_ORIGINS di .env)
51
- app.use(corsMiddleware.middleware());
52
-
53
- // Security headers middleware (konfigurasi via HELMET_ENABLED di .env)
54
- app.use(securityHeaders.middleware());
55
-
56
- // JSON parsing middleware dengan error handling
57
- app.use(bodyParser.json({
58
- limit: '10mb',
59
- verify: (req, res, buf, encoding) => {
60
- // Skip validation untuk empty buffer
61
- if (buf.length === 0) {
62
- return;
63
- }
64
-
65
- try {
66
- JSON.parse(buf);
67
- } catch (error) {
68
- console.error(`JSON Parse Error from ${req.ip}: ${error.message}`);
69
- res.status(400).json({
70
- success: false,
71
- error: 'Invalid JSON payload',
72
- message: 'The payload sent is not a valid JSON format',
73
- details: error.message,
74
- timestamp: new Date().toISOString()
75
- });
76
- throw new Error('Invalid JSON');
77
- }
78
- }
79
- }));
80
-
81
- // URL-encoded parsing middleware
82
- app.use(bodyParser.urlencoded({
83
- extended: true,
84
- limit: '10mb'
85
- }));
86
-
87
- // Request logging middleware (Pino-based)
88
- if (loggingEnabled) {
89
- app.use((req, res, next) => {
90
- // Generate request ID
91
- req.id = req.headers['x-request-id'] || uuidv4();
92
- res.set('X-Request-ID', req.id);
93
-
94
- // Create scoped logger untuk request ini
95
- req.log = createRequestLogger({
96
- requestId: req.id,
97
- method: req.method,
98
- path: req.path,
99
- ip: req.ip
100
- });
101
-
102
- // Capture start time
103
- const startTime = process.hrtime();
104
-
105
- // Log response ketika selesai
106
- res.on('finish', () => {
107
- const [seconds, nanoseconds] = process.hrtime(startTime);
108
- const durationMs = parseFloat((seconds * 1000 + nanoseconds / 1e6).toFixed(2));
109
- logRequest(req, res, durationMs);
110
- });
111
-
112
- next();
113
- });
114
- }
115
-
116
- // API Key validation middleware
117
- if (apiKeyRequired) {
118
- app.use('/api', (req, res, next) => {
119
- const apiKey = req.headers['x-api-key'];
120
- if (!apiKey || apiKey !== config.key) {
121
- return res.status(401).json({
122
- success: false,
123
- error: 'Unauthorized',
124
- message: 'Invalid or missing API Key',
125
- timestamp: new Date().toISOString()
126
- });
127
- }
128
- next();
129
- });
130
- }
131
-
132
- // Rate limiting middleware (store: memory untuk single mode, Redis untuk cluster mode)
133
- rateLimiter.setStore(config.cluster ? 'redis' : 'memory');
134
- app.use('/api', rateLimiter.middleware());
135
-
136
- // Idempotency middleware (protects mutation endpoints from duplicate execution)
137
- if (process.env.IDEMPOTENCY_ENABLED === 'true') {
138
- app.use('/api', idempotencyMiddleware.middleware());
139
- }
140
-
141
- // Body options middleware (extract {data, options} format dari request body)
142
- app.use('/api', bodyOptionsMiddleware.middleware());
143
-
144
- // Auto-load plugin (jika ada)
145
- const moduleName = 'mini-inventory';
146
- const pluginPath = path.join(__dirname, '..', 'plugins', `${moduleName}-plugin.js`);
147
- let plugin = null;
148
- if (fs.existsSync(pluginPath)) {
149
- try {
150
- plugin = require(pluginPath);
151
- if (plugin.onBeforeEndpointsLoad) {
152
- plugin.onBeforeEndpointsLoad(app, config);
153
- }
154
- logger.info({ event: 'plugin_loaded', plugin: `${moduleName}-plugin` }, `Plugin loaded: ${moduleName}-plugin.js`);
155
- } catch (pluginError) {
156
- logger.error({ event: 'plugin_load_error', error: pluginError.message }, `Failed to load plugin: ${moduleName}-plugin.js`);
157
- }
158
- }
159
-
160
- // Global health check endpoint (tanpa prefix module)
161
- app.get('/health', (req, res) => {
162
- const healthInfo = {
163
- status: 'ok',
164
- timestamp: new Date().toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, ''),
165
- service: 'mini-inventory',
166
- uptime: process.uptime(),
167
- memory: process.memoryUsage(),
168
- system: {
169
- platform: process.platform,
170
- nodeVersion: process.version,
171
- pid: process.pid
172
- }
173
- };
174
-
175
- res.json(healthInfo);
176
- });
177
-
178
- // Module-specific health check endpoint (dengan prefix module)
179
- app.get('/api/mini-inventory/health', (req, res) => {
180
- const healthInfo = {
181
- status: 'ok',
182
- timestamp: new Date().toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, ''),
183
- service: 'mini-inventory',
184
- uptime: process.uptime(),
185
- memory: process.memoryUsage(),
186
- system: {
187
- platform: process.platform,
188
- nodeVersion: process.version,
189
- pid: process.pid
190
- }
191
- };
192
-
193
- res.json(healthInfo);
194
- });
195
-
196
- // Service info endpoint
197
- app.get('/api/mini-inventory/info', (req, res) => {
198
- res.json({
199
- name: 'MiniInventory API',
200
- description: 'Auto-generated API module for mini-inventory',
201
- documentation: 'See individual endpoint documentation',
202
- generated: '2026-04-25 07:34:33'
203
- });
204
- });
205
-
206
- // Load dan register endpoint modules
207
- // Binary-compatible: Use working directory instead of __dirname
208
- const isBunCompiled = typeof Bun !== 'undefined' && !process.argv[1];
209
- const getWorkingDir = () => {
210
- // Check if running as compiled binary
211
- if (isBunCompiled) {
212
- // Running as compiled binary: use directory where binary is located
213
- return path.dirname(process.execPath);
214
- } else {
215
- // Running as Node.js/Bun script: __dirname is already in src/modules
216
- // So we just need to add the module name
217
- return __dirname;
218
- }
219
- };
220
-
221
- const workingDir = getWorkingDir();
222
- // For compiled binary: workingDir is binary directory, need full path src/modules/moduleName
223
- // For script: workingDir is already src/modules/, just add moduleName
224
- const modulesDir = isBunCompiled
225
- ? path.join(workingDir, 'src', 'modules', 'mini-inventory')
226
- : path.join(workingDir, 'mini-inventory');
227
-
228
- try {
229
- // Ensure modules directory exists
230
- if (!fs.existsSync(modulesDir)) {
231
- fs.mkdirSync(modulesDir, { recursive: true });
232
- console.log(`Created modules directory: ${modulesDir}`);
233
- }
234
-
235
- // Read dan load semua endpoint files
236
- const files = fs.readdirSync(modulesDir);
237
- const endpointFiles = files.filter(file => file.endsWith('.js'));
238
-
239
- if (endpointFiles.length === 0) {
240
- console.log(`No endpoint files found in ${modulesDir}`);
241
- console.log(`Add endpoint files to enable API functionality`);
242
- } else {
243
- logger.info({ event: 'endpoints_loading', count: endpointFiles.length }, `Loading ${endpointFiles.length} endpoint(s)`);
244
- }
245
-
246
- // Register setiap endpoint
247
- for (const file of endpointFiles) {
248
- try {
249
- const endpointName = path.basename(file, '.js');
250
- const endpointPath = path.join(modulesDir, file);
251
-
252
- // Clear module cache untuk development
253
- if (require.cache[endpointPath]) {
254
- delete require.cache[endpointPath];
255
- }
256
-
257
- const endpointRouter = require(endpointPath);
258
-
259
- if (!endpointRouter) {
260
- console.warn(`Endpoint ${endpointName} did not export a router`);
261
- continue;
262
- }
263
-
264
- // Register endpoint dengan prefix
265
- const endpointPrefix = `/api/mini-inventory/${endpointName}`;
266
- app.use(endpointPrefix, endpointRouter);
267
-
268
- logEndpointRegistered(endpointName, endpointPrefix);
269
-
270
- // Register export routes untuk endpoint ini (auto-detect dari embedded config)
271
- try {
272
- const exportConfig = extractExportConfigFromEndpoint(endpointPath);
273
- if (exportConfig) {
274
- ExportHandler.registerRoutes(app, 'mini-inventory', endpointName, exportConfig);
275
- logger.info({
276
- event: 'export_routes_registered',
277
- endpoint: endpointName,
278
- table: exportConfig.tableName
279
- }, `Export routes registered for ${endpointName}`);
280
- }
281
- } catch (exportError) {
282
- logger.error({
283
- event: 'export_registration_error',
284
- endpoint: endpointName,
285
- error: exportError.message
286
- }, `Export registration failed for ${endpointName}: ${exportError.message}`);
287
- }
288
-
289
- // Register import routes untuk endpoint ini (auto-detect dari embedded config)
290
- try {
291
- const importConfig = extractImportConfigFromEndpoint(endpointPath);
292
- if (importConfig) {
293
- ImportHandler.registerRoutes(app, 'mini-inventory', endpointName, importConfig);
294
- logger.info({
295
- event: 'import_routes_registered',
296
- endpoint: endpointName,
297
- table: importConfig.tableName
298
- }, `Import routes registered for ${endpointName}`);
299
- }
300
- } catch (importError) {
301
- logger.error({
302
- event: 'import_registration_error',
303
- endpoint: endpointName,
304
- error: importError.message
305
- }, `Import registration failed for ${endpointName}: ${importError.message}`);
306
- }
307
-
308
- // Register upload routes untuk endpoint ini (auto-detect dari embedded config)
309
- try {
310
- const uploadConfig = extractUploadConfigFromEndpoint(endpointPath);
311
- if (uploadConfig) {
312
- UploadHandler.registerRoutes(app, 'mini-inventory', endpointName, uploadConfig);
313
- logger.info({
314
- event: 'upload_routes_registered',
315
- endpoint: endpointName,
316
- fields: Object.keys(uploadConfig.fields || {})
317
- }, `Upload routes registered for ${endpointName}`);
318
- }
319
- } catch (uploadError) {
320
- logger.error({
321
- event: 'upload_registration_error',
322
- endpoint: endpointName,
323
- error: uploadError.message
324
- }, `Upload registration failed for ${endpointName}: ${uploadError.message}`);
325
- }
326
-
327
- } catch (endpointError) {
328
- console.error(`Error loading endpoint ${file}:`, endpointError.message);
329
- // Continue loading other endpoints
330
- }
331
- }
332
-
333
- } catch (dirError) {
334
- console.error(`Error reading modules directory ${modulesDir}:`, dirError.message);
335
- }
336
-
337
- // Register cleanup route (optional admin endpoint)
338
- try {
339
- ExportHandler.registerCleanupRoute(app);
340
- } catch (cleanupError) {
341
- logger.error({ event: 'cleanup_route_error', error: cleanupError.message }, 'Export cleanup route registration failed');
342
- }
343
-
344
- // Default root endpoint
345
- app.get('/', (req, res) => {
346
- res.status(403).json({
347
- success: false,
348
- error: 'Forbidden',
349
- message: 'Access to the requested resource is forbidden',
350
- timestamp: new Date().toISOString()
351
- });
352
- });
353
-
354
- // Hook untuk mount middleware tambahan sebelum 404 handler
355
- // Digunakan oleh workbench UI dan middleware eksternal lainnya
356
- if (config.onAppReady && typeof config.onAppReady === 'function') {
357
- config.onAppReady(app);
358
- }
359
-
360
- // 404 handler untuk unknown routes
361
- app.use((req, res) => {
362
- res.status(403).json({
363
- success: false,
364
- error: 'Forbidden',
365
- message: 'Access to the requested resource is forbidden',
366
- timestamp: new Date().toISOString()
367
- });
368
- });
369
-
370
- // Global error handling middleware
371
- app.use((err, req, res, next) => {
372
- console.error(`Global Error Handler - ${req.method} ${req.url}:`, err);
373
-
374
- // Handle specific error types
375
- if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
376
- return res.status(400).json({
377
- success: false,
378
- error: 'Invalid JSON payload',
379
- message: 'The payload sent is not a valid JSON format',
380
- details: err.message,
381
- timestamp: new Date().toISOString()
382
- });
383
- }
384
-
385
- // Handle other errors
386
- if (!res.headersSent) {
387
- const statusCode = err.statusCode || err.status || 500;
388
- const errorResponse = {
389
- success: false,
390
- error: err.name || 'Internal Server Error',
391
- message: err.message || 'An error occurred on the server',
392
- timestamp: new Date().toISOString()
393
- };
394
-
395
- // Add stack trace in development
396
- if (process.env.NODE_ENV !== 'production') {
397
- errorResponse.stack = err.stack;
398
- }
399
-
400
- return res.status(statusCode).json(errorResponse);
401
- }
402
-
403
- next(err);
404
- });
405
-
406
- // Start server
407
- const server = app.listen(port, serverAddress, (err) => {
408
- if (err) {
409
- console.error(`Failed to start ${moduleNameCapitalized} server:`, err);
410
- reject(err);
411
- return;
412
- }
413
-
414
- console.log(`${moduleNameCapitalized} server started successfully!`);
415
-
416
- // Determine display URL based on serverAddress
417
- const displayHost = (serverAddress === '0.0.0.0' || !serverAddress) ? 'localhost' : serverAddress;
418
-
419
- logServerReady({
420
- port,
421
- module: 'mini-inventory',
422
- healthCheck: `http://${displayHost}:${port}/api/mini-inventory/health`,
423
- serviceInfo: `http://${displayHost}:${port}/api/mini-inventory/info`,
424
- baseUrl: `http://${displayHost}:${port}`
425
- });
426
- console.log('');
427
-
428
- // Execute plugin onAfterServerStart hook (jika ada)
429
- if (plugin && plugin.onAfterServerStart) {
430
- try {
431
- plugin.onAfterServerStart(app, config);
432
- } catch (pluginError) {
433
- logger.error({ event: 'plugin_after_start_error', error: pluginError.message }, 'Plugin onAfterServerStart failed');
434
- }
435
- }
436
- });
437
-
438
- // Graceful shutdown handling
439
- const gracefulShutdown = (signal) => {
440
- console.log(`\nReceived ${signal}, starting graceful shutdown...`);
441
-
442
- server.close((err) => {
443
- if (err) {
444
- console.error('Error during server shutdown:', err);
445
- process.exit(1);
446
- }
447
-
448
- console.log('Server closed successfully');
449
- console.log('Goodbye!');
450
- process.exit(0);
451
- });
452
-
453
- // Force shutdown after 10 seconds
454
- setTimeout(() => {
455
- console.error('Forced shutdown after timeout');
456
- process.exit(1);
457
- }, 10000);
458
- };
459
-
460
- // Handle shutdown signals
461
- process.on('SIGINT', () => gracefulShutdown('SIGINT'));
462
- process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
463
-
464
- // Handle uncaught exceptions
465
- process.on('uncaughtException', (error) => {
466
- console.error('Uncaught Exception:', error);
467
- gracefulShutdown('uncaughtException');
468
- });
469
-
470
- process.on('unhandledRejection', (reason, promise) => {
471
- console.error('Unhandled Rejection at:', promise, 'reason:', reason);
472
- gracefulShutdown('unhandledRejection');
473
- });
474
-
475
- // Store server reference untuk testing/management
476
- if (config.onServerReady && typeof config.onServerReady === 'function') {
477
- config.onServerReady(server, app);
478
- }
479
-
480
- } catch (error) {
481
- console.error(`Fatal error in ${moduleNameCapitalized} module:`, error);
482
- reject(error);
483
- }
484
-
485
- // Promise tidak akan pernah resolve untuk menjaga server tetap berjalan
486
- // kecuali ada error atau shutdown signal
487
- });
488
- }
489
-
490
- // Export execute function
491
- module.exports = { execute };
492
-
493
- // Additional exports untuk testing dan management
494
- module.exports.miniInventory = { execute };
495
- module.exports.moduleName = 'mini-inventory';
496
- module.exports.generated = '2026-04-25 07:34:33';
@@ -1,27 +0,0 @@
1
- {
2
- "description": "Payload dengan custom sensitive keyword dan attempt injection",
3
- "processor": [
4
- {
5
- "name": "register",
6
- "method": "POST",
7
- "description": "User registration dengan data KYC sensitif",
8
- "request": {
9
- "body": {
10
- "email": { "type": "string", "required": true, "format": "email" },
11
- "password": { "type": "string", "required": true, "minLength": 8, "sensitive": true },
12
- "ktp_number": { "type": "string", "required": true, "sensitive": true },
13
- "npwp": { "type": "string", "required": false, "sensitive": true },
14
- "phone": { "type": "string", "required": false, "format": "phone-id" },
15
- "attack_name.*": { "type": "string", "sensitive": true },
16
- "another|field": { "type": "string", "sensitive": true }
17
- }
18
- },
19
- "response": {
20
- "message": {
21
- "success": "Registration success.",
22
- "error": "Failed to register."
23
- }
24
- }
25
- }
26
- ]
27
- }
@@ -1,23 +0,0 @@
1
- {
2
- "description": "Dynamic search endpoint dengan opt-out router validation",
3
- "processor": [
4
- {
5
- "name": "search-contact",
6
- "method": "POST",
7
- "description": "Advanced search dengan dynamic filter",
8
- "request": {
9
- "validate": false,
10
- "body": {
11
- "search_by": { "type": "string", "required": true },
12
- "search_value": { "type": "string", "required": true }
13
- }
14
- },
15
- "response": {
16
- "message": {
17
- "success": "Result found.",
18
- "error": "Gagal search."
19
- }
20
- }
21
- }
22
- ]
23
- }
@@ -1,22 +0,0 @@
1
- {
2
- "description": "Login endpoint untuk verifikasi masking field password",
3
- "processor": [
4
- {
5
- "name": "login",
6
- "method": "POST",
7
- "description": "User login",
8
- "request": {
9
- "body": {
10
- "username": { "type": "string", "required": true, "minLength": 3, "maxLength": 64 },
11
- "password": { "type": "string", "required": true, "minLength": 6 }
12
- }
13
- },
14
- "response": {
15
- "message": {
16
- "success": "Login berhasil.",
17
- "error": "Login gagal."
18
- }
19
- }
20
- }
21
- ]
22
- }
@@ -1,52 +0,0 @@
1
- {
2
- "description": "Sales Order processing endpoints (golden fixture)",
3
- "processor": [
4
- {
5
- "name": "submit-order",
6
- "method": "POST",
7
- "description": "Submit draft order menjadi pending approval",
8
- "sql": {
9
- "query": "SELECT so_id, so_number, status FROM sales.sales_order WHERE so_id = $1 AND status = 'draft'",
10
- "params": ["so_id"]
11
- },
12
- "request": {
13
- "body": {
14
- "so_id": { "type": "uuid", "required": true, "description": "ID Sales Order" },
15
- "notes": { "type": "string", "required": false, "maxLength": 200 }
16
- },
17
- "headers": {
18
- "X-App-Code": { "type": "string", "required": true, "mapTo": "app_code" }
19
- }
20
- },
21
- "response": {
22
- "message": {
23
- "success": "Sales order berhasil di-submit untuk approval.",
24
- "empty": "Sales order tidak ditemukan atau bukan berstatus draft.",
25
- "error": "Gagal submit sales order."
26
- }
27
- }
28
- },
29
- {
30
- "name": "approve-order",
31
- "method": "POST",
32
- "description": "Approve sales order",
33
- "sql": {
34
- "query": "SELECT so_id FROM sales.sales_order WHERE so_id = $1 AND status = 'pending_approval'",
35
- "params": ["so_id"]
36
- },
37
- "request": {
38
- "body": {
39
- "so_id": { "type": "uuid", "required": true },
40
- "approved_by": { "type": "uuid", "required": true },
41
- "decision": { "type": "string", "required": true, "enum": ["approve", "partial-approve"] }
42
- }
43
- },
44
- "response": {
45
- "message": {
46
- "success": "Approved.",
47
- "error": "Gagal approve."
48
- }
49
- }
50
- }
51
- ]
52
- }
@@ -1,26 +0,0 @@
1
- {
2
- "description": "Payload dengan sql.query inline untuk verifikasi scaffold SQL",
3
- "processor": [
4
- {
5
- "name": "get-product",
6
- "method": "GET",
7
- "description": "Ambil detail produk berdasarkan ID",
8
- "sql": {
9
- "query": "SELECT product_id, product_code, product_name FROM inventory.product WHERE product_id = $1 AND is_active = true",
10
- "params": ["product_id"]
11
- },
12
- "request": {
13
- "params": {
14
- "product_id": { "type": "uuid", "required": true }
15
- }
16
- },
17
- "response": {
18
- "message": {
19
- "success": "Detail produk ditemukan.",
20
- "empty": "Produk tidak ditemukan.",
21
- "error": "Gagal mengambil produk."
22
- }
23
- }
24
- }
25
- ]
26
- }