@dudousxd/nestjs-codegen 0.12.0 → 0.13.0

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.
@@ -1589,6 +1589,55 @@ function extractParamsType(method, sourceFile, project) {
1589
1589
  }
1590
1590
  return entries.length > 0 ? `{ ${entries.join("; ")} }` : null;
1591
1591
  }
1592
+ function extractUploadedFiles(method) {
1593
+ const FILE = "File | Blob";
1594
+ const entries = [];
1595
+ let multipart = false;
1596
+ const hasUploadedFileParam = method.getParameters().some(
1597
+ (p) => p.getDecorators().some((d) => {
1598
+ const name = d.getName();
1599
+ return name === "UploadedFile" || name === "UploadedFiles";
1600
+ })
1601
+ );
1602
+ for (const decorator of method.getDecorators()) {
1603
+ if (decorator.getName() !== "UseInterceptors") continue;
1604
+ for (const arg of decorator.getArguments()) {
1605
+ if (!import_ts_morph5.Node.isCallExpression(arg)) continue;
1606
+ const interceptor = arg.getExpression().getText();
1607
+ const callArgs = arg.getArguments();
1608
+ const firstArg2 = callArgs[0];
1609
+ if (interceptor === "FileInterceptor") {
1610
+ if (firstArg2 && import_ts_morph5.Node.isStringLiteral(firstArg2)) {
1611
+ entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
1612
+ multipart = true;
1613
+ }
1614
+ } else if (interceptor === "FilesInterceptor") {
1615
+ if (firstArg2 && import_ts_morph5.Node.isStringLiteral(firstArg2)) {
1616
+ entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
1617
+ multipart = true;
1618
+ }
1619
+ } else if (interceptor === "FileFieldsInterceptor") {
1620
+ if (firstArg2 && import_ts_morph5.Node.isArrayLiteralExpression(firstArg2)) {
1621
+ for (const el of firstArg2.getElements()) {
1622
+ if (!import_ts_morph5.Node.isObjectLiteralExpression(el)) continue;
1623
+ const nameProp = el.getProperty("name");
1624
+ if (nameProp && import_ts_morph5.Node.isPropertyAssignment(nameProp)) {
1625
+ const init = nameProp.getInitializer();
1626
+ if (init && import_ts_morph5.Node.isStringLiteral(init)) {
1627
+ entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
1628
+ }
1629
+ }
1630
+ }
1631
+ multipart = true;
1632
+ }
1633
+ } else if (interceptor === "AnyFilesInterceptor") {
1634
+ multipart = true;
1635
+ }
1636
+ }
1637
+ }
1638
+ if (hasUploadedFileParam) multipart = true;
1639
+ return { fields: entries.length > 0 ? entries.join("; ") : null, multipart };
1640
+ }
1592
1641
  function extractResponseType(method, sourceFile, project) {
1593
1642
  const apiResponseDecorator = method.getDecorators().find((d) => d.getName() === "ApiResponse" && (apiResponseStatus(d) ?? 0) < 400);
1594
1643
  if (apiResponseDecorator) {
@@ -1723,6 +1772,11 @@ function extractDtoContract(method, sourceFile, project) {
1723
1772
  let body = extractBodyType(method, sourceFile, project);
1724
1773
  const filterInfo = extractApplyFilterInfo(method, sourceFile, project);
1725
1774
  const query = extractQueryType(method, sourceFile, project);
1775
+ const uploads = extractUploadedFiles(method);
1776
+ if (uploads.fields) {
1777
+ const fileObject = `{ ${uploads.fields} }`;
1778
+ body = body ? `(${body}) & ${fileObject}` : fileObject;
1779
+ }
1726
1780
  const streamElement = detectStreamElement(method);
1727
1781
  const isStream = streamElement !== null;
1728
1782
  if (filterInfo && filterInfo.source === "body") {
@@ -1732,7 +1786,7 @@ function extractDtoContract(method, sourceFile, project) {
1732
1786
  const paramsType = extractParamsType(method, sourceFile, project);
1733
1787
  const response = isStream ? resolveTypeNodeToString(streamElement, sourceFile, project, 3) : extractResponseType(method, sourceFile, project);
1734
1788
  const errorInfo = extractErrorType(method, sourceFile, project);
1735
- if (body === null && query === null && paramsType === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream) {
1789
+ if (body === null && query === null && paramsType === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart) {
1736
1790
  return null;
1737
1791
  }
1738
1792
  let bodyRef = null;
@@ -1805,7 +1859,8 @@ function extractDtoContract(method, sourceFile, project) {
1805
1859
  formWarnings,
1806
1860
  bodySchema,
1807
1861
  querySchema,
1808
- stream: isStream
1862
+ stream: isStream,
1863
+ multipart: uploads.multipart
1809
1864
  };
1810
1865
  }
1811
1866
  function resolveParamClass(method, decoratorName, sourceFile, project) {
@@ -2272,7 +2327,8 @@ function extractDtoRoute(args) {
2272
2327
  formWarnings: dtoContract?.formWarnings ?? [],
2273
2328
  bodySchema: dtoContract?.bodySchema ?? null,
2274
2329
  querySchema: dtoContract?.querySchema ?? null,
2275
- stream: dtoContract?.stream ?? false
2330
+ stream: dtoContract?.stream ?? false,
2331
+ multipart: dtoContract?.multipart ?? false
2276
2332
  }
2277
2333
  });
2278
2334
  }
@@ -2918,6 +2974,7 @@ function buildRequestModel(c) {
2918
2974
  const optsParts = [];
2919
2975
  if (hasQuery) optsParts.push("query: input?.query as Record<string, unknown> | undefined");
2920
2976
  if (hasBody) optsParts.push("body: input?.body");
2977
+ if (hasBody && c.contractSource.multipart) optsParts.push("multipart: true");
2921
2978
  const optsExpr = optsParts.length ? `{ ${optsParts.join(", ")} }` : "{}";
2922
2979
  return {
2923
2980
  routeName: c.name,
@@ -4264,7 +4321,7 @@ async function acquireLock(outDir) {
4264
4321
  }
4265
4322
 
4266
4323
  // src/index.ts
4267
- var VERSION = "0.12.0";
4324
+ var VERSION = "0.13.0";
4268
4325
 
4269
4326
  // src/generate-manifest.ts
4270
4327
  var MANIFEST_FILE = ".codegen-manifest.json";