@uipath/packager-tool-functions 0.0.8 → 0.1.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.
- package/README.md +88 -0
- package/dist/functions-tool-factory.d.ts +1 -1
- package/dist/functions-tool.d.ts +1 -7
- package/dist/index.js +345 -107
- package/dist/js/build-js-functions-package.d.ts +3 -0
- package/dist/js/index.d.ts +1 -0
- package/dist/py/build-py-functions-package.d.ts +3 -0
- package/dist/py/constants.d.ts +14 -0
- package/dist/py/index.d.ts +1 -0
- package/dist/types.d.ts +13 -0
- package/package.json +7 -6
- package/src/functions-tool-factory.ts +1 -1
- package/src/functions-tool.ts +47 -204
- package/src/index.ts +1 -1
- package/src/js/build-js-functions-package.ts +14 -0
- package/src/js/index.ts +1 -0
- package/src/py/build-py-functions-package.ts +287 -0
- package/src/py/constants.ts +40 -0
- package/src/py/index.ts +1 -0
- package/src/types.ts +24 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/packager-tool-functions",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "UiPath Functions tool implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -42,11 +42,12 @@
|
|
|
42
42
|
"@uipath/solutionpackager-tool-core": "0.0.33"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@
|
|
45
|
+
"@uipath/coded-functions-js-packager": "^0.1.0",
|
|
46
|
+
"@types/node": "^25.5.2",
|
|
46
47
|
"@uipath/solutionpackager-tool-core": "0.0.33",
|
|
47
|
-
"@vitest/coverage-v8": "^4.
|
|
48
|
-
"typescript": "^
|
|
49
|
-
"vitest": "^4.
|
|
48
|
+
"@vitest/coverage-v8": "^4.1.3",
|
|
49
|
+
"typescript": "^6.0.2",
|
|
50
|
+
"vitest": "^4.1.3"
|
|
50
51
|
},
|
|
51
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "d982977e86057fd9d0846c955595c64865aeecab"
|
|
52
53
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { FunctionsTool } from "./functions-tool.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Factory for creating
|
|
12
|
+
* Factory for creating Functions project tools.
|
|
13
13
|
* Handles projects with projectType "Function".
|
|
14
14
|
*/
|
|
15
15
|
export class FunctionsToolFactory implements IProjectToolFactory {
|
package/src/functions-tool.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
EntryPointsFileModel,
|
|
3
2
|
IProjectBuildOptions,
|
|
4
3
|
IProjectPackOptions,
|
|
5
4
|
IProjectRestoreOptions,
|
|
6
5
|
IProjectValidateOptions,
|
|
7
|
-
PackageDescriptorFileModel,
|
|
8
6
|
} from "@uipath/solutionpackager-tool-core";
|
|
9
7
|
import {
|
|
10
8
|
type IFileSystem,
|
|
@@ -17,22 +15,14 @@ import {
|
|
|
17
15
|
ToolErrorCodes,
|
|
18
16
|
ToolResult,
|
|
19
17
|
} from "@uipath/solutionpackager-tool-core";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const EXTENSION_TO_RUNTIME: Record<string, string> = {
|
|
29
|
-
".ts": "javascript",
|
|
30
|
-
".js": "javascript",
|
|
31
|
-
".py": "python",
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/** Fallback runtime when uipath.json cannot be read or has no functions. */
|
|
35
|
-
const DEFAULT_RUNTIME = "javascript";
|
|
18
|
+
import { buildJsFunctionsPackage } from "./js/index.js";
|
|
19
|
+
import { buildPyFunctionsPackage } from "./py/index.js";
|
|
20
|
+
import {
|
|
21
|
+
type BuildPackageFn,
|
|
22
|
+
type Language,
|
|
23
|
+
LanguageLabels,
|
|
24
|
+
Languages,
|
|
25
|
+
} from "./types.js";
|
|
36
26
|
|
|
37
27
|
export class FunctionsTool extends ProjectTool {
|
|
38
28
|
private readonly _temporaryStorage: TemporaryStorageService;
|
|
@@ -62,25 +52,28 @@ export class FunctionsTool extends ProjectTool {
|
|
|
62
52
|
options: IProjectBuildOptions,
|
|
63
53
|
_cancellationToken?: AbortSignal,
|
|
64
54
|
): Promise<ToolResult> {
|
|
55
|
+
const language = await this.detectLanguage(options.projectPath);
|
|
65
56
|
const tempFolder = await this._temporaryStorage.getTempFolderPath();
|
|
66
57
|
const localBuildFolder = Path.join(
|
|
67
58
|
tempFolder,
|
|
68
59
|
NugetConstants.OutputFolderName,
|
|
69
60
|
);
|
|
70
|
-
const contentFolder = Path.join(
|
|
71
|
-
localBuildFolder,
|
|
72
|
-
NugetConstants.ContentFolderName,
|
|
73
|
-
);
|
|
74
61
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
const build: BuildPackageFn =
|
|
63
|
+
language === Languages.Python
|
|
64
|
+
? buildPyFunctionsPackage
|
|
65
|
+
: buildJsFunctionsPackage;
|
|
66
|
+
const languageLabel = LanguageLabels[language];
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
await this.
|
|
68
|
+
try {
|
|
69
|
+
this.logger.progress(
|
|
70
|
+
`Building ${languageLabel} Functions package...`,
|
|
71
|
+
);
|
|
72
|
+
await build(this.fileSystem, {
|
|
73
|
+
projectPath: options.projectPath,
|
|
74
|
+
outputPath: localBuildFolder,
|
|
75
|
+
projectStorageId: options.projectStorageId ?? "",
|
|
76
|
+
});
|
|
84
77
|
|
|
85
78
|
return new ToolResult(
|
|
86
79
|
ToolErrorCodes.Success,
|
|
@@ -93,7 +86,7 @@ export class FunctionsTool extends ProjectTool {
|
|
|
93
86
|
this.logger.error(errorMessage);
|
|
94
87
|
return ToolResult.error(
|
|
95
88
|
ToolErrorCodes.InternalError,
|
|
96
|
-
|
|
89
|
+
`Build failed for ${languageLabel} Functions project.`,
|
|
97
90
|
);
|
|
98
91
|
}
|
|
99
92
|
}
|
|
@@ -148,186 +141,36 @@ export class FunctionsTool extends ProjectTool {
|
|
|
148
141
|
}
|
|
149
142
|
}
|
|
150
143
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
144
|
+
// Detects project language from uipath.json functions map extensions.
|
|
145
|
+
// Mirrors detectProjectKind() in @uipath/tool-agent (Agents repo):
|
|
146
|
+
// primary: uipath.json functions map extension (.ts/.js → javascript, .py → python)
|
|
147
|
+
// fallback: pyproject.toml presence → python (same signal Agents uses)
|
|
148
|
+
private async detectLanguage(projectPath: string): Promise<Language> {
|
|
149
|
+
const uipathJsonContent = await this.fileSystem.readFile(
|
|
150
|
+
Path.join(projectPath, "uipath.json"),
|
|
151
|
+
"utf-8",
|
|
152
|
+
);
|
|
153
|
+
if (uipathJsonContent) {
|
|
155
154
|
try {
|
|
156
|
-
const uipathJson = JSON.parse(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
| Record<string, string>
|
|
161
|
-
| undefined;
|
|
162
|
-
const firstEntry = functions
|
|
163
|
-
? Object.values(functions)[0]
|
|
164
|
-
: undefined;
|
|
155
|
+
const uipathJson = JSON.parse(uipathJsonContent as string) as {
|
|
156
|
+
functions?: Record<string, string>;
|
|
157
|
+
};
|
|
158
|
+
const firstEntry = Object.values(uipathJson.functions ?? {})[0];
|
|
165
159
|
if (firstEntry) {
|
|
166
|
-
const filePath = firstEntry.split(":")[0];
|
|
160
|
+
const filePath = firstEntry.split(":")[0] ?? "";
|
|
167
161
|
const ext = filePath.slice(filePath.lastIndexOf("."));
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
162
|
+
if (ext === ".ts" || ext === ".js" || ext === ".mjs")
|
|
163
|
+
return Languages.JavaScript;
|
|
164
|
+
if (ext === ".py") return Languages.Python;
|
|
172
165
|
}
|
|
173
166
|
} catch {
|
|
174
|
-
//
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return DEFAULT_RUNTIME;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
private async copyFiles(
|
|
181
|
-
sourcePath: string,
|
|
182
|
-
destinationPath: string,
|
|
183
|
-
): Promise<void> {
|
|
184
|
-
await this.fileSystem.mkdir(destinationPath);
|
|
185
|
-
|
|
186
|
-
const entries = await this.fileSystem.readdir(sourcePath);
|
|
187
|
-
|
|
188
|
-
for (const entry of entries) {
|
|
189
|
-
if (this.isExcluded(entry)) {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const sourceFile = Path.join(sourcePath, entry);
|
|
194
|
-
const destinationFile = Path.join(destinationPath, entry);
|
|
195
|
-
|
|
196
|
-
const stat = await this.fileSystem.stat(sourceFile);
|
|
197
|
-
if (stat?.isFile()) {
|
|
198
|
-
const content = await this.fileSystem.readFile(sourceFile);
|
|
199
|
-
if (content) {
|
|
200
|
-
await this.fileSystem.writeFile(destinationFile, content);
|
|
201
|
-
}
|
|
202
|
-
} else if (stat?.isDirectory()) {
|
|
203
|
-
await this.copyFiles(sourceFile, destinationFile);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private isExcluded(name: string): boolean {
|
|
209
|
-
if (EXCLUDED_NAMES.has(name)) {
|
|
210
|
-
return true;
|
|
211
|
-
}
|
|
212
|
-
return EXCLUDED_EXTENSIONS.some((ext) => name.endsWith(ext));
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private async createOperateFile(
|
|
216
|
-
options: IProjectBuildOptions,
|
|
217
|
-
contentFolder: string,
|
|
218
|
-
): Promise<void> {
|
|
219
|
-
const operateJsonFilePath = Path.join(
|
|
220
|
-
contentFolder,
|
|
221
|
-
NugetConstants.OperateFileName,
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
const exists = await this.fileSystem.exists(operateJsonFilePath);
|
|
225
|
-
if (!exists) {
|
|
226
|
-
const targetRuntime = await this.detectRuntime(options.projectPath);
|
|
227
|
-
await this.createOperateJsonFile(
|
|
228
|
-
contentFolder,
|
|
229
|
-
options.projectStorageId ?? "",
|
|
230
|
-
operateJsonFilePath,
|
|
231
|
-
targetRuntime,
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private async createOperateJsonFile(
|
|
237
|
-
contentFolder: string,
|
|
238
|
-
projectId: string,
|
|
239
|
-
filePath: string,
|
|
240
|
-
targetRuntime: string,
|
|
241
|
-
): Promise<void> {
|
|
242
|
-
const entryPointsFilePath = Path.join(
|
|
243
|
-
contentFolder,
|
|
244
|
-
NugetConstants.EntryPointsFileName,
|
|
245
|
-
);
|
|
246
|
-
let mainPath = "";
|
|
247
|
-
|
|
248
|
-
const entryPointsExists =
|
|
249
|
-
await this.fileSystem.exists(entryPointsFilePath);
|
|
250
|
-
if (entryPointsExists) {
|
|
251
|
-
const entryPointsContent =
|
|
252
|
-
await this.fileSystem.readFile(entryPointsFilePath);
|
|
253
|
-
if (entryPointsContent) {
|
|
254
|
-
try {
|
|
255
|
-
const entryPointsText = new TextDecoder().decode(
|
|
256
|
-
entryPointsContent,
|
|
257
|
-
);
|
|
258
|
-
const entryPoints: EntryPointsFileModel =
|
|
259
|
-
JSON.parse(entryPointsText);
|
|
260
|
-
mainPath = entryPoints.entryPoints?.[0]?.filePath ?? "";
|
|
261
|
-
} catch {
|
|
262
|
-
// Ignore parsing errors, use empty mainPath
|
|
263
|
-
}
|
|
167
|
+
// fall through to fallback
|
|
264
168
|
}
|
|
265
169
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
$schema: "https://cloud.uipath.com/draft/2024-12/operate",
|
|
269
|
-
contentType: "function",
|
|
270
|
-
projectId: projectId,
|
|
271
|
-
main: mainPath,
|
|
272
|
-
targetRuntime,
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const operateJsonString = JSON.stringify(operateFileModel, null, 2);
|
|
276
|
-
await this.fileSystem.writeFile(filePath, operateJsonString);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
private async createPackageDescriptor(
|
|
280
|
-
localBuildFolder: string,
|
|
281
|
-
): Promise<void> {
|
|
282
|
-
const packageDescriptor: PackageDescriptorFileModel = {
|
|
283
|
-
files: {},
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
this.addFileToDescriptor(
|
|
287
|
-
packageDescriptor,
|
|
288
|
-
NugetConstants.OperateFileName,
|
|
289
|
-
NugetConstants.OperateFileName,
|
|
290
|
-
);
|
|
291
|
-
this.addFileToDescriptor(
|
|
292
|
-
packageDescriptor,
|
|
293
|
-
NugetConstants.EntryPointsFileName,
|
|
294
|
-
NugetConstants.EntryPointsFileName,
|
|
295
|
-
);
|
|
296
|
-
this.addFileToDescriptor(
|
|
297
|
-
packageDescriptor,
|
|
298
|
-
NugetConstants.BindingsFileId,
|
|
299
|
-
NugetConstants.BindingsV2FileName,
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
const packageDescriptorPath = Path.join(
|
|
303
|
-
localBuildFolder,
|
|
304
|
-
NugetConstants.ContentFolderName,
|
|
305
|
-
NugetConstants.PackageDescriptorFileName,
|
|
306
|
-
);
|
|
307
|
-
const packageDescriptorJson = JSON.stringify(
|
|
308
|
-
{
|
|
309
|
-
$schema:
|
|
310
|
-
"https://cloud.uipath.com/draft/2024-12/package-descriptor",
|
|
311
|
-
...packageDescriptor,
|
|
312
|
-
},
|
|
313
|
-
null,
|
|
314
|
-
2,
|
|
315
|
-
);
|
|
316
|
-
await this.fileSystem.writeFile(
|
|
317
|
-
packageDescriptorPath,
|
|
318
|
-
packageDescriptorJson,
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
private addFileToDescriptor(
|
|
323
|
-
packageDescriptor: PackageDescriptorFileModel,
|
|
324
|
-
key: string,
|
|
325
|
-
fileName: string,
|
|
326
|
-
): void {
|
|
327
|
-
const relativePath = Path.join(
|
|
328
|
-
NugetConstants.ContentFolderName,
|
|
329
|
-
fileName,
|
|
170
|
+
const pyprojectStat = await this.fileSystem.stat(
|
|
171
|
+
Path.join(projectPath, "pyproject.toml"),
|
|
330
172
|
);
|
|
331
|
-
|
|
173
|
+
if (pyprojectStat?.isFile()) return Languages.Python;
|
|
174
|
+
return Languages.JavaScript;
|
|
332
175
|
}
|
|
333
176
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ============================================================================
|
|
2
|
-
// Self-register
|
|
2
|
+
// Self-register Functions tool factory with the singleton repository
|
|
3
3
|
// ============================================================================
|
|
4
4
|
|
|
5
5
|
import { toolsFactoryRepository } from "@uipath/solutionpackager-tool-core";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { buildFunctionsPackage } from "@uipath/coded-functions-js-packager";
|
|
2
|
+
import type { IFileSystem } from "@uipath/solutionpackager-tool-core";
|
|
3
|
+
import type { BuildPackageOptions } from "../types.js";
|
|
4
|
+
|
|
5
|
+
export async function buildJsFunctionsPackage(
|
|
6
|
+
fileSystem: IFileSystem,
|
|
7
|
+
options: BuildPackageOptions,
|
|
8
|
+
): Promise<void> {
|
|
9
|
+
await buildFunctionsPackage(fileSystem, {
|
|
10
|
+
projectPath: options.projectPath,
|
|
11
|
+
outputPath: options.outputPath,
|
|
12
|
+
projectStorageId: options.projectStorageId,
|
|
13
|
+
});
|
|
14
|
+
}
|
package/src/js/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { buildJsFunctionsPackage } from "./build-js-functions-package.js";
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EntryPointsFileModel,
|
|
3
|
+
IFileSystem,
|
|
4
|
+
PackageDescriptorFileModel,
|
|
5
|
+
} from "@uipath/solutionpackager-tool-core";
|
|
6
|
+
import { NugetConstants, Path } from "@uipath/solutionpackager-tool-core";
|
|
7
|
+
import type { BuildPackageOptions } from "../types.js";
|
|
8
|
+
import {
|
|
9
|
+
BINDINGS_SOURCE_FILE_NAME,
|
|
10
|
+
BINDINGS_VERSION,
|
|
11
|
+
CONTENT_TYPE,
|
|
12
|
+
ENTRY_POINT_TYPE,
|
|
13
|
+
EXCLUDED_DIRECTORIES,
|
|
14
|
+
EXCLUDED_NAMES,
|
|
15
|
+
SCHEMAS,
|
|
16
|
+
TARGET_RUNTIME,
|
|
17
|
+
UIPATH_JSON_FILE_NAME,
|
|
18
|
+
} from "./constants.js";
|
|
19
|
+
|
|
20
|
+
export async function buildPyFunctionsPackage(
|
|
21
|
+
fileSystem: IFileSystem,
|
|
22
|
+
options: BuildPackageOptions,
|
|
23
|
+
): Promise<void> {
|
|
24
|
+
const contentFolder = Path.join(
|
|
25
|
+
options.outputPath,
|
|
26
|
+
NugetConstants.ContentFolderName,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
await validateProjectFiles(fileSystem, options.projectPath);
|
|
30
|
+
await copyFiles(fileSystem, options.projectPath, contentFolder);
|
|
31
|
+
await writeEntryPointsFile(fileSystem, options.projectPath, contentFolder);
|
|
32
|
+
await createOperateFile(
|
|
33
|
+
fileSystem,
|
|
34
|
+
contentFolder,
|
|
35
|
+
options.projectStorageId,
|
|
36
|
+
);
|
|
37
|
+
await createBindingsFile(fileSystem, options.projectPath, contentFolder);
|
|
38
|
+
await createPackageDescriptor(fileSystem, options.outputPath);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function validateProjectFiles(
|
|
42
|
+
fileSystem: IFileSystem,
|
|
43
|
+
projectPath: string,
|
|
44
|
+
): Promise<void> {
|
|
45
|
+
const uipathJsonPath = Path.join(projectPath, UIPATH_JSON_FILE_NAME);
|
|
46
|
+
const entryPointsPath = Path.join(
|
|
47
|
+
projectPath,
|
|
48
|
+
NugetConstants.EntryPointsFileName,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (!(await fileSystem.exists(uipathJsonPath))) {
|
|
52
|
+
throw new Error("uipath.json is missing from the project.");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!(await fileSystem.exists(entryPointsPath))) {
|
|
56
|
+
throw new Error("entry-points.json is missing from the project.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function copyFiles(
|
|
61
|
+
fileSystem: IFileSystem,
|
|
62
|
+
sourcePath: string,
|
|
63
|
+
destinationPath: string,
|
|
64
|
+
): Promise<void> {
|
|
65
|
+
await fileSystem.mkdir(destinationPath);
|
|
66
|
+
|
|
67
|
+
const entries = await fileSystem.readdir(sourcePath);
|
|
68
|
+
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
const sourceFile = Path.join(sourcePath, entry);
|
|
71
|
+
const destinationFile = Path.join(destinationPath, entry);
|
|
72
|
+
|
|
73
|
+
const stat = await fileSystem.stat(sourceFile);
|
|
74
|
+
if (stat?.isFile()) {
|
|
75
|
+
if (EXCLUDED_NAMES.has(entry)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const content = await fileSystem.readFile(sourceFile);
|
|
79
|
+
if (content) {
|
|
80
|
+
await fileSystem.writeFile(destinationFile, content);
|
|
81
|
+
}
|
|
82
|
+
} else if (stat?.isDirectory()) {
|
|
83
|
+
if (EXCLUDED_DIRECTORIES.has(entry)) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
await copyFiles(fileSystem, sourceFile, destinationFile);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function createOperateFile(
|
|
92
|
+
fileSystem: IFileSystem,
|
|
93
|
+
contentFolder: string,
|
|
94
|
+
projectStorageId: string,
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
const operateJsonFilePath = Path.join(
|
|
97
|
+
contentFolder,
|
|
98
|
+
NugetConstants.OperateFileName,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const exists = await fileSystem.exists(operateJsonFilePath);
|
|
102
|
+
if (exists) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const entryPointsFilePath = Path.join(
|
|
107
|
+
contentFolder,
|
|
108
|
+
NugetConstants.EntryPointsFileName,
|
|
109
|
+
);
|
|
110
|
+
let mainPath = "";
|
|
111
|
+
|
|
112
|
+
const entryPointsExists = await fileSystem.exists(entryPointsFilePath);
|
|
113
|
+
if (entryPointsExists) {
|
|
114
|
+
const entryPointsContent =
|
|
115
|
+
await fileSystem.readFile(entryPointsFilePath);
|
|
116
|
+
if (entryPointsContent) {
|
|
117
|
+
try {
|
|
118
|
+
const entryPointsText = new TextDecoder().decode(
|
|
119
|
+
entryPointsContent,
|
|
120
|
+
);
|
|
121
|
+
const entryPoints: EntryPointsFileModel =
|
|
122
|
+
JSON.parse(entryPointsText);
|
|
123
|
+
mainPath = entryPoints.entryPoints?.[0]?.filePath ?? "";
|
|
124
|
+
} catch {
|
|
125
|
+
// Ignore parse errors, use empty mainPath
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const operateFileModel = {
|
|
131
|
+
$schema: SCHEMAS.Operate,
|
|
132
|
+
contentType: CONTENT_TYPE,
|
|
133
|
+
projectId: projectStorageId,
|
|
134
|
+
main: mainPath,
|
|
135
|
+
targetFramework: "Portable",
|
|
136
|
+
targetRuntime: TARGET_RUNTIME,
|
|
137
|
+
runtimeOptions: {
|
|
138
|
+
isAttended: false,
|
|
139
|
+
requiresUserInteraction: false,
|
|
140
|
+
isConversational: false,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const operateJsonString = JSON.stringify(operateFileModel, null, 2);
|
|
145
|
+
await fileSystem.writeFile(operateJsonFilePath, operateJsonString);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function writeEntryPointsFile(
|
|
149
|
+
fileSystem: IFileSystem,
|
|
150
|
+
projectPath: string,
|
|
151
|
+
contentFolder: string,
|
|
152
|
+
): Promise<void> {
|
|
153
|
+
const sourcePath = Path.join(
|
|
154
|
+
projectPath,
|
|
155
|
+
NugetConstants.EntryPointsFileName,
|
|
156
|
+
);
|
|
157
|
+
const destinationPath = Path.join(
|
|
158
|
+
contentFolder,
|
|
159
|
+
NugetConstants.EntryPointsFileName,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const raw = await fileSystem.readFile(sourcePath);
|
|
163
|
+
if (!raw) {
|
|
164
|
+
throw new Error("entry-points.json is missing from the project.");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let parsed: Record<string, unknown>;
|
|
168
|
+
try {
|
|
169
|
+
parsed = JSON.parse(new TextDecoder().decode(raw));
|
|
170
|
+
} catch {
|
|
171
|
+
throw new Error("entry-points.json is not valid JSON.");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const sourceEntries = Array.isArray(parsed.entryPoints)
|
|
175
|
+
? (parsed.entryPoints as Record<string, unknown>[])
|
|
176
|
+
: [];
|
|
177
|
+
|
|
178
|
+
const normalizedEntries = sourceEntries.map((entry) => ({
|
|
179
|
+
...entry,
|
|
180
|
+
uniqueId:
|
|
181
|
+
typeof entry.uniqueId === "string" && entry.uniqueId.length > 0
|
|
182
|
+
? entry.uniqueId
|
|
183
|
+
: crypto.randomUUID(),
|
|
184
|
+
type:
|
|
185
|
+
typeof entry.type === "string" && entry.type.length > 0
|
|
186
|
+
? entry.type
|
|
187
|
+
: ENTRY_POINT_TYPE,
|
|
188
|
+
}));
|
|
189
|
+
|
|
190
|
+
const normalized = {
|
|
191
|
+
$schema: SCHEMAS.EntryPoint,
|
|
192
|
+
$id: NugetConstants.EntryPointsFileName,
|
|
193
|
+
entryPoints: normalizedEntries,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
await fileSystem.writeFile(
|
|
197
|
+
destinationPath,
|
|
198
|
+
JSON.stringify(normalized, null, 2),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function createBindingsFile(
|
|
203
|
+
fileSystem: IFileSystem,
|
|
204
|
+
projectPath: string,
|
|
205
|
+
contentFolder: string,
|
|
206
|
+
): Promise<void> {
|
|
207
|
+
const bindingsOutputPath = Path.join(
|
|
208
|
+
contentFolder,
|
|
209
|
+
NugetConstants.BindingsV2FileName,
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const sourcePath = Path.join(projectPath, BINDINGS_SOURCE_FILE_NAME);
|
|
213
|
+
let bindings: unknown = null;
|
|
214
|
+
|
|
215
|
+
if (await fileSystem.exists(sourcePath)) {
|
|
216
|
+
const raw = await fileSystem.readFile(sourcePath);
|
|
217
|
+
if (raw) {
|
|
218
|
+
try {
|
|
219
|
+
bindings = JSON.parse(new TextDecoder().decode(raw));
|
|
220
|
+
} catch {
|
|
221
|
+
bindings = null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (bindings === null) {
|
|
227
|
+
bindings = {
|
|
228
|
+
$schema: SCHEMAS.Bindings,
|
|
229
|
+
version: BINDINGS_VERSION,
|
|
230
|
+
resources: [],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
await fileSystem.writeFile(
|
|
235
|
+
bindingsOutputPath,
|
|
236
|
+
JSON.stringify(bindings, null, 2),
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function createPackageDescriptor(
|
|
241
|
+
fileSystem: IFileSystem,
|
|
242
|
+
localBuildFolder: string,
|
|
243
|
+
): Promise<void> {
|
|
244
|
+
const packageDescriptor: PackageDescriptorFileModel = {
|
|
245
|
+
files: {},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
addFileToDescriptor(
|
|
249
|
+
packageDescriptor,
|
|
250
|
+
NugetConstants.OperateFileName,
|
|
251
|
+
NugetConstants.OperateFileName,
|
|
252
|
+
);
|
|
253
|
+
addFileToDescriptor(
|
|
254
|
+
packageDescriptor,
|
|
255
|
+
NugetConstants.EntryPointsFileName,
|
|
256
|
+
NugetConstants.EntryPointsFileName,
|
|
257
|
+
);
|
|
258
|
+
addFileToDescriptor(
|
|
259
|
+
packageDescriptor,
|
|
260
|
+
NugetConstants.BindingsFileId,
|
|
261
|
+
NugetConstants.BindingsV2FileName,
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
const packageDescriptorPath = Path.join(
|
|
265
|
+
localBuildFolder,
|
|
266
|
+
NugetConstants.ContentFolderName,
|
|
267
|
+
NugetConstants.PackageDescriptorFileName,
|
|
268
|
+
);
|
|
269
|
+
const packageDescriptorJson = JSON.stringify(
|
|
270
|
+
{
|
|
271
|
+
$schema: SCHEMAS.PackageDescriptor,
|
|
272
|
+
...packageDescriptor,
|
|
273
|
+
},
|
|
274
|
+
null,
|
|
275
|
+
2,
|
|
276
|
+
);
|
|
277
|
+
await fileSystem.writeFile(packageDescriptorPath, packageDescriptorJson);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function addFileToDescriptor(
|
|
281
|
+
packageDescriptor: PackageDescriptorFileModel,
|
|
282
|
+
key: string,
|
|
283
|
+
fileName: string,
|
|
284
|
+
): void {
|
|
285
|
+
const relativePath = Path.join(NugetConstants.ContentFolderName, fileName);
|
|
286
|
+
packageDescriptor.files[key] = relativePath;
|
|
287
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export const EXCLUDED_NAMES = new Set([
|
|
2
|
+
"agent.json",
|
|
3
|
+
"project.uiproj",
|
|
4
|
+
"bindings.json",
|
|
5
|
+
"entry-points.json",
|
|
6
|
+
".DS_Store",
|
|
7
|
+
"Thumbs.db",
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
export const EXCLUDED_DIRECTORIES = new Set([
|
|
11
|
+
"evaluations",
|
|
12
|
+
"evals",
|
|
13
|
+
".function-builder",
|
|
14
|
+
"node_modules",
|
|
15
|
+
"__pycache__",
|
|
16
|
+
".pytest_cache",
|
|
17
|
+
".venv",
|
|
18
|
+
"venv",
|
|
19
|
+
"env",
|
|
20
|
+
".git",
|
|
21
|
+
".vscode",
|
|
22
|
+
".idea",
|
|
23
|
+
".local",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
export const CONTENT_TYPE = "function";
|
|
27
|
+
export const TARGET_RUNTIME = "python";
|
|
28
|
+
export const UIPATH_JSON_FILE_NAME = "uipath.json";
|
|
29
|
+
export const BINDINGS_SOURCE_FILE_NAME = "bindings.json";
|
|
30
|
+
export const BINDINGS_VERSION = "2.0";
|
|
31
|
+
export const ENTRY_POINT_TYPE = "function";
|
|
32
|
+
|
|
33
|
+
const SCHEMA_BASE_URL = "https://cloud.uipath.com/draft/2024-12";
|
|
34
|
+
|
|
35
|
+
export const SCHEMAS = {
|
|
36
|
+
Bindings: `${SCHEMA_BASE_URL}/bindings`,
|
|
37
|
+
EntryPoint: `${SCHEMA_BASE_URL}/entry-point`,
|
|
38
|
+
Operate: `${SCHEMA_BASE_URL}/operate`,
|
|
39
|
+
PackageDescriptor: `${SCHEMA_BASE_URL}/package-descriptor`,
|
|
40
|
+
} as const;
|
package/src/py/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { buildPyFunctionsPackage } from "./build-py-functions-package.js";
|