@platforma-sdk/block-tools 2.1.5 → 2.1.6
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/dist/cli.js +1 -756
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +187 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/cmd/build-meta.d.ts +10 -0
- package/dist/cmd/build-meta.d.ts.map +1 -0
- package/dist/cmd/build-model.d.ts +11 -0
- package/dist/cmd/build-model.d.ts.map +1 -0
- package/dist/cmd/index.d.ts +11 -0
- package/dist/cmd/index.d.ts.map +1 -0
- package/dist/cmd/pack-block.d.ts +10 -0
- package/dist/cmd/pack-block.d.ts.map +1 -0
- package/dist/cmd/upload-package-v1.d.ts +15 -0
- package/dist/cmd/upload-package-v1.d.ts.map +1 -0
- package/dist/common_types.d.ts +3 -0
- package/dist/common_types.d.ts.map +1 -0
- package/dist/config-BJognM_j.mjs +536 -0
- package/dist/config-BJognM_j.mjs.map +1 -0
- package/dist/config-CfA0Dj6h.js +3 -0
- package/dist/config-CfA0Dj6h.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +43 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/storage.d.ts +29 -0
- package/dist/lib/storage.d.ts.map +1 -0
- package/dist/lib.d.ts +3 -2637
- package/dist/lib.d.ts.map +1 -0
- package/dist/registry_v1/config.d.ts +12 -0
- package/dist/registry_v1/config.d.ts.map +1 -0
- package/dist/registry_v1/config_schema.d.ts +94 -0
- package/dist/registry_v1/config_schema.d.ts.map +1 -0
- package/dist/registry_v1/flags.d.ts +9 -0
- package/dist/registry_v1/flags.d.ts.map +1 -0
- package/dist/registry_v1/index.d.ts +4 -0
- package/dist/registry_v1/index.d.ts.map +1 -0
- package/dist/registry_v1/registry.d.ts +46 -0
- package/dist/registry_v1/registry.d.ts.map +1 -0
- package/dist/registry_v1/v1_repo_schema.d.ts +25 -0
- package/dist/registry_v1/v1_repo_schema.d.ts.map +1 -0
- package/dist/util.d.ts +4 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/v2/build_dist.d.ts +3 -0
- package/dist/v2/build_dist.d.ts.map +1 -0
- package/dist/v2/index.d.ts +4 -0
- package/dist/v2/index.d.ts.map +1 -0
- package/dist/v2/model/block_components.d.ts +384 -0
- package/dist/v2/model/block_components.d.ts.map +1 -0
- package/dist/v2/model/common.d.ts +3 -0
- package/dist/v2/model/common.d.ts.map +1 -0
- package/dist/v2/model/content_conversion.d.ts +35 -0
- package/dist/v2/model/content_conversion.d.ts.map +1 -0
- package/dist/v2/model/content_types.d.ts +478 -0
- package/dist/v2/model/content_types.d.ts.map +1 -0
- package/dist/{lib.d.cts → v2/model/index.d.ts} +449 -1005
- package/dist/v2/model/index.d.ts.map +1 -0
- package/dist/v2/model/meta.d.ts +805 -0
- package/dist/v2/model/meta.d.ts.map +1 -0
- package/dist/v2/registry/schema.d.ts +15 -0
- package/dist/v2/registry/schema.d.ts.map +1 -0
- package/dist/v2/source_package.d.ts +8 -0
- package/dist/v2/source_package.d.ts.map +1 -0
- package/package.json +21 -17
- package/src/cmd/build-meta.ts +38 -0
- package/src/cmd/build-model.ts +76 -0
- package/src/cmd/index.ts +12 -0
- package/src/cmd/pack-block.ts +32 -0
- package/src/cmd/upload-package-v1.ts +105 -0
- package/src/common_types.ts +3 -0
- package/src/lib/storage.test.ts +91 -0
- package/src/lib/storage.ts +140 -0
- package/src/lib.ts +2 -0
- package/src/registry_v1/config.ts +90 -0
- package/src/registry_v1/config_schema.ts +30 -0
- package/src/registry_v1/flags.ts +23 -0
- package/src/registry_v1/index.ts +3 -0
- package/src/registry_v1/registry.test.ts +122 -0
- package/src/registry_v1/registry.ts +253 -0
- package/src/registry_v1/v1_repo_schema.ts +42 -0
- package/src/util.ts +25 -0
- package/src/v2/build_dist.test.ts +16 -0
- package/src/v2/build_dist.ts +29 -0
- package/src/v2/index.ts +3 -0
- package/src/v2/model/block_components.ts +32 -0
- package/src/v2/model/common.ts +2 -0
- package/src/v2/model/content_conversion.ts +178 -0
- package/src/v2/model/content_types.ts +233 -0
- package/src/v2/model/index.ts +46 -0
- package/src/v2/model/meta.ts +36 -0
- package/src/v2/registry/schema.ts +29 -0
- package/src/v2/source_package.test.ts +27 -0
- package/src/v2/source_package.ts +82 -0
- package/dist/cli.cjs +0 -786
- package/dist/cli.cjs.map +0 -1
- package/dist/cli.d.cts +0 -58
- package/dist/cli.d.ts +0 -58
- package/dist/lib.cjs +0 -629
- package/dist/lib.cjs.map +0 -1
- package/dist/lib.js +0 -577
- package/dist/lib.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../src/v2/model/meta.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BlockPackId, BlockPackIdNoVersion } from '@milaboratories/pl-model-middle-layer';
|
|
2
|
+
export declare function packageContentPrefix(bp: BlockPackId): string;
|
|
3
|
+
export declare function payloadFilePath(bp: BlockPackId, file: string): string;
|
|
4
|
+
export declare function packageOverviewPath(bp: BlockPackIdNoVersion): string;
|
|
5
|
+
export declare const GlobalOverviewPath = "v2/overview.json";
|
|
6
|
+
export declare const ManifestFile = "manifest.json";
|
|
7
|
+
export interface GlobalOverviewEntry {
|
|
8
|
+
organization: string;
|
|
9
|
+
package: string;
|
|
10
|
+
allVersions: string[];
|
|
11
|
+
latestVersion: string;
|
|
12
|
+
latestMeta: object;
|
|
13
|
+
}
|
|
14
|
+
export type GlobalOverview = GlobalOverviewEntry[];
|
|
15
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/v2/registry/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAI1F,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,oBAAoB,GAAG,MAAM,CAEpE;AAED,eAAO,MAAM,kBAAkB,qBAA+B,CAAC;AAE/D,eAAO,MAAM,YAAY,kBAAkB,CAAC;AAE5C,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BlockPackDescriptionAbsolute } from './model';
|
|
2
|
+
import { BlockPackDescriptionRaw, BlockPackId } from '@milaboratories/pl-model-middle-layer';
|
|
3
|
+
export declare const BlockDescriptionPackageJsonField = "block";
|
|
4
|
+
export declare function parsePackageName(packageName: string): Pick<BlockPackId, 'organization' | 'name'>;
|
|
5
|
+
export declare function tryLoadPackDescription(moduleRoot: string): Promise<BlockPackDescriptionAbsolute | undefined>;
|
|
6
|
+
export declare function loadPackDescriptionRaw(moduleRoot: string): Promise<BlockPackDescriptionRaw>;
|
|
7
|
+
export declare function loadPackDescription(moduleRoot: string): Promise<BlockPackDescriptionAbsolute>;
|
|
8
|
+
//# sourceMappingURL=source_package.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source_package.d.ts","sourceRoot":"","sources":["../../src/v2/source_package.ts"],"names":[],"mappings":"AAEA,OAAO,EAA+C,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAGpG,OAAO,EAEL,uBAAuB,EACvB,WAAW,EAGZ,MAAM,uCAAuC,CAAC;AAE/C,eAAO,MAAM,gCAAgC,UAAU,CAAC;AAKxD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,GAAG,MAAM,CAAC,CAQhG;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC,CAyBnD;AAED,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAiBjG;AAED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,4BAA4B,CAAC,CAGvC"}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/block-tools",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.6",
|
|
4
4
|
"description": "Utility to manipulate Platforma Blocks and Block Registry",
|
|
5
|
-
"type": "module",
|
|
6
5
|
"exports": {
|
|
7
6
|
".": {
|
|
8
|
-
"types": "./
|
|
9
|
-
"import": "./dist/index.
|
|
10
|
-
"require": "./dist/index.
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.mjs",
|
|
9
|
+
"require": "./dist/index.js"
|
|
11
10
|
}
|
|
12
11
|
},
|
|
13
12
|
"bin": {
|
|
14
13
|
"block-tools": "./bin/run.js"
|
|
15
14
|
},
|
|
16
15
|
"files": [
|
|
17
|
-
"bin/*",
|
|
18
|
-
"dist/**/*",
|
|
19
|
-
"
|
|
16
|
+
"./bin/*",
|
|
17
|
+
"./dist/**/*",
|
|
18
|
+
"./src/**/*",
|
|
19
|
+
"./README.md"
|
|
20
20
|
],
|
|
21
21
|
"license": "UNLICENSED",
|
|
22
22
|
"dependencies": {
|
|
@@ -27,34 +27,38 @@
|
|
|
27
27
|
"tar": "^7.4.3",
|
|
28
28
|
"yaml": "^2.5.1",
|
|
29
29
|
"zod": "^3.23.8",
|
|
30
|
-
"@milaboratories/pl-model-middle-layer": "^1.2.
|
|
31
|
-
"@milaboratories/ts-helpers": "^1.0.
|
|
32
|
-
"@milaboratories/ts-helpers-oclif": "^1.1.
|
|
30
|
+
"@milaboratories/pl-model-middle-layer": "^1.2.17",
|
|
31
|
+
"@milaboratories/ts-helpers": "^1.0.23",
|
|
32
|
+
"@milaboratories/ts-helpers-oclif": "^1.1.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
+
"typescript": "~5.6.2",
|
|
36
|
+
"vite": "^5.4.7",
|
|
37
|
+
"rollup-plugin-node-externals": "^7.1.3",
|
|
38
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
39
|
+
"vite-plugin-dts": "^4.2.1",
|
|
35
40
|
"@types/jest": "^29.5.13",
|
|
36
41
|
"@types/mime-types": "^2.1.4",
|
|
37
|
-
"@types/node": "
|
|
42
|
+
"@types/node": "~20.16.5",
|
|
38
43
|
"@types/semver": "^7.5.8",
|
|
39
44
|
"jest": "^29.7.0",
|
|
40
45
|
"oclif": "^4.14.34",
|
|
41
46
|
"ts-jest": "^29.2.5",
|
|
42
|
-
"
|
|
43
|
-
"typescript": "^5.6.2",
|
|
44
|
-
"@milaboratories/platforma-build-configs": "1.0.0"
|
|
47
|
+
"@milaboratories/platforma-build-configs": "1.0.1"
|
|
45
48
|
},
|
|
46
49
|
"oclif": {
|
|
50
|
+
"bin": "block-tools",
|
|
47
51
|
"commands": {
|
|
48
52
|
"strategy": "explicit",
|
|
49
53
|
"target": "./dist/cli.js",
|
|
50
54
|
"identifier": "COMMANDS"
|
|
51
55
|
},
|
|
52
|
-
"bin": "block-tools",
|
|
53
56
|
"dirname": "block-tools",
|
|
54
57
|
"topicSeparator": " "
|
|
55
58
|
},
|
|
56
59
|
"scripts": {
|
|
57
|
-
"
|
|
60
|
+
"type-check": "tsc --noEmit --composite false",
|
|
61
|
+
"build": "vite build",
|
|
58
62
|
"readme": "exec oclif readme",
|
|
59
63
|
"test": "jest"
|
|
60
64
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { loadPackDescriptionRaw } from '../v2';
|
|
5
|
+
import { BlockPackMetaDescription, BlockPackMetaEmbed } from '../v2/model/meta';
|
|
6
|
+
|
|
7
|
+
export default class BuildMeta extends Command {
|
|
8
|
+
static override description =
|
|
9
|
+
'Extracts meta information from blocks package.json and outputs meta.json with embedded binary ' +
|
|
10
|
+
'and textual information linked from the meta section.';
|
|
11
|
+
|
|
12
|
+
static flags = {
|
|
13
|
+
modulePath: Flags.string({
|
|
14
|
+
char: 'i',
|
|
15
|
+
summary: 'input module path',
|
|
16
|
+
helpValue: '<path>',
|
|
17
|
+
default: '.'
|
|
18
|
+
}),
|
|
19
|
+
|
|
20
|
+
destination: Flags.string({
|
|
21
|
+
char: 'o',
|
|
22
|
+
summary: 'output meta.json file',
|
|
23
|
+
helpValue: '<path>',
|
|
24
|
+
required: true
|
|
25
|
+
})
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
public async run(): Promise<void> {
|
|
29
|
+
const { flags } = await this.parse(BuildMeta);
|
|
30
|
+
const modulePath = path.resolve(flags.modulePath);
|
|
31
|
+
const descriptionRaw = await loadPackDescriptionRaw(modulePath);
|
|
32
|
+
const metaEmbedded = await BlockPackMetaEmbed.parseAsync(
|
|
33
|
+
BlockPackMetaDescription(modulePath).parse(descriptionRaw.meta)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
await fs.promises.writeFile(path.resolve(flags.destination), JSON.stringify(metaEmbedded));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
async function getFileContent(path: string) {
|
|
6
|
+
try {
|
|
7
|
+
return await fs.promises.readFile(path, 'utf8');
|
|
8
|
+
} catch (error: any) {
|
|
9
|
+
if (error.code === 'ENOENT') {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default class BuildModel extends Command {
|
|
17
|
+
static override description =
|
|
18
|
+
'Extracts and outputs block model JSON from pre-built block model module';
|
|
19
|
+
|
|
20
|
+
static flags = {
|
|
21
|
+
modulePath: Flags.string({
|
|
22
|
+
char: 'i',
|
|
23
|
+
summary: 'input module path',
|
|
24
|
+
helpValue: '<path>',
|
|
25
|
+
default: '.'
|
|
26
|
+
}),
|
|
27
|
+
|
|
28
|
+
sourceBundle: Flags.string({
|
|
29
|
+
char: 'b',
|
|
30
|
+
summary: 'bundled model code to embed into the model for callback-based rendering to work',
|
|
31
|
+
helpValue: '<path>',
|
|
32
|
+
default: './dist/bundle.js'
|
|
33
|
+
}),
|
|
34
|
+
|
|
35
|
+
destination: Flags.string({
|
|
36
|
+
char: 'o',
|
|
37
|
+
summary: 'output model file',
|
|
38
|
+
helpValue: '<path>',
|
|
39
|
+
default: './dist/model.json'
|
|
40
|
+
})
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
public async run(): Promise<void> {
|
|
44
|
+
const { flags } = await this.parse(BuildModel);
|
|
45
|
+
const modulePath = path.resolve(flags.modulePath); // i.e. folder with package.json file
|
|
46
|
+
let { model, platforma } = require(modulePath);
|
|
47
|
+
|
|
48
|
+
if (!model) model = platforma;
|
|
49
|
+
if (!model) throw new Error('"model" export not found');
|
|
50
|
+
|
|
51
|
+
const { config } = model;
|
|
52
|
+
|
|
53
|
+
if (!config)
|
|
54
|
+
throw new Error(
|
|
55
|
+
'Malformed "model" object, check it is created with "BlockModel" ' +
|
|
56
|
+
'and ".done()" is executed as the call in the chain.'
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
!('canRun' in config || 'inputsValid' in config) ||
|
|
61
|
+
!('outputs' in config) ||
|
|
62
|
+
!('sections' in config)
|
|
63
|
+
)
|
|
64
|
+
throw new Error('"config" has unexpected structure');
|
|
65
|
+
|
|
66
|
+
const code = await getFileContent(flags.sourceBundle);
|
|
67
|
+
if (code !== undefined) {
|
|
68
|
+
config.code = {
|
|
69
|
+
type: 'plain',
|
|
70
|
+
content: code
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await fs.promises.writeFile(path.resolve(flags.destination), JSON.stringify(config));
|
|
75
|
+
}
|
|
76
|
+
}
|
package/src/cmd/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BuildMeta from './build-meta';
|
|
2
|
+
import BuildModel from './build-model';
|
|
3
|
+
import PackBlock from './pack-block';
|
|
4
|
+
import UploadPackageV1 from './upload-package-v1';
|
|
5
|
+
|
|
6
|
+
// prettier-ignore
|
|
7
|
+
export const COMMANDS = {
|
|
8
|
+
'upload-package-v1': UploadPackageV1,
|
|
9
|
+
'pack': PackBlock,
|
|
10
|
+
'build-model': BuildModel,
|
|
11
|
+
'build-meta': BuildMeta,
|
|
12
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { loadPackDescription } from '../v2/source_package';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { buildBlockPackDist } from '../v2/build_dist';
|
|
5
|
+
|
|
6
|
+
export default class PackBlock extends Command {
|
|
7
|
+
static description =
|
|
8
|
+
'Builds block pack and outputs a block pack manifest consolidating all ' +
|
|
9
|
+
'references assets into a single folder';
|
|
10
|
+
|
|
11
|
+
static flags = {
|
|
12
|
+
modulePath: Flags.string({
|
|
13
|
+
char: 'i',
|
|
14
|
+
summary: 'input module path',
|
|
15
|
+
helpValue: '<path>',
|
|
16
|
+
default: '.'
|
|
17
|
+
}),
|
|
18
|
+
|
|
19
|
+
destinationPath: Flags.string({
|
|
20
|
+
char: 'o',
|
|
21
|
+
summary: 'output folder',
|
|
22
|
+
helpValue: '<path>',
|
|
23
|
+
default: './block-pack'
|
|
24
|
+
})
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
public async run(): Promise<void> {
|
|
28
|
+
const { flags } = await this.parse(PackBlock);
|
|
29
|
+
const description = await loadPackDescription(path.resolve(flags.modulePath));
|
|
30
|
+
await buildBlockPackDist(description, path.resolve(flags.destinationPath));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { getConfig } from '../registry_v1/config';
|
|
3
|
+
import { targetFile } from '../registry_v1/flags';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import YAML from 'yaml';
|
|
6
|
+
import { PlRegPackageConfigDataShard } from '../registry_v1/config_schema';
|
|
7
|
+
import { OclifLoggerAdapter } from '@milaboratories/ts-helpers-oclif';
|
|
8
|
+
|
|
9
|
+
type BasicConfigField = keyof PlRegPackageConfigDataShard &
|
|
10
|
+
('registry' | 'organization' | 'package' | 'version');
|
|
11
|
+
const BasicConfigFields: BasicConfigField[] = ['registry', 'organization', 'package', 'version'];
|
|
12
|
+
|
|
13
|
+
export default class UploadPackageV1 extends Command {
|
|
14
|
+
static description = 'Uploads V1 package and refreshes the registry';
|
|
15
|
+
|
|
16
|
+
static flags = {
|
|
17
|
+
registry: Flags.string({
|
|
18
|
+
char: 'r',
|
|
19
|
+
summary: 'full address of the registry or alias from .pl.reg',
|
|
20
|
+
helpValue: '<address|alias>',
|
|
21
|
+
env: 'PL_REGISTRY'
|
|
22
|
+
}),
|
|
23
|
+
|
|
24
|
+
organization: Flags.string({
|
|
25
|
+
char: 'o',
|
|
26
|
+
summary: 'target organisation',
|
|
27
|
+
env: 'PL_PACKAGE_ORGANIZATION'
|
|
28
|
+
}),
|
|
29
|
+
|
|
30
|
+
package: Flags.string({
|
|
31
|
+
char: 'p',
|
|
32
|
+
summary: 'target package',
|
|
33
|
+
env: 'PL_PACKAGE_NAME'
|
|
34
|
+
}),
|
|
35
|
+
|
|
36
|
+
version: Flags.string({
|
|
37
|
+
char: 'v',
|
|
38
|
+
summary: 'target version',
|
|
39
|
+
env: 'PL_PACKAGE_VERSION'
|
|
40
|
+
}),
|
|
41
|
+
|
|
42
|
+
meta: Flags.file({
|
|
43
|
+
char: 'm',
|
|
44
|
+
summary: 'json file containing meta information to associate with tha package',
|
|
45
|
+
exists: true
|
|
46
|
+
}),
|
|
47
|
+
|
|
48
|
+
file: targetFile({
|
|
49
|
+
char: 'f',
|
|
50
|
+
summary: 'package files',
|
|
51
|
+
multiple: true,
|
|
52
|
+
default: []
|
|
53
|
+
}),
|
|
54
|
+
|
|
55
|
+
refresh: Flags.boolean({
|
|
56
|
+
summary: 'refresh repository after adding the package',
|
|
57
|
+
default: true,
|
|
58
|
+
allowNo: true,
|
|
59
|
+
env: 'PL_REGISTRY_REFRESH'
|
|
60
|
+
})
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
public async run(): Promise<void> {
|
|
64
|
+
const { flags } = await this.parse(UploadPackageV1);
|
|
65
|
+
const configFromFlags: PlRegPackageConfigDataShard = PlRegPackageConfigDataShard.parse({});
|
|
66
|
+
|
|
67
|
+
for (const field of BasicConfigFields) if (flags[field]) configFromFlags[field] = flags[field];
|
|
68
|
+
|
|
69
|
+
if (flags.meta) {
|
|
70
|
+
if (flags.meta.endsWith('.json'))
|
|
71
|
+
configFromFlags.meta = JSON.parse(
|
|
72
|
+
await fs.promises.readFile(flags.meta, { encoding: 'utf-8' })
|
|
73
|
+
);
|
|
74
|
+
else if (flags.meta.endsWith('.yaml'))
|
|
75
|
+
configFromFlags.meta = YAML.parse(
|
|
76
|
+
await fs.promises.readFile(flags.meta, { encoding: 'utf-8' })
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for (const targetFile of flags.file) {
|
|
81
|
+
configFromFlags.files[targetFile.destName] = targetFile.src;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const conf = await getConfig(configFromFlags);
|
|
85
|
+
|
|
86
|
+
this.log(YAML.stringify(conf.conf));
|
|
87
|
+
|
|
88
|
+
const registry = conf.createRegistry(new OclifLoggerAdapter(this));
|
|
89
|
+
const name = conf.fullPackageName;
|
|
90
|
+
|
|
91
|
+
const builder = registry.constructNewPackage(name);
|
|
92
|
+
|
|
93
|
+
for (const [dst, src] of Object.entries(conf.conf.files)) {
|
|
94
|
+
this.log(`Uploading ${src} -> ${dst} ...`);
|
|
95
|
+
const content = await fs.promises.readFile(src);
|
|
96
|
+
await builder.addFile(dst, content);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.log(`Uploading meta information...`);
|
|
100
|
+
await builder.writeMeta(conf.conf.meta);
|
|
101
|
+
await builder.finish();
|
|
102
|
+
|
|
103
|
+
if (flags.refresh) await registry.updateIfNeeded();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { FSStorage, S3Storage, storageByUrl } from './storage';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
|
|
6
|
+
test('file url test #1', async () => {
|
|
7
|
+
const url = new URL('file:./local/path', 'file://' + path.resolve('.') + '/');
|
|
8
|
+
expect(url.pathname).toEqual(path.resolve('./local/path'));
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('file url test #2', async () => {
|
|
12
|
+
const url = new URL('http://a/b/c', 'file://' + path.resolve('.') + '/');
|
|
13
|
+
expect(url.toString()).toEqual('http://a/b/c');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('test local fs read write', async () => {
|
|
17
|
+
const uuid = randomUUID().toString();
|
|
18
|
+
const tmp = path.resolve('tmp');
|
|
19
|
+
const storagePath = path.resolve(tmp, uuid);
|
|
20
|
+
const storage = storageByUrl('file://' + storagePath);
|
|
21
|
+
expect(await storage.getFile('some/deep/file.txt')).toBeUndefined();
|
|
22
|
+
await storage.putFile('some/deep/file.txt', Buffer.from('test1'));
|
|
23
|
+
expect((await storage.getFile('some/deep/file.txt'))?.toString()).toEqual('test1');
|
|
24
|
+
await fs.promises.rm(storagePath, { recursive: true });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('test local fs list', async () => {
|
|
28
|
+
const uuid = randomUUID().toString();
|
|
29
|
+
const tmp = path.resolve('tmp');
|
|
30
|
+
const storagePath = path.resolve(tmp, uuid);
|
|
31
|
+
const storage = storageByUrl('file://' + storagePath);
|
|
32
|
+
await storage.putFile('some/deep1/file_1.txt', Buffer.from('test1'));
|
|
33
|
+
await storage.putFile('some/deep1/file_2.txt', Buffer.from('test1'));
|
|
34
|
+
await storage.putFile('some/deep2/file_1.txt', Buffer.from('test1'));
|
|
35
|
+
const result = await storage.listFiles('some');
|
|
36
|
+
result.sort();
|
|
37
|
+
const expected = ['deep2/file_1.txt', 'deep1/file_1.txt', 'deep1/file_2.txt'];
|
|
38
|
+
expected.sort();
|
|
39
|
+
expect(result).toEqual(expected);
|
|
40
|
+
await storage.deleteFiles('some/deep2/file_1.txt');
|
|
41
|
+
expected.splice(expected.indexOf('some/deep2/file_1.txt'), 1);
|
|
42
|
+
const result1 = await storage.listFiles('some');
|
|
43
|
+
result1.sort();
|
|
44
|
+
expect(result1).toEqual(expected);
|
|
45
|
+
await fs.promises.rm(storagePath, { recursive: true });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const testS3Address = process.env.TEST_S3_ADDRESS;
|
|
49
|
+
if (testS3Address) {
|
|
50
|
+
test('test s3 read write', async () => {
|
|
51
|
+
const uuid = randomUUID().toString();
|
|
52
|
+
const testS3AddressURL = new URL(testS3Address);
|
|
53
|
+
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/, '')}/${uuid}`;
|
|
54
|
+
const storage = storageByUrl(testS3AddressURL.toString()) as S3Storage;
|
|
55
|
+
expect(await storage.getFile('some/deep/file.txt')).toBeUndefined();
|
|
56
|
+
await storage.putFile('some/deep/file.txt', Buffer.from('test1'));
|
|
57
|
+
expect((await storage.getFile('some/deep/file.txt'))?.toString()).toEqual('test1');
|
|
58
|
+
await storage.deleteFiles(`some/deep/file.txt`);
|
|
59
|
+
expect(await storage.getFile('some/deep/file.txt')).toBeUndefined();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('test s3 fs list', async () => {
|
|
63
|
+
const uuid = randomUUID().toString();
|
|
64
|
+
const testS3AddressURL = new URL(testS3Address);
|
|
65
|
+
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/, '')}/${uuid}`;
|
|
66
|
+
const storage = storageByUrl(testS3AddressURL.toString()) as S3Storage;
|
|
67
|
+
await storage.putFile('some/deep1/file_1.txt', Buffer.from('test1'));
|
|
68
|
+
await storage.putFile('some/deep1/file_2.txt', Buffer.from('test1'));
|
|
69
|
+
await storage.putFile('some/deep2/file_1.txt', Buffer.from('test1'));
|
|
70
|
+
const result = await storage.listFiles('some');
|
|
71
|
+
result.sort();
|
|
72
|
+
const expected = ['deep2/file_1.txt', 'deep1/file_1.txt', 'deep1/file_2.txt'];
|
|
73
|
+
expected.sort();
|
|
74
|
+
expect(result).toEqual(expected);
|
|
75
|
+
await storage.deleteFiles('some/deep2/file_1.txt');
|
|
76
|
+
expected.splice(expected.indexOf('some/deep2/file_1.txt'), 1);
|
|
77
|
+
const result1 = await storage.listFiles('some');
|
|
78
|
+
result1.sort();
|
|
79
|
+
expect(result1).toEqual(expected);
|
|
80
|
+
await storage.client.deleteObjects({
|
|
81
|
+
Bucket: storage.bucket,
|
|
82
|
+
Delete: {
|
|
83
|
+
Objects: [
|
|
84
|
+
{ Key: `${storage.root}/some/deep1/file_1.txt` },
|
|
85
|
+
{ Key: `${storage.root}/some/deep1/file_2.txt` },
|
|
86
|
+
{ Key: `${storage.root}/some/deep2/file_1.txt` }
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import pathPosix from 'node:path/posix';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { paginateListObjectsV2, S3 } from '@aws-sdk/client-s3';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
|
|
6
|
+
export interface RegistryStorage {
|
|
7
|
+
putFile(file: string, buffer: Buffer): Promise<void>;
|
|
8
|
+
|
|
9
|
+
getFile(file: string): Promise<Buffer | undefined>;
|
|
10
|
+
|
|
11
|
+
listFiles(prefix: string): Promise<string[]>;
|
|
12
|
+
|
|
13
|
+
deleteFiles(...files: string[]): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class S3Storage implements RegistryStorage {
|
|
17
|
+
constructor(
|
|
18
|
+
public readonly client: S3,
|
|
19
|
+
public readonly bucket: string,
|
|
20
|
+
public readonly root: string
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
async getFile(file: string): Promise<Buffer | undefined> {
|
|
24
|
+
try {
|
|
25
|
+
return Buffer.from(
|
|
26
|
+
await (
|
|
27
|
+
await this.client.getObject({
|
|
28
|
+
Bucket: this.bucket,
|
|
29
|
+
Key: pathPosix.join(this.root, file)
|
|
30
|
+
})
|
|
31
|
+
).Body!.transformToByteArray()
|
|
32
|
+
);
|
|
33
|
+
} catch (e: any) {
|
|
34
|
+
if (e.name === 'NoSuchKey') return undefined;
|
|
35
|
+
else throw e;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async listFiles(prefix: string): Promise<string[]> {
|
|
40
|
+
const listRoot = pathPosix.join(this.root, prefix);
|
|
41
|
+
const paginator = paginateListObjectsV2(
|
|
42
|
+
{ client: this.client },
|
|
43
|
+
{
|
|
44
|
+
Bucket: this.bucket,
|
|
45
|
+
Prefix: listRoot
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
const result: string[] = [];
|
|
49
|
+
for await (const page of paginator)
|
|
50
|
+
result.push(...page.Contents!.map((e) => pathPosix.relative(listRoot, e.Key!)));
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async putFile(file: string, buffer: Buffer): Promise<void> {
|
|
55
|
+
await this.client.putObject({
|
|
56
|
+
Bucket: this.bucket,
|
|
57
|
+
Key: pathPosix.join(this.root, file),
|
|
58
|
+
Body: buffer
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async deleteFiles(...files: string[]): Promise<void> {
|
|
63
|
+
// TODO implement support of more than 1000 files
|
|
64
|
+
const results = await this.client.deleteObjects({
|
|
65
|
+
Bucket: this.bucket,
|
|
66
|
+
Delete: {
|
|
67
|
+
Objects: files.map((file) => ({
|
|
68
|
+
Key: pathPosix.join(this.root, file)
|
|
69
|
+
}))
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
if (results.Errors !== undefined && results.Errors.length > 0)
|
|
73
|
+
throw new Error(`Errors encountered while deleting files: ${results.Errors.join('\n')}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class FSStorage implements RegistryStorage {
|
|
78
|
+
/** Absolute path */
|
|
79
|
+
public readonly root: string;
|
|
80
|
+
|
|
81
|
+
constructor(_root: string) {
|
|
82
|
+
this.root = path.resolve(_root);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private toAbsolutePath(localPath: string): string {
|
|
86
|
+
if (pathPosix.isAbsolute(localPath)) throw new Error('absolute path');
|
|
87
|
+
return path.resolve(this.root, localPath.split(pathPosix.sep).join(path.sep));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async getFile(address: string): Promise<Buffer | undefined> {
|
|
91
|
+
try {
|
|
92
|
+
return await fs.promises.readFile(this.toAbsolutePath(address));
|
|
93
|
+
} catch (err: any) {
|
|
94
|
+
if (err.code == 'ENOENT') return undefined;
|
|
95
|
+
else throw new Error('', { cause: err });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async listFiles(prefix: string): Promise<string[]> {
|
|
100
|
+
try {
|
|
101
|
+
const listRoot = this.toAbsolutePath(prefix);
|
|
102
|
+
return (await fs.promises.readdir(listRoot, { recursive: true, withFileTypes: true }))
|
|
103
|
+
.filter((e) => e.isFile())
|
|
104
|
+
.map((e) =>
|
|
105
|
+
path.relative(listRoot, path.resolve(e.path, e.name)).split(path.sep).join(pathPosix.sep)
|
|
106
|
+
);
|
|
107
|
+
} catch (err: any) {
|
|
108
|
+
if (err.code == 'ENOENT') return [];
|
|
109
|
+
else throw new Error('', { cause: err });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async putFile(address: string, buffer: Buffer): Promise<void> {
|
|
114
|
+
const absoluteAddress = this.toAbsolutePath(address);
|
|
115
|
+
await fs.promises.mkdir(path.dirname(absoluteAddress), { recursive: true });
|
|
116
|
+
await fs.promises.writeFile(absoluteAddress, buffer);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async deleteFiles(...files: string[]): Promise<void> {
|
|
120
|
+
// Folders are not removed, deletes issued sequentially
|
|
121
|
+
for (const file of files) await fs.promises.rm(this.toAbsolutePath(file));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function storageByUrl(address: string): RegistryStorage {
|
|
126
|
+
const url = new URL(address, `file:${path.resolve('.').split(path.sep).join(pathPosix.sep)}/`);
|
|
127
|
+
switch (url.protocol) {
|
|
128
|
+
case 'file:':
|
|
129
|
+
const root = path.resolve(url.pathname);
|
|
130
|
+
return new FSStorage(root);
|
|
131
|
+
case 's3:':
|
|
132
|
+
const options: NonNullable<ConstructorParameters<typeof S3>[0]> = {};
|
|
133
|
+
const region = url.searchParams.get('region');
|
|
134
|
+
if (region) options.region = region;
|
|
135
|
+
const bucket = url.hostname;
|
|
136
|
+
return new S3Storage(new S3(options), bucket, url.pathname.replace(/^\//, ''));
|
|
137
|
+
default:
|
|
138
|
+
throw new Error(`Unknown protocol: ${url.protocol}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
package/src/lib.ts
ADDED