@restforgejs/platform 5.1.16 → 5.1.21
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 +1 -1
- package/cli/consumer.js +1 -1
- package/generators/cli/catalog/dbschema.js +2 -1
- package/generators/cli/endpoint/list.js +264 -0
- package/generators/cli/fast-track.js +395 -37
- package/generators/cli/processor/create.js +7 -7
- package/generators/cli/processor/list.js +229 -0
- package/generators/lib/dbschema-kit/apply-executor.js +20 -0
- package/generators/lib/generators/dashboard-generator.js +5 -5
- package/generators/lib/generators/processor-validation-generator.js +4 -1
- package/generators/lib/migrate/field-type-resolver.js +23 -0
- package/generators/lib/payload/payload-runner.js +80 -3
- 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/check-install.js +8 -8
- package/scripts/verify-integrity.js +1 -1
- package/server.js +1 -1
- 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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contract: endpoint list
|
|
5
|
+
*
|
|
6
|
+
* Menampilkan daftar endpoint dari metadata project di working directory
|
|
7
|
+
* (`metadata/<project>.json`, output dari `endpoint create` / `dashboard create`).
|
|
8
|
+
* File `global.json`, `*-workbench.json`, dan backup (`.backup.` / `.corrupt.`)
|
|
9
|
+
* di-skip.
|
|
10
|
+
*
|
|
11
|
+
* Entry processor di-exclude: `processor create` juga menulis ke map `endpoints`
|
|
12
|
+
* (via MetadataManager.updateEndpointMetadata, hardcode type 'module'), sehingga
|
|
13
|
+
* nama yang terdaftar di map `processors` pada `<project>-workbench.json` bukan
|
|
14
|
+
* endpoint dan hanya tampil di `processor list`.
|
|
15
|
+
*
|
|
16
|
+
* Kolom:
|
|
17
|
+
* - Endpoint Name : key di `metadata.endpoints`
|
|
18
|
+
* - Payload : nama file `payload/<endpoint>.json` bila ada, `-` bila tidak
|
|
19
|
+
* - Action : daftar action bernilai true di metadata, `-` bila kosong
|
|
20
|
+
* (mis. endpoint bertipe dashboard); di-wrap maksimal
|
|
21
|
+
* 4 action per baris, tanpa pemotongan
|
|
22
|
+
*
|
|
23
|
+
* Output default berupa table human-readable (`--format=text`). Output JSON
|
|
24
|
+
* (untuk konsumsi AI agent / mcp-server) tersedia via `--format=json`.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
const path = require('path');
|
|
29
|
+
const ConfigReader = require('../../lib/config/config-reader');
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Baca daftar nama processor dari workbench metadata sebuah project,
|
|
33
|
+
* untuk meng-exclude entry processor dari daftar endpoint.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} metadataDir
|
|
36
|
+
* @param {string} project
|
|
37
|
+
* @returns {Set<string>}
|
|
38
|
+
*/
|
|
39
|
+
function readProcessorNames(metadataDir, project) {
|
|
40
|
+
const workbenchPath = path.join(metadataDir, `${project}-workbench.json`);
|
|
41
|
+
if (!fs.existsSync(workbenchPath)) {
|
|
42
|
+
return new Set();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const workbench = JSON.parse(fs.readFileSync(workbenchPath, 'utf8'));
|
|
47
|
+
if (workbench && typeof workbench.processors === 'object' && workbench.processors !== null) {
|
|
48
|
+
return new Set(Object.keys(workbench.processors));
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.warn(`Warning: skipping unreadable workbench metadata: ${project}-workbench.json (${error.message})`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return new Set();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Baca semua entry endpoint dari folder metadata/ di working directory.
|
|
59
|
+
* Read-only: file metadata yang corrupt di-skip dengan warning, tidak ditulis ulang.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} workingDir
|
|
62
|
+
* @returns {{ project: string, name: string, payload: string|null, actions: string[] }[]}
|
|
63
|
+
*/
|
|
64
|
+
function readEndpointEntries(workingDir) {
|
|
65
|
+
const metadataDir = path.join(workingDir, 'metadata');
|
|
66
|
+
if (!fs.existsSync(metadataDir)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const files = fs.readdirSync(metadataDir).filter(name =>
|
|
71
|
+
name.endsWith('.json') &&
|
|
72
|
+
name !== 'global.json' &&
|
|
73
|
+
!name.endsWith('-workbench.json') &&
|
|
74
|
+
!name.includes('.backup.') &&
|
|
75
|
+
!name.includes('.corrupt.')
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const entries = [];
|
|
79
|
+
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
let metadata;
|
|
82
|
+
try {
|
|
83
|
+
metadata = JSON.parse(fs.readFileSync(path.join(metadataDir, file), 'utf8'));
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn(`Warning: skipping unreadable metadata file: ${file} (${error.message})`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!metadata || typeof metadata.endpoints !== 'object' || metadata.endpoints === null) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const project = metadata.moduleName || path.basename(file, '.json');
|
|
94
|
+
const processorNames = readProcessorNames(metadataDir, project);
|
|
95
|
+
|
|
96
|
+
for (const [endpointName, endpointData] of Object.entries(metadata.endpoints)) {
|
|
97
|
+
if (processorNames.has(endpointName)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const payloadFile = `${endpointName}.json`;
|
|
102
|
+
const hasPayload = fs.existsSync(path.join(workingDir, 'payload', payloadFile));
|
|
103
|
+
|
|
104
|
+
const actions = endpointData && endpointData.actions
|
|
105
|
+
? Object.entries(endpointData.actions)
|
|
106
|
+
.filter(([, enabled]) => enabled === true)
|
|
107
|
+
.map(([action]) => action)
|
|
108
|
+
: [];
|
|
109
|
+
|
|
110
|
+
entries.push({
|
|
111
|
+
project,
|
|
112
|
+
name: endpointName,
|
|
113
|
+
payload: hasPayload ? payloadFile : null,
|
|
114
|
+
actions
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
120
|
+
return entries;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Konversi pattern glob sederhana (`*` = karakter apa pun) menjadi RegExp
|
|
125
|
+
* case-insensitive yang match keseluruhan nama. Tanpa wildcard berarti
|
|
126
|
+
* exact match.
|
|
127
|
+
* @param {string} pattern
|
|
128
|
+
* @returns {RegExp}
|
|
129
|
+
*/
|
|
130
|
+
function patternToRegExp(pattern) {
|
|
131
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
132
|
+
return new RegExp('^' + escaped.replace(/\*/g, '.*') + '$', 'i');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Potong string dengan suffix '..' bila melebihi lebar kolom (pola `project list`).
|
|
137
|
+
* @param {string} value
|
|
138
|
+
* @param {number} width
|
|
139
|
+
* @returns {string}
|
|
140
|
+
*/
|
|
141
|
+
function truncate(value, width) {
|
|
142
|
+
return value.length > width - 2
|
|
143
|
+
? value.substring(0, width - 4) + '..'
|
|
144
|
+
: value;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Render daftar endpoint ke format table human-readable.
|
|
149
|
+
* @param {{ name: string, payload: string|null, actions: string[] }[]} entries
|
|
150
|
+
* @returns {string}
|
|
151
|
+
*/
|
|
152
|
+
function renderHumanTable(entries) {
|
|
153
|
+
const lines = [];
|
|
154
|
+
|
|
155
|
+
const colName = 24;
|
|
156
|
+
const colPayload = 28;
|
|
157
|
+
const colAction = 44;
|
|
158
|
+
|
|
159
|
+
lines.push('');
|
|
160
|
+
lines.push('Registered Endpoints:');
|
|
161
|
+
lines.push('');
|
|
162
|
+
lines.push(
|
|
163
|
+
'Endpoint Name'.padEnd(colName) +
|
|
164
|
+
'Payload'.padEnd(colPayload) +
|
|
165
|
+
'Action'.padEnd(colAction)
|
|
166
|
+
);
|
|
167
|
+
lines.push('-'.repeat(colName + colPayload + colAction));
|
|
168
|
+
|
|
169
|
+
const ACTIONS_PER_LINE = 4;
|
|
170
|
+
|
|
171
|
+
for (const entry of entries) {
|
|
172
|
+
// Wrap action per 4 item; baris pertama menyatu dengan kolom lain,
|
|
173
|
+
// baris lanjutan di-indent sejajar kolom Action.
|
|
174
|
+
const actionLines = [];
|
|
175
|
+
if (entry.actions.length === 0) {
|
|
176
|
+
actionLines.push('-');
|
|
177
|
+
} else {
|
|
178
|
+
for (let i = 0; i < entry.actions.length; i += ACTIONS_PER_LINE) {
|
|
179
|
+
const chunk = entry.actions.slice(i, i + ACTIONS_PER_LINE).join(', ');
|
|
180
|
+
const isLast = i + ACTIONS_PER_LINE >= entry.actions.length;
|
|
181
|
+
actionLines.push(isLast ? chunk : chunk + ',');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
lines.push(
|
|
186
|
+
truncate(entry.name, colName).padEnd(colName) +
|
|
187
|
+
truncate(entry.payload || '-', colPayload).padEnd(colPayload) +
|
|
188
|
+
actionLines[0]
|
|
189
|
+
);
|
|
190
|
+
for (const continuation of actionLines.slice(1)) {
|
|
191
|
+
lines.push(' '.repeat(colName + colPayload) + continuation);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
lines.push('');
|
|
196
|
+
lines.push(`Total: ${entries.length} endpoint(s)`);
|
|
197
|
+
lines.push('');
|
|
198
|
+
|
|
199
|
+
return lines.join('\n');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
module.exports = {
|
|
203
|
+
resource: 'endpoint',
|
|
204
|
+
verb: 'list',
|
|
205
|
+
description: 'Menampilkan daftar endpoint dari metadata project di working directory',
|
|
206
|
+
category: 'management',
|
|
207
|
+
flags: {
|
|
208
|
+
format: {
|
|
209
|
+
type: 'string',
|
|
210
|
+
required: false,
|
|
211
|
+
default: 'text',
|
|
212
|
+
description: 'Format output: `text` (table human-readable) atau `json` (untuk AI agent / mcp-server)'
|
|
213
|
+
},
|
|
214
|
+
name: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
required: false,
|
|
217
|
+
default: null,
|
|
218
|
+
description: 'Filter nama endpoint, case-insensitive. Wildcard `*` = karakter apa pun (mis. `*product*`); tanpa wildcard berarti exact match'
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
examples: [
|
|
222
|
+
'npx restforge endpoint list',
|
|
223
|
+
'npx restforge endpoint list --format=json',
|
|
224
|
+
'npx restforge endpoint list --name=*product*'
|
|
225
|
+
],
|
|
226
|
+
async handler(args) {
|
|
227
|
+
const workingDir = ConfigReader.getWorkingDirectory();
|
|
228
|
+
const allEntries = readEndpointEntries(workingDir);
|
|
229
|
+
const format = (args.format || 'text').toLowerCase();
|
|
230
|
+
|
|
231
|
+
const entries = args.name
|
|
232
|
+
? allEntries.filter(e => patternToRegExp(args.name).test(e.name))
|
|
233
|
+
: allEntries;
|
|
234
|
+
|
|
235
|
+
if (format === 'json') {
|
|
236
|
+
const summary = {
|
|
237
|
+
totalEndpoints: entries.length,
|
|
238
|
+
projects: [...new Set(entries.map(e => e.project))].sort()
|
|
239
|
+
};
|
|
240
|
+
if (args.name) {
|
|
241
|
+
summary.namePattern = args.name;
|
|
242
|
+
}
|
|
243
|
+
const output = {
|
|
244
|
+
schemaVersion: '1.0',
|
|
245
|
+
source: 'endpoint-list',
|
|
246
|
+
summary,
|
|
247
|
+
endpoints: entries
|
|
248
|
+
};
|
|
249
|
+
process.stdout.write(JSON.stringify(output, null, 2) + '\n');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (allEntries.length === 0) {
|
|
254
|
+
console.log('');
|
|
255
|
+
console.log('No endpoints found in this project.');
|
|
256
|
+
console.log('');
|
|
257
|
+
console.log('Use "npx restforge endpoint create" to create a new endpoint.');
|
|
258
|
+
console.log('');
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
process.stdout.write(renderHumanTable(entries) + '\n');
|
|
263
|
+
}
|
|
264
|
+
};
|