arkos 1.4.0-canary.91 → 1.4.1-beta

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.
Files changed (170) hide show
  1. package/dist/cjs/app.js +1 -1
  2. package/dist/cjs/app.js.map +1 -1
  3. package/dist/cjs/exports/index.js.map +1 -1
  4. package/dist/cjs/modules/auth/auth.controller.js +1 -1
  5. package/dist/cjs/modules/auth/auth.controller.js.map +1 -1
  6. package/dist/cjs/modules/auth/auth.service.js +3 -4
  7. package/dist/cjs/modules/auth/auth.service.js.map +1 -1
  8. package/dist/cjs/modules/auth/utils/services/auth-action.service.js +56 -8
  9. package/dist/cjs/modules/auth/utils/services/auth-action.service.js.map +1 -1
  10. package/dist/cjs/modules/base/base.controller.js +6 -3
  11. package/dist/cjs/modules/base/base.controller.js.map +1 -1
  12. package/dist/cjs/modules/base/base.middlewares.js +17 -5
  13. package/dist/cjs/modules/base/base.middlewares.js.map +1 -1
  14. package/dist/cjs/modules/error-handler/error-handler.controller.js +2 -2
  15. package/dist/cjs/modules/error-handler/error-handler.controller.js.map +1 -1
  16. package/dist/cjs/modules/error-handler/utils/catch-async.js.map +1 -1
  17. package/dist/cjs/modules/swagger/swagger.router.js +6 -4
  18. package/dist/cjs/modules/swagger/swagger.router.js.map +1 -1
  19. package/dist/cjs/modules/swagger/utils/built-in-route-path-object-manager.js +7 -0
  20. package/dist/cjs/modules/swagger/utils/built-in-route-path-object-manager.js.map +1 -0
  21. package/dist/cjs/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js +326 -183
  22. package/dist/cjs/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js.map +1 -1
  23. package/dist/cjs/modules/swagger/utils/helpers/get-file-upload-json-schema-paths.js +374 -288
  24. package/dist/cjs/modules/swagger/utils/helpers/get-file-upload-json-schema-paths.js.map +1 -1
  25. package/dist/cjs/modules/swagger/utils/helpers/get-swagger-default-configs.js +1 -5
  26. package/dist/cjs/modules/swagger/utils/helpers/get-swagger-default-configs.js.map +1 -1
  27. package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js +280 -243
  28. package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js.map +1 -1
  29. package/dist/cjs/modules/swagger/utils/helpers/missing-json-schemas-generator.js +3 -0
  30. package/dist/cjs/modules/swagger/utils/helpers/missing-json-schemas-generator.js.map +1 -1
  31. package/dist/cjs/modules/swagger/utils/helpers/swagger.router.helpers.js +8 -6
  32. package/dist/cjs/modules/swagger/utils/helpers/swagger.router.helpers.js.map +1 -1
  33. package/dist/cjs/server.js +17 -15
  34. package/dist/cjs/server.js.map +1 -1
  35. package/dist/cjs/types/index.js.map +1 -1
  36. package/dist/cjs/types/new-arkos-config.js.map +1 -1
  37. package/dist/cjs/utils/arkos-router/index.js +50 -10
  38. package/dist/cjs/utils/arkos-router/index.js.map +1 -1
  39. package/dist/cjs/utils/arkos-router/types/index.js.map +1 -1
  40. package/dist/cjs/utils/arkos-router/utils/helpers/index.js +11 -0
  41. package/dist/cjs/utils/arkos-router/utils/helpers/index.js.map +1 -1
  42. package/dist/cjs/utils/cli/dev.js +18 -57
  43. package/dist/cjs/utils/cli/dev.js.map +1 -1
  44. package/dist/cjs/utils/cli/export-auth-action.js +1 -1
  45. package/dist/cjs/utils/cli/export-auth-action.js.map +1 -1
  46. package/dist/cjs/utils/cli/generate.js +3 -3
  47. package/dist/cjs/utils/cli/generate.js.map +1 -1
  48. package/dist/cjs/utils/cli/index.js +1 -1
  49. package/dist/cjs/utils/cli/index.js.map +1 -1
  50. package/dist/cjs/utils/cli/start.js +19 -12
  51. package/dist/cjs/utils/cli/start.js.map +1 -1
  52. package/dist/cjs/utils/cli/utils/cli.helpers.js +1 -1
  53. package/dist/cjs/utils/cli/utils/runtime-cli-commander.js +51 -6
  54. package/dist/cjs/utils/cli/utils/runtime-cli-commander.js.map +1 -1
  55. package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator/create-dto-template.js +3 -3
  56. package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator/create-dto-template.js.map +1 -1
  57. package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator/update-dto-template.js +3 -3
  58. package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator/update-dto-template.js.map +1 -1
  59. package/dist/cjs/utils/cli/utils/template-generator/templates/middlewares-template.js +6 -3
  60. package/dist/cjs/utils/cli/utils/template-generator/templates/middlewares-template.js.map +1 -1
  61. package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js +3 -1
  62. package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js.map +1 -1
  63. package/dist/cjs/utils/dotenv.helpers.js +15 -7
  64. package/dist/cjs/utils/dotenv.helpers.js.map +1 -1
  65. package/dist/cjs/utils/helpers/api.features.helpers.js +174 -81
  66. package/dist/cjs/utils/helpers/api.features.helpers.js.map +1 -1
  67. package/dist/cjs/utils/helpers/prisma.helpers.js +40 -1
  68. package/dist/cjs/utils/helpers/prisma.helpers.js.map +1 -1
  69. package/dist/cjs/utils/helpers/routers.helpers.js +0 -1
  70. package/dist/cjs/utils/helpers/routers.helpers.js.map +1 -1
  71. package/dist/cjs/utils/prisma/prisma-json-schema-generator.js +19 -4
  72. package/dist/cjs/utils/prisma/prisma-json-schema-generator.js.map +1 -1
  73. package/dist/cjs/utils/validate-dto.js +1 -5
  74. package/dist/cjs/utils/validate-dto.js.map +1 -1
  75. package/dist/cjs/utils/validate-schema.js +2 -7
  76. package/dist/cjs/utils/validate-schema.js.map +1 -1
  77. package/dist/esm/app.js +1 -1
  78. package/dist/esm/app.js.map +1 -1
  79. package/dist/esm/exports/index.js.map +1 -1
  80. package/dist/esm/modules/auth/auth.controller.js +1 -1
  81. package/dist/esm/modules/auth/auth.controller.js.map +1 -1
  82. package/dist/esm/modules/auth/auth.service.js +4 -5
  83. package/dist/esm/modules/auth/auth.service.js.map +1 -1
  84. package/dist/esm/modules/auth/utils/services/auth-action.service.js +56 -5
  85. package/dist/esm/modules/auth/utils/services/auth-action.service.js.map +1 -1
  86. package/dist/esm/modules/base/base.controller.js +6 -3
  87. package/dist/esm/modules/base/base.controller.js.map +1 -1
  88. package/dist/esm/modules/base/base.middlewares.js +17 -5
  89. package/dist/esm/modules/base/base.middlewares.js.map +1 -1
  90. package/dist/esm/modules/error-handler/error-handler.controller.js +2 -2
  91. package/dist/esm/modules/error-handler/error-handler.controller.js.map +1 -1
  92. package/dist/esm/modules/error-handler/utils/catch-async.js.map +1 -1
  93. package/dist/esm/modules/swagger/swagger.router.js +6 -4
  94. package/dist/esm/modules/swagger/swagger.router.js.map +1 -1
  95. package/dist/esm/modules/swagger/utils/built-in-route-path-object-manager.js +5 -0
  96. package/dist/esm/modules/swagger/utils/built-in-route-path-object-manager.js.map +1 -0
  97. package/dist/esm/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js +326 -183
  98. package/dist/esm/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js.map +1 -1
  99. package/dist/esm/modules/swagger/utils/helpers/get-file-upload-json-schema-paths.js +374 -288
  100. package/dist/esm/modules/swagger/utils/helpers/get-file-upload-json-schema-paths.js.map +1 -1
  101. package/dist/esm/modules/swagger/utils/helpers/get-swagger-default-configs.js +1 -2
  102. package/dist/esm/modules/swagger/utils/helpers/get-swagger-default-configs.js.map +1 -1
  103. package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js +280 -243
  104. package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js.map +1 -1
  105. package/dist/esm/modules/swagger/utils/helpers/missing-json-schemas-generator.js +3 -0
  106. package/dist/esm/modules/swagger/utils/helpers/missing-json-schemas-generator.js.map +1 -1
  107. package/dist/esm/modules/swagger/utils/helpers/swagger.router.helpers.js +8 -6
  108. package/dist/esm/modules/swagger/utils/helpers/swagger.router.helpers.js.map +1 -1
  109. package/dist/esm/server.js +17 -15
  110. package/dist/esm/server.js.map +1 -1
  111. package/dist/esm/types/index.js.map +1 -1
  112. package/dist/esm/types/new-arkos-config.js.map +1 -1
  113. package/dist/esm/utils/arkos-router/index.js +51 -11
  114. package/dist/esm/utils/arkos-router/index.js.map +1 -1
  115. package/dist/esm/utils/arkos-router/types/index.js.map +1 -1
  116. package/dist/esm/utils/arkos-router/utils/helpers/index.js +10 -0
  117. package/dist/esm/utils/arkos-router/utils/helpers/index.js.map +1 -1
  118. package/dist/esm/utils/cli/dev.js +19 -58
  119. package/dist/esm/utils/cli/dev.js.map +1 -1
  120. package/dist/esm/utils/cli/export-auth-action.js +1 -1
  121. package/dist/esm/utils/cli/export-auth-action.js.map +1 -1
  122. package/dist/esm/utils/cli/generate.js +3 -3
  123. package/dist/esm/utils/cli/generate.js.map +1 -1
  124. package/dist/esm/utils/cli/index.js +1 -1
  125. package/dist/esm/utils/cli/index.js.map +1 -1
  126. package/dist/esm/utils/cli/start.js +19 -12
  127. package/dist/esm/utils/cli/start.js.map +1 -1
  128. package/dist/esm/utils/cli/utils/cli.helpers.js +1 -1
  129. package/dist/esm/utils/cli/utils/runtime-cli-commander.js +52 -7
  130. package/dist/esm/utils/cli/utils/runtime-cli-commander.js.map +1 -1
  131. package/dist/esm/utils/cli/utils/template-generator/templates/class-validator/create-dto-template.js +3 -3
  132. package/dist/esm/utils/cli/utils/template-generator/templates/class-validator/create-dto-template.js.map +1 -1
  133. package/dist/esm/utils/cli/utils/template-generator/templates/class-validator/update-dto-template.js +3 -3
  134. package/dist/esm/utils/cli/utils/template-generator/templates/class-validator/update-dto-template.js.map +1 -1
  135. package/dist/esm/utils/cli/utils/template-generator/templates/middlewares-template.js +6 -3
  136. package/dist/esm/utils/cli/utils/template-generator/templates/middlewares-template.js.map +1 -1
  137. package/dist/esm/utils/cli/utils/template-generator/templates/router-template.js +3 -1
  138. package/dist/esm/utils/cli/utils/template-generator/templates/router-template.js.map +1 -1
  139. package/dist/esm/utils/dotenv.helpers.js +15 -7
  140. package/dist/esm/utils/dotenv.helpers.js.map +1 -1
  141. package/dist/esm/utils/helpers/api.features.helpers.js +174 -81
  142. package/dist/esm/utils/helpers/api.features.helpers.js.map +1 -1
  143. package/dist/esm/utils/helpers/prisma.helpers.js +39 -1
  144. package/dist/esm/utils/helpers/prisma.helpers.js.map +1 -1
  145. package/dist/esm/utils/helpers/routers.helpers.js +0 -1
  146. package/dist/esm/utils/helpers/routers.helpers.js.map +1 -1
  147. package/dist/esm/utils/prisma/prisma-json-schema-generator.js +19 -4
  148. package/dist/esm/utils/prisma/prisma-json-schema-generator.js.map +1 -1
  149. package/dist/esm/utils/validate-dto.js +1 -2
  150. package/dist/esm/utils/validate-dto.js.map +1 -1
  151. package/dist/esm/utils/validate-schema.js +2 -4
  152. package/dist/esm/utils/validate-schema.js.map +1 -1
  153. package/dist/types/exports/index.d.ts +2 -1
  154. package/dist/types/modules/auth/auth.router.d.ts +1 -1
  155. package/dist/types/modules/auth/auth.service.d.ts +2 -2
  156. package/dist/types/modules/base/base.router.d.ts +1 -1
  157. package/dist/types/modules/swagger/utils/built-in-route-path-object-manager.d.ts +4 -0
  158. package/dist/types/modules/swagger/utils/helpers/get-authentication-json-schema-paths.d.ts +1 -1
  159. package/dist/types/modules/swagger/utils/helpers/get-file-upload-json-schema-paths.d.ts +1 -1
  160. package/dist/types/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.d.ts +1 -1
  161. package/dist/types/modules/swagger/utils/helpers/swagger.router.helpers.d.ts +1 -1
  162. package/dist/types/types/index.d.ts +5 -5
  163. package/dist/types/types/new-arkos-config.d.ts +1 -1
  164. package/dist/types/utils/arkos-router/index.d.ts +2 -1
  165. package/dist/types/utils/arkos-router/types/index.d.ts +15 -14
  166. package/dist/types/utils/arkos-router/utils/helpers/index.d.ts +1 -0
  167. package/dist/types/utils/cli/dev.d.ts +1 -1
  168. package/dist/types/utils/cli/start.d.ts +1 -1
  169. package/dist/types/utils/helpers/prisma.helpers.d.ts +1 -0
  170. package/package.json +2 -2
