@platforma-sdk/package-builder-lib 1.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/assets/conda-dockerfile.template +45 -0
- package/assets/python-dockerfile.template +22 -0
- package/dist/_virtual/_rolldown/runtime.cjs +33 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/core/archive.cjs +52 -0
- package/dist/core/archive.cjs.map +1 -0
- package/dist/core/archive.js +47 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/conda/builder.cjs +226 -0
- package/dist/core/conda/builder.cjs.map +1 -0
- package/dist/core/conda/builder.js +220 -0
- package/dist/core/conda/builder.js.map +1 -0
- package/dist/core/conda/validate-spec.cjs +76 -0
- package/dist/core/conda/validate-spec.cjs.map +1 -0
- package/dist/core/conda/validate-spec.js +73 -0
- package/dist/core/conda/validate-spec.js.map +1 -0
- package/dist/core/core.cjs +403 -0
- package/dist/core/core.cjs.map +1 -0
- package/dist/core/core.d.ts +82 -0
- package/dist/core/core.d.ts.map +1 -0
- package/dist/core/core.js +397 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/docker-conda.cjs +75 -0
- package/dist/core/docker-conda.cjs.map +1 -0
- package/dist/core/docker-conda.js +71 -0
- package/dist/core/docker-conda.js.map +1 -0
- package/dist/core/docker-python.cjs +147 -0
- package/dist/core/docker-python.cjs.map +1 -0
- package/dist/core/docker-python.js +144 -0
- package/dist/core/docker-python.js.map +1 -0
- package/dist/core/docker.cjs +223 -0
- package/dist/core/docker.cjs.map +1 -0
- package/dist/core/docker.js +207 -0
- package/dist/core/docker.js.map +1 -0
- package/dist/core/envs.cjs +58 -0
- package/dist/core/envs.cjs.map +1 -0
- package/dist/core/envs.d.ts +26 -0
- package/dist/core/envs.d.ts.map +1 -0
- package/dist/core/envs.js +51 -0
- package/dist/core/envs.js.map +1 -0
- package/dist/core/package-info.cjs +450 -0
- package/dist/core/package-info.cjs.map +1 -0
- package/dist/core/package-info.d.ts +57 -0
- package/dist/core/package-info.d.ts.map +1 -0
- package/dist/core/package-info.js +447 -0
- package/dist/core/package-info.js.map +1 -0
- package/dist/core/paths.cjs +15 -0
- package/dist/core/paths.cjs.map +1 -0
- package/dist/core/paths.js +14 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/resolver.cjs +99 -0
- package/dist/core/resolver.cjs.map +1 -0
- package/dist/core/resolver.js +95 -0
- package/dist/core/resolver.js.map +1 -0
- package/dist/core/schemas/artifacts.cjs +136 -0
- package/dist/core/schemas/artifacts.cjs.map +1 -0
- package/dist/core/schemas/artifacts.d.ts +280 -0
- package/dist/core/schemas/artifacts.d.ts.map +1 -0
- package/dist/core/schemas/artifacts.js +122 -0
- package/dist/core/schemas/artifacts.js.map +1 -0
- package/dist/core/schemas/entrypoints.cjs +43 -0
- package/dist/core/schemas/entrypoints.cjs.map +1 -0
- package/dist/core/schemas/entrypoints.d.ts +32 -0
- package/dist/core/schemas/entrypoints.d.ts.map +1 -0
- package/dist/core/schemas/entrypoints.js +41 -0
- package/dist/core/schemas/entrypoints.js.map +1 -0
- package/dist/core/schemas/sw-json.cjs +111 -0
- package/dist/core/schemas/sw-json.cjs.map +1 -0
- package/dist/core/schemas/sw-json.js +110 -0
- package/dist/core/schemas/sw-json.js.map +1 -0
- package/dist/core/storage.cjs +86 -0
- package/dist/core/storage.cjs.map +1 -0
- package/dist/core/storage.js +83 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/sw-json-render.cjs +327 -0
- package/dist/core/sw-json-render.cjs.map +1 -0
- package/dist/core/sw-json-render.js +322 -0
- package/dist/core/sw-json-render.js.map +1 -0
- package/dist/core/util.cjs +313 -0
- package/dist/core/util.cjs.map +1 -0
- package/dist/core/util.d.ts +66 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/core/util.js +281 -0
- package/dist/core/util.js.map +1 -0
- package/dist/defaults.cjs +54 -0
- package/dist/defaults.cjs.map +1 -0
- package/dist/defaults.d.ts +21 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +37 -0
- package/dist/defaults.js.map +1 -0
- package/dist/index.cjs +31 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
- package/src/__test__/Dockerfile +1 -0
- package/src/__test__/docker.test.ts +67 -0
- package/src/__test__/package.json +39 -0
- package/src/__test__/python-example/main.py +1 -0
- package/src/__test__/python-example/requirements.txt +0 -0
- package/src/__test__/vite.config.mts +7 -0
- package/src/core/__tests__/docker-conda.test.ts +145 -0
- package/src/core/__tests__/docker-entrypoint-generation.test.ts +119 -0
- package/src/core/__tests__/docker-python.test.ts +374 -0
- package/src/core/__tests__/publish-docker-images.test.ts +309 -0
- package/src/core/archive.ts +102 -0
- package/src/core/conda/builder.test.ts +71 -0
- package/src/core/conda/builder.ts +384 -0
- package/src/core/conda/validate-spec.test.ts +213 -0
- package/src/core/conda/validate-spec.ts +107 -0
- package/src/core/core.ts +835 -0
- package/src/core/docker-conda.ts +149 -0
- package/src/core/docker-python.ts +283 -0
- package/src/core/docker.ts +300 -0
- package/src/core/envs.ts +31 -0
- package/src/core/package-info.test.ts +82 -0
- package/src/core/package-info.ts +843 -0
- package/src/core/paths.ts +16 -0
- package/src/core/resolver.ts +195 -0
- package/src/core/schemas/artifacts.test.ts +72 -0
- package/src/core/schemas/artifacts.ts +279 -0
- package/src/core/schemas/entrypoints.test.ts +171 -0
- package/src/core/schemas/entrypoints.ts +150 -0
- package/src/core/schemas/sw-json.ts +216 -0
- package/src/core/schemas/test-artifacts.ts +362 -0
- package/src/core/storage.ts +125 -0
- package/src/core/sw-json-render.test.ts +215 -0
- package/src/core/sw-json-render.ts +682 -0
- package/src/core/util.ts +390 -0
- package/src/defaults.ts +38 -0
- package/src/index.ts +31 -0
- package/src/requirements.txt +1 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
|
|
6
|
+
export function path(...p: string[]): string {
|
|
7
|
+
return resolve(__dirname, "..", "..", ...p);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function assets(...p: string[]): string {
|
|
11
|
+
return path("assets", ...p);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function dist(...p: string[]): string {
|
|
15
|
+
return path("dist", ...p);
|
|
16
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import type winston from "winston";
|
|
4
|
+
|
|
5
|
+
import * as swJson from "./schemas/sw-json";
|
|
6
|
+
import type * as artifacts from "./schemas/artifacts";
|
|
7
|
+
import type * as entrypoint from "./schemas/entrypoints";
|
|
8
|
+
import * as util from "./util";
|
|
9
|
+
|
|
10
|
+
export const compiledSoftwareSuffix = ".sw.json";
|
|
11
|
+
export const compiledAssetSuffix = ".as.json";
|
|
12
|
+
|
|
13
|
+
export function descriptorFilePath(
|
|
14
|
+
packageRoot: string,
|
|
15
|
+
entrypointType: Extract<entrypoint.EntrypointType, "software" | "asset">,
|
|
16
|
+
entrypointName?: string,
|
|
17
|
+
): string {
|
|
18
|
+
const typeSuffix = entrypointType === "software" ? compiledSoftwareSuffix : compiledAssetSuffix;
|
|
19
|
+
|
|
20
|
+
if (!entrypointName) {
|
|
21
|
+
return path.resolve(packageRoot, "dist", "tengo", entrypointType);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return path.resolve(
|
|
25
|
+
packageRoot,
|
|
26
|
+
"dist",
|
|
27
|
+
"tengo",
|
|
28
|
+
entrypointType,
|
|
29
|
+
`${entrypointName}${typeSuffix}`,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Read and parse 'sw.json' descriptor file from given path.
|
|
35
|
+
*
|
|
36
|
+
* @param packageRoot: string - root directory of the package that contains software descriptor
|
|
37
|
+
* @param packageName: string - name of the package from <packageRoot>/package.json
|
|
38
|
+
* @param entrypointName: string - name of entrypoint with software descriptor
|
|
39
|
+
*
|
|
40
|
+
* @returns swJson.entrypoint - parsed descriptor with meta information of where it came from
|
|
41
|
+
*/
|
|
42
|
+
export function readSwJsonFile(
|
|
43
|
+
packageRoot: string,
|
|
44
|
+
packageName: string,
|
|
45
|
+
entrypointName: string,
|
|
46
|
+
): swJson.swJsonType {
|
|
47
|
+
const filePath = descriptorFilePath(packageRoot, "software", entrypointName);
|
|
48
|
+
return readDescriptorFile(packageName, entrypointName, filePath);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Read 'sw.json' or 'as.json' descriptor file from given path and provide it along with metadata of where it came from
|
|
53
|
+
*
|
|
54
|
+
* @param packageNameForDescriptor: string - name of the package that contains this descriptor
|
|
55
|
+
* @param entrypointForDescriptor: string - name of entrypoint that contains this descriptor inside given package
|
|
56
|
+
* @param descriptorFilePath: string - path to the descriptor file
|
|
57
|
+
* @returns swJson.entrypoint - parsed descriptor with meta information of where it came from
|
|
58
|
+
*/
|
|
59
|
+
export function readDescriptorFile(
|
|
60
|
+
packageNameForDescriptor: string,
|
|
61
|
+
entrypointForDescriptor: string,
|
|
62
|
+
descriptorFilePath: string,
|
|
63
|
+
): swJson.swJsonType {
|
|
64
|
+
if (!fs.existsSync(descriptorFilePath)) {
|
|
65
|
+
throw util.CLIError(
|
|
66
|
+
`entrypoint '${entrypointForDescriptor}' not found in '${descriptorFilePath}'`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const swJsonContent = fs.readFileSync(descriptorFilePath);
|
|
71
|
+
const result = swJson.swJsonSchema.safeParse(JSON.parse(swJsonContent.toString()));
|
|
72
|
+
|
|
73
|
+
if (!result.success) {
|
|
74
|
+
throw util.CLIError(util.formatZodIssues(result.error.issues));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
id: {
|
|
79
|
+
package: packageNameForDescriptor,
|
|
80
|
+
name: entrypointForDescriptor,
|
|
81
|
+
},
|
|
82
|
+
...result.data,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resolve package dependency and read software descriptor from it.
|
|
88
|
+
*
|
|
89
|
+
* @param logger: winston.Logger - logger instance
|
|
90
|
+
* @param currentPackageRoot: string - root directory of the current package
|
|
91
|
+
* @param dependencyPackageName: string - name of the dependency to search
|
|
92
|
+
* @param dependencyEntrypointName: string - name of the entrypooint inside dependency package
|
|
93
|
+
*
|
|
94
|
+
* @returns swJson.entrypoint - parsed descriptor with meta information of where it came from
|
|
95
|
+
*/
|
|
96
|
+
export function resolveDependency(
|
|
97
|
+
logger: winston.Logger,
|
|
98
|
+
currentPackageRoot: string,
|
|
99
|
+
dependencyPackageName: string,
|
|
100
|
+
dependencyEntrypointName: string,
|
|
101
|
+
): swJson.swJsonType {
|
|
102
|
+
const dependencyPath = util.findInstalledModule(
|
|
103
|
+
logger,
|
|
104
|
+
dependencyPackageName,
|
|
105
|
+
currentPackageRoot,
|
|
106
|
+
);
|
|
107
|
+
return readSwJsonFile(dependencyPath, dependencyPackageName, dependencyEntrypointName);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function resolveRunEnvironment(
|
|
111
|
+
logger: winston.Logger,
|
|
112
|
+
packageRoot: string,
|
|
113
|
+
packageName: string,
|
|
114
|
+
envName: string,
|
|
115
|
+
requireType: "java",
|
|
116
|
+
): swJson.runEnvDependencyJava;
|
|
117
|
+
export function resolveRunEnvironment(
|
|
118
|
+
logger: winston.Logger,
|
|
119
|
+
packageRoot: string,
|
|
120
|
+
packageName: string,
|
|
121
|
+
envName: string,
|
|
122
|
+
requireType: "python",
|
|
123
|
+
): swJson.runEnvDependencyPython;
|
|
124
|
+
export function resolveRunEnvironment(
|
|
125
|
+
logger: winston.Logger,
|
|
126
|
+
packageRoot: string,
|
|
127
|
+
packageName: string,
|
|
128
|
+
envName: string,
|
|
129
|
+
requireType: "R",
|
|
130
|
+
): swJson.runEnvDependencyR;
|
|
131
|
+
export function resolveRunEnvironment(
|
|
132
|
+
logger: winston.Logger,
|
|
133
|
+
packageRoot: string,
|
|
134
|
+
packageName: string,
|
|
135
|
+
envName: string,
|
|
136
|
+
requireType: artifacts.runEnvironmentType,
|
|
137
|
+
): swJson.runEnvDependency {
|
|
138
|
+
const [pkgName, id] = util.rSplit(envName, ":", 2);
|
|
139
|
+
const swDescriptor =
|
|
140
|
+
pkgName === ""
|
|
141
|
+
? readSwJsonFile(packageRoot, packageName, id)
|
|
142
|
+
: resolveDependency(logger, packageRoot, pkgName, id);
|
|
143
|
+
|
|
144
|
+
if (!swDescriptor.runEnv) {
|
|
145
|
+
throw util.CLIError(
|
|
146
|
+
`software '${envName}' cannot be used as run environment (no 'runEnv' section in entrypoint descriptor)`,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const runEnv = swDescriptor.runEnv;
|
|
151
|
+
|
|
152
|
+
if (runEnv.type !== requireType) {
|
|
153
|
+
logger.error(
|
|
154
|
+
`run environment '${envName}' type '${runEnv.type}' differs from declared package type '${requireType}'`,
|
|
155
|
+
);
|
|
156
|
+
throw util.CLIError(
|
|
157
|
+
`incompatible environment: env type '${runEnv.type}' != package type '${requireType}'`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
switch (runEnv.type) {
|
|
162
|
+
case "python": {
|
|
163
|
+
return {
|
|
164
|
+
name: envName,
|
|
165
|
+
...runEnv,
|
|
166
|
+
|
|
167
|
+
type: "python",
|
|
168
|
+
["python-version"]: runEnv["python-version"] ?? "",
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
case "R": {
|
|
172
|
+
return {
|
|
173
|
+
name: envName,
|
|
174
|
+
...runEnv,
|
|
175
|
+
|
|
176
|
+
type: "R",
|
|
177
|
+
["r-version"]: runEnv["r-version"] ?? "",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
case "java": {
|
|
181
|
+
return {
|
|
182
|
+
name: envName,
|
|
183
|
+
...runEnv,
|
|
184
|
+
|
|
185
|
+
type: "java",
|
|
186
|
+
["java-version"]: runEnv["java-version"] ?? "",
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
default:
|
|
190
|
+
util.assertNever(runEnv.type);
|
|
191
|
+
throw new Error(
|
|
192
|
+
"renderer logic error: resolveRunEnvironment does not cover all run environment types",
|
|
193
|
+
); // calm down the linter
|
|
194
|
+
}
|
|
195
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import type { z } from "zod/v4";
|
|
3
|
+
import * as artifacts from "./artifacts";
|
|
4
|
+
import * as testArtifacts from "./test-artifacts";
|
|
5
|
+
|
|
6
|
+
const parseArtifact = <T extends z.ZodTypeAny>(data: string, schema: T): z.infer<T> => {
|
|
7
|
+
const parsedData: unknown = JSON.parse(data);
|
|
8
|
+
return schema.parse(parsedData);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// ['conda', artifacts.condaPackageSchema, testArtifacts.CondaArtifact],
|
|
12
|
+
|
|
13
|
+
test.for([
|
|
14
|
+
{
|
|
15
|
+
type: "environment",
|
|
16
|
+
variant: "minimal",
|
|
17
|
+
schema: artifacts.environmentSchema,
|
|
18
|
+
data: testArtifacts.JavaEnvironmentArtifactWithType,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "binary",
|
|
22
|
+
variant: "minimal",
|
|
23
|
+
schema: artifacts.binarySchema,
|
|
24
|
+
data: testArtifacts.BinaryArtifact,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: "binary",
|
|
28
|
+
variant: "version override",
|
|
29
|
+
schema: artifacts.binarySchema,
|
|
30
|
+
data: testArtifacts.CustomVersionArtifact,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: "java",
|
|
34
|
+
variant: "minimal",
|
|
35
|
+
schema: artifacts.javaSchema,
|
|
36
|
+
data: testArtifacts.JavaArtifact,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: "python",
|
|
40
|
+
variant: "minimal",
|
|
41
|
+
schema: artifacts.pythonSchema,
|
|
42
|
+
data: testArtifacts.PythonArtifact,
|
|
43
|
+
},
|
|
44
|
+
{ type: "R", variant: "minimal", schema: artifacts.rSchema, data: testArtifacts.RArtifact },
|
|
45
|
+
{
|
|
46
|
+
type: "docker",
|
|
47
|
+
variant: "minimal",
|
|
48
|
+
schema: artifacts.dockerSchema,
|
|
49
|
+
data: testArtifacts.DockerArtifactWithType,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: "docker",
|
|
53
|
+
variant: "with pkg",
|
|
54
|
+
schema: artifacts.dockerSchema,
|
|
55
|
+
data: testArtifacts.DockerArtifactWithPkg,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "docker",
|
|
59
|
+
variant: "with dockerfile",
|
|
60
|
+
schema: artifacts.dockerSchema,
|
|
61
|
+
data: testArtifacts.DockerArtifactWithDockerfile,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: "conda",
|
|
65
|
+
variant: "minimal",
|
|
66
|
+
schema: artifacts.condaSchema,
|
|
67
|
+
data: testArtifacts.CondaArtifactWithType,
|
|
68
|
+
},
|
|
69
|
+
])("parse $type artifact ($variant)", ({ type, schema, data }) => {
|
|
70
|
+
const binary = parseArtifact(data, schema);
|
|
71
|
+
expect(binary.type).toEqual(type);
|
|
72
|
+
});
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import * as defaults from "../../defaults";
|
|
3
|
+
import * as util from "../util";
|
|
4
|
+
|
|
5
|
+
// All known artifact types
|
|
6
|
+
export const artifactTypes = [
|
|
7
|
+
"asset",
|
|
8
|
+
"environment",
|
|
9
|
+
"binary",
|
|
10
|
+
"java",
|
|
11
|
+
"python",
|
|
12
|
+
"R",
|
|
13
|
+
"docker",
|
|
14
|
+
"conda",
|
|
15
|
+
] as const;
|
|
16
|
+
export type artifactType = (typeof artifactTypes)[number];
|
|
17
|
+
|
|
18
|
+
// TODO: change these to type definitions, not arrays. This will simplify type narrowing logic throughout the code.
|
|
19
|
+
export const archiveArtifactTypes: artifactType[] = [
|
|
20
|
+
"asset",
|
|
21
|
+
"environment",
|
|
22
|
+
"binary",
|
|
23
|
+
"java",
|
|
24
|
+
"python",
|
|
25
|
+
"R",
|
|
26
|
+
"conda",
|
|
27
|
+
] as const;
|
|
28
|
+
export const crossplatformTypes: artifactType[] = ["asset", "java", "python", "R"] as const;
|
|
29
|
+
export const dockerAutogenTypes: artifactType[] = ["python", "conda"] as const;
|
|
30
|
+
export const dockerArchitectures: util.ArchType[] = ["x64"] as const;
|
|
31
|
+
|
|
32
|
+
export function isBuildable(aType: artifactType): boolean {
|
|
33
|
+
// All known artifact types are buildable. No exceptions so far.
|
|
34
|
+
return artifactTypes.includes(aType);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isCrossPlatform(aType: artifactType): boolean {
|
|
38
|
+
return crossplatformTypes.includes(aType);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const runEnvironmentTypes = ["java", "python", "R"] as const;
|
|
42
|
+
export type runEnvironmentType = (typeof runEnvironmentTypes)[number];
|
|
43
|
+
|
|
44
|
+
export const pythonToolsets = ["pip"] as const;
|
|
45
|
+
export type pythonToolsetName = (typeof pythonToolsets)[number];
|
|
46
|
+
|
|
47
|
+
export const registrySchema = z.strictObject({
|
|
48
|
+
name: z.string(),
|
|
49
|
+
downloadURL: z.string().optional(),
|
|
50
|
+
storageURL: z.string().optional(),
|
|
51
|
+
});
|
|
52
|
+
export type registry = z.infer<typeof registrySchema>;
|
|
53
|
+
|
|
54
|
+
export const registryOrRef = z.union([z.string(), registrySchema]);
|
|
55
|
+
|
|
56
|
+
// common fields for all buildable artifacts
|
|
57
|
+
// TODO: create new type for binary packages
|
|
58
|
+
const archiveRulesSchema = z.object({
|
|
59
|
+
registry: registryOrRef.default({
|
|
60
|
+
name: defaults.BIN_REGISTRY_NAME,
|
|
61
|
+
downloadURL: defaults.BIN_REGISTRY_DOWNLOAD_URL,
|
|
62
|
+
}),
|
|
63
|
+
|
|
64
|
+
name: z.string().optional(),
|
|
65
|
+
version: z.string().optional(),
|
|
66
|
+
|
|
67
|
+
root: z.string("package archive content directory is required"),
|
|
68
|
+
roots: z
|
|
69
|
+
.partialRecord(
|
|
70
|
+
z.enum(
|
|
71
|
+
util.AllPlatforms as [
|
|
72
|
+
(typeof util.AllPlatforms)[number],
|
|
73
|
+
...(typeof util.AllPlatforms)[number][],
|
|
74
|
+
],
|
|
75
|
+
),
|
|
76
|
+
z.string("path to package archive content directory cannot be empty").min(1),
|
|
77
|
+
{
|
|
78
|
+
error: (iss) => {
|
|
79
|
+
if (iss.input === undefined) {
|
|
80
|
+
return (
|
|
81
|
+
"list of supported platforms is required: { <platform>: <dir> }\n" +
|
|
82
|
+
"supported platforms:\n " +
|
|
83
|
+
util.AllPlatforms.join("\n ")
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
.refine((val) => Object.keys(val).length > 0, {
|
|
91
|
+
message:
|
|
92
|
+
"specify at least one platform supported by this software in format: { <platform>: <dir> }\n" +
|
|
93
|
+
"supported platforms:\n " +
|
|
94
|
+
util.AllPlatforms.join("\n "),
|
|
95
|
+
})
|
|
96
|
+
.describe(
|
|
97
|
+
"please, provide settings only for supported platforms: " + util.AllPlatforms.join(", "),
|
|
98
|
+
),
|
|
99
|
+
});
|
|
100
|
+
export type archiveRules = z.infer<typeof archiveRulesSchema>;
|
|
101
|
+
|
|
102
|
+
const dockerRulesSchema = z.object({
|
|
103
|
+
["docker-registry"]: z
|
|
104
|
+
.string(
|
|
105
|
+
"python software is also automatically shipped as docker image. Docker registry cannot be empty",
|
|
106
|
+
)
|
|
107
|
+
.min(1)
|
|
108
|
+
.default(defaults.DOCKER_REGISTRY)
|
|
109
|
+
.describe("registry to use for pushing autogenerated docker image"),
|
|
110
|
+
|
|
111
|
+
pkg: z
|
|
112
|
+
.string()
|
|
113
|
+
.default(defaults.DOCKER_PLACEHOLDER_PKG)
|
|
114
|
+
.describe(
|
|
115
|
+
'{pkg} placeholder value to be used in "cmd" and arguments (for docker autogeneration)',
|
|
116
|
+
),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export const artifactIDSchema = z
|
|
120
|
+
.string()
|
|
121
|
+
.regex(/:/, {
|
|
122
|
+
message:
|
|
123
|
+
"tengo artifact ID must have <npmPackage>:<artifactName> format, e.g @milaboratory/runenv-java-corretto:21.2.0.4.1",
|
|
124
|
+
})
|
|
125
|
+
.describe("ID of tengo build artifact");
|
|
126
|
+
|
|
127
|
+
export type artifactIDString = z.infer<typeof artifactIDSchema>;
|
|
128
|
+
|
|
129
|
+
export const assetSchema = archiveRulesSchema
|
|
130
|
+
.omit({ roots: true })
|
|
131
|
+
.extend({ type: z.literal("asset") })
|
|
132
|
+
.strict();
|
|
133
|
+
export type assetType = z.infer<typeof assetSchema>;
|
|
134
|
+
|
|
135
|
+
export const environmentSchema = archiveRulesSchema.omit({ root: true }).extend({
|
|
136
|
+
type: z.literal("environment"),
|
|
137
|
+
|
|
138
|
+
runtime: z
|
|
139
|
+
.enum(runEnvironmentTypes)
|
|
140
|
+
.describe("type of runtime this run environment provides: 'java', 'python' and so on"),
|
|
141
|
+
|
|
142
|
+
["r-version"]: z.string().optional(),
|
|
143
|
+
["python-version"]: z.string().optional(),
|
|
144
|
+
["java-version"]: z.string().optional(),
|
|
145
|
+
|
|
146
|
+
envVars: z
|
|
147
|
+
.array(
|
|
148
|
+
z
|
|
149
|
+
.string()
|
|
150
|
+
.regex(
|
|
151
|
+
/=/,
|
|
152
|
+
"environment variable should be specified in format: <var-name>=<var-value>, i.e.: MY_ENV=value",
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
.optional(),
|
|
156
|
+
|
|
157
|
+
binDir: z
|
|
158
|
+
.string()
|
|
159
|
+
.describe(
|
|
160
|
+
"path to 'bin' directory to be added to PATH when software uses this run environment",
|
|
161
|
+
),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
export type environmentType = z.infer<typeof environmentSchema>;
|
|
165
|
+
|
|
166
|
+
export const binarySchema = archiveRulesSchema.omit({ root: true }).extend({
|
|
167
|
+
type: z.literal("binary"),
|
|
168
|
+
});
|
|
169
|
+
export type binaryType = z.infer<typeof binarySchema>;
|
|
170
|
+
|
|
171
|
+
export const javaSchema = archiveRulesSchema.omit({ roots: true }).extend({
|
|
172
|
+
type: z.literal("java"),
|
|
173
|
+
environment: artifactIDSchema,
|
|
174
|
+
});
|
|
175
|
+
export type javaType = z.infer<typeof javaSchema>;
|
|
176
|
+
|
|
177
|
+
const pipToolsetSchema = z.strictObject({
|
|
178
|
+
toolset: z.literal("pip"),
|
|
179
|
+
requirements: z.string().describe("path to requrements.txt inside package archive"),
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
export const pythonToolsetSchema = z.discriminatedUnion("toolset", [pipToolsetSchema]);
|
|
183
|
+
|
|
184
|
+
export const pythonSchema = archiveRulesSchema
|
|
185
|
+
.omit({ roots: true })
|
|
186
|
+
.extend(dockerRulesSchema.shape)
|
|
187
|
+
.extend({
|
|
188
|
+
type: z.literal("python"),
|
|
189
|
+
|
|
190
|
+
environment: artifactIDSchema,
|
|
191
|
+
dependencies: pythonToolsetSchema.optional(),
|
|
192
|
+
});
|
|
193
|
+
export type pythonType = z.infer<typeof pythonSchema>;
|
|
194
|
+
|
|
195
|
+
export const rSchema = archiveRulesSchema.omit({ roots: true }).extend({
|
|
196
|
+
type: z.literal("R"),
|
|
197
|
+
environment: artifactIDSchema,
|
|
198
|
+
});
|
|
199
|
+
export type rType = z.infer<typeof rSchema>;
|
|
200
|
+
|
|
201
|
+
export const condaSchema = archiveRulesSchema
|
|
202
|
+
.omit({ root: true })
|
|
203
|
+
.extend(dockerRulesSchema.shape)
|
|
204
|
+
.extend({
|
|
205
|
+
type: z.literal("conda"),
|
|
206
|
+
|
|
207
|
+
["micromamba-version"]: z
|
|
208
|
+
.string()
|
|
209
|
+
.default(defaults.CONDA_MICROMAMBA_VERSION)
|
|
210
|
+
.describe("version of micromamba to be used to operate with conda environments"),
|
|
211
|
+
["conda-root-dir"]: z
|
|
212
|
+
.string()
|
|
213
|
+
.default(defaults.CONDA_DATA_LOCATION)
|
|
214
|
+
.describe("root directory of conda environment inside package root"),
|
|
215
|
+
|
|
216
|
+
spec: z
|
|
217
|
+
.string()
|
|
218
|
+
.default(defaults.CONDA_SOURCE_ENV_SPEC_FILE)
|
|
219
|
+
.describe(`path to conda environment yaml specification relative to package.json`),
|
|
220
|
+
});
|
|
221
|
+
export type condaType = z.infer<typeof condaSchema>;
|
|
222
|
+
|
|
223
|
+
export const dockerSchema = z.object({
|
|
224
|
+
type: z.literal("docker"),
|
|
225
|
+
|
|
226
|
+
registry: z
|
|
227
|
+
.string()
|
|
228
|
+
.default(defaults.DOCKER_REGISTRY)
|
|
229
|
+
.describe("registry+repository URL to use for pulling this image"),
|
|
230
|
+
|
|
231
|
+
// build from custom Dockerfile
|
|
232
|
+
context: z
|
|
233
|
+
.string()
|
|
234
|
+
.refine((val) => val !== "./" && val !== ".", {
|
|
235
|
+
message:
|
|
236
|
+
'Context cannot be "./" or "." - use absolute path or relative path without "./" prefix',
|
|
237
|
+
})
|
|
238
|
+
.describe(
|
|
239
|
+
'relative path to context directory from folder where command is executed or absolute path to context folder (cannot be "./" or ".")',
|
|
240
|
+
),
|
|
241
|
+
|
|
242
|
+
dockerfile: z
|
|
243
|
+
.string()
|
|
244
|
+
.default(defaults.DOCKER_DOCKERFILE)
|
|
245
|
+
.describe(
|
|
246
|
+
"relative path to 'Dockerfile' file from folder where command is executed or absolute path to the file",
|
|
247
|
+
),
|
|
248
|
+
|
|
249
|
+
pkg: z
|
|
250
|
+
.string()
|
|
251
|
+
.default(defaults.DOCKER_PLACEHOLDER_PKG)
|
|
252
|
+
.describe('{pkg} placeholder value to be used in "cmd" and arguments'),
|
|
253
|
+
|
|
254
|
+
// import existing image
|
|
255
|
+
// entrypoint: z
|
|
256
|
+
// .array(z.string())
|
|
257
|
+
// .optional()
|
|
258
|
+
// .describe('replace image\'s ENTRYPOINT with this value when running container'),
|
|
259
|
+
});
|
|
260
|
+
export type dockerType = z.infer<typeof dockerSchema>;
|
|
261
|
+
|
|
262
|
+
export const anyArtifactSchema = z.discriminatedUnion("type", [
|
|
263
|
+
assetSchema,
|
|
264
|
+
environmentSchema,
|
|
265
|
+
binarySchema,
|
|
266
|
+
javaSchema,
|
|
267
|
+
pythonSchema,
|
|
268
|
+
rSchema,
|
|
269
|
+
condaSchema,
|
|
270
|
+
dockerSchema,
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
export type anyArtifactType = z.infer<typeof anyArtifactSchema>;
|
|
274
|
+
|
|
275
|
+
export const artifactIndexSchema = z.record(z.string(), anyArtifactSchema);
|
|
276
|
+
export type artifactIndexType = z.infer<typeof artifactIndexSchema>;
|
|
277
|
+
|
|
278
|
+
export type withType<Typ, Orig> = Orig & { type: Typ };
|
|
279
|
+
export type withId<T> = T & { id: string };
|