@platforma-sdk/tengo-builder 1.14.12 → 1.15.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.
@@ -16,6 +16,7 @@ export interface TemplatesAndLibs {
16
16
  templates: Template[],
17
17
  libs: ArtifactSource[],
18
18
  software: ArtifactSource[]
19
+ assets: ArtifactSource[]
19
20
  }
20
21
 
21
22
  export class TengoTemplateCompiler {
@@ -25,6 +26,7 @@ export class TengoTemplateCompiler {
25
26
 
26
27
  private readonly libs = new ArtifactStore<ArtifactSource>(src => src.fullName);
27
28
  private readonly software = new ArtifactStore<ArtifactSource>(src => src.fullName);
29
+ private readonly assets = new ArtifactStore<ArtifactSource>(src => src.fullName);
28
30
  private readonly templates = new ArtifactStore<Template>(tpl => tpl.fullName);
29
31
 
30
32
  private populateTemplateDataFromDependencies(fullName: FullArtifactName,
@@ -58,6 +60,16 @@ export class TengoTemplateCompiler {
58
60
  src: software.src
59
61
  }
60
62
 
63
+ break;
64
+ case 'asset':
65
+ const asset = this.getAssetOrError(dep);
66
+ // Yes, we temporarily put assets into 'software' section of template, so controller can
67
+ // handle it the right way without updates
68
+ data.software[artifactNameToString(dep)] = {
69
+ ...formatArtefactNameAndVersion(asset.fullName),
70
+ src: asset.src
71
+ }
72
+
61
73
  break;
62
74
  case 'template':
63
75
  if (typedArtifactNamesEquals(fullName, dep))
@@ -89,6 +101,7 @@ export class TengoTemplateCompiler {
89
101
  templates: {},
90
102
  libs: {},
91
103
  software: {},
104
+ assets: {},
92
105
  src: tplSrc.src
93
106
  };
94
107
 
@@ -151,6 +164,32 @@ export class TengoTemplateCompiler {
151
164
  return software;
152
165
  }
153
166
 
167
+ addAsset(asset: ArtifactSource) {
168
+ const assetFromMap = this.assets.add(asset.compileMode, asset, false)
169
+ if (assetFromMap)
170
+ throw new Error(
171
+ `compiler already contain info for asset: adding = ${fullNameToString(asset.fullName)}, contains = ${fullNameToString(assetFromMap.fullName)}`
172
+ );
173
+ }
174
+
175
+ allAssets(): ArtifactSource[] {
176
+ return this.assets.array(this.compileMode)
177
+ }
178
+
179
+ getAsset(name: TypedArtifactName): ArtifactSource | undefined {
180
+ if (name.type !== 'asset')
181
+ throw new Error(`illegal artifact type: got ${name.type} instead of 'asset`);
182
+
183
+ return this.assets.get(this.compileMode, name);
184
+ }
185
+
186
+ getAssetOrError(name: TypedArtifactName): ArtifactSource {
187
+ const asset = this.getAsset(name);
188
+ if (!asset)
189
+ throw new Error(`asset info not found: ${artifactNameToString(name)}`);
190
+ return asset;
191
+ }
192
+
154
193
  addTemplate(tpl: Template) {
155
194
  const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);
156
195
  if (tplFromMap)
@@ -184,6 +223,8 @@ export class TengoTemplateCompiler {
184
223
  return this.getLib(name);
185
224
  case 'software':
186
225
  return this.getSoftware(name);
226
+ case 'asset':
227
+ return this.getAsset(name);
187
228
  case 'test':
188
229
  // Tests are ignored by the complier. They should never be compiled into templates or libs and
189
230
  // should never be a dependency.
@@ -206,7 +247,7 @@ export class TengoTemplateCompiler {
206
247
  }
207
248
 
208
249
  compileAndAdd(sources: ArtifactSource[]): TemplatesAndLibs {
209
- const ret: TemplatesAndLibs = { templates: [], libs: [], software: [] };
250
+ const ret: TemplatesAndLibs = { templates: [], libs: [], software: [], assets: [] };
210
251
  let current: ArtifactSource[] = [];
211
252
 
212
253
  for (const src of sources) {
@@ -218,6 +259,10 @@ export class TengoTemplateCompiler {
218
259
  // add software 'as-is' to be able to resolve them as dependencies
219
260
  this.addSoftware(src);
220
261
  ret.software.push(src);
262
+ } else if (src.fullName.type === 'asset') {
263
+ // add assets 'as-is' to be able to resolve them as dependencies
264
+ this.addAsset(src);
265
+ ret.assets.push(src);
221
266
  } else {
222
267
  current.push(src)
223
268
  }
@@ -261,6 +306,11 @@ export class TengoTemplateCompiler {
261
306
  this.addSoftware(src);
262
307
  ret.software.push(src);
263
308
  break;
309
+ case 'asset':
310
+ // software dependencies are added as is
311
+ this.addAsset(src);
312
+ ret.assets.push(src);
313
+ break;
264
314
  case 'template':
265
315
  // templates are compiled and then added
266
316
  try {
@@ -67,6 +67,10 @@ function resolveSoftwareDst(mode: CompileMode, root: string) {
67
67
  return path.resolve(root, mode, 'tengo', 'software');
68
68
  }
69
69
 
70
+ function resolveAssetsDst(mode: CompileMode, root: string) {
71
+ return path.resolve(root, mode, 'tengo', 'asset');
72
+ }
73
+
70
74
  function loadDependencies(
71
75
  logger: winston.Logger,
72
76
  compiler: TengoTemplateCompiler,
@@ -95,12 +99,14 @@ function loadDependencies(
95
99
  const libDistFolder = resolveLibsDst('dist', searchIn);
96
100
  const tplDistFolder = resolveTemplatesDst('dist', searchIn);
97
101
  const softwareDistFolder = resolveSoftwareDst('dist', searchIn);
102
+ const assetDistFolder = resolveAssetsDst('dist', searchIn);
98
103
 
99
104
  const libDistExists = pathType(libDistFolder) === 'dir';
100
105
  const tplDistExists = pathType(tplDistFolder) === 'dir';
101
106
  const softwareDistExists = pathType(softwareDistFolder) === 'dir';
107
+ const assetDistExists = pathType(assetDistFolder) === 'dir';
102
108
 
103
- if (!libDistExists && !tplDistExists && !softwareDistExists)
109
+ if (!libDistExists && !tplDistExists && !softwareDistExists && !assetDistExists)
104
110
  // if neither of tengo-specific folders detected, skipping package
105
111
  return;
106
112
 
@@ -126,6 +132,10 @@ function loadDependencies(
126
132
  if (softwareDistExists) {
127
133
  loadSoftwareFromDir(logger, packageJson, 'dist', softwareDistFolder, compiler);
128
134
  }
135
+
136
+ if (assetDistExists) {
137
+ loadAssetsFromDir(logger, packageJson, 'dist', assetDistFolder, compiler);
138
+ }
129
139
  }
130
140
 
131
141
  function loadLibsFromDir(
@@ -184,7 +194,6 @@ function loadSoftwareFromDir(
184
194
  folder: string,
185
195
  compiler: TengoTemplateCompiler
186
196
  ) {
187
- // adding software
188
197
  for (const f of fs.readdirSync(folder)) {
189
198
  const file = path.resolve(folder, f);
190
199
  if (!f.endsWith(compiledSoftwareSuffix))
@@ -197,8 +206,34 @@ function loadSoftwareFromDir(
197
206
  };
198
207
 
199
208
  const software = new ArtifactSource(mode, fullName, fs.readFileSync(file).toString(), file, []);
209
+
210
+ logger.debug(`Adding dependency ${fullNameToString(fullName)} from ${file}`);
200
211
  compiler.addSoftware(software);
212
+ }
213
+ }
214
+
215
+ function loadAssetsFromDir(
216
+ logger: winston.Logger,
217
+ packageJson: PackageJson,
218
+ mode: CompileMode,
219
+ folder: string,
220
+ compiler: TengoTemplateCompiler
221
+ ) {
222
+ for (const f of fs.readdirSync(folder)) {
223
+ const file = path.resolve(folder, f);
224
+ if (!f.endsWith(compiledSoftwareSuffix))
225
+ throw new Error(`unexpected file in 'asset' folder: ${file}`);
226
+ const fullName: FullArtifactName = {
227
+ type: 'asset',
228
+ pkg: packageJson.name,
229
+ id: f.slice(0, f.length - compiledSoftwareSuffix.length),
230
+ version: packageJson.version
231
+ };
232
+
233
+ const asset = new ArtifactSource(mode, fullName, fs.readFileSync(file).toString(), file, []);
234
+
201
235
  logger.debug(`Adding dependency ${fullNameToString(fullName)} from ${file}`);
236
+ compiler.addAsset(asset);
202
237
  }
203
238
  }
204
239
 
@@ -360,4 +395,15 @@ export function savePacks(logger: winston.Logger, compiled: TemplatesAndLibs, mo
360
395
  fs.writeFileSync(file, sw.src);
361
396
  }
362
397
  }
398
+
399
+ // writing assets
400
+ if (compiled.assets.length > 0) {
401
+ const swOutput = resolveAssetsDst(mode, '.');
402
+ fs.mkdirSync(swOutput, { recursive: true });
403
+ for (const sw of compiled.software) {
404
+ const file = path.resolve(swOutput, sw.fullName.id + compiledSoftwareSuffix);
405
+ logger.info(` - writing ${file}`);
406
+ fs.writeFileSync(file, sw.src);
407
+ }
408
+ }
363
409
  }
@@ -22,7 +22,7 @@ import canonicalize from 'canonicalize';
22
22
 
23
23
  export type CompileMode = 'dist'
24
24
 
25
- export type ArtifactType = 'library' | 'template' | 'test' | 'software'
25
+ export type ArtifactType = 'library' | 'template' | 'test' | 'software' | 'asset'
26
26
 
27
27
  /** Artifact Name including package version */
28
28
  export interface FullArtifactName {
@@ -1,9 +1,15 @@
1
1
  import { parseSource } from './source';
2
- import { testLocalLib1Src, testLocalLib1Name, testLocalLib2Src, testLocalLib1SrcNormalized } from './test.artifacts';
2
+ import {
3
+ testLocalLib1Name,
4
+ testLocalLib1Src,
5
+ testLocalLib2Name,
6
+ testLocalLib2Src,
7
+ testLocalLib1SrcNormalized
8
+ } from './test.artifacts';
3
9
 
4
10
  test('test lib 1 parsing', () => {
5
11
  const libSrc = parseSource('dist', testLocalLib1Src, testLocalLib1Name, true);
6
- expect(libSrc.src).toEqual(testLocalLib1SrcNormalized)
12
+ expect(libSrc.src).toEqual(testLocalLib1SrcNormalized);
7
13
  expect(libSrc.dependencies).toEqual([
8
14
  { type: 'library', pkg: 'package1', id: 'other-lib-2' },
9
15
  { type: 'software', pkg: 'current-package', id: 'software-1' },
@@ -11,18 +17,19 @@ test('test lib 1 parsing', () => {
11
17
  { type: 'template', pkg: 'package1', id: 'template-3' }
12
18
  ]);
13
19
 
14
- expect(
15
- parseSource('dist', testLocalLib1Src, testLocalLib1Name, false).src
16
- ).toEqual(testLocalLib1Src)
20
+ expect(parseSource('dist', testLocalLib1Src, testLocalLib1Name, false).src).toEqual(
21
+ testLocalLib1Src
22
+ );
17
23
  });
18
24
 
19
25
  test('test lib 2 parsing', () => {
20
- const libSrc = parseSource('dist', testLocalLib2Src, testLocalLib1Name, true);
26
+ const libSrc = parseSource('dist', testLocalLib2Src, testLocalLib2Name, true);
21
27
  expect(libSrc.dependencies).toEqual([
22
28
  { type: 'library', pkg: 'package1', id: 'someid' },
23
- { type: 'library', pkg: '@milaboratory/tengo-sdk', id: 'll' },
29
+ { type: 'library', pkg: '@platforma-sdk/workflow-tengo', id: 'assets' },
24
30
  { type: 'template', pkg: 'package2', id: 'template-1' },
25
31
  { type: 'software', pkg: 'package2', id: 'software-1' },
26
- { type: 'template', pkg: 'current-package', id: 'local-template-2' },
32
+ { type: 'asset', pkg: 'package2', id: 'asset-1' },
33
+ { type: 'template', pkg: 'current-package', id: 'local-template-2' }
27
34
  ]);
28
35
  });
@@ -26,6 +26,9 @@ const newImportTemplateRE = (moduleName: string) => {
26
26
  const newImportSoftwareRE = (moduleName: string) => {
27
27
  return functionCallRE(moduleName, 'importSoftware');
28
28
  };
29
+ const newImportAssetRE = (moduleName: string) => {
30
+ return functionCallRE(moduleName, 'importAsset');
31
+ };
29
32
 
30
33
  const singlelineCommentRE = /^\s*(\/\/)|(\/\*.*\*\/)/;
31
34
  const multilineCommentStartRE = /^\s*\/\*/;
@@ -196,7 +199,8 @@ function parseSingleSourceLine(
196
199
  if (!context.tplDepREs.has(iInfo.module)) {
197
200
  context.tplDepREs.set(iInfo.module, [
198
201
  ['template', newImportTemplateRE(iInfo.alias)],
199
- ['software', newImportSoftwareRE(iInfo.alias)]
202
+ ['software', newImportSoftwareRE(iInfo.alias)],
203
+ ['asset', newImportAssetRE(iInfo.alias)]
200
204
  ]);
201
205
  }
202
206
  }
@@ -34,10 +34,12 @@ test('template serialization / deserialization', () => {
34
34
  },
35
35
  templates: {},
36
36
  software: {},
37
+ assets: {},
37
38
  src: 'src 1...'
38
39
  }
39
40
  },
40
41
  software: {},
42
+ assets: {},
41
43
  src: 'src 2 ...'
42
44
  }
43
45
  }
@@ -26,6 +26,15 @@ export interface TemplateSoftwareData {
26
26
  src: string,
27
27
  }
28
28
 
29
+ export interface TemplateAssetData {
30
+ /** i.e. @milaboratory/mixcr:main */
31
+ name: string;
32
+ /** i.e. 4.2.3 */
33
+ version: string;
34
+ /** full contents of asset dependency description */
35
+ src: string,
36
+ }
37
+
29
38
  export interface TemplateData {
30
39
  /** Discriminator for future use */
31
40
  type: 'pl.tengo-template.v2';
@@ -41,6 +50,8 @@ export interface TemplateData {
41
50
  templates: Record<string, TemplateData>;
42
51
  /** i.e. @milaboratory/mixcr:main -> software metadata */
43
52
  software: Record<string, TemplateSoftwareData>;
53
+ /** i.e. @milaboratory/genome:human -> asset metadata */
54
+ assets: Record<string, TemplateAssetData>;
44
55
  /** Template source code */
45
56
  src: string;
46
57
  }
@@ -67,9 +67,16 @@ export {
67
67
  "template3": plapiCustomName.getTemplateId("package1:template-3")
68
68
  }
69
69
  `;
70
+
71
+ export const testLocalLib2Name: FullArtifactName = {
72
+ type: 'library',
73
+ pkg: 'current-package',
74
+ id: 'local-library-2',
75
+ version: '2.3.4'
76
+ };
70
77
  export const testLocalLib2Src = `
71
78
  otherLib := import("package1:someid")
72
- ll := import("@milaboratory/tengo-sdk:ll")
79
+ ll := import("@platforma-sdk/workflow-tengo:assets")
73
80
 
74
81
  /* multiline comments should be ignored
75
82
  a := import(":non-existent-library")
@@ -77,6 +84,7 @@ ll := import("@milaboratory/tengo-sdk:ll")
77
84
 
78
85
  tplID := ll.importTemplate("package2:template-1")
79
86
  softwareID := ll.importSoftware("package2:software-1")
87
+ assetID := ll.importAsset("package2:asset-1")
80
88
 
81
89
  export {
82
90
  "some": "value",
package/src/index.ts CHANGED
@@ -1 +1,24 @@
1
- export { COMMANDS } from './commands';
1
+ // DO NOT EDIT. This file was generated by oclif-index utility.
2
+
3
+ import Cmd0 from './commands/build';
4
+ import Cmd1 from './commands/check';
5
+ import Cmd2 from './commands/test';
6
+ import Cmd3 from './commands/dump/all';
7
+ import Cmd4 from './commands/dump/assets';
8
+ import Cmd5 from './commands/dump/libs';
9
+ import Cmd6 from './commands/dump/software';
10
+ import Cmd7 from './commands/dump/templates';
11
+ import Cmd8 from './commands/dump/tests';
12
+
13
+ // prettier-ignore
14
+ export const COMMANDS = {
15
+ 'build': Cmd0,
16
+ 'check': Cmd1,
17
+ 'test': Cmd2,
18
+ 'dump:all': Cmd3,
19
+ 'dump:assets': Cmd4,
20
+ 'dump:libs': Cmd5,
21
+ 'dump:software': Cmd6,
22
+ 'dump:templates': Cmd7,
23
+ 'dump:tests': Cmd8
24
+ };
@@ -1,6 +1,6 @@
1
1
  import winston from 'winston';
2
2
  import { getPackageInfo, newCompiler, parseSources } from '../compiler/main';
3
- import { typedArtifactNameToString } from '../compiler/package';
3
+ import { ArtifactType, typedArtifactNameToString } from '../compiler/package';
4
4
 
5
5
  export function dumpAll(
6
6
  logger: winston.Logger,
@@ -15,6 +15,8 @@ export function dumpAll(
15
15
  // group output by type:
16
16
  // - all libs
17
17
  // - all templates
18
+ // - all software
19
+ // - all assets
18
20
  // - all tests
19
21
 
20
22
  // Libs
@@ -73,6 +75,24 @@ export function dumpAll(
73
75
  }
74
76
  }
75
77
 
78
+ // Assets
79
+
80
+ for (const asset of compiler.allAssets()) {
81
+ logger.debug(
82
+ `Dumping to pl-tester: ${typedArtifactNameToString(asset.fullName)}`
83
+ );
84
+ stream.write(JSON.stringify(asset) + '\n');
85
+ }
86
+
87
+ for (const src of sources) {
88
+ if (src.fullName.type === 'asset') {
89
+ logger.debug(
90
+ `Dumping to pl-tester: ${typedArtifactNameToString(src.fullName)}`
91
+ );
92
+ stream.write(JSON.stringify(src) + '\n');
93
+ }
94
+ }
95
+
76
96
  // Tests
77
97
 
78
98
  for (const src of sources) {
@@ -118,47 +138,46 @@ export function dumpLibs(
118
138
  }
119
139
  }
120
140
 
121
- export function dumpTemplates(
141
+ function dumpArtifacts(
122
142
  logger: winston.Logger,
123
- stream: NodeJS.WritableStream
143
+ stream: NodeJS.WritableStream,
144
+ aType: ArtifactType,
124
145
  ): void {
125
146
  const packageInfo = getPackageInfo();
126
147
 
127
148
  const sources = parseSources(logger, packageInfo, 'dist', 'src', '');
128
149
 
129
150
  for (const src of sources) {
130
- if (src.fullName.type === 'template') {
151
+ if (src.fullName.type === aType) {
131
152
  stream.write(JSON.stringify(src) + '\n');
132
153
  }
133
154
  }
134
155
  }
135
156
 
136
- export function dumpSoftware(
157
+ export function dumpTemplates(
137
158
  logger: winston.Logger,
138
159
  stream: NodeJS.WritableStream
139
160
  ): void {
140
- const packageInfo = getPackageInfo();
161
+ dumpArtifacts(logger, stream, 'template')
162
+ }
141
163
 
142
- const sources = parseSources(logger, packageInfo, 'dist', 'src', '');
164
+ export function dumpSoftware(
165
+ logger: winston.Logger,
166
+ stream: NodeJS.WritableStream
167
+ ): void {
168
+ dumpArtifacts(logger, stream, 'software')
169
+ }
143
170
 
144
- for (const src of sources) {
145
- if (src.fullName.type === 'software') {
146
- stream.write(JSON.stringify(src) + '\n');
147
- }
148
- }
171
+ export function dumpAssets(
172
+ logger: winston.Logger,
173
+ stream: NodeJS.WritableStream
174
+ ): void {
175
+ dumpArtifacts(logger, stream, 'asset')
149
176
  }
150
177
 
151
178
  export function dumpTests(
152
179
  logger: winston.Logger,
153
180
  stream: NodeJS.WritableStream
154
181
  ): void {
155
- const packageInfo = getPackageInfo();
156
-
157
- const sources = parseSources(logger, packageInfo, 'dist', 'src', '');
158
-
159
- for (const src of sources) {
160
- if (src.fullName.type === 'test') {
161
- stream.write(JSON.stringify(src) + '\n');
162
- }
163
- }
182
+ dumpArtifacts(logger, stream, 'test')
164
183
  }
@@ -1,19 +0,0 @@
1
- import { default as Build } from './build';
2
- import { default as Check } from './check';
3
- import { default as Test } from './test';
4
- import { default as DumpAll } from './dump/all';
5
- import { default as DumpLibs } from './dump/libs';
6
- import { default as DumpSoftware } from './dump/software';
7
- import { default as DumpTemplates } from './dump/templates';
8
- import { default as DumpTests } from './dump/tests';
9
- export declare const COMMANDS: {
10
- build: typeof Build;
11
- check: typeof Check;
12
- test: typeof Test;
13
- 'dump all': typeof DumpAll;
14
- 'dump libs': typeof DumpLibs;
15
- 'dump software': typeof DumpSoftware;
16
- 'dump templates': typeof DumpTemplates;
17
- 'dump tests': typeof DumpTests;
18
- };
19
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,IAAI,MAAM,QAAQ,CAAC;AAE1B,OAAO,OAAO,MAAM,YAAY,CAAC;AACjC,OAAO,QAAQ,MAAM,aAAa,CAAC;AACnC,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAC3C,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAC7C,OAAO,SAAS,MAAM,cAAc,CAAC;AAGrC,eAAO,MAAM,QAAQ;;;;;;;;;CASpB,CAAC"}
@@ -1,21 +0,0 @@
1
- import Build from './build';
2
- import Check from './check';
3
- import Test from './test';
4
-
5
- import DumpAll from './dump/all';
6
- import DumpLibs from './dump/libs';
7
- import DumpSoftware from './dump/software';
8
- import DumpTemplates from './dump/templates';
9
- import DumpTests from './dump/tests';
10
-
11
- // prettier-ignore
12
- export const COMMANDS = {
13
- build: Build,
14
- check: Check,
15
- test: Test,
16
- 'dump all': DumpAll,
17
- 'dump libs': DumpLibs,
18
- 'dump software': DumpSoftware,
19
- 'dump templates': DumpTemplates,
20
- 'dump tests': DumpTests
21
- };