@restforgejs/platform 5.1.21 → 5.2.4
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.
- package/build-info.json +2 -2
- package/cli/consumer-deploy.js +2 -2
- package/cli/consumer.js +2 -2
- package/generators/cli/catalog/dashboard.js +1 -1
- package/generators/cli/catalog/dbschema.js +3 -3
- package/generators/cli/catalog/field-validation.js +1 -1
- package/generators/cli/catalog/query-declarative.js +1 -1
- package/generators/cli/config/clear-default.js +1 -1
- package/generators/cli/config/get-default.js +1 -1
- package/generators/cli/config/list.js +1 -1
- package/generators/cli/config/schema.js +1 -1
- package/generators/cli/config/set-default.js +2 -2
- package/generators/cli/config/template.js +1 -1
- package/generators/cli/dashboard/create.js +7 -7
- package/generators/cli/data/pull.js +12 -12
- package/generators/cli/data/push.js +9 -9
- package/generators/cli/endpoint/create.js +11 -11
- package/generators/cli/endpoint/list.js +3 -3
- package/generators/cli/fast-track.js +65 -12
- package/generators/cli/init.js +2 -2
- package/generators/cli/kafka/consumer-create.js +5 -5
- package/generators/cli/key/generate.js +3 -3
- package/generators/cli/key/list.js +2 -2
- package/generators/cli/key/revoke.js +3 -3
- package/generators/cli/payload/diff.js +3 -3
- package/generators/cli/payload/generate.js +5 -5
- package/generators/cli/payload/sync.js +5 -5
- package/generators/cli/payload/validate.js +3 -3
- package/generators/cli/processor/create.js +7 -7
- package/generators/cli/processor/list.js +3 -3
- package/generators/cli/project/delete.js +2 -2
- package/generators/cli/project/list.js +1 -1
- package/generators/cli/query/validate.js +3 -3
- package/generators/cli/schema/apply.js +13 -13
- package/generators/cli/schema/describe.js +6 -6
- package/generators/cli/schema/diff.js +10 -10
- package/generators/cli/schema/generate-ddl.js +11 -11
- package/generators/cli/schema/init.js +95 -95
- package/generators/cli/schema/introspect.js +8 -8
- package/generators/cli/schema/list.js +6 -6
- package/generators/cli/schema/migrate.js +91 -13
- package/generators/cli/schema/models.js +6 -6
- package/generators/cli/schema/template.js +223 -222
- package/generators/cli/schema/validate.js +6 -6
- package/generators/cli/test/generate.js +6 -6
- package/generators/lib/dbschema-kit/introspect-mapper.js +20 -0
- package/generators/lib/migrate/migrate-runner.js +12 -2
- package/generators/lib/migrate/sql-parser.js +5 -3
- package/generators/lib/payload/payload-runner.js +31 -5
- package/generators/lib/templates/dashboard-catalog.js +1 -1
- package/generators/lib/templates/db-connection-env.js +1 -1
- package/generators/lib/templates/dbschema-catalog.js +1 -1
- package/generators/lib/templates/field-validation-catalog.js +1 -1
- package/generators/lib/templates/mysql-template.js +1 -1
- package/generators/lib/templates/oracle-template.js +1 -1
- package/generators/lib/templates/postgres-template.js +1 -1
- package/generators/lib/templates/query-declarative-catalog.js +1 -1
- package/generators/lib/templates/sqlite-template.js +1 -1
- package/integrity-manifest.json +18 -18
- package/package.json +1 -1
- package/scripts/verify-integrity.js +1 -1
- package/server.js +2 -2
- package/src/components/handlers/adjust_handler.js +1 -1
- package/src/components/handlers/audit_handler.js +1 -1
- package/src/components/handlers/delete_handler.js +1 -1
- package/src/components/handlers/export_handler.js +1 -1
- package/src/components/handlers/import_handler.js +1 -1
- package/src/components/handlers/insert_handler.js +1 -1
- package/src/components/handlers/update_handler.js +1 -1
- package/src/components/handlers/upload_handler.js +1 -1
- package/src/components/handlers/workflow_handler.js +1 -1
- package/src/components/integrations/webhook.js +1 -1
- package/src/consumers/baseConsumer.js +1 -1
- package/src/consumers/declarativeMapper.js +1 -1
- package/src/consumers/handlers/apiHandler.js +1 -1
- package/src/consumers/handlers/consoleHandler.js +1 -1
- package/src/consumers/handlers/databaseHandler.js +1 -1
- package/src/consumers/handlers/index.js +1 -1
- package/src/consumers/handlers/kafkaHandler.js +1 -1
- package/src/consumers/index.js +1 -1
- package/src/consumers/messageTransformer.js +1 -1
- package/src/consumers/validator.js +1 -1
- package/src/core/db/dialect/base-dialect.js +1 -1
- package/src/core/db/dialect/index.js +1 -1
- package/src/core/db/dialect/mysql-dialect.js +1 -1
- package/src/core/db/dialect/oracle-dialect.js +1 -1
- package/src/core/db/dialect/postgres-dialect.js +1 -1
- package/src/core/db/dialect/sqlite-dialect.js +1 -1
- package/src/core/db/flatten-helper.js +1 -1
- package/src/core/db/query-builder-error.js +1 -1
- package/src/core/db/query-builder.js +1 -1
- package/src/core/db/relation-helper.js +1 -1
- package/src/core/handlers/delete_handler.js +1 -1
- package/src/core/handlers/insert_handler.js +1 -1
- package/src/core/handlers/update_handler.js +1 -1
- package/src/core/models/base-model.js +1 -1
- package/src/core/utils/cache-manager.js +1 -1
- package/src/core/utils/component-engine.js +1 -1
- package/src/core/utils/context-builder.js +1 -1
- package/src/core/utils/datetime-formatter.js +1 -1
- package/src/core/utils/datetime-parser.js +1 -1
- package/src/core/utils/db.js +1 -1
- package/src/core/utils/logger.js +1 -1
- package/src/core/utils/payload-loader.js +1 -1
- package/src/core/utils/security-checks.js +1 -1
- package/src/middleware/body-options.js +1 -1
- package/src/middleware/cors.js +1 -1
- package/src/middleware/idempotency.js +1 -1
- package/src/middleware/rate-limiter.js +1 -1
- package/src/middleware/request-logger.js +1 -1
- package/src/middleware/security-headers.js +1 -1
- package/src/models/base-model-mysql.js +1 -1
- package/src/models/base-model-oracle.js +1 -1
- package/src/models/base-model-sqlite.js +1 -1
- package/src/models/base-model.js +1 -1
- package/src/pro/caching/redis-client.js +1 -1
- package/src/pro/caching/redis-helper.js +1 -1
- package/src/pro/consumers/baseConsumer.js +1 -1
- package/src/pro/consumers/declarativeMapper.js +1 -1
- package/src/pro/consumers/handlers/apiHandler.js +1 -1
- package/src/pro/consumers/handlers/consoleHandler.js +1 -1
- package/src/pro/consumers/handlers/databaseHandler.js +1 -1
- package/src/pro/consumers/handlers/index.js +1 -1
- package/src/pro/consumers/handlers/kafkaHandler.js +1 -1
- package/src/pro/consumers/index.js +1 -1
- package/src/pro/consumers/messageTransformer.js +1 -1
- package/src/pro/consumers/validator.js +1 -1
- package/src/pro/database/base-model-mysql.js +1 -1
- package/src/pro/database/base-model-oracle.js +1 -1
- package/src/pro/database/base-model-sqlite.js +1 -1
- package/src/pro/database/db-mysql.js +1 -1
- package/src/pro/database/db-oracle.js +1 -1
- package/src/pro/database/db-sqlite.js +1 -1
- package/src/pro/excel/excel-generator.js +1 -1
- package/src/pro/excel/excel-parser.js +1 -1
- package/src/pro/excel/export-service.js +1 -1
- package/src/pro/excel/export_handler.js +1 -1
- package/src/pro/excel/import-service.js +1 -1
- package/src/pro/excel/import-validator.js +1 -1
- package/src/pro/excel/import_handler.js +1 -1
- package/src/pro/excel/upsert-builder.js +1 -1
- package/src/pro/idgen/idgen-routes.js +1 -1
- package/src/pro/integrations/lookup-resolver.js +1 -1
- package/src/pro/integrations/upload-handler-v2.js +1 -1
- package/src/pro/integrations/upload-handler.js +1 -1
- package/src/pro/integrations/webhook.js +1 -1
- package/src/pro/locking/lock-routes.js +1 -1
- package/src/pro/locking/resource-lock-manager.js +1 -1
- package/src/pro/messaging/kafkaConsumerService.js +1 -1
- package/src/pro/messaging/kafkaService.js +1 -1
- package/src/pro/messaging/messagehubService.js +1 -1
- package/src/pro/messaging/rabbitmqService.js +1 -1
- package/src/pro/scheduler/job-manager.js +1 -1
- package/src/pro/scheduler/job-routes.js +1 -1
- package/src/pro/scheduler/job-validator.js +1 -1
- package/src/pro/storage/base-storage-provider.js +1 -1
- package/src/pro/storage/file-metadata-helper.js +1 -1
- package/src/pro/storage/index.js +1 -1
- package/src/pro/storage/local-storage-provider.js +1 -1
- package/src/pro/storage/s3-storage-provider.js +1 -1
- package/src/pro/storage/upload-cleanup-job.js +1 -1
- package/src/pro/storage/upload-cleanup-scheduler.js +1 -1
- package/src/pro/storage/upload-pending-tracker.js +1 -1
- package/src/pro/websocket/broadcast-helper.js +1 -1
- package/src/pro/websocket/index.js +1 -1
- package/src/pro/websocket/livesync-server.js +1 -1
- package/src/pro/websocket/ws-broadcaster.js +1 -1
- package/src/services/export-service.js +1 -1
- package/src/services/import-service.js +1 -1
- package/src/services/kafkaConsumerService.js +1 -1
- package/src/services/kafkaService.js +1 -1
- package/src/services/messagehubService.js +1 -1
- package/src/services/rabbitmqService.js +1 -1
- package/src/utils/cache-invalidation-registry.js +1 -1
- package/src/utils/cache-manager.js +1 -1
- package/src/utils/component-engine.js +1 -1
- package/src/utils/config-extractor.js +1 -1
- package/src/utils/consumerLogger.js +1 -1
- package/src/utils/context-builder.js +1 -1
- package/src/utils/dashboard-helpers.js +1 -1
- package/src/utils/dateHelper.js +1 -1
- package/src/utils/datetime-formatter.js +1 -1
- package/src/utils/datetime-parser.js +1 -1
- package/src/utils/db-bootstrap.js +1 -1
- package/src/utils/db-mysql.js +1 -1
- package/src/utils/db-oracle.js +1 -1
- package/src/utils/db-sqlite.js +1 -1
- package/src/utils/db.js +1 -1
- package/src/utils/demo-generator.js +1 -1
- package/src/utils/excel-generator.js +1 -1
- package/src/utils/excel-parser.js +1 -1
- package/src/utils/file-watcher.js +1 -1
- package/src/utils/id-generator.js +1 -1
- package/src/utils/idempotency-manager.js +1 -1
- package/src/utils/import-validator.js +1 -1
- package/src/utils/license-client.js +1 -1
- package/src/utils/lock-manager.js +1 -1
- package/src/utils/logger.js +1 -1
- package/src/utils/lookup-resolver.js +1 -1
- package/src/utils/payload-loader.js +1 -1
- package/src/utils/processor-response.js +1 -1
- package/src/utils/rabbitmq.js +1 -1
- package/src/utils/redis-client.js +1 -1
- package/src/utils/redis-helper.js +1 -1
- package/src/utils/request-scope.js +1 -1
- package/src/utils/security-checks.js +1 -1
- package/src/utils/service-resolver.js +1 -1
- package/src/utils/shutdown-coordinator.js +1 -1
- package/src/utils/soft-delete-dashboard-guard.js +1 -1
- package/src/utils/sql-table-extractor.js +1 -1
- package/src/utils/trusted-keys.js +1 -1
- package/src/utils/upload-handler.js +1 -1
- package/src/utils/upsert-builder.js +1 -1
- package/src/utils/workflow-hook-executor.js +1 -1
|
@@ -1,222 +1,223 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Contract: schema template
|
|
5
|
-
*
|
|
6
|
-
* Browse, preview, dan generate template schema dari koleksi RestForge Schema
|
|
7
|
-
* Reference (85 template, 30 domain, 33 section). Verb ini bertindak sebagai
|
|
8
|
-
* wrapper terhadap binary native `sdf-tools.exe` yang di-ship melalui folder
|
|
9
|
-
* bin/. Semua filter dan display flag diteruskan ke binary; help text di sisi
|
|
10
|
-
* Node mempertahankan kontrak CLI (contract validator + help generator).
|
|
11
|
-
*
|
|
12
|
-
* Binary lookup: <package-root>/bin/sdf-tools.exe relatif terhadap file ini
|
|
13
|
-
* (resolusi sama untuk source workspace dan installation di node_modules).
|
|
14
|
-
*
|
|
15
|
-
* Platform: saat ini hanya Windows (sdf-tools.exe). Pemanggilan di non-Windows
|
|
16
|
-
* akan return error eksplisit, bukan crash diam-diam.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const os = require('os');
|
|
21
|
-
const path = require('path');
|
|
22
|
-
const { spawnSync } = require('child_process');
|
|
23
|
-
|
|
24
|
-
const VALUE_FLAGS = ['domain', 'table', 'category', 'pattern', 'section', 'lang', '
|
|
25
|
-
const BOOLEAN_FLAGS = [
|
|
26
|
-
'has-sdf',
|
|
27
|
-
'no-sdf',
|
|
28
|
-
'show',
|
|
29
|
-
'example',
|
|
30
|
-
'generate',
|
|
31
|
-
'force',
|
|
32
|
-
'list-domains',
|
|
33
|
-
'list-categories',
|
|
34
|
-
'list-sections',
|
|
35
|
-
'stats'
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
function resolveBinaryPath() {
|
|
39
|
-
if (os.platform() !== 'win32') return null;
|
|
40
|
-
return path.resolve(__dirname, '..', '..', '..', 'bin', 'sdf-tools.exe');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function buildBinaryArgs(args) {
|
|
44
|
-
const out = [];
|
|
45
|
-
for (const name of VALUE_FLAGS) {
|
|
46
|
-
const value = args[name];
|
|
47
|
-
if (value === undefined || value === null || value === '') continue;
|
|
48
|
-
out.push(`--${name}=${value}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
'npx restforge schema template
|
|
176
|
-
'npx restforge schema template --domain=erp
|
|
177
|
-
'npx restforge schema template --
|
|
178
|
-
'npx restforge schema template --table=sales_order --show
|
|
179
|
-
'npx restforge schema template --table=sales_order --
|
|
180
|
-
'npx restforge schema template --
|
|
181
|
-
'npx restforge schema template --
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
err
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
err
|
|
218
|
-
err.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contract: schema template
|
|
5
|
+
*
|
|
6
|
+
* Browse, preview, dan generate template schema dari koleksi RestForge Schema
|
|
7
|
+
* Reference (85 template, 30 domain, 33 section). Verb ini bertindak sebagai
|
|
8
|
+
* wrapper terhadap binary native `sdf-tools.exe` yang di-ship melalui folder
|
|
9
|
+
* bin/. Semua filter dan display flag diteruskan ke binary; help text di sisi
|
|
10
|
+
* Node mempertahankan kontrak CLI (contract validator + help generator).
|
|
11
|
+
*
|
|
12
|
+
* Binary lookup: <package-root>/bin/sdf-tools.exe relatif terhadap file ini
|
|
13
|
+
* (resolusi sama untuk source workspace dan installation di node_modules).
|
|
14
|
+
*
|
|
15
|
+
* Platform: saat ini hanya Windows (sdf-tools.exe). Pemanggilan di non-Windows
|
|
16
|
+
* akan return error eksplisit, bukan crash diam-diam.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const os = require('os');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
const { spawnSync } = require('child_process');
|
|
23
|
+
|
|
24
|
+
const VALUE_FLAGS = ['domain', 'table', 'category', 'pattern', 'section', 'lang', 'format'];
|
|
25
|
+
const BOOLEAN_FLAGS = [
|
|
26
|
+
'has-sdf',
|
|
27
|
+
'no-sdf',
|
|
28
|
+
'show',
|
|
29
|
+
'example',
|
|
30
|
+
'generate',
|
|
31
|
+
'force',
|
|
32
|
+
'list-domains',
|
|
33
|
+
'list-categories',
|
|
34
|
+
'list-sections',
|
|
35
|
+
'stats'
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function resolveBinaryPath() {
|
|
39
|
+
if (os.platform() !== 'win32') return null;
|
|
40
|
+
return path.resolve(__dirname, '..', '..', '..', 'bin', 'sdf-tools.exe');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function buildBinaryArgs(args) {
|
|
44
|
+
const out = [];
|
|
45
|
+
for (const name of VALUE_FLAGS) {
|
|
46
|
+
const value = args[name];
|
|
47
|
+
if (value === undefined || value === null || value === '') continue;
|
|
48
|
+
out.push(`--${name}=${value}`);
|
|
49
|
+
}
|
|
50
|
+
if (args['schema-path']) out.push(`--path=${args['schema-path']}`);
|
|
51
|
+
for (const name of BOOLEAN_FLAGS) {
|
|
52
|
+
if (args[name] === true) {
|
|
53
|
+
out.push(`--${name}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
resource: 'schema',
|
|
61
|
+
verb: 'template',
|
|
62
|
+
description: 'Browse, preview, and generate schema templates from the RestForge Schema Reference collection',
|
|
63
|
+
category: 'utility',
|
|
64
|
+
flags: {
|
|
65
|
+
domain: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
required: false,
|
|
68
|
+
default: null,
|
|
69
|
+
description: 'Filter by domain (csv, e.g., erp or erp,finance)'
|
|
70
|
+
},
|
|
71
|
+
table: {
|
|
72
|
+
type: 'string',
|
|
73
|
+
required: false,
|
|
74
|
+
default: null,
|
|
75
|
+
description: 'Filter by table name (wildcard glob: sales*, *_invoice)'
|
|
76
|
+
},
|
|
77
|
+
category: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
required: false,
|
|
80
|
+
default: null,
|
|
81
|
+
description: 'Filter by category: master-data or transactional'
|
|
82
|
+
},
|
|
83
|
+
pattern: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
required: false,
|
|
86
|
+
default: null,
|
|
87
|
+
description: 'Filter by pattern: single-table or master-detail'
|
|
88
|
+
},
|
|
89
|
+
section: {
|
|
90
|
+
type: 'string',
|
|
91
|
+
required: false,
|
|
92
|
+
default: null,
|
|
93
|
+
description: 'Filter by section code (see --list-sections)'
|
|
94
|
+
},
|
|
95
|
+
'has-sdf': {
|
|
96
|
+
type: 'boolean',
|
|
97
|
+
required: false,
|
|
98
|
+
default: false,
|
|
99
|
+
description: 'Filter only templates that have an SDF version'
|
|
100
|
+
},
|
|
101
|
+
'no-sdf': {
|
|
102
|
+
type: 'boolean',
|
|
103
|
+
required: false,
|
|
104
|
+
default: false,
|
|
105
|
+
description: 'Filter only templates that do not have an SDF version (gap analysis)'
|
|
106
|
+
},
|
|
107
|
+
show: {
|
|
108
|
+
type: 'boolean',
|
|
109
|
+
required: false,
|
|
110
|
+
default: false,
|
|
111
|
+
description: 'Print schema template (requires --table=<specific_name>)'
|
|
112
|
+
},
|
|
113
|
+
example: {
|
|
114
|
+
type: 'boolean',
|
|
115
|
+
required: false,
|
|
116
|
+
default: false,
|
|
117
|
+
description: 'Include sample data section (use with --show)'
|
|
118
|
+
},
|
|
119
|
+
lang: {
|
|
120
|
+
type: 'string',
|
|
121
|
+
required: false,
|
|
122
|
+
default: null,
|
|
123
|
+
description: 'Schema format: sdf (default) or sql'
|
|
124
|
+
},
|
|
125
|
+
generate: {
|
|
126
|
+
type: 'boolean',
|
|
127
|
+
required: false,
|
|
128
|
+
default: false,
|
|
129
|
+
description: 'Generate template to filesystem (requires --table and --schema-path)'
|
|
130
|
+
},
|
|
131
|
+
'schema-path': {
|
|
132
|
+
type: 'string',
|
|
133
|
+
required: false,
|
|
134
|
+
default: null,
|
|
135
|
+
description: 'Destination path for --generate (directory or file)'
|
|
136
|
+
},
|
|
137
|
+
force: {
|
|
138
|
+
type: 'boolean',
|
|
139
|
+
required: false,
|
|
140
|
+
default: false,
|
|
141
|
+
description: 'Overwrite existing destination file when using --generate'
|
|
142
|
+
},
|
|
143
|
+
'list-domains': {
|
|
144
|
+
type: 'boolean',
|
|
145
|
+
required: false,
|
|
146
|
+
default: false,
|
|
147
|
+
description: 'List all available application domains'
|
|
148
|
+
},
|
|
149
|
+
'list-categories': {
|
|
150
|
+
type: 'boolean',
|
|
151
|
+
required: false,
|
|
152
|
+
default: false,
|
|
153
|
+
description: 'List all template categories'
|
|
154
|
+
},
|
|
155
|
+
'list-sections': {
|
|
156
|
+
type: 'boolean',
|
|
157
|
+
required: false,
|
|
158
|
+
default: false,
|
|
159
|
+
description: 'List all sections with their categories'
|
|
160
|
+
},
|
|
161
|
+
stats: {
|
|
162
|
+
type: 'boolean',
|
|
163
|
+
required: false,
|
|
164
|
+
default: false,
|
|
165
|
+
description: 'Show collection statistics (per category, pattern, domain, section)'
|
|
166
|
+
},
|
|
167
|
+
format: {
|
|
168
|
+
type: 'string',
|
|
169
|
+
required: false,
|
|
170
|
+
default: null,
|
|
171
|
+
description: 'Output format: table (default), plain, or json'
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
examples: [
|
|
175
|
+
'npx restforge schema template',
|
|
176
|
+
'npx restforge schema template --domain=erp',
|
|
177
|
+
'npx restforge schema template --domain=erp,inventory --category=master-data',
|
|
178
|
+
'npx restforge schema template --table=sales_order --show',
|
|
179
|
+
'npx restforge schema template --table=sales_order --show --lang=sql',
|
|
180
|
+
'npx restforge schema template --table=sales_order --generate --schema-path=./schema --lang=sdf',
|
|
181
|
+
'npx restforge schema template --stats',
|
|
182
|
+
'npx restforge schema template --list-domains'
|
|
183
|
+
],
|
|
184
|
+
async handler(args) {
|
|
185
|
+
const binaryPath = resolveBinaryPath();
|
|
186
|
+
if (!binaryPath) {
|
|
187
|
+
const err = new Error(
|
|
188
|
+
`schema template hanya tersedia di Windows (sdf-tools.exe). Platform saat ini: ${os.platform()}`
|
|
189
|
+
);
|
|
190
|
+
err.exitCode = 3;
|
|
191
|
+
throw err;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!fs.existsSync(binaryPath)) {
|
|
195
|
+
const err = new Error(
|
|
196
|
+
`sdf-tools.exe tidak ditemukan di ${binaryPath}. ` +
|
|
197
|
+
'Pastikan binary sudah di-build dan tersedia di folder bin/ package.'
|
|
198
|
+
);
|
|
199
|
+
err.exitCode = 3;
|
|
200
|
+
throw err;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const binaryArgs = buildBinaryArgs(args);
|
|
204
|
+
const result = spawnSync(binaryPath, binaryArgs, {
|
|
205
|
+
stdio: 'inherit',
|
|
206
|
+
windowsHide: true
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
if (result.error) {
|
|
210
|
+
const err = new Error(`Gagal menjalankan sdf-tools.exe: ${result.error.message}`);
|
|
211
|
+
err.exitCode = 1;
|
|
212
|
+
throw err;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const status = typeof result.status === 'number' ? result.status : 1;
|
|
216
|
+
if (status !== 0) {
|
|
217
|
+
const err = new Error(`sdf-tools.exe exit code ${status}`);
|
|
218
|
+
err.exitCode = status;
|
|
219
|
+
err.silent = true;
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
@@ -63,21 +63,21 @@ function printSuccessLines(absPath, models) {
|
|
|
63
63
|
module.exports = {
|
|
64
64
|
resource: 'schema',
|
|
65
65
|
verb: 'validate',
|
|
66
|
-
description: '
|
|
66
|
+
description: 'Validate schema definition files (single-model and cross-model)',
|
|
67
67
|
category: 'introspection',
|
|
68
68
|
flags: {
|
|
69
|
-
path: {
|
|
69
|
+
'schema-path': {
|
|
70
70
|
type: 'string',
|
|
71
71
|
required: true,
|
|
72
|
-
description: 'Path file
|
|
72
|
+
description: 'Path to schema file or directory (e.g., ./schema or ./schema/users.js)'
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
examples: [
|
|
76
|
-
'npx restforge schema validate --path=./schema',
|
|
77
|
-
'npx restforge schema validate --path=./my-schema'
|
|
76
|
+
'npx restforge schema validate --schema-path=./schema',
|
|
77
|
+
'npx restforge schema validate --schema-path=./my-schema'
|
|
78
78
|
],
|
|
79
79
|
async handler(args) {
|
|
80
|
-
const schemaPath = args
|
|
80
|
+
const schemaPath = args['schema-path'];
|
|
81
81
|
const absPath = path.resolve(process.cwd(), schemaPath);
|
|
82
82
|
|
|
83
83
|
let models;
|
|
@@ -145,36 +145,36 @@ function handleInit(args) {
|
|
|
145
145
|
module.exports = {
|
|
146
146
|
resource: 'test',
|
|
147
147
|
verb: 'generate',
|
|
148
|
-
description: 'Generate integration test file (Jest + Supertest)
|
|
148
|
+
description: 'Generate an integration test file (Jest + Supertest) for an endpoint',
|
|
149
149
|
category: 'generation',
|
|
150
150
|
flags: {
|
|
151
151
|
project: {
|
|
152
152
|
type: 'string',
|
|
153
153
|
required: true,
|
|
154
|
-
description: '
|
|
154
|
+
description: 'Target project name'
|
|
155
155
|
},
|
|
156
156
|
endpoint: {
|
|
157
157
|
type: 'string',
|
|
158
158
|
required: true,
|
|
159
|
-
description: '
|
|
159
|
+
description: 'Endpoint name to test'
|
|
160
160
|
},
|
|
161
161
|
port: {
|
|
162
162
|
type: 'number',
|
|
163
163
|
required: false,
|
|
164
164
|
default: 3000,
|
|
165
|
-
description: '
|
|
165
|
+
description: 'Server port when running tests'
|
|
166
166
|
},
|
|
167
167
|
init: {
|
|
168
168
|
type: 'boolean',
|
|
169
169
|
required: false,
|
|
170
170
|
default: false,
|
|
171
|
-
description: '
|
|
171
|
+
description: 'Initialize test-data.json configuration (global + per-endpoint if endpoint is provided)'
|
|
172
172
|
},
|
|
173
173
|
force: {
|
|
174
174
|
type: 'boolean',
|
|
175
175
|
required: false,
|
|
176
176
|
default: false,
|
|
177
|
-
description: '
|
|
177
|
+
description: 'Overwrite existing test files'
|
|
178
178
|
}
|
|
179
179
|
},
|
|
180
180
|
examples: [
|
|
@@ -599,6 +599,26 @@ function parseCheckExpression(rawExpr) {
|
|
|
599
599
|
}
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
+
// PostgreSQL normalises IN-list CHECKs to: (col)::type = ANY ((ARRAY['a'::type, ...]::type[]))
|
|
603
|
+
// This form appears verbatim in pg_get_constraintdef output and is semantically identical to IN (...).
|
|
604
|
+
const pgAnyRe = /^\(?([A-Za-z_][A-Za-z0-9_]*)\)?(?:::\w+(?:\s+\w+)*)?\s*=\s*ANY\s*\((.+)\)\s*$/i;
|
|
605
|
+
const pgAnyM = e.match(pgAnyRe);
|
|
606
|
+
if (pgAnyM) {
|
|
607
|
+
const field = pgAnyM[1].toLowerCase();
|
|
608
|
+
const anyArg = pgAnyM[2];
|
|
609
|
+
const arrOpen = anyArg.toUpperCase().indexOf('ARRAY[');
|
|
610
|
+
if (arrOpen !== -1) {
|
|
611
|
+
const arrClose = anyArg.indexOf(']', arrOpen + 6);
|
|
612
|
+
if (arrClose !== -1) {
|
|
613
|
+
const raw = anyArg.slice(arrOpen + 6, arrClose);
|
|
614
|
+
// strip per-element type casts like ::character varying before parsing
|
|
615
|
+
const stripped = raw.replace(/::\w+(?:\s+\w+)*/g, '');
|
|
616
|
+
const values = parseValueList(stripped);
|
|
617
|
+
if (values) return { field, op: 'in', value: values };
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
602
622
|
return { _unparsable: true, expression: rawExpr };
|
|
603
623
|
}
|
|
604
624
|
|
|
@@ -176,9 +176,19 @@ function loadRdf(filePath) {
|
|
|
176
176
|
* Petakan nama tabel JOIN (snake_case, mis. visitor_categories) ke file RDF
|
|
177
177
|
* sibling di folder payload. Coba bentuk kebab dulu (visitor-categories.json),
|
|
178
178
|
* lalu bentuk snake (visitor_categories.json).
|
|
179
|
+
*
|
|
180
|
+
* `qualifiedName` (opsional) = identifier JOIN apa adanya sebelum schema
|
|
181
|
+
* di-strip (mis. 'sch02.company'). Tabel di custom schema ditulis `payload
|
|
182
|
+
* generate` dengan baseFilename = `--table=` literal (lihat payload-runner.js),
|
|
183
|
+
* jadi file di disk-nya `sch02-company.json`, BUKAN `company.json`. Tanpa
|
|
184
|
+
* kandidat ini, related table di schema custom selalu gagal ditemukan
|
|
185
|
+
* walau file-nya ada (lihat bug: "no RDF file found ... tried: company.json, company.json").
|
|
179
186
|
*/
|
|
180
|
-
function findRelatedRdfPath(tableName, payloadDir) {
|
|
187
|
+
function findRelatedRdfPath(tableName, payloadDir, qualifiedName) {
|
|
181
188
|
const candidates = [`${snakeToKebab(tableName)}.json`, `${tableName}.json`];
|
|
189
|
+
if (qualifiedName && qualifiedName !== tableName) {
|
|
190
|
+
candidates.push(`${qualifiedName.replace(/[._]/g, '-')}.json`);
|
|
191
|
+
}
|
|
182
192
|
for (const c of candidates) {
|
|
183
193
|
const p = path.join(payloadDir, c);
|
|
184
194
|
if (fs.existsSync(p)) return { path: p, candidates };
|
|
@@ -259,7 +269,7 @@ async function run(args) {
|
|
|
259
269
|
if (!t || seenTables.has(t)) continue;
|
|
260
270
|
seenTables.add(t);
|
|
261
271
|
|
|
262
|
-
const { path: relPath, candidates } = findRelatedRdfPath(t, payloadDir);
|
|
272
|
+
const { path: relPath, candidates } = findRelatedRdfPath(t, payloadDir, join.tableQualified);
|
|
263
273
|
if (!relPath) {
|
|
264
274
|
warnings.push(`Related table '${t}' referenced by JOIN but no RDF file found in ${payloadDir} (tried: ${candidates.join(', ')}); page not generated, only the select reference is kept`);
|
|
265
275
|
continue;
|
|
@@ -23,10 +23,11 @@ function parseTableRef(refstr) {
|
|
|
23
23
|
const afterWhere = refstr.split(WHERE_SPLIT_RE)[0].trim();
|
|
24
24
|
const cleaned = afterWhere.split(ORDER_SPLIT_RE)[0].trim();
|
|
25
25
|
const tokens = cleaned.split(/\s+/).filter(Boolean);
|
|
26
|
-
if (tokens.length === 0) return { tableName: '', alias: '' };
|
|
27
|
-
const
|
|
26
|
+
if (tokens.length === 0) return { tableName: '', alias: '', qualifiedName: '' };
|
|
27
|
+
const qualifiedName = tokens[0];
|
|
28
|
+
const tableName = stripSchema(qualifiedName);
|
|
28
29
|
const alias = tokens.length > 1 ? tokens[1] : '';
|
|
29
|
-
return { tableName, alias };
|
|
30
|
+
return { tableName, alias, qualifiedName };
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
function parseJoinCondition(condition, mainAlias) {
|
|
@@ -108,6 +109,7 @@ function parseDatatablesQuery(sql) {
|
|
|
108
109
|
const cond = parseJoinCondition(condition, mainAlias);
|
|
109
110
|
joins.push({
|
|
110
111
|
tableName: ref.tableName,
|
|
112
|
+
tableQualified: ref.qualifiedName,
|
|
111
113
|
tableAlias: ref.alias,
|
|
112
114
|
localColumn: cond.localColumn,
|
|
113
115
|
remoteColumn: cond.remoteColumn
|