prisma-swagger-autogen 1.0.6 → 1.0.8
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/dist/cli.js +13 -12
- package/package.json +2 -2
- package/dist/bin.cjs +0 -2
- package/dist/chunk-LHCOAEWQ.cjs +0 -193
- package/dist/chunk-NLFDSHIX.js +0 -193
- package/dist/cli.cjs +0 -221
- package/dist/cli.d.cts +0 -2
- package/dist/cli.d.ts +0 -2
- package/dist/index.cjs +0 -229
- package/dist/index.d.cts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -194
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
// src/index.ts
|
|
4
2
|
import fs from "fs";
|
|
5
3
|
import path from "path";
|
|
@@ -28,10 +26,9 @@ function pluralize(name) {
|
|
|
28
26
|
return `${name}s`;
|
|
29
27
|
}
|
|
30
28
|
function getRequire() {
|
|
31
|
-
|
|
32
|
-
return createRequire(base);
|
|
29
|
+
return createRequire(typeof __filename !== "undefined" ? __filename : process.cwd() + "/");
|
|
33
30
|
}
|
|
34
|
-
function loadDmmfFromProject(schemaPath) {
|
|
31
|
+
async function loadDmmfFromProject(schemaPath) {
|
|
35
32
|
const resolvedSchemaPath = schemaPath ? path.resolve(process.cwd(), schemaPath) : path.resolve(process.cwd(), "prisma/schema.prisma");
|
|
36
33
|
if (!fs.existsSync(resolvedSchemaPath)) {
|
|
37
34
|
throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
|
|
@@ -42,7 +39,11 @@ function loadDmmfFromProject(schemaPath) {
|
|
|
42
39
|
if (typeof internals.getDMMF !== "function") {
|
|
43
40
|
throw new Error(`@prisma/internals.getDMMF not available`);
|
|
44
41
|
}
|
|
45
|
-
|
|
42
|
+
const dmmf = await internals.getDMMF({ datamodel });
|
|
43
|
+
if (!dmmf || !dmmf.datamodel || !Array.isArray(dmmf.datamodel.models) || !Array.isArray(dmmf.datamodel.enums)) {
|
|
44
|
+
throw new Error(`Unexpected DMMF shape returned by @prisma/internals.getDMMF`);
|
|
45
|
+
}
|
|
46
|
+
return dmmf;
|
|
46
47
|
}
|
|
47
48
|
function scalarToSchema(scalar) {
|
|
48
49
|
switch (scalar) {
|
|
@@ -102,9 +103,7 @@ function stripWriteFields(model, getSchema, omit) {
|
|
|
102
103
|
if (!schema.properties) return schema;
|
|
103
104
|
const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
|
|
104
105
|
for (const key of Object.keys(schema.properties)) {
|
|
105
|
-
if (omit.has(key) || relationFieldNames.has(key))
|
|
106
|
-
delete schema.properties[key];
|
|
107
|
-
}
|
|
106
|
+
if (omit.has(key) || relationFieldNames.has(key)) delete schema.properties[key];
|
|
108
107
|
}
|
|
109
108
|
if (Array.isArray(schema.required)) {
|
|
110
109
|
schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
|
|
@@ -132,8 +131,8 @@ function listResponseSchema(itemRef) {
|
|
|
132
131
|
required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
|
|
133
132
|
};
|
|
134
133
|
}
|
|
135
|
-
function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
136
|
-
const dmmf = loadDmmfFromProject(schemaPath);
|
|
134
|
+
async function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
135
|
+
const dmmf = await loadDmmfFromProject(schemaPath);
|
|
137
136
|
const schemas = {};
|
|
138
137
|
const getRefName = (modelName) => `Get${modelName}Response`;
|
|
139
138
|
for (const e of dmmf.datamodel.enums) {
|
|
@@ -186,7 +185,7 @@ swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
|
|
|
186
185
|
async function run(args = []) {
|
|
187
186
|
const schemaFlagIndex = args.findIndex((a) => a === "--schema");
|
|
188
187
|
const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
|
|
189
|
-
const schemas = buildSchemasFromPrismaDmmf(schemaPath);
|
|
188
|
+
const schemas = await buildSchemasFromPrismaDmmf(schemaPath);
|
|
190
189
|
generateSwaggerConfigJs(schemas);
|
|
191
190
|
}
|
|
192
191
|
|
|
@@ -195,3 +194,5 @@ void run(process.argv.slice(2)).catch((e) => {
|
|
|
195
194
|
console.error(e);
|
|
196
195
|
process.exitCode = 1;
|
|
197
196
|
});
|
|
197
|
+
ss.exitCode = 1;
|
|
198
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-swagger-autogen",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Generate swagger-autogen config + Prisma DMMF schemas and fix swagger-autogen output.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joyce Marvin Rafflenbeul",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"LICENSE"
|
|
40
40
|
],
|
|
41
41
|
"scripts": {
|
|
42
|
-
"build": "tsup src/index.ts
|
|
42
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --out-dir dist && tsup src/cli.ts --format esm --out-dir dist --no-dts",
|
|
43
43
|
"prepublishOnly": "npm run build"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
package/dist/bin.cjs
DELETED
package/dist/chunk-LHCOAEWQ.cjs
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/index.ts
|
|
2
|
-
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
3
|
-
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
4
|
-
var _module = require('module');
|
|
5
|
-
var _glob = require('glob');
|
|
6
|
-
var CONFIG = {
|
|
7
|
-
projectRoot: process.cwd(),
|
|
8
|
-
controllersGlob: "./src/web/api/controllers/**/*.ts",
|
|
9
|
-
outFile: "./swagger.config.js",
|
|
10
|
-
openapiOut: "./src/web/api/openapi.json",
|
|
11
|
-
serviceTitle: "Prescription Service",
|
|
12
|
-
serverUrl: "http://localhost:3008",
|
|
13
|
-
securitySchemeName: "keycloakOAuth",
|
|
14
|
-
oauth: {
|
|
15
|
-
tokenUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/token",
|
|
16
|
-
refreshUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/refresh",
|
|
17
|
-
scopes: { openid: "openid scope" }
|
|
18
|
-
},
|
|
19
|
-
omitFieldsInWriteDtos: /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "v"])
|
|
20
|
-
};
|
|
21
|
-
function ensurePosix(p) {
|
|
22
|
-
return p.split(_path2.default.sep).join(_path2.default.posix.sep);
|
|
23
|
-
}
|
|
24
|
-
function pluralize(name) {
|
|
25
|
-
if (name.endsWith("s")) return `${name}es`;
|
|
26
|
-
return `${name}s`;
|
|
27
|
-
}
|
|
28
|
-
function getRequire() {
|
|
29
|
-
const base = typeof __filename !== "undefined" ? __filename : import.meta.url;
|
|
30
|
-
return _module.createRequire.call(void 0, base);
|
|
31
|
-
}
|
|
32
|
-
function loadDmmfFromProject(schemaPath) {
|
|
33
|
-
const resolvedSchemaPath = schemaPath ? _path2.default.resolve(process.cwd(), schemaPath) : _path2.default.resolve(process.cwd(), "prisma/schema.prisma");
|
|
34
|
-
if (!_fs2.default.existsSync(resolvedSchemaPath)) {
|
|
35
|
-
throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
|
|
36
|
-
}
|
|
37
|
-
const datamodel = _fs2.default.readFileSync(resolvedSchemaPath, "utf8");
|
|
38
|
-
const require2 = getRequire();
|
|
39
|
-
const internals = require2("@prisma/internals");
|
|
40
|
-
if (typeof internals.getDMMF !== "function") {
|
|
41
|
-
throw new Error(`@prisma/internals.getDMMF not available`);
|
|
42
|
-
}
|
|
43
|
-
return internals.getDMMF({ datamodel });
|
|
44
|
-
}
|
|
45
|
-
function scalarToSchema(scalar) {
|
|
46
|
-
switch (scalar) {
|
|
47
|
-
case "String":
|
|
48
|
-
return { type: "string" };
|
|
49
|
-
case "Boolean":
|
|
50
|
-
return { type: "boolean" };
|
|
51
|
-
case "Int":
|
|
52
|
-
return { type: "integer" };
|
|
53
|
-
case "BigInt":
|
|
54
|
-
return { type: "integer", format: "int64" };
|
|
55
|
-
case "Float":
|
|
56
|
-
return { type: "number" };
|
|
57
|
-
case "Decimal":
|
|
58
|
-
return { type: "number" };
|
|
59
|
-
case "DateTime":
|
|
60
|
-
return { type: "string", format: "date-time" };
|
|
61
|
-
case "Json":
|
|
62
|
-
return { type: "object" };
|
|
63
|
-
case "Bytes":
|
|
64
|
-
return { type: "string", format: "byte" };
|
|
65
|
-
default:
|
|
66
|
-
return { type: "string" };
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function fieldSchema(field, getRefName) {
|
|
70
|
-
if (field.kind === "scalar") {
|
|
71
|
-
const base = scalarToSchema(field.type);
|
|
72
|
-
if (field.isList) return { type: "array", items: base };
|
|
73
|
-
return base;
|
|
74
|
-
}
|
|
75
|
-
if (field.kind === "enum") {
|
|
76
|
-
const base = { $ref: `#/components/schemas/${field.type}` };
|
|
77
|
-
if (field.isList) return { type: "array", items: base };
|
|
78
|
-
return base;
|
|
79
|
-
}
|
|
80
|
-
if (field.kind === "object") {
|
|
81
|
-
const ref = { $ref: `#/components/schemas/${getRefName(String(field.type))}` };
|
|
82
|
-
if (field.isList) return { type: "array", items: ref };
|
|
83
|
-
return ref;
|
|
84
|
-
}
|
|
85
|
-
return { type: "object" };
|
|
86
|
-
}
|
|
87
|
-
function modelToGetSchema(model, getRefName) {
|
|
88
|
-
const properties = {};
|
|
89
|
-
const required = [];
|
|
90
|
-
for (const f of model.fields) {
|
|
91
|
-
properties[f.name] = fieldSchema(f, getRefName);
|
|
92
|
-
if (f.isRequired) required.push(f.name);
|
|
93
|
-
}
|
|
94
|
-
const schema = { type: "object", properties };
|
|
95
|
-
if (required.length) schema.required = required;
|
|
96
|
-
return schema;
|
|
97
|
-
}
|
|
98
|
-
function stripWriteFields(model, getSchema, omit) {
|
|
99
|
-
const schema = JSON.parse(JSON.stringify(getSchema));
|
|
100
|
-
if (!schema.properties) return schema;
|
|
101
|
-
const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
|
|
102
|
-
for (const key of Object.keys(schema.properties)) {
|
|
103
|
-
if (omit.has(key) || relationFieldNames.has(key)) {
|
|
104
|
-
delete schema.properties[key];
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (Array.isArray(schema.required)) {
|
|
108
|
-
schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
|
|
109
|
-
if (schema.required.length === 0) delete schema.required;
|
|
110
|
-
}
|
|
111
|
-
return schema;
|
|
112
|
-
}
|
|
113
|
-
function makeAllOptional(schema) {
|
|
114
|
-
const s = JSON.parse(JSON.stringify(schema));
|
|
115
|
-
delete s.required;
|
|
116
|
-
return s;
|
|
117
|
-
}
|
|
118
|
-
function listResponseSchema(itemRef) {
|
|
119
|
-
return {
|
|
120
|
-
type: "object",
|
|
121
|
-
properties: {
|
|
122
|
-
count: { type: "number" },
|
|
123
|
-
hasPreviousPage: { type: "boolean" },
|
|
124
|
-
hasNextPage: { type: "boolean" },
|
|
125
|
-
pageNumber: { type: "number" },
|
|
126
|
-
pageSize: { type: "number" },
|
|
127
|
-
totalPages: { type: "number" },
|
|
128
|
-
items: { type: "array", items: { $ref: itemRef } }
|
|
129
|
-
},
|
|
130
|
-
required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
134
|
-
const dmmf = loadDmmfFromProject(schemaPath);
|
|
135
|
-
const schemas = {};
|
|
136
|
-
const getRefName = (modelName) => `Get${modelName}Response`;
|
|
137
|
-
for (const e of dmmf.datamodel.enums) {
|
|
138
|
-
schemas[e.name] = { type: "string", enum: e.values.map((v) => v.name) };
|
|
139
|
-
}
|
|
140
|
-
for (const model of dmmf.datamodel.models) {
|
|
141
|
-
const getName = `Get${model.name}Response`;
|
|
142
|
-
const postName = `Post${model.name}Request`;
|
|
143
|
-
const putName = `Put${model.name}Request`;
|
|
144
|
-
const listName = `List${pluralize(model.name)}Response`;
|
|
145
|
-
const getSchema = modelToGetSchema(model, getRefName);
|
|
146
|
-
const postSchema = stripWriteFields(model, getSchema, CONFIG.omitFieldsInWriteDtos);
|
|
147
|
-
const putSchema = makeAllOptional(postSchema);
|
|
148
|
-
schemas[getName] = getSchema;
|
|
149
|
-
schemas[postName] = postSchema;
|
|
150
|
-
schemas[putName] = putSchema;
|
|
151
|
-
schemas[listName] = listResponseSchema(`#/components/schemas/${getName}`);
|
|
152
|
-
}
|
|
153
|
-
return schemas;
|
|
154
|
-
}
|
|
155
|
-
function generateSwaggerConfigJs(schemas) {
|
|
156
|
-
const routes = _glob.globSync.call(void 0, CONFIG.controllersGlob, { nodir: true }).map((p) => ensurePosix(p));
|
|
157
|
-
const docs = {
|
|
158
|
-
info: { title: CONFIG.serviceTitle },
|
|
159
|
-
servers: [{ url: CONFIG.serverUrl }],
|
|
160
|
-
components: {
|
|
161
|
-
schemas,
|
|
162
|
-
securitySchemes: {
|
|
163
|
-
[CONFIG.securitySchemeName]: {
|
|
164
|
-
type: "oauth2",
|
|
165
|
-
description: "This API uses OAuth2 with the password flow.",
|
|
166
|
-
flows: {
|
|
167
|
-
password: {
|
|
168
|
-
tokenUrl: CONFIG.oauth.tokenUrl,
|
|
169
|
-
refreshUrl: CONFIG.oauth.refreshUrl,
|
|
170
|
-
scopes: CONFIG.oauth.scopes
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
|
|
177
|
-
};
|
|
178
|
-
const fileContent = `const swaggerAutogen = require('swagger-autogen')();
|
|
179
|
-
const docs = ${JSON.stringify(docs, null, 2)};
|
|
180
|
-
const routes = ${JSON.stringify(routes, null, 2)};
|
|
181
|
-
swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
|
|
182
|
-
_fs2.default.writeFileSync(_path2.default.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
|
|
183
|
-
}
|
|
184
|
-
async function run(args = []) {
|
|
185
|
-
const schemaFlagIndex = args.findIndex((a) => a === "--schema");
|
|
186
|
-
const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
|
|
187
|
-
const schemas = buildSchemasFromPrismaDmmf(schemaPath);
|
|
188
|
-
generateSwaggerConfigJs(schemas);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
exports.run = run;
|
package/dist/chunk-NLFDSHIX.js
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { createRequire } from "module";
|
|
5
|
-
import { globSync } from "glob";
|
|
6
|
-
var CONFIG = {
|
|
7
|
-
projectRoot: process.cwd(),
|
|
8
|
-
controllersGlob: "./src/web/api/controllers/**/*.ts",
|
|
9
|
-
outFile: "./swagger.config.js",
|
|
10
|
-
openapiOut: "./src/web/api/openapi.json",
|
|
11
|
-
serviceTitle: "Prescription Service",
|
|
12
|
-
serverUrl: "http://localhost:3008",
|
|
13
|
-
securitySchemeName: "keycloakOAuth",
|
|
14
|
-
oauth: {
|
|
15
|
-
tokenUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/token",
|
|
16
|
-
refreshUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/refresh",
|
|
17
|
-
scopes: { openid: "openid scope" }
|
|
18
|
-
},
|
|
19
|
-
omitFieldsInWriteDtos: /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "v"])
|
|
20
|
-
};
|
|
21
|
-
function ensurePosix(p) {
|
|
22
|
-
return p.split(path.sep).join(path.posix.sep);
|
|
23
|
-
}
|
|
24
|
-
function pluralize(name) {
|
|
25
|
-
if (name.endsWith("s")) return `${name}es`;
|
|
26
|
-
return `${name}s`;
|
|
27
|
-
}
|
|
28
|
-
function getRequire() {
|
|
29
|
-
const base = typeof __filename !== "undefined" ? __filename : import.meta.url;
|
|
30
|
-
return createRequire(base);
|
|
31
|
-
}
|
|
32
|
-
function loadDmmfFromProject(schemaPath) {
|
|
33
|
-
const resolvedSchemaPath = schemaPath ? path.resolve(process.cwd(), schemaPath) : path.resolve(process.cwd(), "prisma/schema.prisma");
|
|
34
|
-
if (!fs.existsSync(resolvedSchemaPath)) {
|
|
35
|
-
throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
|
|
36
|
-
}
|
|
37
|
-
const datamodel = fs.readFileSync(resolvedSchemaPath, "utf8");
|
|
38
|
-
const require2 = getRequire();
|
|
39
|
-
const internals = require2("@prisma/internals");
|
|
40
|
-
if (typeof internals.getDMMF !== "function") {
|
|
41
|
-
throw new Error(`@prisma/internals.getDMMF not available`);
|
|
42
|
-
}
|
|
43
|
-
return internals.getDMMF({ datamodel });
|
|
44
|
-
}
|
|
45
|
-
function scalarToSchema(scalar) {
|
|
46
|
-
switch (scalar) {
|
|
47
|
-
case "String":
|
|
48
|
-
return { type: "string" };
|
|
49
|
-
case "Boolean":
|
|
50
|
-
return { type: "boolean" };
|
|
51
|
-
case "Int":
|
|
52
|
-
return { type: "integer" };
|
|
53
|
-
case "BigInt":
|
|
54
|
-
return { type: "integer", format: "int64" };
|
|
55
|
-
case "Float":
|
|
56
|
-
return { type: "number" };
|
|
57
|
-
case "Decimal":
|
|
58
|
-
return { type: "number" };
|
|
59
|
-
case "DateTime":
|
|
60
|
-
return { type: "string", format: "date-time" };
|
|
61
|
-
case "Json":
|
|
62
|
-
return { type: "object" };
|
|
63
|
-
case "Bytes":
|
|
64
|
-
return { type: "string", format: "byte" };
|
|
65
|
-
default:
|
|
66
|
-
return { type: "string" };
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function fieldSchema(field, getRefName) {
|
|
70
|
-
if (field.kind === "scalar") {
|
|
71
|
-
const base = scalarToSchema(field.type);
|
|
72
|
-
if (field.isList) return { type: "array", items: base };
|
|
73
|
-
return base;
|
|
74
|
-
}
|
|
75
|
-
if (field.kind === "enum") {
|
|
76
|
-
const base = { $ref: `#/components/schemas/${field.type}` };
|
|
77
|
-
if (field.isList) return { type: "array", items: base };
|
|
78
|
-
return base;
|
|
79
|
-
}
|
|
80
|
-
if (field.kind === "object") {
|
|
81
|
-
const ref = { $ref: `#/components/schemas/${getRefName(String(field.type))}` };
|
|
82
|
-
if (field.isList) return { type: "array", items: ref };
|
|
83
|
-
return ref;
|
|
84
|
-
}
|
|
85
|
-
return { type: "object" };
|
|
86
|
-
}
|
|
87
|
-
function modelToGetSchema(model, getRefName) {
|
|
88
|
-
const properties = {};
|
|
89
|
-
const required = [];
|
|
90
|
-
for (const f of model.fields) {
|
|
91
|
-
properties[f.name] = fieldSchema(f, getRefName);
|
|
92
|
-
if (f.isRequired) required.push(f.name);
|
|
93
|
-
}
|
|
94
|
-
const schema = { type: "object", properties };
|
|
95
|
-
if (required.length) schema.required = required;
|
|
96
|
-
return schema;
|
|
97
|
-
}
|
|
98
|
-
function stripWriteFields(model, getSchema, omit) {
|
|
99
|
-
const schema = JSON.parse(JSON.stringify(getSchema));
|
|
100
|
-
if (!schema.properties) return schema;
|
|
101
|
-
const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
|
|
102
|
-
for (const key of Object.keys(schema.properties)) {
|
|
103
|
-
if (omit.has(key) || relationFieldNames.has(key)) {
|
|
104
|
-
delete schema.properties[key];
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (Array.isArray(schema.required)) {
|
|
108
|
-
schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
|
|
109
|
-
if (schema.required.length === 0) delete schema.required;
|
|
110
|
-
}
|
|
111
|
-
return schema;
|
|
112
|
-
}
|
|
113
|
-
function makeAllOptional(schema) {
|
|
114
|
-
const s = JSON.parse(JSON.stringify(schema));
|
|
115
|
-
delete s.required;
|
|
116
|
-
return s;
|
|
117
|
-
}
|
|
118
|
-
function listResponseSchema(itemRef) {
|
|
119
|
-
return {
|
|
120
|
-
type: "object",
|
|
121
|
-
properties: {
|
|
122
|
-
count: { type: "number" },
|
|
123
|
-
hasPreviousPage: { type: "boolean" },
|
|
124
|
-
hasNextPage: { type: "boolean" },
|
|
125
|
-
pageNumber: { type: "number" },
|
|
126
|
-
pageSize: { type: "number" },
|
|
127
|
-
totalPages: { type: "number" },
|
|
128
|
-
items: { type: "array", items: { $ref: itemRef } }
|
|
129
|
-
},
|
|
130
|
-
required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
134
|
-
const dmmf = loadDmmfFromProject(schemaPath);
|
|
135
|
-
const schemas = {};
|
|
136
|
-
const getRefName = (modelName) => `Get${modelName}Response`;
|
|
137
|
-
for (const e of dmmf.datamodel.enums) {
|
|
138
|
-
schemas[e.name] = { type: "string", enum: e.values.map((v) => v.name) };
|
|
139
|
-
}
|
|
140
|
-
for (const model of dmmf.datamodel.models) {
|
|
141
|
-
const getName = `Get${model.name}Response`;
|
|
142
|
-
const postName = `Post${model.name}Request`;
|
|
143
|
-
const putName = `Put${model.name}Request`;
|
|
144
|
-
const listName = `List${pluralize(model.name)}Response`;
|
|
145
|
-
const getSchema = modelToGetSchema(model, getRefName);
|
|
146
|
-
const postSchema = stripWriteFields(model, getSchema, CONFIG.omitFieldsInWriteDtos);
|
|
147
|
-
const putSchema = makeAllOptional(postSchema);
|
|
148
|
-
schemas[getName] = getSchema;
|
|
149
|
-
schemas[postName] = postSchema;
|
|
150
|
-
schemas[putName] = putSchema;
|
|
151
|
-
schemas[listName] = listResponseSchema(`#/components/schemas/${getName}`);
|
|
152
|
-
}
|
|
153
|
-
return schemas;
|
|
154
|
-
}
|
|
155
|
-
function generateSwaggerConfigJs(schemas) {
|
|
156
|
-
const routes = globSync(CONFIG.controllersGlob, { nodir: true }).map((p) => ensurePosix(p));
|
|
157
|
-
const docs = {
|
|
158
|
-
info: { title: CONFIG.serviceTitle },
|
|
159
|
-
servers: [{ url: CONFIG.serverUrl }],
|
|
160
|
-
components: {
|
|
161
|
-
schemas,
|
|
162
|
-
securitySchemes: {
|
|
163
|
-
[CONFIG.securitySchemeName]: {
|
|
164
|
-
type: "oauth2",
|
|
165
|
-
description: "This API uses OAuth2 with the password flow.",
|
|
166
|
-
flows: {
|
|
167
|
-
password: {
|
|
168
|
-
tokenUrl: CONFIG.oauth.tokenUrl,
|
|
169
|
-
refreshUrl: CONFIG.oauth.refreshUrl,
|
|
170
|
-
scopes: CONFIG.oauth.scopes
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
|
|
177
|
-
};
|
|
178
|
-
const fileContent = `const swaggerAutogen = require('swagger-autogen')();
|
|
179
|
-
const docs = ${JSON.stringify(docs, null, 2)};
|
|
180
|
-
const routes = ${JSON.stringify(routes, null, 2)};
|
|
181
|
-
swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
|
|
182
|
-
fs.writeFileSync(path.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
|
|
183
|
-
}
|
|
184
|
-
async function run(args = []) {
|
|
185
|
-
const schemaFlagIndex = args.findIndex((a) => a === "--schema");
|
|
186
|
-
const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
|
|
187
|
-
const schemas = buildSchemasFromPrismaDmmf(schemaPath);
|
|
188
|
-
generateSwaggerConfigJs(schemas);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export {
|
|
192
|
-
run
|
|
193
|
-
};
|
package/dist/cli.cjs
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
-
mod
|
|
24
|
-
));
|
|
25
|
-
|
|
26
|
-
// src/index.ts
|
|
27
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
28
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
29
|
-
var import_node_module = require("module");
|
|
30
|
-
var import_glob = require("glob");
|
|
31
|
-
var import_meta = {};
|
|
32
|
-
var CONFIG = {
|
|
33
|
-
projectRoot: process.cwd(),
|
|
34
|
-
controllersGlob: "./src/web/api/controllers/**/*.ts",
|
|
35
|
-
outFile: "./swagger.config.js",
|
|
36
|
-
openapiOut: "./src/web/api/openapi.json",
|
|
37
|
-
serviceTitle: "Prescription Service",
|
|
38
|
-
serverUrl: "http://localhost:3008",
|
|
39
|
-
securitySchemeName: "keycloakOAuth",
|
|
40
|
-
oauth: {
|
|
41
|
-
tokenUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/token",
|
|
42
|
-
refreshUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/refresh",
|
|
43
|
-
scopes: { openid: "openid scope" }
|
|
44
|
-
},
|
|
45
|
-
omitFieldsInWriteDtos: /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "v"])
|
|
46
|
-
};
|
|
47
|
-
function ensurePosix(p) {
|
|
48
|
-
return p.split(import_node_path.default.sep).join(import_node_path.default.posix.sep);
|
|
49
|
-
}
|
|
50
|
-
function pluralize(name) {
|
|
51
|
-
if (name.endsWith("s")) return `${name}es`;
|
|
52
|
-
return `${name}s`;
|
|
53
|
-
}
|
|
54
|
-
function getRequire() {
|
|
55
|
-
const base = typeof __filename !== "undefined" ? __filename : import_meta.url;
|
|
56
|
-
return (0, import_node_module.createRequire)(base);
|
|
57
|
-
}
|
|
58
|
-
function loadDmmfFromProject(schemaPath) {
|
|
59
|
-
const resolvedSchemaPath = schemaPath ? import_node_path.default.resolve(process.cwd(), schemaPath) : import_node_path.default.resolve(process.cwd(), "prisma/schema.prisma");
|
|
60
|
-
if (!import_node_fs.default.existsSync(resolvedSchemaPath)) {
|
|
61
|
-
throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
|
|
62
|
-
}
|
|
63
|
-
const datamodel = import_node_fs.default.readFileSync(resolvedSchemaPath, "utf8");
|
|
64
|
-
const require2 = getRequire();
|
|
65
|
-
const internals = require2("@prisma/internals");
|
|
66
|
-
if (typeof internals.getDMMF !== "function") {
|
|
67
|
-
throw new Error(`@prisma/internals.getDMMF not available`);
|
|
68
|
-
}
|
|
69
|
-
return internals.getDMMF({ datamodel });
|
|
70
|
-
}
|
|
71
|
-
function scalarToSchema(scalar) {
|
|
72
|
-
switch (scalar) {
|
|
73
|
-
case "String":
|
|
74
|
-
return { type: "string" };
|
|
75
|
-
case "Boolean":
|
|
76
|
-
return { type: "boolean" };
|
|
77
|
-
case "Int":
|
|
78
|
-
return { type: "integer" };
|
|
79
|
-
case "BigInt":
|
|
80
|
-
return { type: "integer", format: "int64" };
|
|
81
|
-
case "Float":
|
|
82
|
-
return { type: "number" };
|
|
83
|
-
case "Decimal":
|
|
84
|
-
return { type: "number" };
|
|
85
|
-
case "DateTime":
|
|
86
|
-
return { type: "string", format: "date-time" };
|
|
87
|
-
case "Json":
|
|
88
|
-
return { type: "object" };
|
|
89
|
-
case "Bytes":
|
|
90
|
-
return { type: "string", format: "byte" };
|
|
91
|
-
default:
|
|
92
|
-
return { type: "string" };
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
function fieldSchema(field, getRefName) {
|
|
96
|
-
if (field.kind === "scalar") {
|
|
97
|
-
const base = scalarToSchema(field.type);
|
|
98
|
-
if (field.isList) return { type: "array", items: base };
|
|
99
|
-
return base;
|
|
100
|
-
}
|
|
101
|
-
if (field.kind === "enum") {
|
|
102
|
-
const base = { $ref: `#/components/schemas/${field.type}` };
|
|
103
|
-
if (field.isList) return { type: "array", items: base };
|
|
104
|
-
return base;
|
|
105
|
-
}
|
|
106
|
-
if (field.kind === "object") {
|
|
107
|
-
const ref = { $ref: `#/components/schemas/${getRefName(String(field.type))}` };
|
|
108
|
-
if (field.isList) return { type: "array", items: ref };
|
|
109
|
-
return ref;
|
|
110
|
-
}
|
|
111
|
-
return { type: "object" };
|
|
112
|
-
}
|
|
113
|
-
function modelToGetSchema(model, getRefName) {
|
|
114
|
-
const properties = {};
|
|
115
|
-
const required = [];
|
|
116
|
-
for (const f of model.fields) {
|
|
117
|
-
properties[f.name] = fieldSchema(f, getRefName);
|
|
118
|
-
if (f.isRequired) required.push(f.name);
|
|
119
|
-
}
|
|
120
|
-
const schema = { type: "object", properties };
|
|
121
|
-
if (required.length) schema.required = required;
|
|
122
|
-
return schema;
|
|
123
|
-
}
|
|
124
|
-
function stripWriteFields(model, getSchema, omit) {
|
|
125
|
-
const schema = JSON.parse(JSON.stringify(getSchema));
|
|
126
|
-
if (!schema.properties) return schema;
|
|
127
|
-
const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
|
|
128
|
-
for (const key of Object.keys(schema.properties)) {
|
|
129
|
-
if (omit.has(key) || relationFieldNames.has(key)) {
|
|
130
|
-
delete schema.properties[key];
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (Array.isArray(schema.required)) {
|
|
134
|
-
schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
|
|
135
|
-
if (schema.required.length === 0) delete schema.required;
|
|
136
|
-
}
|
|
137
|
-
return schema;
|
|
138
|
-
}
|
|
139
|
-
function makeAllOptional(schema) {
|
|
140
|
-
const s = JSON.parse(JSON.stringify(schema));
|
|
141
|
-
delete s.required;
|
|
142
|
-
return s;
|
|
143
|
-
}
|
|
144
|
-
function listResponseSchema(itemRef) {
|
|
145
|
-
return {
|
|
146
|
-
type: "object",
|
|
147
|
-
properties: {
|
|
148
|
-
count: { type: "number" },
|
|
149
|
-
hasPreviousPage: { type: "boolean" },
|
|
150
|
-
hasNextPage: { type: "boolean" },
|
|
151
|
-
pageNumber: { type: "number" },
|
|
152
|
-
pageSize: { type: "number" },
|
|
153
|
-
totalPages: { type: "number" },
|
|
154
|
-
items: { type: "array", items: { $ref: itemRef } }
|
|
155
|
-
},
|
|
156
|
-
required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
160
|
-
const dmmf = loadDmmfFromProject(schemaPath);
|
|
161
|
-
const schemas = {};
|
|
162
|
-
const getRefName = (modelName) => `Get${modelName}Response`;
|
|
163
|
-
for (const e of dmmf.datamodel.enums) {
|
|
164
|
-
schemas[e.name] = { type: "string", enum: e.values.map((v) => v.name) };
|
|
165
|
-
}
|
|
166
|
-
for (const model of dmmf.datamodel.models) {
|
|
167
|
-
const getName = `Get${model.name}Response`;
|
|
168
|
-
const postName = `Post${model.name}Request`;
|
|
169
|
-
const putName = `Put${model.name}Request`;
|
|
170
|
-
const listName = `List${pluralize(model.name)}Response`;
|
|
171
|
-
const getSchema = modelToGetSchema(model, getRefName);
|
|
172
|
-
const postSchema = stripWriteFields(model, getSchema, CONFIG.omitFieldsInWriteDtos);
|
|
173
|
-
const putSchema = makeAllOptional(postSchema);
|
|
174
|
-
schemas[getName] = getSchema;
|
|
175
|
-
schemas[postName] = postSchema;
|
|
176
|
-
schemas[putName] = putSchema;
|
|
177
|
-
schemas[listName] = listResponseSchema(`#/components/schemas/${getName}`);
|
|
178
|
-
}
|
|
179
|
-
return schemas;
|
|
180
|
-
}
|
|
181
|
-
function generateSwaggerConfigJs(schemas) {
|
|
182
|
-
const routes = (0, import_glob.globSync)(CONFIG.controllersGlob, { nodir: true }).map((p) => ensurePosix(p));
|
|
183
|
-
const docs = {
|
|
184
|
-
info: { title: CONFIG.serviceTitle },
|
|
185
|
-
servers: [{ url: CONFIG.serverUrl }],
|
|
186
|
-
components: {
|
|
187
|
-
schemas,
|
|
188
|
-
securitySchemes: {
|
|
189
|
-
[CONFIG.securitySchemeName]: {
|
|
190
|
-
type: "oauth2",
|
|
191
|
-
description: "This API uses OAuth2 with the password flow.",
|
|
192
|
-
flows: {
|
|
193
|
-
password: {
|
|
194
|
-
tokenUrl: CONFIG.oauth.tokenUrl,
|
|
195
|
-
refreshUrl: CONFIG.oauth.refreshUrl,
|
|
196
|
-
scopes: CONFIG.oauth.scopes
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
|
|
203
|
-
};
|
|
204
|
-
const fileContent = `const swaggerAutogen = require('swagger-autogen')();
|
|
205
|
-
const docs = ${JSON.stringify(docs, null, 2)};
|
|
206
|
-
const routes = ${JSON.stringify(routes, null, 2)};
|
|
207
|
-
swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
|
|
208
|
-
import_node_fs.default.writeFileSync(import_node_path.default.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
|
|
209
|
-
}
|
|
210
|
-
async function run(args = []) {
|
|
211
|
-
const schemaFlagIndex = args.findIndex((a) => a === "--schema");
|
|
212
|
-
const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
|
|
213
|
-
const schemas = buildSchemasFromPrismaDmmf(schemaPath);
|
|
214
|
-
generateSwaggerConfigJs(schemas);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// src/cli.ts
|
|
218
|
-
void run(process.argv.slice(2)).catch((e) => {
|
|
219
|
-
console.error(e);
|
|
220
|
-
process.exitCode = 1;
|
|
221
|
-
});
|
package/dist/cli.d.cts
DELETED
package/dist/cli.d.ts
DELETED
package/dist/index.cjs
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all)
|
|
11
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
-
};
|
|
13
|
-
var __copyProps = (to, from, except, desc) => {
|
|
14
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
-
for (let key of __getOwnPropNames(from))
|
|
16
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
-
}
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
-
mod
|
|
28
|
-
));
|
|
29
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
-
|
|
31
|
-
// src/index.ts
|
|
32
|
-
var index_exports = {};
|
|
33
|
-
__export(index_exports, {
|
|
34
|
-
run: () => run
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(index_exports);
|
|
37
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
38
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
39
|
-
var import_node_module = require("module");
|
|
40
|
-
var import_glob = require("glob");
|
|
41
|
-
var import_meta = {};
|
|
42
|
-
var CONFIG = {
|
|
43
|
-
projectRoot: process.cwd(),
|
|
44
|
-
controllersGlob: "./src/web/api/controllers/**/*.ts",
|
|
45
|
-
outFile: "./swagger.config.js",
|
|
46
|
-
openapiOut: "./src/web/api/openapi.json",
|
|
47
|
-
serviceTitle: "Prescription Service",
|
|
48
|
-
serverUrl: "http://localhost:3008",
|
|
49
|
-
securitySchemeName: "keycloakOAuth",
|
|
50
|
-
oauth: {
|
|
51
|
-
tokenUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/token",
|
|
52
|
-
refreshUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/refresh",
|
|
53
|
-
scopes: { openid: "openid scope" }
|
|
54
|
-
},
|
|
55
|
-
omitFieldsInWriteDtos: /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "v"])
|
|
56
|
-
};
|
|
57
|
-
function ensurePosix(p) {
|
|
58
|
-
return p.split(import_node_path.default.sep).join(import_node_path.default.posix.sep);
|
|
59
|
-
}
|
|
60
|
-
function pluralize(name) {
|
|
61
|
-
if (name.endsWith("s")) return `${name}es`;
|
|
62
|
-
return `${name}s`;
|
|
63
|
-
}
|
|
64
|
-
function getRequire() {
|
|
65
|
-
const base = typeof __filename !== "undefined" ? __filename : import_meta.url;
|
|
66
|
-
return (0, import_node_module.createRequire)(base);
|
|
67
|
-
}
|
|
68
|
-
function loadDmmfFromProject(schemaPath) {
|
|
69
|
-
const resolvedSchemaPath = schemaPath ? import_node_path.default.resolve(process.cwd(), schemaPath) : import_node_path.default.resolve(process.cwd(), "prisma/schema.prisma");
|
|
70
|
-
if (!import_node_fs.default.existsSync(resolvedSchemaPath)) {
|
|
71
|
-
throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
|
|
72
|
-
}
|
|
73
|
-
const datamodel = import_node_fs.default.readFileSync(resolvedSchemaPath, "utf8");
|
|
74
|
-
const require2 = getRequire();
|
|
75
|
-
const internals = require2("@prisma/internals");
|
|
76
|
-
if (typeof internals.getDMMF !== "function") {
|
|
77
|
-
throw new Error(`@prisma/internals.getDMMF not available`);
|
|
78
|
-
}
|
|
79
|
-
return internals.getDMMF({ datamodel });
|
|
80
|
-
}
|
|
81
|
-
function scalarToSchema(scalar) {
|
|
82
|
-
switch (scalar) {
|
|
83
|
-
case "String":
|
|
84
|
-
return { type: "string" };
|
|
85
|
-
case "Boolean":
|
|
86
|
-
return { type: "boolean" };
|
|
87
|
-
case "Int":
|
|
88
|
-
return { type: "integer" };
|
|
89
|
-
case "BigInt":
|
|
90
|
-
return { type: "integer", format: "int64" };
|
|
91
|
-
case "Float":
|
|
92
|
-
return { type: "number" };
|
|
93
|
-
case "Decimal":
|
|
94
|
-
return { type: "number" };
|
|
95
|
-
case "DateTime":
|
|
96
|
-
return { type: "string", format: "date-time" };
|
|
97
|
-
case "Json":
|
|
98
|
-
return { type: "object" };
|
|
99
|
-
case "Bytes":
|
|
100
|
-
return { type: "string", format: "byte" };
|
|
101
|
-
default:
|
|
102
|
-
return { type: "string" };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
function fieldSchema(field, getRefName) {
|
|
106
|
-
if (field.kind === "scalar") {
|
|
107
|
-
const base = scalarToSchema(field.type);
|
|
108
|
-
if (field.isList) return { type: "array", items: base };
|
|
109
|
-
return base;
|
|
110
|
-
}
|
|
111
|
-
if (field.kind === "enum") {
|
|
112
|
-
const base = { $ref: `#/components/schemas/${field.type}` };
|
|
113
|
-
if (field.isList) return { type: "array", items: base };
|
|
114
|
-
return base;
|
|
115
|
-
}
|
|
116
|
-
if (field.kind === "object") {
|
|
117
|
-
const ref = { $ref: `#/components/schemas/${getRefName(String(field.type))}` };
|
|
118
|
-
if (field.isList) return { type: "array", items: ref };
|
|
119
|
-
return ref;
|
|
120
|
-
}
|
|
121
|
-
return { type: "object" };
|
|
122
|
-
}
|
|
123
|
-
function modelToGetSchema(model, getRefName) {
|
|
124
|
-
const properties = {};
|
|
125
|
-
const required = [];
|
|
126
|
-
for (const f of model.fields) {
|
|
127
|
-
properties[f.name] = fieldSchema(f, getRefName);
|
|
128
|
-
if (f.isRequired) required.push(f.name);
|
|
129
|
-
}
|
|
130
|
-
const schema = { type: "object", properties };
|
|
131
|
-
if (required.length) schema.required = required;
|
|
132
|
-
return schema;
|
|
133
|
-
}
|
|
134
|
-
function stripWriteFields(model, getSchema, omit) {
|
|
135
|
-
const schema = JSON.parse(JSON.stringify(getSchema));
|
|
136
|
-
if (!schema.properties) return schema;
|
|
137
|
-
const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
|
|
138
|
-
for (const key of Object.keys(schema.properties)) {
|
|
139
|
-
if (omit.has(key) || relationFieldNames.has(key)) {
|
|
140
|
-
delete schema.properties[key];
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (Array.isArray(schema.required)) {
|
|
144
|
-
schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
|
|
145
|
-
if (schema.required.length === 0) delete schema.required;
|
|
146
|
-
}
|
|
147
|
-
return schema;
|
|
148
|
-
}
|
|
149
|
-
function makeAllOptional(schema) {
|
|
150
|
-
const s = JSON.parse(JSON.stringify(schema));
|
|
151
|
-
delete s.required;
|
|
152
|
-
return s;
|
|
153
|
-
}
|
|
154
|
-
function listResponseSchema(itemRef) {
|
|
155
|
-
return {
|
|
156
|
-
type: "object",
|
|
157
|
-
properties: {
|
|
158
|
-
count: { type: "number" },
|
|
159
|
-
hasPreviousPage: { type: "boolean" },
|
|
160
|
-
hasNextPage: { type: "boolean" },
|
|
161
|
-
pageNumber: { type: "number" },
|
|
162
|
-
pageSize: { type: "number" },
|
|
163
|
-
totalPages: { type: "number" },
|
|
164
|
-
items: { type: "array", items: { $ref: itemRef } }
|
|
165
|
-
},
|
|
166
|
-
required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
170
|
-
const dmmf = loadDmmfFromProject(schemaPath);
|
|
171
|
-
const schemas = {};
|
|
172
|
-
const getRefName = (modelName) => `Get${modelName}Response`;
|
|
173
|
-
for (const e of dmmf.datamodel.enums) {
|
|
174
|
-
schemas[e.name] = { type: "string", enum: e.values.map((v) => v.name) };
|
|
175
|
-
}
|
|
176
|
-
for (const model of dmmf.datamodel.models) {
|
|
177
|
-
const getName = `Get${model.name}Response`;
|
|
178
|
-
const postName = `Post${model.name}Request`;
|
|
179
|
-
const putName = `Put${model.name}Request`;
|
|
180
|
-
const listName = `List${pluralize(model.name)}Response`;
|
|
181
|
-
const getSchema = modelToGetSchema(model, getRefName);
|
|
182
|
-
const postSchema = stripWriteFields(model, getSchema, CONFIG.omitFieldsInWriteDtos);
|
|
183
|
-
const putSchema = makeAllOptional(postSchema);
|
|
184
|
-
schemas[getName] = getSchema;
|
|
185
|
-
schemas[postName] = postSchema;
|
|
186
|
-
schemas[putName] = putSchema;
|
|
187
|
-
schemas[listName] = listResponseSchema(`#/components/schemas/${getName}`);
|
|
188
|
-
}
|
|
189
|
-
return schemas;
|
|
190
|
-
}
|
|
191
|
-
function generateSwaggerConfigJs(schemas) {
|
|
192
|
-
const routes = (0, import_glob.globSync)(CONFIG.controllersGlob, { nodir: true }).map((p) => ensurePosix(p));
|
|
193
|
-
const docs = {
|
|
194
|
-
info: { title: CONFIG.serviceTitle },
|
|
195
|
-
servers: [{ url: CONFIG.serverUrl }],
|
|
196
|
-
components: {
|
|
197
|
-
schemas,
|
|
198
|
-
securitySchemes: {
|
|
199
|
-
[CONFIG.securitySchemeName]: {
|
|
200
|
-
type: "oauth2",
|
|
201
|
-
description: "This API uses OAuth2 with the password flow.",
|
|
202
|
-
flows: {
|
|
203
|
-
password: {
|
|
204
|
-
tokenUrl: CONFIG.oauth.tokenUrl,
|
|
205
|
-
refreshUrl: CONFIG.oauth.refreshUrl,
|
|
206
|
-
scopes: CONFIG.oauth.scopes
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
|
|
213
|
-
};
|
|
214
|
-
const fileContent = `const swaggerAutogen = require('swagger-autogen')();
|
|
215
|
-
const docs = ${JSON.stringify(docs, null, 2)};
|
|
216
|
-
const routes = ${JSON.stringify(routes, null, 2)};
|
|
217
|
-
swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
|
|
218
|
-
import_node_fs.default.writeFileSync(import_node_path.default.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
|
|
219
|
-
}
|
|
220
|
-
async function run(args = []) {
|
|
221
|
-
const schemaFlagIndex = args.findIndex((a) => a === "--schema");
|
|
222
|
-
const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
|
|
223
|
-
const schemas = buildSchemasFromPrismaDmmf(schemaPath);
|
|
224
|
-
generateSwaggerConfigJs(schemas);
|
|
225
|
-
}
|
|
226
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
227
|
-
0 && (module.exports = {
|
|
228
|
-
run
|
|
229
|
-
});
|
package/dist/index.d.cts
DELETED
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/index.ts
|
|
4
|
-
import fs from "fs";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import { createRequire } from "module";
|
|
7
|
-
import { globSync } from "glob";
|
|
8
|
-
var CONFIG = {
|
|
9
|
-
projectRoot: process.cwd(),
|
|
10
|
-
controllersGlob: "./src/web/api/controllers/**/*.ts",
|
|
11
|
-
outFile: "./swagger.config.js",
|
|
12
|
-
openapiOut: "./src/web/api/openapi.json",
|
|
13
|
-
serviceTitle: "Prescription Service",
|
|
14
|
-
serverUrl: "http://localhost:3008",
|
|
15
|
-
securitySchemeName: "keycloakOAuth",
|
|
16
|
-
oauth: {
|
|
17
|
-
tokenUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/token",
|
|
18
|
-
refreshUrl: "http://auth.localhost/realms/haemo/protocol/openid-connect/refresh",
|
|
19
|
-
scopes: { openid: "openid scope" }
|
|
20
|
-
},
|
|
21
|
-
omitFieldsInWriteDtos: /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "v"])
|
|
22
|
-
};
|
|
23
|
-
function ensurePosix(p) {
|
|
24
|
-
return p.split(path.sep).join(path.posix.sep);
|
|
25
|
-
}
|
|
26
|
-
function pluralize(name) {
|
|
27
|
-
if (name.endsWith("s")) return `${name}es`;
|
|
28
|
-
return `${name}s`;
|
|
29
|
-
}
|
|
30
|
-
function getRequire() {
|
|
31
|
-
const base = typeof __filename !== "undefined" ? __filename : import.meta.url;
|
|
32
|
-
return createRequire(base);
|
|
33
|
-
}
|
|
34
|
-
function loadDmmfFromProject(schemaPath) {
|
|
35
|
-
const resolvedSchemaPath = schemaPath ? path.resolve(process.cwd(), schemaPath) : path.resolve(process.cwd(), "prisma/schema.prisma");
|
|
36
|
-
if (!fs.existsSync(resolvedSchemaPath)) {
|
|
37
|
-
throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
|
|
38
|
-
}
|
|
39
|
-
const datamodel = fs.readFileSync(resolvedSchemaPath, "utf8");
|
|
40
|
-
const require2 = getRequire();
|
|
41
|
-
const internals = require2("@prisma/internals");
|
|
42
|
-
if (typeof internals.getDMMF !== "function") {
|
|
43
|
-
throw new Error(`@prisma/internals.getDMMF not available`);
|
|
44
|
-
}
|
|
45
|
-
return internals.getDMMF({ datamodel });
|
|
46
|
-
}
|
|
47
|
-
function scalarToSchema(scalar) {
|
|
48
|
-
switch (scalar) {
|
|
49
|
-
case "String":
|
|
50
|
-
return { type: "string" };
|
|
51
|
-
case "Boolean":
|
|
52
|
-
return { type: "boolean" };
|
|
53
|
-
case "Int":
|
|
54
|
-
return { type: "integer" };
|
|
55
|
-
case "BigInt":
|
|
56
|
-
return { type: "integer", format: "int64" };
|
|
57
|
-
case "Float":
|
|
58
|
-
return { type: "number" };
|
|
59
|
-
case "Decimal":
|
|
60
|
-
return { type: "number" };
|
|
61
|
-
case "DateTime":
|
|
62
|
-
return { type: "string", format: "date-time" };
|
|
63
|
-
case "Json":
|
|
64
|
-
return { type: "object" };
|
|
65
|
-
case "Bytes":
|
|
66
|
-
return { type: "string", format: "byte" };
|
|
67
|
-
default:
|
|
68
|
-
return { type: "string" };
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function fieldSchema(field, getRefName) {
|
|
72
|
-
if (field.kind === "scalar") {
|
|
73
|
-
const base = scalarToSchema(field.type);
|
|
74
|
-
if (field.isList) return { type: "array", items: base };
|
|
75
|
-
return base;
|
|
76
|
-
}
|
|
77
|
-
if (field.kind === "enum") {
|
|
78
|
-
const base = { $ref: `#/components/schemas/${field.type}` };
|
|
79
|
-
if (field.isList) return { type: "array", items: base };
|
|
80
|
-
return base;
|
|
81
|
-
}
|
|
82
|
-
if (field.kind === "object") {
|
|
83
|
-
const ref = { $ref: `#/components/schemas/${getRefName(String(field.type))}` };
|
|
84
|
-
if (field.isList) return { type: "array", items: ref };
|
|
85
|
-
return ref;
|
|
86
|
-
}
|
|
87
|
-
return { type: "object" };
|
|
88
|
-
}
|
|
89
|
-
function modelToGetSchema(model, getRefName) {
|
|
90
|
-
const properties = {};
|
|
91
|
-
const required = [];
|
|
92
|
-
for (const f of model.fields) {
|
|
93
|
-
properties[f.name] = fieldSchema(f, getRefName);
|
|
94
|
-
if (f.isRequired) required.push(f.name);
|
|
95
|
-
}
|
|
96
|
-
const schema = { type: "object", properties };
|
|
97
|
-
if (required.length) schema.required = required;
|
|
98
|
-
return schema;
|
|
99
|
-
}
|
|
100
|
-
function stripWriteFields(model, getSchema, omit) {
|
|
101
|
-
const schema = JSON.parse(JSON.stringify(getSchema));
|
|
102
|
-
if (!schema.properties) return schema;
|
|
103
|
-
const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
|
|
104
|
-
for (const key of Object.keys(schema.properties)) {
|
|
105
|
-
if (omit.has(key) || relationFieldNames.has(key)) {
|
|
106
|
-
delete schema.properties[key];
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (Array.isArray(schema.required)) {
|
|
110
|
-
schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
|
|
111
|
-
if (schema.required.length === 0) delete schema.required;
|
|
112
|
-
}
|
|
113
|
-
return schema;
|
|
114
|
-
}
|
|
115
|
-
function makeAllOptional(schema) {
|
|
116
|
-
const s = JSON.parse(JSON.stringify(schema));
|
|
117
|
-
delete s.required;
|
|
118
|
-
return s;
|
|
119
|
-
}
|
|
120
|
-
function listResponseSchema(itemRef) {
|
|
121
|
-
return {
|
|
122
|
-
type: "object",
|
|
123
|
-
properties: {
|
|
124
|
-
count: { type: "number" },
|
|
125
|
-
hasPreviousPage: { type: "boolean" },
|
|
126
|
-
hasNextPage: { type: "boolean" },
|
|
127
|
-
pageNumber: { type: "number" },
|
|
128
|
-
pageSize: { type: "number" },
|
|
129
|
-
totalPages: { type: "number" },
|
|
130
|
-
items: { type: "array", items: { $ref: itemRef } }
|
|
131
|
-
},
|
|
132
|
-
required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
function buildSchemasFromPrismaDmmf(schemaPath) {
|
|
136
|
-
const dmmf = loadDmmfFromProject(schemaPath);
|
|
137
|
-
const schemas = {};
|
|
138
|
-
const getRefName = (modelName) => `Get${modelName}Response`;
|
|
139
|
-
for (const e of dmmf.datamodel.enums) {
|
|
140
|
-
schemas[e.name] = { type: "string", enum: e.values.map((v) => v.name) };
|
|
141
|
-
}
|
|
142
|
-
for (const model of dmmf.datamodel.models) {
|
|
143
|
-
const getName = `Get${model.name}Response`;
|
|
144
|
-
const postName = `Post${model.name}Request`;
|
|
145
|
-
const putName = `Put${model.name}Request`;
|
|
146
|
-
const listName = `List${pluralize(model.name)}Response`;
|
|
147
|
-
const getSchema = modelToGetSchema(model, getRefName);
|
|
148
|
-
const postSchema = stripWriteFields(model, getSchema, CONFIG.omitFieldsInWriteDtos);
|
|
149
|
-
const putSchema = makeAllOptional(postSchema);
|
|
150
|
-
schemas[getName] = getSchema;
|
|
151
|
-
schemas[postName] = postSchema;
|
|
152
|
-
schemas[putName] = putSchema;
|
|
153
|
-
schemas[listName] = listResponseSchema(`#/components/schemas/${getName}`);
|
|
154
|
-
}
|
|
155
|
-
return schemas;
|
|
156
|
-
}
|
|
157
|
-
function generateSwaggerConfigJs(schemas) {
|
|
158
|
-
const routes = globSync(CONFIG.controllersGlob, { nodir: true }).map((p) => ensurePosix(p));
|
|
159
|
-
const docs = {
|
|
160
|
-
info: { title: CONFIG.serviceTitle },
|
|
161
|
-
servers: [{ url: CONFIG.serverUrl }],
|
|
162
|
-
components: {
|
|
163
|
-
schemas,
|
|
164
|
-
securitySchemes: {
|
|
165
|
-
[CONFIG.securitySchemeName]: {
|
|
166
|
-
type: "oauth2",
|
|
167
|
-
description: "This API uses OAuth2 with the password flow.",
|
|
168
|
-
flows: {
|
|
169
|
-
password: {
|
|
170
|
-
tokenUrl: CONFIG.oauth.tokenUrl,
|
|
171
|
-
refreshUrl: CONFIG.oauth.refreshUrl,
|
|
172
|
-
scopes: CONFIG.oauth.scopes
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
|
|
179
|
-
};
|
|
180
|
-
const fileContent = `const swaggerAutogen = require('swagger-autogen')();
|
|
181
|
-
const docs = ${JSON.stringify(docs, null, 2)};
|
|
182
|
-
const routes = ${JSON.stringify(routes, null, 2)};
|
|
183
|
-
swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
|
|
184
|
-
fs.writeFileSync(path.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
|
|
185
|
-
}
|
|
186
|
-
async function run(args = []) {
|
|
187
|
-
const schemaFlagIndex = args.findIndex((a) => a === "--schema");
|
|
188
|
-
const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
|
|
189
|
-
const schemas = buildSchemasFromPrismaDmmf(schemaPath);
|
|
190
|
-
generateSwaggerConfigJs(schemas);
|
|
191
|
-
}
|
|
192
|
-
export {
|
|
193
|
-
run
|
|
194
|
-
};
|