@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.
Files changed (134) hide show
  1. package/assets/conda-dockerfile.template +45 -0
  2. package/assets/python-dockerfile.template +22 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +33 -0
  4. package/dist/_virtual/_rolldown/runtime.js +13 -0
  5. package/dist/core/archive.cjs +52 -0
  6. package/dist/core/archive.cjs.map +1 -0
  7. package/dist/core/archive.js +47 -0
  8. package/dist/core/archive.js.map +1 -0
  9. package/dist/core/conda/builder.cjs +226 -0
  10. package/dist/core/conda/builder.cjs.map +1 -0
  11. package/dist/core/conda/builder.js +220 -0
  12. package/dist/core/conda/builder.js.map +1 -0
  13. package/dist/core/conda/validate-spec.cjs +76 -0
  14. package/dist/core/conda/validate-spec.cjs.map +1 -0
  15. package/dist/core/conda/validate-spec.js +73 -0
  16. package/dist/core/conda/validate-spec.js.map +1 -0
  17. package/dist/core/core.cjs +403 -0
  18. package/dist/core/core.cjs.map +1 -0
  19. package/dist/core/core.d.ts +82 -0
  20. package/dist/core/core.d.ts.map +1 -0
  21. package/dist/core/core.js +397 -0
  22. package/dist/core/core.js.map +1 -0
  23. package/dist/core/docker-conda.cjs +75 -0
  24. package/dist/core/docker-conda.cjs.map +1 -0
  25. package/dist/core/docker-conda.js +71 -0
  26. package/dist/core/docker-conda.js.map +1 -0
  27. package/dist/core/docker-python.cjs +147 -0
  28. package/dist/core/docker-python.cjs.map +1 -0
  29. package/dist/core/docker-python.js +144 -0
  30. package/dist/core/docker-python.js.map +1 -0
  31. package/dist/core/docker.cjs +223 -0
  32. package/dist/core/docker.cjs.map +1 -0
  33. package/dist/core/docker.js +207 -0
  34. package/dist/core/docker.js.map +1 -0
  35. package/dist/core/envs.cjs +58 -0
  36. package/dist/core/envs.cjs.map +1 -0
  37. package/dist/core/envs.d.ts +26 -0
  38. package/dist/core/envs.d.ts.map +1 -0
  39. package/dist/core/envs.js +51 -0
  40. package/dist/core/envs.js.map +1 -0
  41. package/dist/core/package-info.cjs +450 -0
  42. package/dist/core/package-info.cjs.map +1 -0
  43. package/dist/core/package-info.d.ts +57 -0
  44. package/dist/core/package-info.d.ts.map +1 -0
  45. package/dist/core/package-info.js +447 -0
  46. package/dist/core/package-info.js.map +1 -0
  47. package/dist/core/paths.cjs +15 -0
  48. package/dist/core/paths.cjs.map +1 -0
  49. package/dist/core/paths.js +14 -0
  50. package/dist/core/paths.js.map +1 -0
  51. package/dist/core/resolver.cjs +99 -0
  52. package/dist/core/resolver.cjs.map +1 -0
  53. package/dist/core/resolver.js +95 -0
  54. package/dist/core/resolver.js.map +1 -0
  55. package/dist/core/schemas/artifacts.cjs +136 -0
  56. package/dist/core/schemas/artifacts.cjs.map +1 -0
  57. package/dist/core/schemas/artifacts.d.ts +280 -0
  58. package/dist/core/schemas/artifacts.d.ts.map +1 -0
  59. package/dist/core/schemas/artifacts.js +122 -0
  60. package/dist/core/schemas/artifacts.js.map +1 -0
  61. package/dist/core/schemas/entrypoints.cjs +43 -0
  62. package/dist/core/schemas/entrypoints.cjs.map +1 -0
  63. package/dist/core/schemas/entrypoints.d.ts +32 -0
  64. package/dist/core/schemas/entrypoints.d.ts.map +1 -0
  65. package/dist/core/schemas/entrypoints.js +41 -0
  66. package/dist/core/schemas/entrypoints.js.map +1 -0
  67. package/dist/core/schemas/sw-json.cjs +111 -0
  68. package/dist/core/schemas/sw-json.cjs.map +1 -0
  69. package/dist/core/schemas/sw-json.js +110 -0
  70. package/dist/core/schemas/sw-json.js.map +1 -0
  71. package/dist/core/storage.cjs +86 -0
  72. package/dist/core/storage.cjs.map +1 -0
  73. package/dist/core/storage.js +83 -0
  74. package/dist/core/storage.js.map +1 -0
  75. package/dist/core/sw-json-render.cjs +327 -0
  76. package/dist/core/sw-json-render.cjs.map +1 -0
  77. package/dist/core/sw-json-render.js +322 -0
  78. package/dist/core/sw-json-render.js.map +1 -0
  79. package/dist/core/util.cjs +313 -0
  80. package/dist/core/util.cjs.map +1 -0
  81. package/dist/core/util.d.ts +66 -0
  82. package/dist/core/util.d.ts.map +1 -0
  83. package/dist/core/util.js +281 -0
  84. package/dist/core/util.js.map +1 -0
  85. package/dist/defaults.cjs +54 -0
  86. package/dist/defaults.cjs.map +1 -0
  87. package/dist/defaults.d.ts +21 -0
  88. package/dist/defaults.d.ts.map +1 -0
  89. package/dist/defaults.js +37 -0
  90. package/dist/defaults.js.map +1 -0
  91. package/dist/index.cjs +31 -0
  92. package/dist/index.cjs.map +1 -0
  93. package/dist/index.d.ts +20 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +12 -0
  96. package/dist/index.js.map +1 -0
  97. package/package.json +56 -0
  98. package/src/__test__/Dockerfile +1 -0
  99. package/src/__test__/docker.test.ts +67 -0
  100. package/src/__test__/package.json +39 -0
  101. package/src/__test__/python-example/main.py +1 -0
  102. package/src/__test__/python-example/requirements.txt +0 -0
  103. package/src/__test__/vite.config.mts +7 -0
  104. package/src/core/__tests__/docker-conda.test.ts +145 -0
  105. package/src/core/__tests__/docker-entrypoint-generation.test.ts +119 -0
  106. package/src/core/__tests__/docker-python.test.ts +374 -0
  107. package/src/core/__tests__/publish-docker-images.test.ts +309 -0
  108. package/src/core/archive.ts +102 -0
  109. package/src/core/conda/builder.test.ts +71 -0
  110. package/src/core/conda/builder.ts +384 -0
  111. package/src/core/conda/validate-spec.test.ts +213 -0
  112. package/src/core/conda/validate-spec.ts +107 -0
  113. package/src/core/core.ts +835 -0
  114. package/src/core/docker-conda.ts +149 -0
  115. package/src/core/docker-python.ts +283 -0
  116. package/src/core/docker.ts +300 -0
  117. package/src/core/envs.ts +31 -0
  118. package/src/core/package-info.test.ts +82 -0
  119. package/src/core/package-info.ts +843 -0
  120. package/src/core/paths.ts +16 -0
  121. package/src/core/resolver.ts +195 -0
  122. package/src/core/schemas/artifacts.test.ts +72 -0
  123. package/src/core/schemas/artifacts.ts +279 -0
  124. package/src/core/schemas/entrypoints.test.ts +171 -0
  125. package/src/core/schemas/entrypoints.ts +150 -0
  126. package/src/core/schemas/sw-json.ts +216 -0
  127. package/src/core/schemas/test-artifacts.ts +362 -0
  128. package/src/core/storage.ts +125 -0
  129. package/src/core/sw-json-render.test.ts +215 -0
  130. package/src/core/sw-json-render.ts +682 -0
  131. package/src/core/util.ts +390 -0
  132. package/src/defaults.ts +38 -0
  133. package/src/index.ts +31 -0
  134. 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 };