prisma-swagger-autogen 1.0.0 → 1.0.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.
@@ -1,8 +1,8 @@
1
1
  // src/index.ts
2
2
  import fs from "fs";
3
3
  import path from "path";
4
+ import { createRequire } from "module";
4
5
  import { globSync } from "glob";
5
- import { execSync } from "child_process";
6
6
  var CONFIG = {
7
7
  projectRoot: process.cwd(),
8
8
  controllersGlob: "./src/web/api/controllers/**/*.ts",
@@ -25,6 +25,28 @@ function pluralize(name) {
25
25
  if (name.endsWith("s")) return `${name}es`;
26
26
  return `${name}s`;
27
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
+ let internals;
40
+ try {
41
+ internals = require2("@prisma/internals");
42
+ } catch {
43
+ throw new Error(`Unable to load @prisma/internals`);
44
+ }
45
+ if (typeof internals.getDMMF !== "function") {
46
+ throw new Error(`@prisma/internals.getDMMF not available`);
47
+ }
48
+ return internals.getDMMF({ datamodel });
49
+ }
28
50
  function scalarToSchema(scalar) {
29
51
  switch (scalar) {
30
52
  case "String":
@@ -83,7 +105,9 @@ function stripWriteFields(model, getSchema, omit) {
83
105
  if (!schema.properties) return schema;
84
106
  const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
85
107
  for (const key of Object.keys(schema.properties)) {
86
- if (omit.has(key) || relationFieldNames.has(key)) delete schema.properties[key];
108
+ if (omit.has(key) || relationFieldNames.has(key)) {
109
+ delete schema.properties[key];
110
+ }
87
111
  }
88
112
  if (Array.isArray(schema.required)) {
89
113
  schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
@@ -100,95 +124,19 @@ function listResponseSchema(itemRef) {
100
124
  return {
101
125
  type: "object",
102
126
  properties: {
103
- count: { type: "number", example: 3 },
104
- hasPreviousPage: { type: "boolean", example: false },
105
- hasNextPage: { type: "boolean", example: true },
106
- pageNumber: { type: "number", example: 1 },
107
- pageSize: { type: "number", example: 10 },
108
- totalPages: { type: "number", example: 1 },
127
+ count: { type: "number" },
128
+ hasPreviousPage: { type: "boolean" },
129
+ hasNextPage: { type: "boolean" },
130
+ pageNumber: { type: "number" },
131
+ pageSize: { type: "number" },
132
+ totalPages: { type: "number" },
109
133
  items: { type: "array", items: { $ref: itemRef } }
110
134
  },
111
135
  required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
112
136
  };
113
137
  }
114
- function exampleForScalarType(type, format) {
115
- if (type === "string" && format === "date-time") return (/* @__PURE__ */ new Date(0)).toISOString();
116
- switch (type) {
117
- case "string":
118
- return "string";
119
- case "integer":
120
- return 0;
121
- case "number":
122
- return 0;
123
- case "boolean":
124
- return true;
125
- case "object":
126
- return {};
127
- default:
128
- return null;
129
- }
130
- }
131
- function buildExampleFromSchema(schema, components, depth = 0) {
132
- if (depth > 2) return void 0;
133
- if (schema.$ref) {
134
- const name = String(schema.$ref).split("/").pop() || "";
135
- const target = components[name];
136
- if (!target) return void 0;
137
- return buildExampleFromSchema(target, components, depth + 1);
138
- }
139
- if (Array.isArray(schema.allOf) && schema.allOf.length) {
140
- const merged = {};
141
- for (const part of schema.allOf) {
142
- const ex = buildExampleFromSchema(part, components, depth + 1);
143
- if (ex && typeof ex === "object" && !Array.isArray(ex)) Object.assign(merged, ex);
144
- }
145
- return Object.keys(merged).length ? merged : void 0;
146
- }
147
- if (schema.type === "array" && schema.items) {
148
- const item = buildExampleFromSchema(schema.items, components, depth + 1);
149
- return item === void 0 ? [] : [item];
150
- }
151
- if (schema.type === "object" && schema.properties) {
152
- const obj = {};
153
- for (const [k, v] of Object.entries(schema.properties)) {
154
- const ex = buildExampleFromSchema(v, components, depth + 1);
155
- if (ex !== void 0) obj[k] = ex;
156
- }
157
- return obj;
158
- }
159
- if (Array.isArray(schema.enum) && schema.enum.length) return schema.enum[0];
160
- if (typeof schema.type === "string") return exampleForScalarType(schema.type, schema.format);
161
- return void 0;
162
- }
163
- function attachExample(schema, components) {
164
- const s = JSON.parse(JSON.stringify(schema));
165
- if (s.example === void 0) {
166
- const ex = buildExampleFromSchema(s, components);
167
- if (ex !== void 0) s.example = ex;
168
- }
169
- return s;
170
- }
171
- async function loadDmmfFromProject() {
172
- const schemaPath = path.resolve(process.cwd(), "prisma/schema.prisma");
173
- if (!fs.existsSync(schemaPath)) {
174
- throw new Error(`Prisma schema not found at: ${schemaPath}`);
175
- }
176
- const cmd = `npx prisma generate --schema "${schemaPath}" --print`;
177
- const stdout = execSync(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
178
- const firstBrace = stdout.indexOf("{");
179
- const lastBrace = stdout.lastIndexOf("}");
180
- if (firstBrace === -1 || lastBrace === -1) {
181
- throw new Error(`Failed to parse Prisma DMMF from: ${cmd}`);
182
- }
183
- const jsonText = stdout.slice(firstBrace, lastBrace + 1);
184
- const parsed = JSON.parse(jsonText);
185
- const dmmf = parsed?.dmmf ?? parsed;
186
- if (!dmmf?.datamodel?.models) {
187
- throw new Error(`Prisma DMMF not found in prisma output. Got keys: ${Object.keys(parsed || {})}`);
188
- }
189
- return dmmf;
190
- }
191
- function buildSchemasFromDmmf(dmmf) {
138
+ function buildSchemasFromPrismaDmmf(schemaPath) {
139
+ const dmmf = loadDmmfFromProject(schemaPath);
192
140
  const schemas = {};
193
141
  const getRefName = (modelName) => `Get${modelName}Response`;
194
142
  for (const e of dmmf.datamodel.enums) {
@@ -242,10 +190,6 @@ function buildSchemasFromDmmf(dmmf) {
242
190
  type: "https://tools.ietf.org/html/rfc7231#section-6.6.1"
243
191
  }
244
192
  };
245
- for (const name of Object.keys(schemas)) {
246
- if (name.startsWith("Post") && name.endsWith("Request")) schemas[name] = attachExample(schemas[name], schemas);
247
- if (name.startsWith("Put") && name.endsWith("Request")) schemas[name] = attachExample(schemas[name], schemas);
248
- }
249
193
  return schemas;
250
194
  }
251
195
  function generateSwaggerConfigJs(schemas) {
@@ -272,60 +216,15 @@ function generateSwaggerConfigJs(schemas) {
272
216
  security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
273
217
  };
274
218
  const fileContent = `const swaggerAutogen = require('swagger-autogen')();
275
- const fs = require('fs');
276
- const path = require('node:path');
277
-
278
- function isPlainObject(v){return v!==null && typeof v==='object' && !Array.isArray(v);}
279
-
280
- function normalizeSchema(schema){
281
- if(!isPlainObject(schema)) return schema;
282
- if(schema.$ref) return schema;
283
-
284
- if(isPlainObject(schema.type) && typeof schema.type.example === 'string') schema.type = schema.type.example;
285
- if(isPlainObject(schema.format) && typeof schema.format.example === 'string') schema.format = schema.format.example;
286
- if(isPlainObject(schema.required) && Array.isArray(schema.required.example)) schema.required = schema.required.example;
287
- if(isPlainObject(schema.enum) && Array.isArray(schema.enum.example)) schema.enum = schema.enum.example;
288
-
289
- if(Array.isArray(schema.allOf)) schema.allOf = schema.allOf.map(normalizeSchema);
290
- if(isPlainObject(schema.items)) schema.items = normalizeSchema(schema.items);
291
- if(isPlainObject(schema.additionalProperties)) schema.additionalProperties = normalizeSchema(schema.additionalProperties);
292
-
293
- if(isPlainObject(schema.properties)){
294
- for(const k of Object.keys(schema.properties)){
295
- schema.properties[k] = normalizeSchema(schema.properties[k]);
296
- }
297
- }
298
-
299
- return schema;
300
- }
301
-
302
- function fixOpenApiFile(openapiPath){
303
- const abs = path.resolve(process.cwd(), openapiPath);
304
- if(!fs.existsSync(abs)) return;
305
- const doc = JSON.parse(fs.readFileSync(abs,'utf8'));
306
-
307
- if(doc && doc.components && isPlainObject(doc.components.schemas)){
308
- for(const name of Object.keys(doc.components.schemas)){
309
- doc.components.schemas[name] = normalizeSchema(doc.components.schemas[name]);
310
- }
311
- }
312
-
313
- fs.writeFileSync(abs, JSON.stringify(doc,null,2),'utf8');
314
- }
315
-
316
219
  const docs = ${JSON.stringify(docs, null, 2)};
317
220
  const routes = ${JSON.stringify(routes, null, 2)};
318
-
319
- swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs)
320
- .then(() => fixOpenApiFile('${ensurePosix(CONFIG.openapiOut)}'))
321
- .catch((e) => { console.error(e); process.exitCode = 1; });
322
- `;
323
- const outPath = path.resolve(CONFIG.projectRoot, CONFIG.outFile);
324
- fs.writeFileSync(outPath, fileContent, "utf8");
221
+ swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
222
+ fs.writeFileSync(path.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
325
223
  }
326
- async function run(_args) {
327
- const dmmf = await loadDmmfFromProject();
328
- const schemas = buildSchemasFromDmmf(dmmf);
224
+ async function run(args = []) {
225
+ const schemaFlagIndex = args.findIndex((a) => a === "--schema");
226
+ const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
227
+ const schemas = buildSchemasFromPrismaDmmf(schemaPath);
329
228
  generateSwaggerConfigJs(schemas);
330
229
  }
331
230
 
package/dist/cli.cjs CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env node
2
1
  "use strict";
3
2
  var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
@@ -26,8 +25,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
25
  // src/index.ts
27
26
  var import_node_fs = __toESM(require("fs"), 1);
28
27
  var import_node_path = __toESM(require("path"), 1);
28
+ var import_node_module = require("module");
29
29
  var import_glob = require("glob");
30
- var import_node_child_process = require("child_process");
30
+ var import_meta = {};
31
31
  var CONFIG = {
32
32
  projectRoot: process.cwd(),
33
33
  controllersGlob: "./src/web/api/controllers/**/*.ts",
@@ -50,6 +50,28 @@ function pluralize(name) {
50
50
  if (name.endsWith("s")) return `${name}es`;
51
51
  return `${name}s`;
52
52
  }
53
+ function getRequire() {
54
+ const base = typeof __filename !== "undefined" ? __filename : import_meta.url;
55
+ return (0, import_node_module.createRequire)(base);
56
+ }
57
+ function loadDmmfFromProject(schemaPath) {
58
+ const resolvedSchemaPath = schemaPath ? import_node_path.default.resolve(process.cwd(), schemaPath) : import_node_path.default.resolve(process.cwd(), "prisma/schema.prisma");
59
+ if (!import_node_fs.default.existsSync(resolvedSchemaPath)) {
60
+ throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
61
+ }
62
+ const datamodel = import_node_fs.default.readFileSync(resolvedSchemaPath, "utf8");
63
+ const require2 = getRequire();
64
+ let internals;
65
+ try {
66
+ internals = require2("@prisma/internals");
67
+ } catch {
68
+ throw new Error(`Unable to load @prisma/internals`);
69
+ }
70
+ if (typeof internals.getDMMF !== "function") {
71
+ throw new Error(`@prisma/internals.getDMMF not available`);
72
+ }
73
+ return internals.getDMMF({ datamodel });
74
+ }
53
75
  function scalarToSchema(scalar) {
54
76
  switch (scalar) {
55
77
  case "String":
@@ -108,7 +130,9 @@ function stripWriteFields(model, getSchema, omit) {
108
130
  if (!schema.properties) return schema;
109
131
  const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
110
132
  for (const key of Object.keys(schema.properties)) {
111
- if (omit.has(key) || relationFieldNames.has(key)) delete schema.properties[key];
133
+ if (omit.has(key) || relationFieldNames.has(key)) {
134
+ delete schema.properties[key];
135
+ }
112
136
  }
113
137
  if (Array.isArray(schema.required)) {
114
138
  schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
@@ -125,95 +149,19 @@ function listResponseSchema(itemRef) {
125
149
  return {
126
150
  type: "object",
127
151
  properties: {
128
- count: { type: "number", example: 3 },
129
- hasPreviousPage: { type: "boolean", example: false },
130
- hasNextPage: { type: "boolean", example: true },
131
- pageNumber: { type: "number", example: 1 },
132
- pageSize: { type: "number", example: 10 },
133
- totalPages: { type: "number", example: 1 },
152
+ count: { type: "number" },
153
+ hasPreviousPage: { type: "boolean" },
154
+ hasNextPage: { type: "boolean" },
155
+ pageNumber: { type: "number" },
156
+ pageSize: { type: "number" },
157
+ totalPages: { type: "number" },
134
158
  items: { type: "array", items: { $ref: itemRef } }
135
159
  },
136
160
  required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
137
161
  };
138
162
  }
139
- function exampleForScalarType(type, format) {
140
- if (type === "string" && format === "date-time") return (/* @__PURE__ */ new Date(0)).toISOString();
141
- switch (type) {
142
- case "string":
143
- return "string";
144
- case "integer":
145
- return 0;
146
- case "number":
147
- return 0;
148
- case "boolean":
149
- return true;
150
- case "object":
151
- return {};
152
- default:
153
- return null;
154
- }
155
- }
156
- function buildExampleFromSchema(schema, components, depth = 0) {
157
- if (depth > 2) return void 0;
158
- if (schema.$ref) {
159
- const name = String(schema.$ref).split("/").pop() || "";
160
- const target = components[name];
161
- if (!target) return void 0;
162
- return buildExampleFromSchema(target, components, depth + 1);
163
- }
164
- if (Array.isArray(schema.allOf) && schema.allOf.length) {
165
- const merged = {};
166
- for (const part of schema.allOf) {
167
- const ex = buildExampleFromSchema(part, components, depth + 1);
168
- if (ex && typeof ex === "object" && !Array.isArray(ex)) Object.assign(merged, ex);
169
- }
170
- return Object.keys(merged).length ? merged : void 0;
171
- }
172
- if (schema.type === "array" && schema.items) {
173
- const item = buildExampleFromSchema(schema.items, components, depth + 1);
174
- return item === void 0 ? [] : [item];
175
- }
176
- if (schema.type === "object" && schema.properties) {
177
- const obj = {};
178
- for (const [k, v] of Object.entries(schema.properties)) {
179
- const ex = buildExampleFromSchema(v, components, depth + 1);
180
- if (ex !== void 0) obj[k] = ex;
181
- }
182
- return obj;
183
- }
184
- if (Array.isArray(schema.enum) && schema.enum.length) return schema.enum[0];
185
- if (typeof schema.type === "string") return exampleForScalarType(schema.type, schema.format);
186
- return void 0;
187
- }
188
- function attachExample(schema, components) {
189
- const s = JSON.parse(JSON.stringify(schema));
190
- if (s.example === void 0) {
191
- const ex = buildExampleFromSchema(s, components);
192
- if (ex !== void 0) s.example = ex;
193
- }
194
- return s;
195
- }
196
- async function loadDmmfFromProject() {
197
- const schemaPath = import_node_path.default.resolve(process.cwd(), "prisma/schema.prisma");
198
- if (!import_node_fs.default.existsSync(schemaPath)) {
199
- throw new Error(`Prisma schema not found at: ${schemaPath}`);
200
- }
201
- const cmd = `npx prisma generate --schema "${schemaPath}" --print`;
202
- const stdout = (0, import_node_child_process.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
203
- const firstBrace = stdout.indexOf("{");
204
- const lastBrace = stdout.lastIndexOf("}");
205
- if (firstBrace === -1 || lastBrace === -1) {
206
- throw new Error(`Failed to parse Prisma DMMF from: ${cmd}`);
207
- }
208
- const jsonText = stdout.slice(firstBrace, lastBrace + 1);
209
- const parsed = JSON.parse(jsonText);
210
- const dmmf = parsed?.dmmf ?? parsed;
211
- if (!dmmf?.datamodel?.models) {
212
- throw new Error(`Prisma DMMF not found in prisma output. Got keys: ${Object.keys(parsed || {})}`);
213
- }
214
- return dmmf;
215
- }
216
- function buildSchemasFromDmmf(dmmf) {
163
+ function buildSchemasFromPrismaDmmf(schemaPath) {
164
+ const dmmf = loadDmmfFromProject(schemaPath);
217
165
  const schemas = {};
218
166
  const getRefName = (modelName) => `Get${modelName}Response`;
219
167
  for (const e of dmmf.datamodel.enums) {
@@ -267,10 +215,6 @@ function buildSchemasFromDmmf(dmmf) {
267
215
  type: "https://tools.ietf.org/html/rfc7231#section-6.6.1"
268
216
  }
269
217
  };
270
- for (const name of Object.keys(schemas)) {
271
- if (name.startsWith("Post") && name.endsWith("Request")) schemas[name] = attachExample(schemas[name], schemas);
272
- if (name.startsWith("Put") && name.endsWith("Request")) schemas[name] = attachExample(schemas[name], schemas);
273
- }
274
218
  return schemas;
275
219
  }
276
220
  function generateSwaggerConfigJs(schemas) {
@@ -297,60 +241,15 @@ function generateSwaggerConfigJs(schemas) {
297
241
  security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
298
242
  };
299
243
  const fileContent = `const swaggerAutogen = require('swagger-autogen')();
300
- const fs = require('fs');
301
- const path = require('node:path');
302
-
303
- function isPlainObject(v){return v!==null && typeof v==='object' && !Array.isArray(v);}
304
-
305
- function normalizeSchema(schema){
306
- if(!isPlainObject(schema)) return schema;
307
- if(schema.$ref) return schema;
308
-
309
- if(isPlainObject(schema.type) && typeof schema.type.example === 'string') schema.type = schema.type.example;
310
- if(isPlainObject(schema.format) && typeof schema.format.example === 'string') schema.format = schema.format.example;
311
- if(isPlainObject(schema.required) && Array.isArray(schema.required.example)) schema.required = schema.required.example;
312
- if(isPlainObject(schema.enum) && Array.isArray(schema.enum.example)) schema.enum = schema.enum.example;
313
-
314
- if(Array.isArray(schema.allOf)) schema.allOf = schema.allOf.map(normalizeSchema);
315
- if(isPlainObject(schema.items)) schema.items = normalizeSchema(schema.items);
316
- if(isPlainObject(schema.additionalProperties)) schema.additionalProperties = normalizeSchema(schema.additionalProperties);
317
-
318
- if(isPlainObject(schema.properties)){
319
- for(const k of Object.keys(schema.properties)){
320
- schema.properties[k] = normalizeSchema(schema.properties[k]);
321
- }
322
- }
323
-
324
- return schema;
325
- }
326
-
327
- function fixOpenApiFile(openapiPath){
328
- const abs = path.resolve(process.cwd(), openapiPath);
329
- if(!fs.existsSync(abs)) return;
330
- const doc = JSON.parse(fs.readFileSync(abs,'utf8'));
331
-
332
- if(doc && doc.components && isPlainObject(doc.components.schemas)){
333
- for(const name of Object.keys(doc.components.schemas)){
334
- doc.components.schemas[name] = normalizeSchema(doc.components.schemas[name]);
335
- }
336
- }
337
-
338
- fs.writeFileSync(abs, JSON.stringify(doc,null,2),'utf8');
339
- }
340
-
341
244
  const docs = ${JSON.stringify(docs, null, 2)};
342
245
  const routes = ${JSON.stringify(routes, null, 2)};
343
-
344
- swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs)
345
- .then(() => fixOpenApiFile('${ensurePosix(CONFIG.openapiOut)}'))
346
- .catch((e) => { console.error(e); process.exitCode = 1; });
347
- `;
348
- const outPath = import_node_path.default.resolve(CONFIG.projectRoot, CONFIG.outFile);
349
- import_node_fs.default.writeFileSync(outPath, fileContent, "utf8");
246
+ swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
247
+ import_node_fs.default.writeFileSync(import_node_path.default.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
350
248
  }
351
- async function run(_args) {
352
- const dmmf = await loadDmmfFromProject();
353
- const schemas = buildSchemasFromDmmf(dmmf);
249
+ async function run(args = []) {
250
+ const schemaFlagIndex = args.findIndex((a) => a === "--schema");
251
+ const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
252
+ const schemas = buildSchemasFromPrismaDmmf(schemaPath);
354
253
  generateSwaggerConfigJs(schemas);
355
254
  }
356
255
 
package/dist/cli.d.cts CHANGED
@@ -1 +1,2 @@
1
- #!/usr/bin/env node
1
+
2
+ export { }
package/dist/cli.d.ts CHANGED
@@ -1 +1,2 @@
1
- #!/usr/bin/env node
1
+
2
+ export { }
package/dist/cli.js CHANGED
@@ -1,7 +1,6 @@
1
- #!/usr/bin/env node
2
1
  import {
3
2
  run
4
- } from "./chunk-SNNQZQLO.js";
3
+ } from "./chunk-6R6DHPOL.js";
5
4
 
6
5
  // src/cli.ts
7
6
  run(process.argv.slice(2)).catch((e) => {
package/dist/index.cjs CHANGED
@@ -35,8 +35,9 @@ __export(index_exports, {
35
35
  module.exports = __toCommonJS(index_exports);
36
36
  var import_node_fs = __toESM(require("fs"), 1);
37
37
  var import_node_path = __toESM(require("path"), 1);
38
+ var import_node_module = require("module");
38
39
  var import_glob = require("glob");
39
- var import_node_child_process = require("child_process");
40
+ var import_meta = {};
40
41
  var CONFIG = {
41
42
  projectRoot: process.cwd(),
42
43
  controllersGlob: "./src/web/api/controllers/**/*.ts",
@@ -59,6 +60,28 @@ function pluralize(name) {
59
60
  if (name.endsWith("s")) return `${name}es`;
60
61
  return `${name}s`;
61
62
  }
63
+ function getRequire() {
64
+ const base = typeof __filename !== "undefined" ? __filename : import_meta.url;
65
+ return (0, import_node_module.createRequire)(base);
66
+ }
67
+ function loadDmmfFromProject(schemaPath) {
68
+ const resolvedSchemaPath = schemaPath ? import_node_path.default.resolve(process.cwd(), schemaPath) : import_node_path.default.resolve(process.cwd(), "prisma/schema.prisma");
69
+ if (!import_node_fs.default.existsSync(resolvedSchemaPath)) {
70
+ throw new Error(`Prisma schema not found at ${resolvedSchemaPath}`);
71
+ }
72
+ const datamodel = import_node_fs.default.readFileSync(resolvedSchemaPath, "utf8");
73
+ const require2 = getRequire();
74
+ let internals;
75
+ try {
76
+ internals = require2("@prisma/internals");
77
+ } catch {
78
+ throw new Error(`Unable to load @prisma/internals`);
79
+ }
80
+ if (typeof internals.getDMMF !== "function") {
81
+ throw new Error(`@prisma/internals.getDMMF not available`);
82
+ }
83
+ return internals.getDMMF({ datamodel });
84
+ }
62
85
  function scalarToSchema(scalar) {
63
86
  switch (scalar) {
64
87
  case "String":
@@ -117,7 +140,9 @@ function stripWriteFields(model, getSchema, omit) {
117
140
  if (!schema.properties) return schema;
118
141
  const relationFieldNames = new Set(model.fields.filter((f) => f.kind === "object").map((f) => f.name));
119
142
  for (const key of Object.keys(schema.properties)) {
120
- if (omit.has(key) || relationFieldNames.has(key)) delete schema.properties[key];
143
+ if (omit.has(key) || relationFieldNames.has(key)) {
144
+ delete schema.properties[key];
145
+ }
121
146
  }
122
147
  if (Array.isArray(schema.required)) {
123
148
  schema.required = schema.required.filter((k) => !omit.has(k) && !relationFieldNames.has(k));
@@ -134,95 +159,19 @@ function listResponseSchema(itemRef) {
134
159
  return {
135
160
  type: "object",
136
161
  properties: {
137
- count: { type: "number", example: 3 },
138
- hasPreviousPage: { type: "boolean", example: false },
139
- hasNextPage: { type: "boolean", example: true },
140
- pageNumber: { type: "number", example: 1 },
141
- pageSize: { type: "number", example: 10 },
142
- totalPages: { type: "number", example: 1 },
162
+ count: { type: "number" },
163
+ hasPreviousPage: { type: "boolean" },
164
+ hasNextPage: { type: "boolean" },
165
+ pageNumber: { type: "number" },
166
+ pageSize: { type: "number" },
167
+ totalPages: { type: "number" },
143
168
  items: { type: "array", items: { $ref: itemRef } }
144
169
  },
145
170
  required: ["count", "hasPreviousPage", "hasNextPage", "pageNumber", "pageSize", "totalPages", "items"]
146
171
  };
147
172
  }
148
- function exampleForScalarType(type, format) {
149
- if (type === "string" && format === "date-time") return (/* @__PURE__ */ new Date(0)).toISOString();
150
- switch (type) {
151
- case "string":
152
- return "string";
153
- case "integer":
154
- return 0;
155
- case "number":
156
- return 0;
157
- case "boolean":
158
- return true;
159
- case "object":
160
- return {};
161
- default:
162
- return null;
163
- }
164
- }
165
- function buildExampleFromSchema(schema, components, depth = 0) {
166
- if (depth > 2) return void 0;
167
- if (schema.$ref) {
168
- const name = String(schema.$ref).split("/").pop() || "";
169
- const target = components[name];
170
- if (!target) return void 0;
171
- return buildExampleFromSchema(target, components, depth + 1);
172
- }
173
- if (Array.isArray(schema.allOf) && schema.allOf.length) {
174
- const merged = {};
175
- for (const part of schema.allOf) {
176
- const ex = buildExampleFromSchema(part, components, depth + 1);
177
- if (ex && typeof ex === "object" && !Array.isArray(ex)) Object.assign(merged, ex);
178
- }
179
- return Object.keys(merged).length ? merged : void 0;
180
- }
181
- if (schema.type === "array" && schema.items) {
182
- const item = buildExampleFromSchema(schema.items, components, depth + 1);
183
- return item === void 0 ? [] : [item];
184
- }
185
- if (schema.type === "object" && schema.properties) {
186
- const obj = {};
187
- for (const [k, v] of Object.entries(schema.properties)) {
188
- const ex = buildExampleFromSchema(v, components, depth + 1);
189
- if (ex !== void 0) obj[k] = ex;
190
- }
191
- return obj;
192
- }
193
- if (Array.isArray(schema.enum) && schema.enum.length) return schema.enum[0];
194
- if (typeof schema.type === "string") return exampleForScalarType(schema.type, schema.format);
195
- return void 0;
196
- }
197
- function attachExample(schema, components) {
198
- const s = JSON.parse(JSON.stringify(schema));
199
- if (s.example === void 0) {
200
- const ex = buildExampleFromSchema(s, components);
201
- if (ex !== void 0) s.example = ex;
202
- }
203
- return s;
204
- }
205
- async function loadDmmfFromProject() {
206
- const schemaPath = import_node_path.default.resolve(process.cwd(), "prisma/schema.prisma");
207
- if (!import_node_fs.default.existsSync(schemaPath)) {
208
- throw new Error(`Prisma schema not found at: ${schemaPath}`);
209
- }
210
- const cmd = `npx prisma generate --schema "${schemaPath}" --print`;
211
- const stdout = (0, import_node_child_process.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
212
- const firstBrace = stdout.indexOf("{");
213
- const lastBrace = stdout.lastIndexOf("}");
214
- if (firstBrace === -1 || lastBrace === -1) {
215
- throw new Error(`Failed to parse Prisma DMMF from: ${cmd}`);
216
- }
217
- const jsonText = stdout.slice(firstBrace, lastBrace + 1);
218
- const parsed = JSON.parse(jsonText);
219
- const dmmf = parsed?.dmmf ?? parsed;
220
- if (!dmmf?.datamodel?.models) {
221
- throw new Error(`Prisma DMMF not found in prisma output. Got keys: ${Object.keys(parsed || {})}`);
222
- }
223
- return dmmf;
224
- }
225
- function buildSchemasFromDmmf(dmmf) {
173
+ function buildSchemasFromPrismaDmmf(schemaPath) {
174
+ const dmmf = loadDmmfFromProject(schemaPath);
226
175
  const schemas = {};
227
176
  const getRefName = (modelName) => `Get${modelName}Response`;
228
177
  for (const e of dmmf.datamodel.enums) {
@@ -276,10 +225,6 @@ function buildSchemasFromDmmf(dmmf) {
276
225
  type: "https://tools.ietf.org/html/rfc7231#section-6.6.1"
277
226
  }
278
227
  };
279
- for (const name of Object.keys(schemas)) {
280
- if (name.startsWith("Post") && name.endsWith("Request")) schemas[name] = attachExample(schemas[name], schemas);
281
- if (name.startsWith("Put") && name.endsWith("Request")) schemas[name] = attachExample(schemas[name], schemas);
282
- }
283
228
  return schemas;
284
229
  }
285
230
  function generateSwaggerConfigJs(schemas) {
@@ -306,60 +251,15 @@ function generateSwaggerConfigJs(schemas) {
306
251
  security: [{ [CONFIG.securitySchemeName]: ["openid"] }]
307
252
  };
308
253
  const fileContent = `const swaggerAutogen = require('swagger-autogen')();
309
- const fs = require('fs');
310
- const path = require('node:path');
311
-
312
- function isPlainObject(v){return v!==null && typeof v==='object' && !Array.isArray(v);}
313
-
314
- function normalizeSchema(schema){
315
- if(!isPlainObject(schema)) return schema;
316
- if(schema.$ref) return schema;
317
-
318
- if(isPlainObject(schema.type) && typeof schema.type.example === 'string') schema.type = schema.type.example;
319
- if(isPlainObject(schema.format) && typeof schema.format.example === 'string') schema.format = schema.format.example;
320
- if(isPlainObject(schema.required) && Array.isArray(schema.required.example)) schema.required = schema.required.example;
321
- if(isPlainObject(schema.enum) && Array.isArray(schema.enum.example)) schema.enum = schema.enum.example;
322
-
323
- if(Array.isArray(schema.allOf)) schema.allOf = schema.allOf.map(normalizeSchema);
324
- if(isPlainObject(schema.items)) schema.items = normalizeSchema(schema.items);
325
- if(isPlainObject(schema.additionalProperties)) schema.additionalProperties = normalizeSchema(schema.additionalProperties);
326
-
327
- if(isPlainObject(schema.properties)){
328
- for(const k of Object.keys(schema.properties)){
329
- schema.properties[k] = normalizeSchema(schema.properties[k]);
330
- }
331
- }
332
-
333
- return schema;
334
- }
335
-
336
- function fixOpenApiFile(openapiPath){
337
- const abs = path.resolve(process.cwd(), openapiPath);
338
- if(!fs.existsSync(abs)) return;
339
- const doc = JSON.parse(fs.readFileSync(abs,'utf8'));
340
-
341
- if(doc && doc.components && isPlainObject(doc.components.schemas)){
342
- for(const name of Object.keys(doc.components.schemas)){
343
- doc.components.schemas[name] = normalizeSchema(doc.components.schemas[name]);
344
- }
345
- }
346
-
347
- fs.writeFileSync(abs, JSON.stringify(doc,null,2),'utf8');
348
- }
349
-
350
254
  const docs = ${JSON.stringify(docs, null, 2)};
351
255
  const routes = ${JSON.stringify(routes, null, 2)};
352
-
353
- swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs)
354
- .then(() => fixOpenApiFile('${ensurePosix(CONFIG.openapiOut)}'))
355
- .catch((e) => { console.error(e); process.exitCode = 1; });
356
- `;
357
- const outPath = import_node_path.default.resolve(CONFIG.projectRoot, CONFIG.outFile);
358
- import_node_fs.default.writeFileSync(outPath, fileContent, "utf8");
256
+ swaggerAutogen('${ensurePosix(CONFIG.openapiOut)}', routes, docs);`;
257
+ import_node_fs.default.writeFileSync(import_node_path.default.resolve(CONFIG.projectRoot, CONFIG.outFile), fileContent, "utf8");
359
258
  }
360
- async function run(_args) {
361
- const dmmf = await loadDmmfFromProject();
362
- const schemas = buildSchemasFromDmmf(dmmf);
259
+ async function run(args = []) {
260
+ const schemaFlagIndex = args.findIndex((a) => a === "--schema");
261
+ const schemaPath = schemaFlagIndex >= 0 ? args[schemaFlagIndex + 1] : void 0;
262
+ const schemas = buildSchemasFromPrismaDmmf(schemaPath);
363
263
  generateSwaggerConfigJs(schemas);
364
264
  }
365
265
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- declare function run(_args: string[]): Promise<void>;
1
+ declare function run(args?: string[]): Promise<void>;
2
2
 
3
3
  export { run };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- declare function run(_args: string[]): Promise<void>;
1
+ declare function run(args?: string[]): Promise<void>;
2
2
 
3
3
  export { run };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-SNNQZQLO.js";
3
+ } from "./chunk-6R6DHPOL.js";
4
4
  export {
5
5
  run
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-swagger-autogen",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
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",
@@ -42,9 +42,11 @@
42
42
  "build": "tsup src/index.ts src/cli.ts --format esm,cjs --dts --out-dir dist --tsconfig tsconfig.json",
43
43
  "prepublishOnly": "npm run build"
44
44
  },
45
+ "dependencies": {
46
+ "@prisma/internals": "^6.0.0"
47
+ },
45
48
  "peerDependencies": {
46
49
  "@prisma/client": ">=4",
47
- "prisma": ">=4",
48
50
  "glob": ">=10",
49
51
  "swagger-autogen": ">=2"
50
52
  },