@superblocksteam/util 1.14.2 → 2.0.3-next.50

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 (95) hide show
  1. package/.prettierrc +1 -0
  2. package/dist/api-files/api.d.mts +7 -0
  3. package/dist/api-files/api.d.mts.map +1 -0
  4. package/dist/api-files/api.mjs +262 -0
  5. package/dist/api-files/api.mjs.map +1 -0
  6. package/dist/api-files/constants.d.ts +6 -0
  7. package/dist/api-files/constants.d.ts.map +1 -0
  8. package/dist/api-files/constants.js +9 -0
  9. package/dist/api-files/constants.js.map +1 -0
  10. package/dist/api-files/index.d.ts +7 -0
  11. package/dist/api-files/index.d.ts.map +1 -0
  12. package/dist/api-files/index.js +13 -0
  13. package/dist/api-files/index.js.map +1 -0
  14. package/dist/api-files/types.d.ts +117 -0
  15. package/dist/api-files/types.d.ts.map +1 -0
  16. package/dist/api-files/types.js +17 -0
  17. package/dist/api-files/types.js.map +1 -0
  18. package/dist/component-configs.d.ts +1 -0
  19. package/dist/component-configs.d.ts.map +1 -0
  20. package/dist/component-configs.js +10 -9
  21. package/dist/component-configs.js.map +1 -0
  22. package/dist/constants.d.ts +1 -0
  23. package/dist/constants.d.ts.map +1 -0
  24. package/dist/constants.js +1 -0
  25. package/dist/constants.js.map +1 -0
  26. package/dist/data-types.d.ts +1 -0
  27. package/dist/data-types.d.ts.map +1 -0
  28. package/dist/data-types.js +1 -0
  29. package/dist/data-types.js.map +1 -0
  30. package/dist/events.d.ts +1 -0
  31. package/dist/events.d.ts.map +1 -0
  32. package/dist/events.js +1 -0
  33. package/dist/events.js.map +1 -0
  34. package/dist/file-uploader.d.ts +1 -0
  35. package/dist/file-uploader.d.ts.map +1 -0
  36. package/dist/file-uploader.js +1 -0
  37. package/dist/file-uploader.js.map +1 -0
  38. package/dist/generate-component-types.d.ts +2 -1
  39. package/dist/generate-component-types.d.ts.map +1 -0
  40. package/dist/generate-component-types.js +5 -5
  41. package/dist/generate-component-types.js.map +1 -0
  42. package/dist/identifiers.d.ts +1 -0
  43. package/dist/identifiers.d.ts.map +1 -0
  44. package/dist/identifiers.js +2 -1
  45. package/dist/identifiers.js.map +1 -0
  46. package/dist/index.d.ts +16 -11
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +16 -11
  49. package/dist/index.js.map +1 -0
  50. package/dist/localGitRepoState.d.ts +2 -1
  51. package/dist/localGitRepoState.d.ts.map +1 -0
  52. package/dist/localGitRepoState.js +1 -0
  53. package/dist/localGitRepoState.js.map +1 -0
  54. package/dist/login.d.ts +1 -0
  55. package/dist/login.d.ts.map +1 -0
  56. package/dist/login.js +6 -5
  57. package/dist/login.js.map +1 -0
  58. package/dist/mask-unix-signals.d.ts +27 -0
  59. package/dist/mask-unix-signals.d.ts.map +1 -0
  60. package/dist/mask-unix-signals.js +81 -0
  61. package/dist/mask-unix-signals.js.map +1 -0
  62. package/dist/resource-configs.d.ts +9 -1
  63. package/dist/resource-configs.d.ts.map +1 -0
  64. package/dist/resource-configs.js +66 -11
  65. package/dist/resource-configs.js.map +1 -0
  66. package/dist/types.d.ts +8 -7
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +1 -0
  69. package/dist/types.js.map +1 -0
  70. package/dist/unreachable.d.ts +2 -1
  71. package/dist/unreachable.d.ts.map +1 -0
  72. package/dist/unreachable.js +3 -2
  73. package/dist/unreachable.js.map +1 -0
  74. package/dist/validation.d.ts +1 -0
  75. package/dist/validation.d.ts.map +1 -0
  76. package/dist/validation.js +4 -3
  77. package/dist/validation.js.map +1 -0
  78. package/eslint.config.js +11 -1
  79. package/package.json +18 -11
  80. package/src/api-files/api.mts +504 -0
  81. package/src/api-files/constants.ts +6 -0
  82. package/src/api-files/index.ts +15 -0
  83. package/src/api-files/types.ts +134 -0
  84. package/src/component-configs.ts +3 -3
  85. package/src/generate-component-types.ts +2 -2
  86. package/src/index.ts +15 -11
  87. package/src/localGitRepoState.ts +1 -1
  88. package/src/login.ts +1 -1
  89. package/src/mask-unix-signals.ts +86 -0
  90. package/src/resource-configs.ts +81 -1
  91. package/src/types.ts +8 -11
  92. package/src/unreachable.ts +4 -2
  93. package/src/validation.ts +4 -3
  94. package/tsconfig.json +9 -2
  95. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,UAAU,sBAAsB,CAAC,CAAC,SAAS,QAAQ;IACjD;;;;OAIG;IACH,WAAW,EAAE,CAAC,SAAS,SAAS,GAC5B,MAAM,GAAG,SAAS,GAAG,QAAQ,GAC7B,MAAM,GAAG,SAAS,CAAC;IAEvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC;CAClB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,QAAQ;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,CAAC;IAEZ;;;QAGI;IACJ,sBAAsB,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAEnD;;;QAGI;IACJ,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;QAGI;IACJ,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,QAAQ,GAChB,eAAe,CAAC,QAAQ,CAAC,GACzB,eAAe,CAAC,QAAQ,CAAC,GACzB,eAAe,CAAC,SAAS,CAAC,GAC1B,eAAe,CAAC,KAAK,CAAC,CAAC;AAE3B,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,IAAI,CAAC;IAET;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB,UAAU,EAAE,KAAK,CAIb,eAAe,CAAC,QAAQ,CAAC,GACzB,eAAe,CAAC,QAAQ,CAAC,GACzB,eAAe,CAAC,SAAS,CAAC,GAC1B,eAAe,CAAC,KAAK,CAAC,CACzB,CAAC;IAEF;;;;;OAKG;IACH,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IAEH,cAAc,CAAC,EAAE;QACf,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH"}