@@ -2,8 +2,8 @@ import { getModuleComponents } from "../../../../utils/dynamic-loader.js";
2
2
  import { isEndpointDisabled } from "../../../base/utils/helpers/base.router.helpers.js";
3
3
  import deepmerge from "../../../../utils/helpers/deepmerge.helper.js";
4
4
  import { fileUploadDefaultRestrictions } from "../../../file-upload/file-upload.service.js";
5
- export default function getFileUploadJsonSchemaPaths(arkosConfig) {
6
- const paths = {};
5
+ export default function getFileUploadJsonSchemaPaths(arkosConfig, existingPaths) {
6
+ const paths = { ...existingPaths };
7
7
  if (!arkosConfig.fileUpload)
8
8
  return paths;
9
9
  const FileUploadModuleComponents = getModuleComponents("file-upload");
@@ -54,359 +54,445 @@ export default function getFileUploadJsonSchemaPaths(arkosConfig) {
54
54
  const cleanBasePath = basePathname.endsWith("/")
55
55
  ? basePathname.slice(0, -1)
56
56
  : basePathname;
57
- paths[`${cleanBasePath}/{filePath*}`] = {
58
- get: {
59
- tags: ["File Upload"],
60
- summary: "Retrieve uploaded file",
61
- description: `Serves static files from the upload directory (${baseUploadDir}). This endpoint uses wildcard path matching to serve files from any subdirectory.`,
62
- operationId: "findFile",
63
- ...(shouldIncludeSecurity("View") && {
64
- security: [{ BearerAuth: [] }],
65
- }),
66
- parameters: [
67
- {
68
- name: "filePath",
69
- in: "path",
70
- required: true,
71
- schema: { type: "string" },
72
- description: "Path to the file including file type directory (e.g., images/photo.jpg, videos/clip.mp4)",
73
- },
74
- ],
75
- responses: {
76
- "200": {
77
- description: "File retrieved successfully",
78
- content: {
79
- "application/octet-stream": {
80
- schema: {
81
- type: "string",
82
- format: "binary",
83
- },
57
+ const pathname = `${cleanBasePath}/{filePath*}`;
58
+ if (!paths[pathname])
59
+ paths[pathname] = {};
60
+ const currentPath = paths[pathname].get;
61
+ const defaultParameters = [
62
+ {
63
+ name: "filePath",
64
+ in: "path",
65
+ required: true,
66
+ schema: { type: "string" },
67
+ description: "Path to the file including file type directory (e.g., images/photo.jpg, videos/clip.mp4)",
68
+ },
69
+ ];
70
+ const existingParams = currentPath?.parameters || [];
71
+ const existingParamKeys = new Set(existingParams.map((p) => `${p.in}-${p.name}`));
72
+ const mergedParameters = [
73
+ ...existingParams,
74
+ ...defaultParameters.filter((p) => !existingParamKeys.has(`${p.in}-${p.name}`)),
75
+ ];
76
+ const defaultSpec = {
77
+ tags: ["File Upload", ...(currentPath?.tags || [])].filter((tag) => tag !== "Defaults"),
78
+ summary: currentPath?.summary === pathname || !currentPath?.summary
79
+ ? "Retrieve uploaded file"
80
+ : currentPath?.summary,
81
+ description: currentPath?.description === pathname || !currentPath?.description
82
+ ? `Serves static files from the upload directory (${baseUploadDir}). This endpoint uses wildcard path matching to serve files from any subdirectory.`
83
+ : currentPath?.description,
84
+ operationId: currentPath?.operationId?.includes(pathname) ||
85
+ !currentPath?.operationId
86
+ ? "findFile"
87
+ : currentPath?.operationId,
88
+ ...(shouldIncludeSecurity("View") && {
89
+ security: [{ BearerAuth: [] }],
90
+ }),
91
+ parameters: mergedParameters,
92
+ responses: {
93
+ ...(currentPath?.responses || {}),
94
+ "200": currentPath?.responses?.["200"] || {
95
+ description: "File retrieved successfully",
96
+ content: {
97
+ "application/octet-stream": {
98
+ schema: {
99
+ type: "string",
100
+ format: "binary",
84
101
  },
85
102
  },
86
103
  },
87
- "404": {
88
- description: "File not found",
89
- },
90
- ...(shouldIncludeSecurity("View") && {
91
- "401": { description: "Authentication required" },
92
- "403": { description: "Insufficient permissions to view files" },
93
- }),
94
104
  },
105
+ "404": currentPath?.responses?.["404"] || {
106
+ description: "File not found",
107
+ },
108
+ ...(shouldIncludeSecurity("View") && {
109
+ "401": currentPath?.responses?.["401"] || {
110
+ description: "Authentication required",
111
+ },
112
+ "403": currentPath?.responses?.["403"] || {
113
+ description: "Insufficient permissions to view files",
114
+ },
115
+ }),
95
116
  },
96
117
  };
118
+ paths[pathname].get = { ...(currentPath || {}), ...defaultSpec };
97
119
  }
98
120
  if (!isFileUploadEndpointDisabled("uploadFile")) {
99
121
  const cleanBasePath = basePathname.endsWith("/")
100
122
  ? basePathname.slice(0, -1)
101
123
  : basePathname;
102
- paths[`${cleanBasePath}/{fileType}`] = {
103
- post: {
104
- tags: ["File Upload"],
105
- summary: "Upload file(s)",
106
- description: "Upload one or multiple files. Supports image processing options for image uploads.",
107
- operationId: "uploadFile",
108
- ...(shouldIncludeSecurity("Create") && {
109
- security: [{ BearerAuth: [] }],
110
- }),
111
- parameters: [
112
- {
113
- name: "fileType",
114
- in: "path",
115
- required: true,
116
- schema: {
117
- type: "string",
118
- enum: ["images", "videos", "documents", "files"],
119
- },
120
- description: "Type of file being uploaded",
121
- },
122
- {
123
- name: "format",
124
- in: "query",
125
- required: false,
126
- schema: {
127
- type: "string",
128
- enum: ["jpeg", "jpg", "png", "webp", "gif", "avif"],
129
- },
130
- description: "Image format for conversion (only applicable for fileType=images)",
131
- },
132
- {
133
- name: "width",
134
- in: "query",
135
- required: false,
136
- schema: { type: "integer", minimum: 1 },
137
- description: "Target width for image resize (only applicable for fileType=images)",
138
- },
139
- {
140
- name: "height",
141
- in: "query",
142
- required: false,
143
- schema: { type: "integer", minimum: 1 },
144
- description: "Target height for image resize (only applicable for fileType=images)",
145
- },
146
- {
147
- name: "resizeTo",
148
- in: "query",
149
- required: false,
124
+ const pathname = `${cleanBasePath}/{fileType}`;
125
+ if (!paths[pathname])
126
+ paths[pathname] = {};
127
+ const currentPath = paths[pathname].post;
128
+ const defaultParameters = [
129
+ {
130
+ name: "fileType",
131
+ in: "path",
132
+ required: true,
133
+ schema: {
134
+ type: "string",
135
+ enum: ["images", "videos", "documents", "files"],
136
+ },
137
+ description: "Type of file being uploaded",
138
+ },
139
+ {
140
+ name: "format",
141
+ in: "query",
142
+ required: false,
143
+ schema: {
144
+ type: "string",
145
+ enum: ["jpeg", "jpg", "png", "webp", "gif", "avif"],
146
+ },
147
+ description: "Image format for conversion (only applicable for fileType=images)",
148
+ },
149
+ {
150
+ name: "width",
151
+ in: "query",
152
+ required: false,
153
+ schema: { type: "integer", minimum: 1 },
154
+ description: "Target width for image resize (only applicable for fileType=images)",
155
+ },
156
+ {
157
+ name: "height",
158
+ in: "query",
159
+ required: false,
160
+ schema: { type: "integer", minimum: 1 },
161
+ description: "Target height for image resize (only applicable for fileType=images)",
162
+ },
163
+ {
164
+ name: "resizeTo",
165
+ in: "query",
166
+ required: false,
167
+ schema: {
168
+ type: "string",
169
+ enum: ["cover", "contain", "fill", "inside", "outside"],
170
+ },
171
+ description: "Resize strategy (only applicable for fileType=images)",
172
+ },
173
+ ];
174
+ const existingParams = currentPath?.parameters || [];
175
+ const existingParamKeys = new Set(existingParams.map((p) => `${p.in}-${p.name}`));
176
+ const mergedParameters = [
177
+ ...existingParams,
178
+ ...defaultParameters.filter((p) => !existingParamKeys.has(`${p.in}-${p.name}`)),
179
+ ];
180
+ const defaultSpec = {
181
+ tags: ["File Upload", ...(currentPath?.tags || [])].filter((tag) => tag !== "Defaults"),
182
+ summary: currentPath?.summary === pathname || !currentPath?.summary
183
+ ? "Upload file(s)"
184
+ : currentPath?.summary,
185
+ description: currentPath?.description === pathname || !currentPath?.description
186
+ ? "Upload one or multiple files. Supports image processing options for image uploads."
187
+ : currentPath?.description,
188
+ operationId: currentPath?.operationId?.includes(pathname) ||
189
+ !currentPath?.operationId
190
+ ? "uploadFile"
191
+ : currentPath?.operationId,
192
+ ...(shouldIncludeSecurity("Create") && {
193
+ security: [{ BearerAuth: [] }],
194
+ }),
195
+ parameters: mergedParameters,
196
+ requestBody: currentPath?.requestBody || {
197
+ required: true,
198
+ content: {
199
+ "multipart/form-data": {
150
200
  schema: {
151
- type: "string",
152
- enum: ["cover", "contain", "fill", "inside", "outside"],
201
+ type: "object",
202
+ properties: {
203
+ images: {
204
+ type: "array",
205
+ items: { type: "string", format: "binary" },
206
+ description: getFileTypeDescription("images"),
207
+ },
208
+ videos: {
209
+ type: "array",
210
+ items: { type: "string", format: "binary" },
211
+ description: getFileTypeDescription("videos"),
212
+ },
213
+ documents: {
214
+ type: "array",
215
+ items: { type: "string", format: "binary" },
216
+ description: getFileTypeDescription("documents"),
217
+ },
218
+ files: {
219
+ type: "array",
220
+ items: { type: "string", format: "binary" },
221
+ description: getFileTypeDescription("files"),
222
+ },
223
+ },
153
224
  },
154
- description: "Resize strategy (only applicable for fileType=images)",
155
225
  },
156
- ],
157
- requestBody: {
158
- required: true,
226
+ },
227
+ },
228
+ responses: {
229
+ ...(currentPath?.responses || {}),
230
+ "200": currentPath?.responses?.["200"] || {
231
+ description: "File(s) uploaded successfully",
159
232
  content: {
160
- "multipart/form-data": {
233
+ "application/json": {
161
234
  schema: {
162
235
  type: "object",
163
236
  properties: {
164
- images: {
165
- type: "array",
166
- items: { type: "string", format: "binary" },
167
- description: getFileTypeDescription("images"),
168
- },
169
- videos: {
170
- type: "array",
171
- items: { type: "string", format: "binary" },
172
- description: getFileTypeDescription("videos"),
173
- },
174
- documents: {
175
- type: "array",
176
- items: { type: "string", format: "binary" },
177
- description: getFileTypeDescription("documents"),
178
- },
179
- files: {
180
- type: "array",
181
- items: { type: "string", format: "binary" },
182
- description: getFileTypeDescription("files"),
237
+ success: { type: "boolean", example: true },
238
+ data: {
239
+ oneOf: [
240
+ { type: "string", description: "URL of uploaded file" },
241
+ {
242
+ type: "array",
243
+ items: { type: "string" },
244
+ description: "URLs of uploaded files",
245
+ },
246
+ ],
183
247
  },
248
+ message: { type: "string" },
184
249
  },
185
250
  },
186
251
  },
187
252
  },
188
253
  },
189
- responses: {
190
- "200": {
191
- description: "File(s) uploaded successfully",
192
- content: {
193
- "application/json": {
194
- schema: {
195
- type: "object",
196
- properties: {
197
- success: { type: "boolean", example: true },
198
- data: {
199
- oneOf: [
200
- { type: "string", description: "URL of uploaded file" },
201
- {
202
- type: "array",
203
- items: { type: "string" },
204
- description: "URLs of uploaded files",
205
- },
206
- ],
207
- },
208
- message: { type: "string" },
209
- },
210
- },
211
- },
212
- },
254
+ "400": currentPath?.responses?.["400"] || {
255
+ description: "Invalid file type, size limit exceeded, or no file uploaded",
256
+ },
257
+ ...(shouldIncludeSecurity("Create") && {
258
+ "401": currentPath?.responses?.["401"] || {
259
+ description: "Authentication required",
213
260
  },
214
- "400": {
215
- description: "Invalid file type, size limit exceeded, or no file uploaded",
261
+ "403": currentPath?.responses?.["403"] || {
262
+ description: "Insufficient permissions to upload files",
216
263
  },
217
- ...(shouldIncludeSecurity("Create") && {
218
- "401": { description: "Authentication required" },
219
- "403": { description: "Insufficient permissions to upload files" },
220
- }),
221
- },
264
+ }),
222
265
  },
223
266
  };
267
+ paths[pathname].post = { ...(currentPath || {}), ...defaultSpec };
224
268
  }
225
269
  if (!isFileUploadEndpointDisabled("updateFile")) {
226
270
  const cleanBasePath = basePathname.endsWith("/")
227
271
  ? basePathname.slice(0, -1)
228
272
  : basePathname;
229
- paths[`${cleanBasePath}/{fileType}/{fileName}`] = {
230
- ...(paths[`${cleanBasePath}/{fileType}/{fileName}`] || {}),
231
- patch: {
232
- tags: ["File Upload"],
233
- summary: "Update existing file",
234
- description: "Replace an existing file with a new one. Deletes the old file and uploads the new one.",
235
- operationId: "updateFile",
236
- ...(shouldIncludeSecurity("Update") && {
237
- security: [{ BearerAuth: [] }],
238
- }),
239
- parameters: [
240
- {
241
- name: "fileType",
242
- in: "path",
243
- required: true,
244
- schema: {
245
- type: "string",
246
- enum: ["images", "videos", "documents", "files"],
247
- },
248
- description: "Type of file being updated",
249
- },
250
- {
251
- name: "fileName",
252
- in: "path",
253
- required: true,
254
- schema: { type: "string" },
255
- description: "Name of the file to update",
256
- },
257
- {
258
- name: "format",
259
- in: "query",
260
- required: false,
261
- schema: {
262
- type: "string",
263
- enum: ["jpeg", "jpg", "png", "webp", "gif", "avif"],
264
- },
265
- description: "Image format for conversion (only applicable for fileType=images)",
266
- },
267
- {
268
- name: "width",
269
- in: "query",
270
- required: false,
271
- schema: { type: "integer", minimum: 1 },
272
- description: "Target width for image resize (only applicable for fileType=images)",
273
- },
274
- {
275
- name: "height",
276
- in: "query",
277
- required: false,
278
- schema: { type: "integer", minimum: 1 },
279
- description: "Target height for image resize (only applicable for fileType=images)",
280
- },
281
- {
282
- name: "resizeTo",
283
- in: "query",
284
- required: false,
273
+ const pathname = `${cleanBasePath}/{fileType}/{fileName}`;
274
+ if (!paths[pathname])
275
+ paths[pathname] = {};
276
+ const currentPath = paths[pathname].patch;
277
+ const defaultParameters = [
278
+ {
279
+ name: "fileType",
280
+ in: "path",
281
+ required: true,
282
+ schema: {
283
+ type: "string",
284
+ enum: ["images", "videos", "documents", "files"],
285
+ },
286
+ description: "Type of file being updated",
287
+ },
288
+ {
289
+ name: "fileName",
290
+ in: "path",
291
+ required: true,
292
+ schema: { type: "string" },
293
+ description: "Name of the file to update",
294
+ },
295
+ {
296
+ name: "format",
297
+ in: "query",
298
+ required: false,
299
+ schema: {
300
+ type: "string",
301
+ enum: ["jpeg", "jpg", "png", "webp", "gif", "avif"],
302
+ },
303
+ description: "Image format for conversion (only applicable for fileType=images)",
304
+ },
305
+ {
306
+ name: "width",
307
+ in: "query",
308
+ required: false,
309
+ schema: { type: "integer", minimum: 1 },
310
+ description: "Target width for image resize (only applicable for fileType=images)",
311
+ },
312
+ {
313
+ name: "height",
314
+ in: "query",
315
+ required: false,
316
+ schema: { type: "integer", minimum: 1 },
317
+ description: "Target height for image resize (only applicable for fileType=images)",
318
+ },
319
+ {
320
+ name: "resizeTo",
321
+ in: "query",
322
+ required: false,
323
+ schema: {
324
+ type: "string",
325
+ enum: ["cover", "contain", "fill", "inside", "outside"],
326
+ },
327
+ description: "Resize strategy (only applicable for fileType=images)",
328
+ },
329
+ ];
330
+ const existingParams = currentPath?.parameters || [];
331
+ const existingParamKeys = new Set(existingParams.map((p) => `${p.in}-${p.name}`));
332
+ const mergedParameters = [
333
+ ...existingParams,
334
+ ...defaultParameters.filter((p) => !existingParamKeys.has(`${p.in}-${p.name}`)),
335
+ ];
336
+ const defaultSpec = {
337
+ tags: ["File Upload", ...(currentPath?.tags || [])].filter((tag) => tag !== "Defaults"),
338
+ summary: currentPath?.summary === pathname || !currentPath?.summary
339
+ ? "Update existing file"
340
+ : currentPath?.summary,
341
+ description: currentPath?.description === pathname || !currentPath?.description
342
+ ? "Replace an existing file with a new one. Deletes the old file and uploads the new one."
343
+ : currentPath?.description,
344
+ operationId: currentPath?.operationId?.includes(pathname) ||
345
+ !currentPath?.operationId
346
+ ? "updateFile"
347
+ : currentPath?.operationId,
348
+ ...(shouldIncludeSecurity("Update") && {
349
+ security: [{ BearerAuth: [] }],
350
+ }),
351
+ parameters: mergedParameters,
352
+ requestBody: currentPath?.requestBody || {
353
+ required: true,
354
+ content: {
355
+ "multipart/form-data": {
285
356
  schema: {
286
- type: "string",
287
- enum: ["cover", "contain", "fill", "inside", "outside"],
357
+ type: "object",
358
+ properties: {
359
+ images: {
360
+ type: "array",
361
+ items: { type: "string", format: "binary" },
362
+ description: getFileTypeDescription("images"),
363
+ },
364
+ videos: {
365
+ type: "array",
366
+ items: { type: "string", format: "binary" },
367
+ description: getFileTypeDescription("videos"),
368
+ },
369
+ documents: {
370
+ type: "array",
371
+ items: { type: "string", format: "binary" },
372
+ description: getFileTypeDescription("documents"),
373
+ },
374
+ files: {
375
+ type: "array",
376
+ items: { type: "string", format: "binary" },
377
+ description: getFileTypeDescription("files"),
378
+ },
379
+ },
288
380
  },
289
- description: "Resize strategy (only applicable for fileType=images)",
290
381
  },
291
- ],
292
- requestBody: {
293
- required: true,
382
+ },
383
+ },
384
+ responses: {
385
+ ...(currentPath?.responses || {}),
386
+ "200": currentPath?.responses?.["200"] || {
387
+ description: "File updated successfully",
294
388
  content: {
295
- "multipart/form-data": {
389
+ "application/json": {
296
390
  schema: {
297
391
  type: "object",
298
392
  properties: {
299
- images: {
300
- type: "array",
301
- items: { type: "string", format: "binary" },
302
- description: getFileTypeDescription("images"),
303
- },
304
- videos: {
305
- type: "array",
306
- items: { type: "string", format: "binary" },
307
- description: getFileTypeDescription("videos"),
308
- },
309
- documents: {
310
- type: "array",
311
- items: { type: "string", format: "binary" },
312
- description: getFileTypeDescription("documents"),
313
- },
314
- files: {
315
- type: "array",
316
- items: { type: "string", format: "binary" },
317
- description: getFileTypeDescription("files"),
393
+ success: { type: "boolean", example: true },
394
+ data: {
395
+ oneOf: [
396
+ { type: "string", description: "URL of updated file" },
397
+ {
398
+ type: "array",
399
+ items: { type: "string" },
400
+ description: "URLs of updated files",
401
+ },
402
+ ],
318
403
  },
404
+ message: { type: "string" },
319
405
  },
320
406
  },
321
407
  },
322
408
  },
323
409
  },
324
- responses: {
325
- "200": {
326
- description: "File updated successfully",
327
- content: {
328
- "application/json": {
329
- schema: {
330
- type: "object",
331
- properties: {
332
- success: { type: "boolean", example: true },
333
- data: {
334
- oneOf: [
335
- { type: "string", description: "URL of updated file" },
336
- {
337
- type: "array",
338
- items: { type: "string" },
339
- description: "URLs of updated files",
340
- },
341
- ],
342
- },
343
- message: { type: "string" },
344
- },
345
- },
346
- },
347
- },
348
- },
349
- "400": {
350
- description: "Invalid file type, size limit exceeded, or no file uploaded",
410
+ "400": currentPath?.responses?.["400"] || {
411
+ description: "Invalid file type, size limit exceeded, or no file uploaded",
412
+ },
413
+ "404": currentPath?.responses?.["404"] || {
414
+ description: "Original file not found",
415
+ },
416
+ ...(shouldIncludeSecurity("Update") && {
417
+ "401": currentPath?.responses?.["401"] || {
418
+ description: "Authentication required",
351
419
  },
352
- "404": {
353
- description: "Original file not found",
420
+ "403": currentPath?.responses?.["403"] || {
421
+ description: "Insufficient permissions to update files",
354
422
  },
355
- ...(shouldIncludeSecurity("Update") && {
356
- "401": { description: "Authentication required" },
357
- "403": { description: "Insufficient permissions to update files" },
358
- }),
359
- },
423
+ }),
360
424
  },
361
425
  };
426
+ paths[pathname].patch = { ...(currentPath || {}), ...defaultSpec };
362
427
  }
363
428
  if (!isFileUploadEndpointDisabled("deleteFile")) {
364
429
  const cleanBasePath = basePathname.endsWith("/")
365
430
  ? basePathname.slice(0, -1)
366
431
  : basePathname;
367
- if (!paths[`${cleanBasePath}/{fileType}/{fileName}`]) {
368
- paths[`${cleanBasePath}/{fileType}/{fileName}`] = {};
369
- }
370
- paths[`${cleanBasePath}/{fileType}/{fileName}`].delete = {
371
- tags: ["File Upload"],
372
- summary: "Delete file",
373
- description: "Delete an uploaded file from the server",
374
- operationId: "deleteFile",
432
+ const pathname = `${cleanBasePath}/{fileType}/{fileName}`;
433
+ if (!paths[pathname])
434
+ paths[pathname] = {};
435
+ const currentPath = paths[pathname].delete;
436
+ const defaultParameters = [
437
+ {
438
+ name: "fileType",
439
+ in: "path",
440
+ required: true,
441
+ schema: {
442
+ type: "string",
443
+ enum: ["images", "videos", "documents", "files"],
444
+ },
445
+ description: "Type of file being deleted",
446
+ },
447
+ {
448
+ name: "fileName",
449
+ in: "path",
450
+ required: true,
451
+ schema: { type: "string" },
452
+ description: "Name of the file to delete",
453
+ },
454
+ ];
455
+ const existingParams = currentPath?.parameters || [];
456
+ const existingParamKeys = new Set(existingParams.map((p) => `${p.in}-${p.name}`));
457
+ const mergedParameters = [
458
+ ...existingParams,
459
+ ...defaultParameters.filter((p) => !existingParamKeys.has(`${p.in}-${p.name}`)),
460
+ ];
461
+ const defaultSpec = {
462
+ tags: ["File Upload", ...(currentPath?.tags || [])].filter((tag) => tag !== "Defaults"),
463
+ summary: currentPath?.summary === pathname || !currentPath?.summary
464
+ ? "Delete file"
465
+ : currentPath?.summary,
466
+ description: currentPath?.description === pathname || !currentPath?.description
467
+ ? "Delete an uploaded file from the server"
468
+ : currentPath?.description,
469
+ operationId: currentPath?.operationId?.includes(pathname) ||
470
+ !currentPath?.operationId
471
+ ? "deleteFile"
472
+ : currentPath?.operationId,
375
473
  ...(shouldIncludeSecurity("Delete") && {
376
474
  security: [{ BearerAuth: [] }],
377
475
  }),
378
- parameters: [
379
- {
380
- name: "fileType",
381
- in: "path",
382
- required: true,
383
- schema: {
384
- type: "string",
385
- enum: ["images", "videos", "documents", "files"],
386
- },
387
- description: "Type of file being deleted",
388
- },
389
- {
390
- name: "fileName",
391
- in: "path",
392
- required: true,
393
- schema: { type: "string" },
394
- description: "Name of the file to delete",
395
- },
396
- ],
476
+ parameters: mergedParameters,
397
477
  responses: {
398
- "204": {
478
+ ...(currentPath?.responses || {}),
479
+ "204": currentPath?.responses?.["204"] || {
399
480
  description: "File deleted successfully",
400
481
  },
401
- "404": {
482
+ "404": currentPath?.responses?.["404"] || {
402
483
  description: "File not found",
403
484
  },
404
485
  ...(shouldIncludeSecurity("Delete") && {
405
- "401": { description: "Authentication required" },
406
- "403": { description: "Insufficient permissions to delete files" },
486
+ "401": currentPath?.responses?.["401"] || {
487
+ description: "Authentication required",
488
+ },
489
+ "403": currentPath?.responses?.["403"] || {
490
+ description: "Insufficient permissions to delete files",
491
+ },
407
492
  }),
408
493
  },
409
494
  };
495
+ paths[pathname].delete = { ...(currentPath || {}), ...defaultSpec };
410
496
  }
411
497
  return paths;
412
498
  }