@restforgejs/platform 4.2.8 → 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 (324) 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/templates/dashboard-catalog.js +1 -437
  25. package/generators/lib/templates/db-connection-env.js +1 -212
  26. package/generators/lib/templates/dbschema-catalog.js +1 -489
  27. package/generators/lib/templates/field-validation-catalog.js +1 -531
  28. package/generators/lib/templates/mysql-template.js +1 -3863
  29. package/generators/lib/templates/oracle-template.js +1 -3915
  30. package/generators/lib/templates/postgres-template.js +1 -5838
  31. package/generators/lib/templates/query-declarative-catalog.js +1 -199
  32. package/generators/lib/templates/sqlite-template.js +1 -3440
  33. package/generators/lib/utils/env-manager.js +6 -0
  34. package/generators/lib/utils/path-validator.js +71 -0
  35. package/generators/lib/validators/payload-validator.js +1 -2
  36. package/integrity-manifest.json +28 -10
  37. package/package.json +11 -3
  38. package/scripts/verify-integrity.js +1 -1
  39. package/server.js +1 -1
  40. package/src/components/handlers/adjust_handler.js +1 -1
  41. package/src/components/handlers/audit_handler.js +1 -1
  42. package/src/components/handlers/delete_handler.js +1 -1
  43. package/src/components/handlers/export_handler.js +1 -1
  44. package/src/components/handlers/import_handler.js +1 -1
  45. package/src/components/handlers/insert_handler.js +1 -1
  46. package/src/components/handlers/update_handler.js +1 -1
  47. package/src/components/handlers/upload_handler.js +1 -1
  48. package/src/components/handlers/workflow_handler.js +1 -1
  49. package/src/components/integrations/webhook.js +1 -1
  50. package/src/consumers/baseConsumer.js +1 -1
  51. package/src/consumers/declarativeMapper.js +1 -1
  52. package/src/consumers/handlers/apiHandler.js +1 -1
  53. package/src/consumers/handlers/consoleHandler.js +1 -1
  54. package/src/consumers/handlers/databaseHandler.js +1 -1
  55. package/src/consumers/handlers/index.js +1 -1
  56. package/src/consumers/handlers/kafkaHandler.js +1 -1
  57. package/src/consumers/index.js +1 -1
  58. package/src/consumers/messageTransformer.js +1 -1
  59. package/src/consumers/validator.js +1 -1
  60. package/src/core/db/dialect/base-dialect.js +1 -1
  61. package/src/core/db/dialect/index.js +1 -1
  62. package/src/core/db/dialect/mysql-dialect.js +1 -1
  63. package/src/core/db/dialect/oracle-dialect.js +1 -1
  64. package/src/core/db/dialect/postgres-dialect.js +1 -1
  65. package/src/core/db/dialect/sqlite-dialect.js +1 -1
  66. package/src/core/db/flatten-helper.js +1 -1
  67. package/src/core/db/query-builder-error.js +1 -1
  68. package/src/core/db/query-builder.js +1 -1
  69. package/src/core/db/relation-helper.js +1 -1
  70. package/src/core/handlers/delete_handler.js +1 -1
  71. package/src/core/handlers/insert_handler.js +1 -1
  72. package/src/core/handlers/update_handler.js +1 -1
  73. package/src/core/models/base-model.js +1 -1
  74. package/src/core/utils/cache-manager.js +1 -1
  75. package/src/core/utils/component-engine.js +1 -1
  76. package/src/core/utils/context-builder.js +1 -1
  77. package/src/core/utils/datetime-formatter.js +1 -1
  78. package/src/core/utils/datetime-parser.js +1 -1
  79. package/src/core/utils/db.js +1 -1
  80. package/src/core/utils/logger.js +1 -1
  81. package/src/core/utils/payload-loader.js +1 -1
  82. package/src/core/utils/security-checks.js +1 -1
  83. package/src/middleware/body-options.js +1 -1
  84. package/src/middleware/cors.js +1 -1
  85. package/src/middleware/idempotency.js +1 -1
  86. package/src/middleware/rate-limiter.js +1 -1
  87. package/src/middleware/request-logger.js +1 -1
  88. package/src/middleware/security-headers.js +1 -1
  89. package/src/models/base-model-mysql.js +1 -1
  90. package/src/models/base-model-oracle.js +1 -1
  91. package/src/models/base-model-sqlite.js +1 -1
  92. package/src/models/base-model.js +1 -1
  93. package/src/pro/caching/redis-client.js +1 -1
  94. package/src/pro/caching/redis-helper.js +1 -1
  95. package/src/pro/consumers/baseConsumer.js +1 -1
  96. package/src/pro/consumers/declarativeMapper.js +1 -1
  97. package/src/pro/consumers/handlers/apiHandler.js +1 -1
  98. package/src/pro/consumers/handlers/consoleHandler.js +1 -1
  99. package/src/pro/consumers/handlers/databaseHandler.js +1 -1
  100. package/src/pro/consumers/handlers/index.js +1 -1
  101. package/src/pro/consumers/handlers/kafkaHandler.js +1 -1
  102. package/src/pro/consumers/index.js +1 -1
  103. package/src/pro/consumers/messageTransformer.js +1 -1
  104. package/src/pro/consumers/validator.js +1 -1
  105. package/src/pro/database/base-model-mysql.js +1 -1
  106. package/src/pro/database/base-model-oracle.js +1 -1
  107. package/src/pro/database/base-model-sqlite.js +1 -1
  108. package/src/pro/database/db-mysql.js +1 -1
  109. package/src/pro/database/db-oracle.js +1 -1
  110. package/src/pro/database/db-sqlite.js +1 -1
  111. package/src/pro/excel/excel-generator.js +1 -1
  112. package/src/pro/excel/excel-parser.js +1 -1
  113. package/src/pro/excel/export-service.js +1 -1
  114. package/src/pro/excel/export_handler.js +1 -1
  115. package/src/pro/excel/import-service.js +1 -1
  116. package/src/pro/excel/import-validator.js +1 -1
  117. package/src/pro/excel/import_handler.js +1 -1
  118. package/src/pro/excel/upsert-builder.js +1 -1
  119. package/src/pro/idgen/idgen-routes.js +1 -1
  120. package/src/pro/integrations/lookup-resolver.js +1 -1
  121. package/src/pro/integrations/upload-handler-v2.js +1 -1
  122. package/src/pro/integrations/upload-handler.js +1 -1
  123. package/src/pro/integrations/webhook.js +1 -1
  124. package/src/pro/locking/lock-routes.js +1 -1
  125. package/src/pro/locking/resource-lock-manager.js +1 -1
  126. package/src/pro/messaging/kafkaConsumerService.js +1 -1
  127. package/src/pro/messaging/kafkaService.js +1 -1
  128. package/src/pro/messaging/messagehubService.js +1 -1
  129. package/src/pro/messaging/rabbitmqService.js +1 -1
  130. package/src/pro/scheduler/job-manager.js +1 -1
  131. package/src/pro/scheduler/job-routes.js +1 -1
  132. package/src/pro/scheduler/job-validator.js +1 -1
  133. package/src/pro/storage/base-storage-provider.js +1 -1
  134. package/src/pro/storage/file-metadata-helper.js +1 -1
  135. package/src/pro/storage/index.js +1 -1
  136. package/src/pro/storage/local-storage-provider.js +1 -1
  137. package/src/pro/storage/s3-storage-provider.js +1 -1
  138. package/src/pro/storage/upload-cleanup-job.js +1 -1
  139. package/src/pro/storage/upload-cleanup-scheduler.js +1 -1
  140. package/src/pro/storage/upload-pending-tracker.js +1 -1
  141. package/src/pro/websocket/broadcast-helper.js +1 -1
  142. package/src/pro/websocket/index.js +1 -1
  143. package/src/pro/websocket/livesync-server.js +1 -1
  144. package/src/pro/websocket/ws-broadcaster.js +1 -1
  145. package/src/services/export-service.js +1 -1
  146. package/src/services/import-service.js +1 -1
  147. package/src/services/kafkaConsumerService.js +1 -1
  148. package/src/services/kafkaService.js +1 -1
  149. package/src/services/messagehubService.js +1 -1
  150. package/src/services/rabbitmqService.js +1 -1
  151. package/src/utils/cache-invalidation-registry.js +1 -1
  152. package/src/utils/cache-manager.js +1 -1
  153. package/src/utils/component-engine.js +1 -1
  154. package/src/utils/config-extractor.js +1 -1
  155. package/src/utils/consumerLogger.js +1 -1
  156. package/src/utils/context-builder.js +1 -1
  157. package/src/utils/dashboard-helpers.js +1 -1
  158. package/src/utils/dateHelper.js +1 -1
  159. package/src/utils/datetime-formatter.js +1 -1
  160. package/src/utils/datetime-parser.js +1 -1
  161. package/src/utils/db-bootstrap.js +1 -1
  162. package/src/utils/db-mysql.js +1 -1
  163. package/src/utils/db-oracle.js +1 -1
  164. package/src/utils/db-sqlite.js +1 -1
  165. package/src/utils/db.js +1 -1
  166. package/src/utils/demo-generator.js +1 -1
  167. package/src/utils/excel-generator.js +1 -1
  168. package/src/utils/excel-parser.js +1 -1
  169. package/src/utils/file-watcher.js +1 -1
  170. package/src/utils/id-generator.js +1 -1
  171. package/src/utils/idempotency-manager.js +1 -1
  172. package/src/utils/import-validator.js +1 -1
  173. package/src/utils/license-client.js +1 -1
  174. package/src/utils/lock-manager.js +1 -1
  175. package/src/utils/logger.js +1 -1
  176. package/src/utils/lookup-resolver.js +1 -1
  177. package/src/utils/payload-loader.js +1 -1
  178. package/src/utils/processor-response.js +1 -1
  179. package/src/utils/rabbitmq.js +1 -1
  180. package/src/utils/redis-client.js +1 -1
  181. package/src/utils/redis-helper.js +1 -1
  182. package/src/utils/request-scope.js +1 -1
  183. package/src/utils/security-checks.js +1 -1
  184. package/src/utils/service-resolver.js +1 -1
  185. package/src/utils/shutdown-coordinator.js +1 -1
  186. package/src/utils/trusted-keys.js +1 -1
  187. package/src/utils/upload-handler.js +1 -1
  188. package/src/utils/upsert-builder.js +1 -1
  189. package/src/utils/workflow-hook-executor.js +1 -1
  190. package/generators/metadata/global.json +0 -58
  191. package/generators/metadata/test-mysql-workbench.json +0 -118
  192. package/generators/metadata/test-mysql.json +0 -56
  193. package/generators/metadata/test-oracle-workbench.json +0 -118
  194. package/generators/metadata/test-oracle.json +0 -56
  195. package/generators/metadata/test-pg-workbench.json +0 -118
  196. package/generators/metadata/test-pg.json +0 -56
  197. package/generators/scripts/obfuscate-source.js +0 -356
  198. package/generators/scripts/validate-catalog.js +0 -430
  199. package/generators/scripts/validate-dbschema-catalog.js +0 -708
  200. package/generators/tests/baseline/mysql/mini_inventory_item/src/models/mini-inventory/item.js +0 -944
  201. package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
  202. package/generators/tests/baseline/mysql/mini_inventory_item/src/modules/mini-inventory.js +0 -336
  203. package/generators/tests/baseline/oracle/mini_inventory_item/src/models/mini-inventory/item.js +0 -1002
  204. package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory/item.js +0 -740
  205. package/generators/tests/baseline/oracle/mini_inventory_item/src/modules/mini-inventory.js +0 -336
  206. package/generators/tests/baseline/postgres/mini_inventory_item/src/models/mini-inventory/item.js +0 -1333
  207. package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory/item.js +0 -1173
  208. package/generators/tests/baseline/postgres/mini_inventory_item/src/modules/mini-inventory.js +0 -496
  209. package/generators/tests/fixtures/payloads/custom-sensitive.json +0 -27
  210. package/generators/tests/fixtures/payloads/dynamic-search-optout.json +0 -23
  211. package/generators/tests/fixtures/payloads/login-with-password.json +0 -22
  212. package/generators/tests/fixtures/payloads/order-process.json +0 -52
  213. package/generators/tests/fixtures/payloads/with-inline-sql.json +0 -26
  214. package/generators/tests/integration-tahap4b/README.md +0 -145
  215. package/generators/tests/integration-tahap4b/run-concurrent.js +0 -77
  216. package/generators/tests/integration-tahap4b/seed.sql +0 -53
  217. package/generators/tests/integration-tahap4b/verify.sql +0 -110
  218. package/generators/tests/unit/cli/create-dashboard.test.js +0 -505
  219. package/generators/tests/unit/cli/create-processor.test.js +0 -319
  220. package/generators/tests/unit/cli/dispatch-dashboard.test.js +0 -149
  221. package/generators/tests/unit/lib/dashboard-generator.test.js +0 -895
  222. package/generators/tests/unit/lib/dashboard-validator.test.js +0 -354
  223. package/generators/tests/unit/lib/dbschema-kit/apply-executor.test.js +0 -437
  224. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-introspect.test.js +0 -393
  225. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-generate-ddl.test.js +0 -104
  226. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-init.test.js +0 -119
  227. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-list.test.js +0 -48
  228. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-migrate.test.js +0 -175
  229. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-kit-validate.test.js +0 -102
  230. package/generators/tests/unit/lib/dbschema-kit/cli/dbschema-models.test.js +0 -43
  231. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/all-schemas-listing.js +0 -84
  232. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/connection-error.js +0 -13
  233. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/empty.js +0 -12
  234. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/multi-schema.js +0 -124
  235. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/single-schema-inventory.js +0 -64
  236. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/introspect-stubs/two-tables.js +0 -66
  237. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/connection-error.js +0 -9
  238. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/partial.js +0 -29
  239. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/rollback.js +0 -26
  240. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/migrate-stubs/success.js +0 -43
  241. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/audit/events.js +0 -18
  242. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/inventory/products.js +0 -9
  243. package/generators/tests/unit/lib/dbschema-kit/cli/fixtures/multi-schema/users.js +0 -8
  244. package/generators/tests/unit/lib/dbschema-kit/connection.test.js +0 -112
  245. package/generators/tests/unit/lib/dbschema-kit/ddl-generator.test.js +0 -205
  246. package/generators/tests/unit/lib/dbschema-kit/define-model.test.js +0 -56
  247. package/generators/tests/unit/lib/dbschema-kit/dialect/index.test.js +0 -46
  248. package/generators/tests/unit/lib/dbschema-kit/dialect/mysql.test.js +0 -126
  249. package/generators/tests/unit/lib/dbschema-kit/dialect/oracle.test.js +0 -126
  250. package/generators/tests/unit/lib/dbschema-kit/dialect/postgres.test.js +0 -131
  251. package/generators/tests/unit/lib/dbschema-kit/dialect/sqlite.test.js +0 -126
  252. package/generators/tests/unit/lib/dbschema-kit/driver-loader.test.js +0 -93
  253. package/generators/tests/unit/lib/dbschema-kit/emitters/create-index.test.js +0 -173
  254. package/generators/tests/unit/lib/dbschema-kit/emitters/create-table.test.js +0 -376
  255. package/generators/tests/unit/lib/dbschema-kit/emitters/drop-table.test.js +0 -78
  256. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/invalid-dialect.env +0 -6
  257. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-dialect.env +0 -5
  258. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/missing-host.env +0 -5
  259. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/oracle-valid.env +0 -6
  260. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/postgres-valid.env +0 -7
  261. package/generators/tests/unit/lib/dbschema-kit/fixtures/connection/sqlite-valid.env +0 -2
  262. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/category.js +0 -11
  263. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/item_product.js +0 -11
  264. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound.js +0 -24
  265. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/stock_inbound_item.js +0 -28
  266. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/supplier.js +0 -9
  267. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory/warehouse.js +0 -9
  268. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-invalid/orphan.js +0 -17
  269. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/category.js +0 -11
  270. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/item_product.js +0 -11
  271. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/supplier.js +0 -9
  272. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/master/warehouse.js +0 -9
  273. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound.js +0 -24
  274. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/mini-inventory-multifolder/transactions/stock_inbound_item.js +0 -28
  275. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/audit/events.js +0 -18
  276. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/inventory/products.js +0 -9
  277. package/generators/tests/unit/lib/dbschema-kit/fixtures/integration/multi-schema/public/users.js +0 -9
  278. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/extra/category.js +0 -8
  279. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-subfolder/master/category.js +0 -8
  280. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/bar.js +0 -8
  281. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/duplicate-tablename/foo.js +0 -8
  282. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/empty-folder/README.md +0 -1
  283. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-export/plain.js +0 -3
  284. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/invalid-schema/bad.js +0 -6
  285. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/legacy-pattern/legacy.js +0 -12
  286. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/audit/products.js +0 -9
  287. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-distinct/inventory/products.js +0 -9
  288. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/a/products.js +0 -8
  289. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/multi-schema-duplicate/b/products.js +0 -8
  290. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/nested-deep/a/b/c/deep_table.js +0 -8
  291. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/.hidden/ignored.js +0 -7
  292. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/category.js +0 -8
  293. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/master/supplier.js +0 -8
  294. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound.js +0 -8
  295. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/recursive-multi-folder/transactions/stock_inbound_item.js +0 -8
  296. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/category.js +0 -8
  297. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-multiple/item_product.js +0 -9
  298. package/generators/tests/unit/lib/dbschema-kit/fixtures/loader/valid-single/category.js +0 -8
  299. package/generators/tests/unit/lib/dbschema-kit/integration.test.js +0 -217
  300. package/generators/tests/unit/lib/dbschema-kit/introspect-mapper.test.js +0 -403
  301. package/generators/tests/unit/lib/dbschema-kit/ir-builder.test.js +0 -390
  302. package/generators/tests/unit/lib/dbschema-kit/loader.test.js +0 -128
  303. package/generators/tests/unit/lib/dbschema-kit/naming.test.js +0 -170
  304. package/generators/tests/unit/lib/dbschema-kit/parser/shorthand-parser.test.js +0 -237
  305. package/generators/tests/unit/lib/dbschema-kit/schema-printer.test.js +0 -251
  306. package/generators/tests/unit/lib/dbschema-kit/statement-modifier.test.js +0 -105
  307. package/generators/tests/unit/lib/dbschema-kit/statement-splitter.test.js +0 -165
  308. package/generators/tests/unit/lib/dbschema-kit/topological-sort.test.js +0 -135
  309. package/generators/tests/unit/lib/dbschema-kit/validator/check-compatibility-validator.test.js +0 -373
  310. package/generators/tests/unit/lib/dbschema-kit/validator/circular-relation-validator.test.js +0 -454
  311. package/generators/tests/unit/lib/dbschema-kit/validator/cross-model-validator.test.js +0 -512
  312. package/generators/tests/unit/lib/dbschema-kit/validator/enhanced-validate-integration.test.js +0 -390
  313. package/generators/tests/unit/lib/dbschema-kit/validator/naming-convention-validator.test.js +0 -306
  314. package/generators/tests/unit/lib/dbschema-kit/validator/schema-validator.test.js +0 -443
  315. package/generators/tests/unit/lib/dbschema-kit/validator/type-compatibility-validator.test.js +0 -440
  316. package/generators/tests/unit/lib/dbschema-kit/validator/validator-reporter.test.js +0 -172
  317. package/generators/tests/unit/lib/metadata-manager-dashboard.test.js +0 -256
  318. package/generators/tests/unit/lib/payload-validator-fieldpolicy.test.js +0 -240
  319. package/generators/tests/unit/lib/processor-validation-generator.test.js +0 -300
  320. package/generators/tests/unit/lib/sensitive-field-masker.test.js +0 -170
  321. package/generators/tests/unit/lib/sql-table-extractor.test.js +0 -119
  322. package/scripts/generate-integrity-manifest.js +0 -124
  323. package/scripts/snapshot-cli-contracts.js +0 -194
  324. 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
- }