package/dist/types.js CHANGED
@@ -1,2 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -1 +1,2 @@
1
- export declare function unreachable(value: never): never;
1
+ export declare function unreachable(value: never, errMsg?: string): never;
2
+ //# sourceMappingURL=unreachable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unreachable.d.ts","sourceRoot":"","sources":["../src/unreachable.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAIhE"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.unreachable = unreachable;
4
- function unreachable(value) {
5
- throw new TypeError("Encountered impossible value: " + JSON.stringify(value));
4
+ function unreachable(value, errMsg) {
5
+ throw new TypeError(errMsg ?? "Encountered impossible value: " + JSON.stringify(value));
6
6
  }
7
+ //# sourceMappingURL=unreachable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unreachable.js","sourceRoot":"","sources":["../src/unreachable.ts"],"names":[],"mappings":";;AAAA,kCAIC;AAJD,SAAgB,WAAW,CAAC,KAAY,EAAE,MAAe;IACvD,MAAM,IAAI,SAAS,CACjB,MAAM,IAAI,gCAAgC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CACnE,CAAC;AACJ,CAAC"}
@@ -2,3 +2,4 @@ export declare function validateCustomComponents(data: any): {
2
2
  valid: boolean;
3
3
  message?: string;
4
4
  };
5
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AA4IA,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,GAAG,GAAG;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAWA"}
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.validateCustomComponents = validateCustomComponents;
7
7
  const ajv_1 = __importDefault(require("ajv"));
8
8
  const better_ajv_errors_1 = __importDefault(require("better-ajv-errors"));
9
- const identifiers_1 = require("./identifiers");
9
+ const identifiers_js_1 = require("./identifiers.js");
10
10
  const ajv = new ajv_1.default();
11
11
  ajv.addKeyword({
12
12
  keyword: "stringFormat",
@@ -17,7 +17,7 @@ ajv.addKeyword({
17
17
  validateFunc = (data) => {
18
18
  if (typeof data != "string")
19
19
  return false;
20
- if (!(0, identifiers_1.isValidIdentifier)(data)) {
20
+ if (!(0, identifiers_js_1.isValidIdentifier)(data)) {
21
21
  validateFunc.errors = [
22
22
  {
23
23
  keyword: "format",
@@ -26,7 +26,7 @@ ajv.addKeyword({
26
26
  ];
27
27
  return false;
28
28
  }
29
- if ((0, identifiers_1.isReservedPropertyName)(data)) {
29
+ if ((0, identifiers_js_1.isReservedPropertyName)(data)) {
30
30
  validateFunc.errors = [
31
31
  {
32
32
  keyword: "format",
@@ -149,3 +149,4 @@ function validateCustomComponents(data) {
149
149
  }
150
150
  return { valid: true };
151
151
  }
152
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
package/eslint.config.js CHANGED
@@ -21,7 +21,7 @@ const config = [
21
21
  },
22
22
  js.configs.recommended,
23
23
  ...tseslint.configs.recommended,
24
- eslintPluginPrettierRecommended,
24
+ { files: ["./*", "src/**"], ...eslintPluginPrettierRecommended },
25
25
  {
26
26
  plugins: {
27
27
  "@typescript-eslint": tseslint.plugin,
@@ -39,6 +39,8 @@ const config = [
39
39
  "@typescript-eslint/no-explicit-any": "off",
40
40
  "@typescript-eslint/no-unused-vars": "error",
41
41
  "@typescript-eslint/no-var-requires": "off",
42
+ "@typescript-eslint/no-import-type-side-effects": "error",
43
+ "@typescript-eslint/consistent-type-imports": "error",
42
44
  "unicorn/no-nested-ternary": "off",
43
45
  "import/order": [
44
46
  "error",
@@ -57,6 +59,14 @@ const config = [
57
59
  },
58
60
  ],
59
61
  "import/no-cycle": "error",
62
+ "import/extensions": [
63
+ "error",
64
+ "ignorePackages",
65
+ {
66
+ ts: "never",
67
+ tsx: "never",
68
+ },
69
+ ],
60
70
  "no-template-curly-in-string": "off",
61
71
  "no-useless-escape": "off",
62
72
  "no-void": ["error", { allowAsStatement: true }],
package/package.json CHANGED
@@ -1,39 +1,46 @@
1
1
  {
2
2
  "name": "@superblocksteam/util",
3
- "version": "1.14.2",
4
- "main": "dist/index.js",
3
+ "description": "",
4
+ "version": "2.0.3-next.50",
5
5
  "homepage": "https://www.superblocks.com",
6
6
  "license": "Superblocks Community Software License",
7
- "description": "",
7
+ "main": "dist/index.js",
8
8
  "dependencies": {
9
9
  "ajv": "^8.12.0",
10
- "better-ajv-errors": "^1.2.0",
10
+ "better-ajv-errors": "1.2.0",
11
11
  "fs-extra": "^11.1.1",
12
12
  "lodash": "^4.17.21",
13
+ "lodash-es": "^4.17.21",
13
14
  "mime-types": "^2.1.35",
14
- "typescript": "^5.1.3"
15
+ "slugify": "^1.6.6",
16
+ "typescript": "^5.1.3",
17
+ "yaml": "^2.4.2"
15
18
  },
16
19
  "devDependencies": {
20
+ "@eslint/js": "^9.16.0",
17
21
  "@types/fs-extra": "^11.0.1",
18
22
  "@types/lodash": "^4.17.7",
23
+ "@types/lodash-es": "^4.17.12",
19
24
  "@types/mime-types": "^2.1.1",
20
25
  "@types/node": "^20.11.18",
21
26
  "@typescript-eslint/eslint-plugin": "^8.25.0",
22
27
  "@typescript-eslint/parser": "^8.25.0",
23
28
  "eslint": "^9.21.0",
29
+ "eslint-plugin-import": "2.31.0",
30
+ "eslint-plugin-mocha": "^10.5.0",
24
31
  "eslint-plugin-prettier": "^5.2.5",
25
32
  "eslint-plugin-unicorn": "^47.0.0",
26
33
  "prettier": "^3.5.2",
27
- "tslib": "^2.5.0"
34
+ "tslib": "^2.5.0",
35
+ "typescript-eslint": "^8.18.0"
28
36
  },
29
37
  "scripts": {
30
- "dev": "tsc --watch",
31
38
  "build": "tsc --build",
32
- "clean": "npm run clean:build && rm -rf node_modules",
33
- "clean:build": "tsc --build --clean && rm -rf dist tsconfig.tsbuildinfo",
39
+ "check": "pnpm run lint && pnpm run typecheck",
40
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
41
+ "dev": "tsc --build --watch",
34
42
  "lint": "eslint .",
35
43
  "lint:fix": "eslint . --fix",
36
- "typecheck": "tsc --noEmit",
37
- "check": "pnpm run lint && pnpm run typecheck"
44
+ "typecheck": "tsc --noEmit"
38
45
  }
39
46
  }
@@ -0,0 +1,504 @@
1
+ import fs from "fs-extra";
2
+ import { cloneDeep } from "lodash-es";
3
+ import slugify from "slugify";
4
+ import { parse, stringify as ymlstringify } from "yaml";
5
+ import {
6
+ DEFAULT_LINES_FOR_LARGE_STEPS,
7
+ LANGUAGE_STEP_EXTENSIONS,
8
+ } from "./constants.js";
9
+ import type {
10
+ AdditionalStepFiles,
11
+ Api,
12
+ ApiRepresentation,
13
+ ApiWrapper,
14
+ Block,
15
+ LanguageContent,
16
+ Step,
17
+ } from "./types.js";
18
+
19
+ function slugifyName(originalName: any): string {
20
+ return (slugify as any)(originalName, {
21
+ replacement: "_",
22
+ lower: true,
23
+ });
24
+ }
25
+
26
+ function findUnusedFilePath(
27
+ filename: string,
28
+ extension: string,
29
+ existingFilePaths: Set<string>,
30
+ ): string {
31
+ let proposedFilename = `${filename}.${extension}`;
32
+ let i = 1;
33
+ while (existingFilePaths.has(proposedFilename)) {
34
+ proposedFilename = `${filename}_${i}.${extension}`;
35
+ i++;
36
+ }
37
+ existingFilePaths.add(proposedFilename);
38
+ return proposedFilename;
39
+ }
40
+
41
+ function extractAdditionalStepFiles(
42
+ api: Api,
43
+ additionalStepFiles: AdditionalStepFiles[],
44
+ stepPathMap: Record<string, string>,
45
+ currentStepNames: string[],
46
+ apiRepresentation?: ApiRepresentation,
47
+ ): Api {
48
+ if (!api.blocks || !apiRepresentation?.extractLargeSourceFiles) {
49
+ return api;
50
+ }
51
+ // TODO: lodash
52
+ const apiClone = cloneDeep(api);
53
+ const minLinesForExtraction =
54
+ apiRepresentation?.minLinesForExtraction ?? DEFAULT_LINES_FOR_LARGE_STEPS;
55
+ const existingFilePaths = new Set<string>();
56
+ extractAdditionalStepFilesFromBlocks(
57
+ apiClone.blocks ?? [],
58
+ additionalStepFiles,
59
+ existingFilePaths,
60
+ minLinesForExtraction,
61
+ stepPathMap,
62
+ currentStepNames,
63
+ );
64
+ return apiClone;
65
+ }
66
+
67
+ function extractAdditionalStepFilesFromStep(
68
+ step: Step,
69
+ name: string,
70
+ additionalStepFiles: AdditionalStepFiles[],
71
+ existingFilePaths: Set<string>,
72
+ minLinesForExtraction: number,
73
+ stepPathMap: Record<string, string>,
74
+ currentStepNames: string[],
75
+ ) {
76
+ // Handle language step files
77
+ if (step && "integration" in step) {
78
+ const integration = step.integration as keyof Step;
79
+ const extension =
80
+ LANGUAGE_STEP_EXTENSIONS[
81
+ integration as keyof typeof LANGUAGE_STEP_EXTENSIONS
82
+ ];
83
+ if (extension) {
84
+ const languageContent = step[integration] as LanguageContent;
85
+ if (languageContent) {
86
+ const blockBody = languageContent.body;
87
+ if (blockBody && typeof blockBody === "string") {
88
+ const lines = blockBody?.split("\n");
89
+ const linesNum = lines?.length;
90
+ if (linesNum && linesNum > minLinesForExtraction) {
91
+ // Record the separate file is needed, with the language contents
92
+ let relativePath;
93
+ if (stepPathMap?.[name]) {
94
+ relativePath = stepPathMap[name].startsWith("./")
95
+ ? stepPathMap[name].split("./")?.[1]
96
+ : stepPathMap[name];
97
+ } else {
98
+ relativePath = findUnusedFilePath(
99
+ slugifyName(name),
100
+ extension,
101
+ existingFilePaths,
102
+ );
103
+ stepPathMap[name] = `./${relativePath}`;
104
+ }
105
+ additionalStepFiles.push({
106
+ relativePath: relativePath,
107
+ contents: blockBody,
108
+ language: integration,
109
+ });
110
+ currentStepNames.push(name);
111
+ // Replace the body with a reference to the separate file
112
+ languageContent.body = {
113
+ path: `./${relativePath}`,
114
+ };
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ function extractAdditionalStepFilesFromBlocks(
123
+ blocks: Block[],
124
+ additionalStepFiles: AdditionalStepFiles[],
125
+ existingFilePaths: Set<string>,
126
+ minLinesForExtraction: number,
127
+ stepPathMap: Record<string, string>,
128
+ currentStepNames: string[],
129
+ ) {
130
+ for (const block of blocks) {
131
+ // Handle language step files
132
+ if (block.step) {
133
+ extractAdditionalStepFilesFromStep(
134
+ block.step,
135
+ block.name,
136
+ additionalStepFiles,
137
+ existingFilePaths,
138
+ minLinesForExtraction,
139
+ stepPathMap,
140
+ currentStepNames,
141
+ );
142
+ }
143
+
144
+ // Handle loops
145
+ extractAdditionalStepFilesFromBlocks(
146
+ block.loop?.blocks ?? [],
147
+ additionalStepFiles,
148
+ existingFilePaths,
149
+ minLinesForExtraction,
150
+ stepPathMap,
151
+ currentStepNames,
152
+ );
153
+ // Handle try/catch
154
+ if (block.tryCatch) {
155
+ extractAdditionalStepFilesFromBlocks(
156
+ block.tryCatch.try?.blocks ?? [],
157
+ additionalStepFiles,
158
+ existingFilePaths,
159
+ minLinesForExtraction,
160
+ stepPathMap,
161
+ currentStepNames,
162
+ );
163
+ extractAdditionalStepFilesFromBlocks(
164
+ block.tryCatch.catch?.blocks ?? [],
165
+ additionalStepFiles,
166
+ existingFilePaths,
167
+ minLinesForExtraction,
168
+ stepPathMap,
169
+ currentStepNames,
170
+ );
171
+ extractAdditionalStepFilesFromBlocks(
172
+ block.tryCatch.finally?.blocks ?? [],
173
+ additionalStepFiles,
174
+ existingFilePaths,
175
+ minLinesForExtraction,
176
+ stepPathMap,
177
+ currentStepNames,
178
+ );
179
+ }
180
+ // Handle conditional
181
+ if (block.conditional) {
182
+ extractAdditionalStepFilesFromBlocks(
183
+ block.conditional.if?.blocks ?? [],
184
+ additionalStepFiles,
185
+ existingFilePaths,
186
+ minLinesForExtraction,
187
+ stepPathMap,
188
+ currentStepNames,
189
+ );
190
+ for (const elseIfBlock of block.conditional.elseIf ?? []) {
191
+ extractAdditionalStepFilesFromBlocks(
192
+ elseIfBlock.blocks,
193
+ additionalStepFiles,
194
+ existingFilePaths,
195
+ minLinesForExtraction,
196
+ stepPathMap,
197
+ currentStepNames,
198
+ );
199
+ }
200
+ extractAdditionalStepFilesFromBlocks(
201
+ block.conditional.else?.blocks ?? [],
202
+ additionalStepFiles,
203
+ existingFilePaths,
204
+ minLinesForExtraction,
205
+ stepPathMap,
206
+ currentStepNames,
207
+ );
208
+ }
209
+ // Handle Parallel API
210
+ if (block.parallel) {
211
+ for (const path of Object.values(block.parallel?.static?.paths ?? {})) {
212
+ extractAdditionalStepFilesFromBlocks(
213
+ path.blocks,
214
+ additionalStepFiles,
215
+ existingFilePaths,
216
+ minLinesForExtraction,
217
+ stepPathMap,
218
+ currentStepNames,
219
+ );
220
+ }
221
+ extractAdditionalStepFilesFromBlocks(
222
+ block.parallel?.dynamic?.blocks ?? [],
223
+ additionalStepFiles,
224
+ existingFilePaths,
225
+ minLinesForExtraction,
226
+ stepPathMap,
227
+ currentStepNames,
228
+ );
229
+ }
230
+ // Handle stream
231
+ if (block.stream) {
232
+ const trigger = block.stream.trigger;
233
+ if (trigger && trigger.step) {
234
+ extractAdditionalStepFilesFromStep(
235
+ trigger.step,
236
+ trigger.name,
237
+ additionalStepFiles,
238
+ existingFilePaths,
239
+ minLinesForExtraction,
240
+ stepPathMap,
241
+ currentStepNames,
242
+ );
243
+ }
244
+ extractAdditionalStepFilesFromBlocks(
245
+ block.stream.process?.blocks ?? [],
246
+ additionalStepFiles,
247
+ existingFilePaths,
248
+ minLinesForExtraction,
249
+ stepPathMap,
250
+ currentStepNames,
251
+ );
252
+ }
253
+ }
254
+ }
255
+
256
+ async function readYamlFile(path: string): Promise<any> {
257
+ return parse(await fs.readFile(path, "utf8"));
258
+ }
259
+
260
+ async function resolveLanguageSpecificStepContentFromBlocks(
261
+ parentPath: string,
262
+ blocks: Block[],
263
+ stepPathMap: Record<string, string>,
264
+ ) {
265
+ for (const block of blocks) {
266
+ // Handle language-specific step content
267
+ if (block.step) {
268
+ const step = block.step;
269
+ await resolveLanguageSpecificStepContentFromStep(
270
+ parentPath,
271
+ step,
272
+ block.name,
273
+ stepPathMap,
274
+ );
275
+ }
276
+ // Handle conditional blocks
277
+ if (block.conditional) {
278
+ await resolveLanguageSpecificStepContentFromBlocks(
279
+ parentPath,
280
+ block.conditional.if?.blocks ?? [],
281
+ stepPathMap,
282
+ );
283
+ for (const elseIfBlock of block.conditional.elseIf) {
284
+ await resolveLanguageSpecificStepContentFromBlocks(
285
+ parentPath,
286
+ elseIfBlock.blocks,
287
+ stepPathMap,
288
+ );
289
+ }
290
+ await resolveLanguageSpecificStepContentFromBlocks(
291
+ parentPath,
292
+ block.conditional.else?.blocks ?? [],
293
+ stepPathMap,
294
+ );
295
+ }
296
+ // Handle loop blocks
297
+ await resolveLanguageSpecificStepContentFromBlocks(
298
+ parentPath,
299
+ block.loop?.blocks ?? [],
300
+ stepPathMap,
301
+ );
302
+ // Handle try-catch blocks
303
+ if (block.tryCatch) {
304
+ await resolveLanguageSpecificStepContentFromBlocks(
305
+ parentPath,
306
+ block.tryCatch.try?.blocks ?? [],
307
+ stepPathMap,
308
+ );
309
+ await resolveLanguageSpecificStepContentFromBlocks(
310
+ parentPath,
311
+ block.tryCatch.catch?.blocks ?? [],
312
+ stepPathMap,
313
+ );
314
+ await resolveLanguageSpecificStepContentFromBlocks(
315
+ parentPath,
316
+ block.tryCatch.finally?.blocks ?? [],
317
+ stepPathMap,
318
+ );
319
+ }
320
+ // Handle parallel blocks
321
+ if (block.parallel) {
322
+ for (const path of Object.values(block.parallel?.static?.paths ?? {})) {
323
+ await resolveLanguageSpecificStepContentFromBlocks(
324
+ parentPath,
325
+ path.blocks,
326
+ stepPathMap,
327
+ );
328
+ }
329
+ await resolveLanguageSpecificStepContentFromBlocks(
330
+ parentPath,
331
+ block.parallel?.dynamic?.blocks ?? [],
332
+ stepPathMap,
333
+ );
334
+ }
335
+ // Handle stream blocks
336
+ if (block.stream) {
337
+ await resolveLanguageSpecificStepContentFromBlocks(
338
+ parentPath,
339
+ block.stream.process?.blocks ?? [],
340
+ stepPathMap,
341
+ );
342
+ await resolveLanguageSpecificStepContentFromStep(
343
+ parentPath,
344
+ block.stream.trigger?.step ?? ({} as Step),
345
+ block.stream.trigger?.name,
346
+ stepPathMap,
347
+ );
348
+ }
349
+ }
350
+ }
351
+
352
+ async function resolveLanguageSpecificStepContentFromStep(
353
+ parentPath: string,
354
+ step: Step,
355
+ stepName?: string,
356
+ stepPathMap?: Record<string, string>,
357
+ ) {
358
+ // Handle language-specific step content
359
+ if (
360
+ !step?.integration ||
361
+ !LANGUAGE_STEP_EXTENSIONS[
362
+ step.integration as keyof typeof LANGUAGE_STEP_EXTENSIONS
363
+ ]
364
+ ) {
365
+ return;
366
+ }
367
+ const languageContent = step[
368
+ step.integration as keyof Step
369
+ ] as LanguageContent;
370
+ if (
371
+ languageContent.body &&
372
+ typeof languageContent.body === "object" &&
373
+ "path" in languageContent.body
374
+ ) {
375
+ const languageFilePath = `${parentPath}/${languageContent.body.path}`;
376
+ if (await fs.pathExists(languageFilePath)) {
377
+ // Read the file content
378
+ const stepBodyContent = await fs.readFile(languageFilePath, "utf8");
379
+ if (stepBodyContent && languageContent) {
380
+ if (stepPathMap && stepName) {
381
+ stepPathMap[stepName] = languageContent.body.path;
382
+ }
383
+ languageContent.body = stepBodyContent;
384
+ }
385
+ }
386
+ }
387
+ }
388
+
389
+ export async function writeApiFiles(
390
+ api: ApiWrapper,
391
+ apiNameSlug: string,
392
+ directoryPath: string,
393
+ nestedApiFiles: boolean,
394
+ apiPromises: Array<Promise<void>>,
395
+ additionalStepFiles: AdditionalStepFiles[],
396
+ apiRepresentation?: ApiRepresentation,
397
+ existingFilePaths?: Set<string>,
398
+ stepPathMap?: Record<string, string>,
399
+ ) {
400
+ let pathForApiFile = directoryPath;
401
+ let yamlFileName = `${apiNameSlug}.yaml`;
402
+
403
+ const currentStepNames: string[] = [];
404
+ // Determine whether to extract into separate files the source code from the steps
405
+ const updatedApi = extractAdditionalStepFiles(
406
+ api.apiPb,
407
+ additionalStepFiles,
408
+ stepPathMap ?? {},
409
+ currentStepNames,
410
+ apiRepresentation,
411
+ );
412
+
413
+ // Stop tracking unused step paths from removed steps (e.g. when a step is renamed or removed)
414
+ if (stepPathMap) {
415
+ Object.keys(stepPathMap).forEach((stepName) => {
416
+ if (!currentStepNames.includes(stepName)) {
417
+ const stepFileName = stepPathMap[stepName].startsWith("./")
418
+ ? stepPathMap[stepName].split("./")[1]
419
+ : stepPathMap[stepName];
420
+ fs.remove(`${pathForApiFile}/${stepFileName}`);
421
+ delete stepPathMap[stepName];
422
+ }
423
+ });
424
+ }
425
+
426
+ if (apiRepresentation?.extractLargeSourceFiles) {
427
+ if (nestedApiFiles) {
428
+ // This API has at least one large step code file, so we need a nested directory
429
+ pathForApiFile = `${pathForApiFile}/${apiNameSlug}`;
430
+ yamlFileName = "api.yaml";
431
+ }
432
+ // Make sure the directory exists
433
+ await fs.ensureDir(pathForApiFile);
434
+ // Write any additional step source code files to the disk
435
+ for (const stepFile of additionalStepFiles) {
436
+ const sourceFilePath = `${pathForApiFile}/${stepFile.relativePath}`;
437
+ const handleApi = async () => {
438
+ await fs.outputFile(sourceFilePath, stepFile.contents);
439
+ };
440
+ apiPromises.push(handleApi());
441
+ // Mark the existing source file as being reused
442
+ existingFilePaths?.delete(sourceFilePath);
443
+ }
444
+ } else {
445
+ // No additional step files to write, so mark the API directory as existing so that it will be removed later.
446
+ // Do this even if the current representation does not extract large source files, in case they were previously
447
+ existingFilePaths?.add(`${directoryPath}/${apiNameSlug}`);
448
+ }
449
+
450
+ // Convert the updated API to YAML and write it to disk
451
+ const apiContent = ymlstringify(updatedApi, {
452
+ sortMapEntries: true,
453
+ blockQuote: "literal",
454
+ });
455
+ const yamlFilePath = `${pathForApiFile}/${yamlFileName}`;
456
+ const handleApi = async () => {
457
+ await fs.outputFile(yamlFilePath, apiContent);
458
+ };
459
+ apiPromises.push(handleApi());
460
+ // Mark the existing source file as being reused
461
+ existingFilePaths?.delete(yamlFilePath);
462
+ }
463
+
464
+ export async function readAppApiYamlFile(
465
+ parentDirectory: string,
466
+ apiName?: string,
467
+ ): Promise<{ api: Api; stepPathMap: Record<string, string> }> {
468
+ // The API is either stored in its entirety in a single YAML file, or
469
+ // or in a subdirectory containing the YAML file and zero or more language-specific files.
470
+ const apiNameSlug = slugifyName(apiName ?? "api");
471
+ const singularApiYamlPath = `${parentDirectory}/${apiNameSlug}.yaml`;
472
+ const apiDirPath = `${parentDirectory}/${apiNameSlug}`;
473
+ const nestedApiYamlPath = `${apiDirPath}/api.yaml`;
474
+
475
+ // Read the YAML file
476
+ let yamlPath: string;
477
+ let yamlParentPath: string;
478
+ if (await fs.pathExists(singularApiYamlPath)) {
479
+ // The API YAML file is in the parent directory
480
+ yamlPath = singularApiYamlPath;
481
+ yamlParentPath = parentDirectory;
482
+ } else if (await fs.pathExists(nestedApiYamlPath)) {
483
+ // The API YAML file is nested in an API-specific directory
484
+ yamlPath = nestedApiYamlPath;
485
+ yamlParentPath = apiDirPath;
486
+ } else {
487
+ throw new Error(`API ${apiName ?? ""} not found at ${parentDirectory}`);
488
+ }
489
+
490
+ // That is nested in an API-specific directory
491
+ const apiDefn = (await readYamlFile(yamlPath)) as Api;
492
+
493
+ // Map step name -> step path
494
+ const stepPathMap: Record<string, string> = {};
495
+
496
+ // The API YAML file may or may not have language-specific content in separate files.
497
+ // Replace any file references with the actual content
498
+ await resolveLanguageSpecificStepContentFromBlocks(
499
+ yamlParentPath,
500
+ apiDefn.blocks ?? [],
501
+ stepPathMap,
502
+ );
503
+ return { api: apiDefn, stepPathMap };
504
+ }
@@ -0,0 +1,6 @@
1
+ export const LANGUAGE_STEP_EXTENSIONS = {
2
+ javascript: "js",
3
+ python: "py",
4
+ } as const;
5
+
6
+ export const DEFAULT_LINES_FOR_LARGE_STEPS = 1;