go-duck-cli 1.3.2 → 1.3.3
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/generators/ai_docs.js +14 -11
- package/generators/devops.js +62 -0
- package/generators/postman.js +21 -18
- package/generators/swagger.js +8 -5
- package/package.json +1 -1
package/generators/ai_docs.js
CHANGED
|
@@ -5,6 +5,9 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
|
|
|
5
5
|
const aiDocsDir = path.join(outputDir, 'docs', 'ai');
|
|
6
6
|
await fs.ensureDir(aiDocsDir);
|
|
7
7
|
|
|
8
|
+
const apiPrefixRaw = config.server?.rest?.['api-path-prefix'] || '/api';
|
|
9
|
+
const apiPrefix = apiPrefixRaw.endsWith('/') ? apiPrefixRaw.slice(0, -1) : apiPrefixRaw;
|
|
10
|
+
|
|
8
11
|
// 1. ARCHITECTURE.md
|
|
9
12
|
const appName = config.name || 'go-duck-app';
|
|
10
13
|
const hasMongo = config.datasource?.mongodb?.enabled;
|
|
@@ -32,7 +35,7 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
|
|
|
32
35
|
archContent += `- **Active**: ${storageActive ? 'Yes' : 'No'}\n`;
|
|
33
36
|
if (storageActive) {
|
|
34
37
|
archContent += `- **Enabled Nodes**: ${Object.keys(config.storage).filter(k => config.storage[k]?.enabled).join(', ')}\n`;
|
|
35
|
-
archContent += `- **Endpoints**: \n - Upload: \`POST /
|
|
38
|
+
archContent += `- **Endpoints**: \n - Upload: \`POST ${apiPrefix}/storage/upload?provider=\`\n - Exact Retrieve: \`GET ${apiPrefix}/storage/download/*key?provider=\`\n - Cross-Scan Locate: \`GET ${apiPrefix}/storage/scan/*key\`\n`;
|
|
36
39
|
}
|
|
37
40
|
const bootstrapActive = config.storage?.bootstrap?.enabled;
|
|
38
41
|
if (bootstrapActive) {
|
|
@@ -53,25 +56,25 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
|
|
|
53
56
|
|
|
54
57
|
// 2. ENDPOINTS.md
|
|
55
58
|
let endpointsContent = `# REST & gRPC API Surface\n\n`;
|
|
56
|
-
endpointsContent += `## Base Path:
|
|
59
|
+
endpointsContent += `## Base Path: \`${apiPrefix}\`\n\n`;
|
|
57
60
|
endpointsContent += `### Standard Entity Endpoints\n`;
|
|
58
61
|
for (const entity of entities) {
|
|
59
62
|
const routeName = entity.name.toLowerCase() + 's';
|
|
60
63
|
endpointsContent += `\n#### ${entity.name}\n`;
|
|
61
|
-
endpointsContent += `- \`GET
|
|
62
|
-
endpointsContent += `- \`GET
|
|
63
|
-
endpointsContent += `- \`POST
|
|
64
|
-
endpointsContent += `- \`PUT
|
|
65
|
-
endpointsContent += `- \`DELETE
|
|
66
|
-
endpointsContent += `- \`POST
|
|
64
|
+
endpointsContent += `- \`GET ${apiPrefix}/${routeName}\` (Pagination & dynamic sorting, e.g. \`?page=1&size=10&eager=true&sort=id,asc\`)\n`;
|
|
65
|
+
endpointsContent += `- \`GET ${apiPrefix}/${routeName}/:id\`\n`;
|
|
66
|
+
endpointsContent += `- \`POST ${apiPrefix}/${routeName}\`\n`;
|
|
67
|
+
endpointsContent += `- \`PUT ${apiPrefix}/${routeName}/:id\`\n`;
|
|
68
|
+
endpointsContent += `- \`DELETE ${apiPrefix}/${routeName}/:id\`\n`;
|
|
69
|
+
endpointsContent += `- \`POST ${apiPrefix}/${routeName}/bulk\` (Bulk Create/Update)\n`;
|
|
67
70
|
if (entity.isSearchable) {
|
|
68
|
-
endpointsContent += `- \`GET /
|
|
71
|
+
endpointsContent += `- \`GET ${apiPrefix}/search/${routeName}?q={query}\` (Elasticsearch)\n`;
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
endpointsContent += `\n## Infrastructure & Management APIs (SuperAdmin Protected)\n`;
|
|
73
|
-
endpointsContent += `- \`GET /
|
|
74
|
-
endpointsContent += `- \`POST /
|
|
76
|
+
endpointsContent += `- \`GET ${apiPrefix}/admin/audit\` (Fetches Global Delta logs from the Centralized Audit Engine)\n`;
|
|
77
|
+
endpointsContent += `- \`POST ${apiPrefix}/admin/metering/limit\` (Set SaaS Quota limits)\n`;
|
|
75
78
|
endpointsContent += `- \`POST /management/tenant/assign\` (Dynamically initialize new Tenant DBs)\n`;
|
|
76
79
|
|
|
77
80
|
endpointsContent += `\n## Open APIs (No JWT required)\n`;
|
package/generators/devops.js
CHANGED
|
@@ -210,10 +210,26 @@ services:
|
|
|
210
210
|
- GO_DUCK_DATASOURCE_PASSWORD=${config.datasource?.password || 'password'}
|
|
211
211
|
- GO_DUCK_DATASOURCE_DATABASE=${config.datasource?.database || 'go_duck_master'}
|
|
212
212
|
- GO_DUCK_DATASOURCE_PORT=5432
|
|
213
|
+
- GO_DUCK_DATASOURCE_MONGODB_ENABLED=${config.datasource?.mongodb?.enabled ? 'true' : 'false'}
|
|
214
|
+
- GO_DUCK_DATASOURCE_MONGODB_URI=mongodb://mongodb:27017
|
|
215
|
+
- GO_DUCK_DATASOURCE_MONGODB_DATABASE=${config.datasource?.mongodb?.database || 'goduck_document_store'}
|
|
213
216
|
- GO_DUCK_CACHE_REDIS_HOST=redis:6379
|
|
217
|
+
- GO_DUCK_CACHE_REDIS_PASSWORD=${config.cache?.redis?.password || ''}
|
|
214
218
|
- GO_DUCK_MESSAGING_MQTT_BROKER=tcp://mosquitto:1883
|
|
219
|
+
- GO_DUCK_MESSAGING_MQTT_USERNAME=${config.messaging?.mqtt?.username || 'dev_user'}
|
|
220
|
+
- GO_DUCK_MESSAGING_MQTT_PASSWORD=${config.messaging?.mqtt?.password || 'dev_password'}
|
|
215
221
|
- GO_DUCK_TELEMETRY_OTEL_ENDPOINT=otel-collector:4317
|
|
216
222
|
- GO_DUCK_ELASTICSEARCH_ADDRESSES=http://elasticsearch:9200
|
|
223
|
+
- GO_DUCK_ELASTICSEARCH_USERNAME=${config.elasticsearch?.username || 'elastic'}
|
|
224
|
+
- GO_DUCK_ELASTICSEARCH_PASSWORD=${config.elasticsearch?.password || 'changeme'}
|
|
225
|
+
- GO_DUCK_SECURITY_KEYCLOAK_HOST=http://keycloak:8080
|
|
226
|
+
- GO_DUCK_SECURITY_KEYCLOAK_REALM=${config.security?.['keycloak-realm'] || 'go-duck-realm'}
|
|
227
|
+
- GO_DUCK_SECURITY_KEYCLOAK_APP_CLIENT_ID=${config.security?.['keycloak-app-client-id'] || 'go-duck-app'}
|
|
228
|
+
- GO_DUCK_SECURITY_KEYCLOAK_SERVICE_CLIENT_ID=${config.security?.['keycloak-service-client-id'] || 'go-duck-service'}
|
|
229
|
+
- GO_DUCK_SECURITY_KEYCLOAK_SERVICE_SECRET=${config.security?.['keycloak-service-secret'] || 'service-secret-123'}
|
|
230
|
+
- GO_DUCK_STORAGE_MINIO_ENDPOINT=http://minio:9000
|
|
231
|
+
- GO_DUCK_STORAGE_MINIO_ACCESS_KEY=${config.storage?.minio?.['access-key'] || 'minioadmin'}
|
|
232
|
+
- GO_DUCK_STORAGE_MINIO_SECRET_KEY=${config.storage?.minio?.['secret-key'] || 'minioadmin'}
|
|
217
233
|
restart: always
|
|
218
234
|
networks:
|
|
219
235
|
- go-duck-net
|
|
@@ -244,10 +260,26 @@ services:
|
|
|
244
260
|
- GO_DUCK_DATASOURCE_PASSWORD=${config.datasource?.password || 'password'}
|
|
245
261
|
- GO_DUCK_DATASOURCE_DATABASE=${config.datasource?.database || 'go_duck_master'}
|
|
246
262
|
- GO_DUCK_DATASOURCE_PORT=5432
|
|
263
|
+
- GO_DUCK_DATASOURCE_MONGODB_ENABLED=${config.datasource?.mongodb?.enabled ? 'true' : 'false'}
|
|
264
|
+
- GO_DUCK_DATASOURCE_MONGODB_URI=mongodb://mongodb:27017
|
|
265
|
+
- GO_DUCK_DATASOURCE_MONGODB_DATABASE=${config.datasource?.mongodb?.database || 'goduck_document_store'}
|
|
247
266
|
- GO_DUCK_CACHE_REDIS_HOST=redis:6379
|
|
267
|
+
- GO_DUCK_CACHE_REDIS_PASSWORD=${config.cache?.redis?.password || ''}
|
|
248
268
|
- GO_DUCK_MESSAGING_MQTT_BROKER=tcp://mosquitto:1883
|
|
269
|
+
- GO_DUCK_MESSAGING_MQTT_USERNAME=${config.messaging?.mqtt?.username || 'dev_user'}
|
|
270
|
+
- GO_DUCK_MESSAGING_MQTT_PASSWORD=${config.messaging?.mqtt?.password || 'dev_password'}
|
|
249
271
|
- GO_DUCK_TELEMETRY_OTEL_ENDPOINT=otel-collector:4317
|
|
250
272
|
- GO_DUCK_ELASTICSEARCH_ADDRESSES=http://elasticsearch:9200
|
|
273
|
+
- GO_DUCK_ELASTICSEARCH_USERNAME=${config.elasticsearch?.username || 'elastic'}
|
|
274
|
+
- GO_DUCK_ELASTICSEARCH_PASSWORD=${config.elasticsearch?.password || 'changeme'}
|
|
275
|
+
- GO_DUCK_SECURITY_KEYCLOAK_HOST=http://keycloak:8080
|
|
276
|
+
- GO_DUCK_SECURITY_KEYCLOAK_REALM=${config.security?.['keycloak-realm'] || 'go-duck-realm'}
|
|
277
|
+
- GO_DUCK_SECURITY_KEYCLOAK_APP_CLIENT_ID=${config.security?.['keycloak-app-client-id'] || 'go-duck-app'}
|
|
278
|
+
- GO_DUCK_SECURITY_KEYCLOAK_SERVICE_CLIENT_ID=${config.security?.['keycloak-service-client-id'] || 'go-duck-service'}
|
|
279
|
+
- GO_DUCK_SECURITY_KEYCLOAK_SERVICE_SECRET=${config.security?.['keycloak-service-secret'] || 'service-secret-123'}
|
|
280
|
+
- GO_DUCK_STORAGE_MINIO_ENDPOINT=http://minio:9000
|
|
281
|
+
- GO_DUCK_STORAGE_MINIO_ACCESS_KEY=${config.storage?.minio?.['access-key'] || 'minioadmin'}
|
|
282
|
+
- GO_DUCK_STORAGE_MINIO_SECRET_KEY=${config.storage?.minio?.['secret-key'] || 'minioadmin'}
|
|
251
283
|
depends_on:
|
|
252
284
|
postgres:
|
|
253
285
|
condition: service_healthy
|
|
@@ -467,18 +499,48 @@ spec:
|
|
|
467
499
|
value: "${config.datasource?.database || 'go_duck_master'}"
|
|
468
500
|
- name: GO_DUCK_DATASOURCE_PORT
|
|
469
501
|
value: "5432"
|
|
502
|
+
- name: GO_DUCK_DATASOURCE_MONGODB_ENABLED
|
|
503
|
+
value: "${config.datasource?.mongodb?.enabled ? 'true' : 'false'}"
|
|
504
|
+
- name: GO_DUCK_DATASOURCE_MONGODB_URI
|
|
505
|
+
value: mongodb://mongodb.${shortName}-mongodb-k8s.svc.cluster.local:27017
|
|
506
|
+
- name: GO_DUCK_DATASOURCE_MONGODB_DATABASE
|
|
507
|
+
value: "${config.datasource?.mongodb?.database || 'goduck_document_store'}"
|
|
470
508
|
- name: GO_DUCK_CACHE_REDIS_HOST
|
|
471
509
|
value: redis.${shortName}-redis-k8s.svc.cluster.local:6379
|
|
510
|
+
- name: GO_DUCK_CACHE_REDIS_PASSWORD
|
|
511
|
+
value: "${config.cache?.redis?.password || ''}"
|
|
472
512
|
- name: GO_DUCK_MESSAGING_MQTT_BROKER
|
|
473
513
|
value: tcp://mosquitto.${shortName}-mosquitto-k8s.svc.cluster.local:1883
|
|
514
|
+
- name: GO_DUCK_MESSAGING_MQTT_USERNAME
|
|
515
|
+
value: "${config.messaging?.mqtt?.username || 'dev_user'}"
|
|
516
|
+
- name: GO_DUCK_MESSAGING_MQTT_PASSWORD
|
|
517
|
+
value: "${config.messaging?.mqtt?.password || 'dev_password'}"
|
|
474
518
|
- name: GO_DUCK_MESSAGING_NATS_URL
|
|
475
519
|
value: nats://nats.${shortName}-nats-k8s.svc.cluster.local:4222
|
|
476
520
|
- name: GO_DUCK_TELEMETRY_OTEL_ENDPOINT
|
|
477
521
|
value: otel-collector.${shortName}-otel-collector-k8s.svc.cluster.local:4317
|
|
478
522
|
- name: GO_DUCK_ELASTICSEARCH_ADDRESSES
|
|
479
523
|
value: http://elasticsearch.${shortName}-elasticsearch-k8s.svc.cluster.local:9200
|
|
524
|
+
- name: GO_DUCK_ELASTICSEARCH_USERNAME
|
|
525
|
+
value: "${config.elasticsearch?.username || 'elastic'}"
|
|
526
|
+
- name: GO_DUCK_ELASTICSEARCH_PASSWORD
|
|
527
|
+
value: "${config.elasticsearch?.password || 'changeme'}"
|
|
480
528
|
- name: GO_DUCK_SECURITY_KEYCLOAK_HOST
|
|
481
529
|
value: http://keycloak.${shortName}-keycloak-k8s.svc.cluster.local:8080
|
|
530
|
+
- name: GO_DUCK_SECURITY_KEYCLOAK_REALM
|
|
531
|
+
value: "${config.security?.['keycloak-realm'] || 'go-duck-realm'}"
|
|
532
|
+
- name: GO_DUCK_SECURITY_KEYCLOAK_APP_CLIENT_ID
|
|
533
|
+
value: "${config.security?.['keycloak-app-client-id'] || 'go-duck-app'}"
|
|
534
|
+
- name: GO_DUCK_SECURITY_KEYCLOAK_SERVICE_CLIENT_ID
|
|
535
|
+
value: "${config.security?.['keycloak-service-client-id'] || 'go-duck-service'}"
|
|
536
|
+
- name: GO_DUCK_SECURITY_KEYCLOAK_SERVICE_SECRET
|
|
537
|
+
value: "${config.security?.['keycloak-service-secret'] || 'service-secret-123'}"
|
|
538
|
+
- name: GO_DUCK_STORAGE_MINIO_ENDPOINT
|
|
539
|
+
value: "http://minio.${shortName}-minio-k8s.svc.cluster.local:9000"
|
|
540
|
+
- name: GO_DUCK_STORAGE_MINIO_ACCESS_KEY
|
|
541
|
+
value: "${config.storage?.minio?.['access-key'] || 'minioadmin'}"
|
|
542
|
+
- name: GO_DUCK_STORAGE_MINIO_SECRET_KEY
|
|
543
|
+
value: "${config.storage?.minio?.['secret-key'] || 'minioadmin'}"
|
|
482
544
|
ports:
|
|
483
545
|
- name: http
|
|
484
546
|
containerPort: ${appPort}
|
package/generators/postman.js
CHANGED
|
@@ -4,6 +4,9 @@ import chalk from 'chalk';
|
|
|
4
4
|
|
|
5
5
|
export const generatePostmanCollection = async (config, entities, outputDir, openEntities = []) => {
|
|
6
6
|
const docsDir = path.join(outputDir, 'docs');
|
|
7
|
+
const apiPrefixRaw = config.server?.rest?.['api-path-prefix'] || '/api';
|
|
8
|
+
const apiPrefix = apiPrefixRaw.endsWith('/') ? apiPrefixRaw.slice(0, -1) : apiPrefixRaw;
|
|
9
|
+
const apiPathArr = apiPrefix.split('/').filter(p => p !== '');
|
|
7
10
|
await fs.ensureDir(docsDir);
|
|
8
11
|
|
|
9
12
|
const collection = {
|
|
@@ -140,11 +143,11 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
140
143
|
{ key: "X-Tenant-ID", value: "{{tenant}}" }
|
|
141
144
|
],
|
|
142
145
|
url: {
|
|
143
|
-
raw:
|
|
146
|
+
raw: `http://{{host}}:{{port}}${apiPrefix}/admin/audit`,
|
|
144
147
|
protocol: "http",
|
|
145
148
|
host: ["{{host}}"],
|
|
146
149
|
port: "{{port}}",
|
|
147
|
-
path: [
|
|
150
|
+
path: [...apiPathArr, "admin", "audit"]
|
|
148
151
|
}
|
|
149
152
|
}
|
|
150
153
|
},
|
|
@@ -157,11 +160,11 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
157
160
|
{ key: "X-Tenant-ID", value: "{{tenant}}" }
|
|
158
161
|
],
|
|
159
162
|
url: {
|
|
160
|
-
raw:
|
|
163
|
+
raw: `http://{{host}}:{{port}}${apiPrefix}/metering/usage`,
|
|
161
164
|
protocol: "http",
|
|
162
165
|
host: ["{{host}}"],
|
|
163
166
|
port: "{{port}}",
|
|
164
|
-
path: [
|
|
167
|
+
path: [...apiPathArr, "metering", "usage"]
|
|
165
168
|
}
|
|
166
169
|
}
|
|
167
170
|
}
|
|
@@ -390,7 +393,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
390
393
|
request: {
|
|
391
394
|
method: "GET",
|
|
392
395
|
header: [ { key: "X-Tenant-ID", value: "{{tenant}}" } ],
|
|
393
|
-
url: { raw: `http://{{host}}:{{port}}/open
|
|
396
|
+
url: { raw: `http://{{host}}:{{port}}/open${apiPrefix}/${name}s?page=1&size=10&eager=true&sort=id,asc`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: ["open", ...apiPathArr, `${name}s`], query: [ { key: "page", value: "1" }, { key: "size", value: "10" }, { key: "eager", value: "true" }, { key: "sort", value: "id,asc" } ] }
|
|
394
397
|
}
|
|
395
398
|
});
|
|
396
399
|
publicItems.push({
|
|
@@ -398,7 +401,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
398
401
|
request: {
|
|
399
402
|
method: "GET",
|
|
400
403
|
header: [ { key: "X-Tenant-ID", value: "{{tenant}}" } ],
|
|
401
|
-
url: { raw: `http://{{host}}:{{port}}/open
|
|
404
|
+
url: { raw: `http://{{host}}:{{port}}/open${apiPrefix}/${name}s/1`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: ["open", ...apiPathArr, `${name}s`, "1"] }
|
|
402
405
|
}
|
|
403
406
|
});
|
|
404
407
|
}
|
|
@@ -409,7 +412,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
409
412
|
method: "POST",
|
|
410
413
|
header: [ { key: "X-Tenant-ID", value: "{{tenant}}" }, { key: "Content-Type", value: "application/json" } ],
|
|
411
414
|
body: { mode: "raw", raw: generateDummyJson(entity.fields) },
|
|
412
|
-
url: { raw: `http://{{host}}:{{port}}/open
|
|
415
|
+
url: { raw: `http://{{host}}:{{port}}/open${apiPrefix}/${name}s`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: ["open", ...apiPathArr, `${name}s`] }
|
|
413
416
|
}
|
|
414
417
|
});
|
|
415
418
|
}
|
|
@@ -425,7 +428,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
425
428
|
request: {
|
|
426
429
|
method: "GET",
|
|
427
430
|
header: [ { key: "Authorization", value: "Bearer {{token}}" }, { key: "X-Tenant-ID", value: "{{tenant}}" } ],
|
|
428
|
-
url: { raw: `http://{{host}}:{{port}}
|
|
431
|
+
url: { raw: `http://{{host}}:{{port}}${apiPrefix}/${name}s?page=1&size=10&eager=true&sort=id,asc`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: [...apiPathArr, `${name}s`], query: [ { key: "page", value: "1" }, { key: "size", value: "10" }, { key: "eager", value: "true" }, { key: "sort", value: "id,asc" } ] }
|
|
429
432
|
}
|
|
430
433
|
},
|
|
431
434
|
{
|
|
@@ -434,7 +437,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
434
437
|
method: "POST",
|
|
435
438
|
header: [ { key: "Authorization", value: "Bearer {{token}}" }, { key: "X-Tenant-ID", value: "{{tenant}}" }, { key: "Content-Type", value: "application/json" } ],
|
|
436
439
|
body: { mode: "raw", raw: generateDummyJson(entity.fields) },
|
|
437
|
-
url: { raw: `http://{{host}}:{{port}}
|
|
440
|
+
url: { raw: `http://{{host}}:{{port}}${apiPrefix}/${name}s`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: [...apiPathArr, `${name}s`] }
|
|
438
441
|
}
|
|
439
442
|
},
|
|
440
443
|
{
|
|
@@ -442,7 +445,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
442
445
|
request: {
|
|
443
446
|
method: "GET",
|
|
444
447
|
header: [ { key: "Authorization", value: "Bearer {{token}}" }, { key: "X-Tenant-ID", value: "{{tenant}}" } ],
|
|
445
|
-
url: { raw: `http://{{host}}:{{port}}
|
|
448
|
+
url: { raw: `http://{{host}}:{{port}}${apiPrefix}/${name}s/1`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: [...apiPathArr, `${name}s`, "1"] }
|
|
446
449
|
}
|
|
447
450
|
},
|
|
448
451
|
{
|
|
@@ -450,7 +453,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
450
453
|
request: {
|
|
451
454
|
method: "GET",
|
|
452
455
|
header: [ { key: "Authorization", value: "Bearer {{token}}" }, { key: "X-Tenant-ID", value: "{{tenant}}" } ],
|
|
453
|
-
url: { raw: `http://{{host}}:{{port}}/
|
|
456
|
+
url: { raw: `http://{{host}}:{{port}}${apiPrefix}/rpc/${name}?id=gt.0`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: [...apiPathArr, "rpc", name], query: [ { key: "id", value: "gt.0" } ] }
|
|
454
457
|
}
|
|
455
458
|
}
|
|
456
459
|
];
|
|
@@ -461,7 +464,7 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
461
464
|
request: {
|
|
462
465
|
method: "GET",
|
|
463
466
|
header: [ { key: "Authorization", value: "Bearer {{token}}" }, { key: "X-Tenant-ID", value: "{{tenant}}" } ],
|
|
464
|
-
url: { raw: `http://{{host}}:{{port}}/
|
|
467
|
+
url: { raw: `http://{{host}}:{{port}}${apiPrefix}/search/${name}?q=Sample`, protocol: "http", host: ["{{host}}"], port: "{{port}}", path: [...apiPathArr, "search", name], query: [ { key: "q", value: "Sample" } ] }
|
|
465
468
|
}
|
|
466
469
|
});
|
|
467
470
|
}
|
|
@@ -513,11 +516,11 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
513
516
|
]
|
|
514
517
|
},
|
|
515
518
|
url: {
|
|
516
|
-
raw:
|
|
519
|
+
raw: `http://{{host}}:{{port}}${apiPrefix}/storage/upload?provider=sftp`,
|
|
517
520
|
protocol: "http",
|
|
518
521
|
host: ["{{host}}"],
|
|
519
522
|
port: "{{port}}",
|
|
520
|
-
path: [
|
|
523
|
+
path: [...apiPathArr, "storage", "upload"],
|
|
521
524
|
query: [{ key: "provider", value: "sftp" }]
|
|
522
525
|
}
|
|
523
526
|
}
|
|
@@ -531,11 +534,11 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
531
534
|
{ key: "X-Tenant-ID", value: "{{tenant}}" }
|
|
532
535
|
],
|
|
533
536
|
url: {
|
|
534
|
-
raw:
|
|
537
|
+
raw: `http://{{host}}:{{port}}${apiPrefix}/storage/download/farm/animals/photo.jpg?provider=sftp`,
|
|
535
538
|
protocol: "http",
|
|
536
539
|
host: ["{{host}}"],
|
|
537
540
|
port: "{{port}}",
|
|
538
|
-
path: [
|
|
541
|
+
path: [...apiPathArr, "storage", "download", "farm", "animals", "photo.jpg"],
|
|
539
542
|
query: [{ key: "provider", value: "sftp" }]
|
|
540
543
|
}
|
|
541
544
|
}
|
|
@@ -549,11 +552,11 @@ export const generatePostmanCollection = async (config, entities, outputDir, ope
|
|
|
549
552
|
{ key: "X-Tenant-ID", value: "{{tenant}}" }
|
|
550
553
|
],
|
|
551
554
|
url: {
|
|
552
|
-
raw:
|
|
555
|
+
raw: `http://{{host}}:{{port}}${apiPrefix}/storage/scan/farm/animals/photo.jpg`,
|
|
553
556
|
protocol: "http",
|
|
554
557
|
host: ["{{host}}"],
|
|
555
558
|
port: "{{port}}",
|
|
556
|
-
path: [
|
|
559
|
+
path: [...apiPathArr, "storage", "scan", "farm", "animals", "photo.jpg"]
|
|
557
560
|
}
|
|
558
561
|
}
|
|
559
562
|
}
|
package/generators/swagger.js
CHANGED
|
@@ -6,6 +6,9 @@ export const generateSwaggerDocs = async (config, entities, outputDir, openEntit
|
|
|
6
6
|
const docsDir = path.join(outputDir, 'docs');
|
|
7
7
|
await fs.ensureDir(docsDir);
|
|
8
8
|
|
|
9
|
+
const apiPrefixRaw = config.server?.rest?.['api-path-prefix'] || '/api';
|
|
10
|
+
const apiPrefix = apiPrefixRaw.endsWith('/') ? apiPrefixRaw.slice(0, -1) : apiPrefixRaw;
|
|
11
|
+
|
|
9
12
|
const swagger = {
|
|
10
13
|
openapi: '3.0.0',
|
|
11
14
|
info: {
|
|
@@ -201,14 +204,14 @@ export const generateSwaggerDocs = async (config, entities, outputDir, openEntit
|
|
|
201
204
|
};
|
|
202
205
|
|
|
203
206
|
// 1a. Secured Paths
|
|
204
|
-
addEntityOperations(
|
|
207
|
+
addEntityOperations(apiPrefix, false);
|
|
205
208
|
|
|
206
209
|
// 1b. Public Paths (if marked as open)
|
|
207
|
-
addEntityOperations('/open
|
|
210
|
+
addEntityOperations('/open' + apiPrefix, true);
|
|
208
211
|
}
|
|
209
212
|
|
|
210
213
|
// 2. Add System Paths
|
|
211
|
-
swagger.paths[
|
|
214
|
+
swagger.paths[`${apiPrefix}/rpc/{table}`] = {
|
|
212
215
|
get: {
|
|
213
216
|
tags: ['Search Engine'],
|
|
214
217
|
summary: 'Generic PostgREST RPC Engine',
|
|
@@ -240,7 +243,7 @@ export const generateSwaggerDocs = async (config, entities, outputDir, openEntit
|
|
|
240
243
|
}
|
|
241
244
|
};
|
|
242
245
|
|
|
243
|
-
swagger.paths[
|
|
246
|
+
swagger.paths[`${apiPrefix}/admin/audit`] = {
|
|
244
247
|
get: {
|
|
245
248
|
tags: ['Observability'],
|
|
246
249
|
summary: 'Fetch Audit Trail',
|
|
@@ -281,7 +284,7 @@ export const generateSwaggerDocs = async (config, entities, outputDir, openEntit
|
|
|
281
284
|
};
|
|
282
285
|
|
|
283
286
|
if (config.elasticsearch?.enabled) {
|
|
284
|
-
swagger.paths[
|
|
287
|
+
swagger.paths[`${apiPrefix}/search/{entity}`] = {
|
|
285
288
|
get: {
|
|
286
289
|
tags: ['Search Engine'],
|
|
287
290
|
summary: 'Elasticsearch Global Search',
|