@platforma-sdk/block-tools 2.6.27 → 2.6.29
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 +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +15 -13
- package/dist/cli.mjs.map +1 -1
- package/dist/{config-XBQ2O39y.mjs → config-DKBY0B2u.mjs} +272 -273
- package/dist/config-DKBY0B2u.mjs.map +1 -0
- package/dist/config-Ycas5fbX.js +3 -0
- package/dist/config-Ycas5fbX.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -17
- package/dist/index.mjs.map +1 -1
- package/dist/registry_v1/v1_repo_schema.d.ts +2 -2
- package/package.json +18 -15
- package/src/cmd/build-meta.ts +9 -9
- package/src/cmd/build-model.ts +20 -16
- package/src/cmd/index.ts +0 -1
- package/src/cmd/list-overview-snapshots.ts +5 -5
- package/src/cmd/mark-stable.ts +14 -15
- package/src/cmd/pack.ts +7 -7
- package/src/cmd/publish.ts +16 -16
- package/src/cmd/refresh-registry.ts +4 -10
- package/src/cmd/restore-overview-from-snapshot.ts +16 -16
- package/src/cmd/update-deps.ts +3 -2
- package/src/cmd/upload-package-v1.ts +12 -12
- package/src/io/folder_reader.ts +15 -11
- package/src/io/storage.ts +25 -23
- package/src/registry_v1/config.ts +11 -10
- package/src/registry_v1/config_schema.ts +5 -5
- package/src/registry_v1/flags.ts +3 -2
- package/src/registry_v1/registry.ts +34 -35
- package/src/registry_v1/v1_repo_schema.ts +2 -2
- package/src/util.ts +15 -11
- package/src/v2/build_dist.ts +12 -9
- package/src/v2/model/block_components.ts +6 -6
- package/src/v2/model/block_description.ts +13 -13
- package/src/v2/model/block_meta.ts +10 -9
- package/src/v2/model/content_conversion.ts +28 -26
- package/src/v2/registry/index.ts +3 -3
- package/src/v2/registry/registry.test.ts +1 -1
- package/src/v2/registry/registry.ts +64 -63
- package/src/v2/registry/registry_reader.ts +47 -46
- package/src/v2/registry/schema_internal.ts +3 -3
- package/src/v2/registry/schema_public.ts +29 -26
- package/src/v2/source_package.ts +26 -23
- package/dist/config-DjpRXRy9.js +0 -3
- package/dist/config-DjpRXRy9.js.map +0 -1
- package/dist/config-XBQ2O39y.mjs.map +0 -1
package/src/cmd/pack.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { loadPackDescription } from '../v2/source_package';
|
|
3
|
-
import path from 'path';
|
|
3
|
+
import path from 'node:path';
|
|
4
4
|
import { buildBlockPackDist } from '../v2/build_dist';
|
|
5
5
|
|
|
6
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';
|
|
7
|
+
static description
|
|
8
|
+
= 'Builds block pack and outputs a block pack manifest consolidating all '
|
|
9
|
+
+ 'references assets into a single folder';
|
|
10
10
|
|
|
11
11
|
static flags = {
|
|
12
12
|
modulePath: Flags.string({
|
|
13
13
|
char: 'i',
|
|
14
14
|
summary: 'input module path',
|
|
15
15
|
helpValue: '<path>',
|
|
16
|
-
default: '.'
|
|
16
|
+
default: '.',
|
|
17
17
|
}),
|
|
18
18
|
|
|
19
19
|
destinationPath: Flags.string({
|
|
20
20
|
char: 'o',
|
|
21
21
|
summary: 'output folder',
|
|
22
22
|
helpValue: '<path>',
|
|
23
|
-
default: './block-pack'
|
|
24
|
-
})
|
|
23
|
+
default: './block-pack',
|
|
24
|
+
}),
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
public async run(): Promise<void> {
|
package/src/cmd/publish.ts
CHANGED
|
@@ -9,7 +9,7 @@ import path from 'node:path';
|
|
|
9
9
|
|
|
10
10
|
function simpleDeepMerge<T extends Record<string, unknown>>(
|
|
11
11
|
target: Record<string, unknown>,
|
|
12
|
-
source: T
|
|
12
|
+
source: T,
|
|
13
13
|
): T {
|
|
14
14
|
const result = { ...target };
|
|
15
15
|
|
|
@@ -29,52 +29,52 @@ function simpleDeepMerge<T extends Record<string, unknown>>(
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export default class Publish extends Command {
|
|
32
|
-
static description
|
|
33
|
-
'Publishes the block package and refreshes the registry (for v2 block-pack schema)';
|
|
32
|
+
static description
|
|
33
|
+
= 'Publishes the block package and refreshes the registry (for v2 block-pack schema)';
|
|
34
34
|
|
|
35
35
|
static flags = {
|
|
36
|
-
registry: Flags.string({
|
|
36
|
+
'registry': Flags.string({
|
|
37
37
|
char: 'r',
|
|
38
38
|
summary: 'full address of the registry',
|
|
39
39
|
helpValue: '<address>',
|
|
40
40
|
env: 'PL_REGISTRY',
|
|
41
|
-
required: true
|
|
41
|
+
required: true,
|
|
42
42
|
}),
|
|
43
43
|
|
|
44
|
-
manifest: Flags.file({
|
|
44
|
+
'manifest': Flags.file({
|
|
45
45
|
char: 'm',
|
|
46
46
|
summary: 'manifest file path',
|
|
47
47
|
exists: true,
|
|
48
|
-
default: `./block-pack/${ManifestFileName}
|
|
48
|
+
default: `./block-pack/${ManifestFileName}`,
|
|
49
49
|
}),
|
|
50
50
|
|
|
51
51
|
'version-override': Flags.file({
|
|
52
52
|
char: 'v',
|
|
53
|
-
summary: 'override package version'
|
|
53
|
+
summary: 'override package version',
|
|
54
54
|
}),
|
|
55
55
|
|
|
56
|
-
refresh: Flags.boolean({
|
|
56
|
+
'refresh': Flags.boolean({
|
|
57
57
|
summary: 'refresh repository after adding the package',
|
|
58
58
|
default: true,
|
|
59
59
|
allowNo: true,
|
|
60
|
-
env: 'PL_REGISTRY_REFRESH'
|
|
60
|
+
env: 'PL_REGISTRY_REFRESH',
|
|
61
61
|
}),
|
|
62
62
|
|
|
63
|
-
unstable: Flags.boolean({
|
|
63
|
+
'unstable': Flags.boolean({
|
|
64
64
|
summary: 'do not add the published package to stable channel',
|
|
65
65
|
default: false,
|
|
66
|
-
env: 'PL_PUBLISH_UNSTABLE'
|
|
67
|
-
})
|
|
66
|
+
env: 'PL_PUBLISH_UNSTABLE',
|
|
67
|
+
}),
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
public async run(): Promise<void> {
|
|
71
71
|
const { flags } = await this.parse(Publish);
|
|
72
72
|
|
|
73
73
|
const manifestPath = path.resolve(flags.manifest);
|
|
74
|
-
const rawManifest = JSON.parse(await fs.promises.readFile(manifestPath, { encoding: 'utf-8' }))
|
|
74
|
+
const rawManifest = JSON.parse(await fs.promises.readFile(manifestPath, { encoding: 'utf-8' })) as Record<string, unknown>;
|
|
75
75
|
let manifest = BlockPackManifest.parse(rawManifest);
|
|
76
76
|
// To keep extra fields from the manifest and keep coerced fields
|
|
77
|
-
manifest = simpleDeepMerge(rawManifest, manifest);
|
|
77
|
+
manifest = simpleDeepMerge(rawManifest, manifest as BlockPackManifest & Record<string, unknown>);
|
|
78
78
|
const manifestRoot = path.dirname(manifestPath);
|
|
79
79
|
|
|
80
80
|
this.log(`Manifest root = ${manifestRoot}`);
|
|
@@ -86,7 +86,7 @@ export default class Publish extends Command {
|
|
|
86
86
|
const registry = new BlockRegistryV2(storage, new OclifLoggerAdapter(this));
|
|
87
87
|
|
|
88
88
|
await registry.publishPackage(manifest, async (file) =>
|
|
89
|
-
Buffer.from(await fs.promises.readFile(path.resolve(manifestRoot, file)))
|
|
89
|
+
Buffer.from(await fs.promises.readFile(path.resolve(manifestRoot, file))),
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
if (!flags.unstable) {
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import { BlockRegistryV2
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import {
|
|
5
|
-
overrideDescriptionVersion,
|
|
6
|
-
overrideManifestVersion,
|
|
7
|
-
StableChannel
|
|
8
|
-
} from '@milaboratories/pl-model-middle-layer';
|
|
2
|
+
import { BlockRegistryV2 } from '../v2';
|
|
9
3
|
import { storageByUrl } from '../io';
|
|
10
4
|
import { OclifLoggerAdapter } from '@milaboratories/ts-helpers-oclif';
|
|
11
5
|
|
|
@@ -18,7 +12,7 @@ export default class RefreshRegistry extends Command {
|
|
|
18
12
|
summary: 'full address of the registry',
|
|
19
13
|
helpValue: '<address>',
|
|
20
14
|
env: 'PL_REGISTRY',
|
|
21
|
-
required: true
|
|
15
|
+
required: true,
|
|
22
16
|
}),
|
|
23
17
|
|
|
24
18
|
mode: Flags.string({
|
|
@@ -27,8 +21,8 @@ export default class RefreshRegistry extends Command {
|
|
|
27
21
|
helpValue: '<mode>',
|
|
28
22
|
options: ['force', 'normal', 'dry-run'],
|
|
29
23
|
env: 'PL_REGISTRY_REFRESH_DRY_RUN',
|
|
30
|
-
default: 'normal'
|
|
31
|
-
})
|
|
24
|
+
default: 'normal',
|
|
25
|
+
}),
|
|
32
26
|
};
|
|
33
27
|
|
|
34
28
|
public async run(): Promise<void> {
|
|
@@ -7,39 +7,39 @@ export default class RestoreOverviewFromSnapshot extends Command {
|
|
|
7
7
|
static description = 'Restore global overview from a snapshot';
|
|
8
8
|
|
|
9
9
|
static flags = {
|
|
10
|
-
registry: Flags.string({
|
|
10
|
+
'registry': Flags.string({
|
|
11
11
|
char: 'r',
|
|
12
12
|
summary: 'full address of the registry',
|
|
13
13
|
helpValue: '<address>',
|
|
14
14
|
env: 'PL_REGISTRY',
|
|
15
|
-
required: true
|
|
15
|
+
required: true,
|
|
16
16
|
}),
|
|
17
17
|
|
|
18
|
-
snapshot: Flags.string({
|
|
18
|
+
'snapshot': Flags.string({
|
|
19
19
|
char: 's',
|
|
20
20
|
summary: 'snapshot timestamp ID to restore from',
|
|
21
21
|
helpValue: '<timestamp>',
|
|
22
|
-
required: true
|
|
22
|
+
required: true,
|
|
23
23
|
}),
|
|
24
24
|
|
|
25
25
|
'skip-confirmation': Flags.boolean({
|
|
26
26
|
summary: 'skip confirmation prompt (use with caution)',
|
|
27
|
-
default: false
|
|
28
|
-
})
|
|
27
|
+
default: false,
|
|
28
|
+
}),
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
public async run(): Promise<void> {
|
|
32
32
|
const { flags } = await this.parse(RestoreOverviewFromSnapshot);
|
|
33
33
|
const storage = storageByUrl(flags.registry);
|
|
34
34
|
const registry = new BlockRegistryV2(storage, new OclifLoggerAdapter(this));
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
// Check if snapshot exists
|
|
37
37
|
const snapshots = await registry.listGlobalOverviewSnapshots();
|
|
38
|
-
const targetSnapshot = snapshots.find(s => s.timestamp === flags.snapshot);
|
|
39
|
-
|
|
38
|
+
const targetSnapshot = snapshots.find((s) => s.timestamp === flags.snapshot);
|
|
39
|
+
|
|
40
40
|
if (!targetSnapshot) {
|
|
41
41
|
this.error(`Snapshot '${flags.snapshot}' not found. Available snapshots:\n${
|
|
42
|
-
snapshots.map(s => ` - ${s.timestamp}`).join('\n') || ' (none)'
|
|
42
|
+
snapshots.map((s) => ` - ${s.timestamp}`).join('\n') || ' (none)'
|
|
43
43
|
}`);
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -48,17 +48,17 @@ export default class RestoreOverviewFromSnapshot extends Command {
|
|
|
48
48
|
const readline = await import('node:readline');
|
|
49
49
|
const rl = readline.createInterface({
|
|
50
50
|
input: process.stdin,
|
|
51
|
-
output: process.stdout
|
|
51
|
+
output: process.stdout,
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
const answer = await new Promise<string>((resolve) => {
|
|
55
55
|
rl.question(
|
|
56
|
-
`⚠️ This will overwrite the current global overview with snapshot '${flags.snapshot}'.\n`
|
|
57
|
-
`Are you sure you want to continue? (y/N): `,
|
|
58
|
-
resolve
|
|
56
|
+
`⚠️ This will overwrite the current global overview with snapshot '${flags.snapshot}'.\n`
|
|
57
|
+
+ `Are you sure you want to continue? (y/N): `,
|
|
58
|
+
resolve,
|
|
59
59
|
);
|
|
60
60
|
});
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
rl.close();
|
|
63
63
|
|
|
64
64
|
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
@@ -72,7 +72,7 @@ export default class RestoreOverviewFromSnapshot extends Command {
|
|
|
72
72
|
await registry.restoreGlobalOverviewFromSnapshot(flags.snapshot);
|
|
73
73
|
this.log(`✅ Successfully restored global overview from snapshot '${flags.snapshot}'`);
|
|
74
74
|
} catch (error) {
|
|
75
|
-
this.error(`Failed to restore from snapshot: ${error}`);
|
|
75
|
+
this.error(`Failed to restore from snapshot: ${String(error)}`);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/cmd/update-deps.ts
CHANGED
|
@@ -3,11 +3,12 @@ import { execFileSync } from 'node:child_process';
|
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
|
|
5
5
|
export default class UpdateDeps extends Command {
|
|
6
|
-
static override description
|
|
7
|
-
'Updates @platforma-sdk and @milaboratories packages in pnpm-workspace.yaml catalog to their latest versions from npm registry.';
|
|
6
|
+
static override description
|
|
7
|
+
= 'Updates @platforma-sdk and @milaboratories packages in pnpm-workspace.yaml catalog to their latest versions from npm registry.';
|
|
8
8
|
|
|
9
9
|
static override examples = ['<%= config.bin %> <%= command.id %>'];
|
|
10
10
|
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- oclif requires async but implementation is sync
|
|
11
12
|
public async run(): Promise<void> {
|
|
12
13
|
const require = createRequire(import.meta.url);
|
|
13
14
|
const updaterPath = require.resolve('@platforma-sdk/blocks-deps-updater/scripts/updater.js');
|
|
@@ -18,46 +18,46 @@ export default class UploadPackageV1 extends Command {
|
|
|
18
18
|
char: 'r',
|
|
19
19
|
summary: 'full address of the registry or alias from .pl.reg',
|
|
20
20
|
helpValue: '<address|alias>',
|
|
21
|
-
env: 'PL_REGISTRY'
|
|
21
|
+
env: 'PL_REGISTRY',
|
|
22
22
|
}),
|
|
23
23
|
|
|
24
24
|
organization: Flags.string({
|
|
25
25
|
char: 'o',
|
|
26
26
|
summary: 'target organisation',
|
|
27
|
-
env: 'PL_PACKAGE_ORGANIZATION'
|
|
27
|
+
env: 'PL_PACKAGE_ORGANIZATION',
|
|
28
28
|
}),
|
|
29
29
|
|
|
30
30
|
package: Flags.string({
|
|
31
31
|
char: 'p',
|
|
32
32
|
summary: 'target package',
|
|
33
|
-
env: 'PL_PACKAGE_NAME'
|
|
33
|
+
env: 'PL_PACKAGE_NAME',
|
|
34
34
|
}),
|
|
35
35
|
|
|
36
36
|
version: Flags.string({
|
|
37
37
|
char: 'v',
|
|
38
38
|
summary: 'target version',
|
|
39
|
-
env: 'PL_PACKAGE_VERSION'
|
|
39
|
+
env: 'PL_PACKAGE_VERSION',
|
|
40
40
|
}),
|
|
41
41
|
|
|
42
42
|
meta: Flags.file({
|
|
43
43
|
char: 'm',
|
|
44
44
|
summary: 'json file containing meta information to associate with tha package',
|
|
45
|
-
exists: true
|
|
45
|
+
exists: true,
|
|
46
46
|
}),
|
|
47
47
|
|
|
48
48
|
file: targetFile({
|
|
49
49
|
char: 'f',
|
|
50
50
|
summary: 'package files',
|
|
51
51
|
multiple: true,
|
|
52
|
-
default: []
|
|
52
|
+
default: [],
|
|
53
53
|
}),
|
|
54
54
|
|
|
55
55
|
refresh: Flags.boolean({
|
|
56
56
|
summary: 'refresh repository after adding the package',
|
|
57
57
|
default: true,
|
|
58
58
|
allowNo: true,
|
|
59
|
-
env: 'PL_REGISTRY_REFRESH'
|
|
60
|
-
})
|
|
59
|
+
env: 'PL_REGISTRY_REFRESH',
|
|
60
|
+
}),
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
public async run(): Promise<void> {
|
|
@@ -69,12 +69,12 @@ export default class UploadPackageV1 extends Command {
|
|
|
69
69
|
if (flags.meta) {
|
|
70
70
|
if (flags.meta.endsWith('.json'))
|
|
71
71
|
configFromFlags.meta = JSON.parse(
|
|
72
|
-
await fs.promises.readFile(flags.meta, { encoding: 'utf-8' })
|
|
73
|
-
)
|
|
72
|
+
await fs.promises.readFile(flags.meta, { encoding: 'utf-8' }),
|
|
73
|
+
) as Record<string, unknown>;
|
|
74
74
|
else if (flags.meta.endsWith('.yaml'))
|
|
75
75
|
configFromFlags.meta = YAML.parse(
|
|
76
|
-
await fs.promises.readFile(flags.meta, { encoding: 'utf-8' })
|
|
77
|
-
)
|
|
76
|
+
await fs.promises.readFile(flags.meta, { encoding: 'utf-8' }),
|
|
77
|
+
) as Record<string, unknown>;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
for (const targetFile of flags.file) {
|
package/src/io/folder_reader.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Dispatcher
|
|
2
|
-
import {
|
|
1
|
+
import type { Dispatcher } from 'undici';
|
|
2
|
+
import { request } from 'undici';
|
|
3
|
+
import type { RelativeContentReader } from '../v2';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import pathPosix from 'node:path/posix';
|
|
5
6
|
import fsp from 'node:fs/promises';
|
|
@@ -15,13 +16,13 @@ export interface FolderReader {
|
|
|
15
16
|
class HttpFolderReader implements FolderReader {
|
|
16
17
|
constructor(
|
|
17
18
|
public readonly rootUrl: URL,
|
|
18
|
-
private readonly httpDispatcher: Dispatcher
|
|
19
|
+
private readonly httpDispatcher: Dispatcher,
|
|
19
20
|
) {}
|
|
20
21
|
|
|
21
22
|
public async readFile(file: string): Promise<Buffer> {
|
|
22
23
|
const targetUrl = new URL(file, this.rootUrl);
|
|
23
24
|
const response = await request(targetUrl, {
|
|
24
|
-
dispatcher: this.httpDispatcher
|
|
25
|
+
dispatcher: this.httpDispatcher,
|
|
25
26
|
});
|
|
26
27
|
return Buffer.from(await response.body.arrayBuffer());
|
|
27
28
|
}
|
|
@@ -32,8 +33,9 @@ class HttpFolderReader implements FolderReader {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
public getContentReader(relativePath?: string): RelativeContentReader {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
const reader: HttpFolderReader = relativePath !== undefined
|
|
37
|
+
? this.relativeReader(relativePath)
|
|
38
|
+
: this;
|
|
37
39
|
return (path) => reader.readFile(path);
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -41,7 +43,7 @@ class HttpFolderReader implements FolderReader {
|
|
|
41
43
|
class FSFolderReader implements FolderReader {
|
|
42
44
|
constructor(
|
|
43
45
|
public readonly rootUrl: URL,
|
|
44
|
-
private readonly root: string
|
|
46
|
+
private readonly root: string,
|
|
45
47
|
) {}
|
|
46
48
|
|
|
47
49
|
public async readFile(file: string): Promise<Buffer> {
|
|
@@ -53,13 +55,14 @@ class FSFolderReader implements FolderReader {
|
|
|
53
55
|
if (!relativePath.endsWith('/')) relativePath = relativePath + '/';
|
|
54
56
|
return new FSFolderReader(
|
|
55
57
|
new URL(relativePath, this.rootUrl),
|
|
56
|
-
path.join(this.root, ...relativePath.split(pathPosix.sep))
|
|
58
|
+
path.join(this.root, ...relativePath.split(pathPosix.sep)),
|
|
57
59
|
);
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
public getContentReader(relativePath?: string): RelativeContentReader {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
const reader: FSFolderReader = relativePath !== undefined
|
|
64
|
+
? this.relativeReader(relativePath)
|
|
65
|
+
: this;
|
|
63
66
|
return (path) => reader.readFile(path);
|
|
64
67
|
}
|
|
65
68
|
}
|
|
@@ -76,9 +79,10 @@ export function folderReaderByUrl(address: string, httpDispatcher?: Dispatcher):
|
|
|
76
79
|
if (!address.endsWith('/')) address = address + '/';
|
|
77
80
|
const url = new URL(address, `file:${localToPosix(path.resolve('.'))}/`);
|
|
78
81
|
switch (url.protocol) {
|
|
79
|
-
case 'file:':
|
|
82
|
+
case 'file:': {
|
|
80
83
|
const rootPath = posixToLocalPath(url.pathname);
|
|
81
84
|
return new FSFolderReader(url, rootPath);
|
|
85
|
+
}
|
|
82
86
|
case 'https:':
|
|
83
87
|
case 'http:':
|
|
84
88
|
return new HttpFolderReader(url, httpDispatcher ?? defaultHttpDispatcher());
|
package/src/io/storage.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class S3Storage implements RegistryStorage {
|
|
|
17
17
|
constructor(
|
|
18
18
|
public readonly client: S3,
|
|
19
19
|
public readonly bucket: string,
|
|
20
|
-
public readonly root: string
|
|
20
|
+
public readonly root: string,
|
|
21
21
|
) {}
|
|
22
22
|
|
|
23
23
|
async getFile(file: string): Promise<Buffer | undefined> {
|
|
@@ -26,12 +26,12 @@ export class S3Storage implements RegistryStorage {
|
|
|
26
26
|
await (
|
|
27
27
|
await this.client.getObject({
|
|
28
28
|
Bucket: this.bucket,
|
|
29
|
-
Key: pathPosix.join(this.root, file)
|
|
29
|
+
Key: pathPosix.join(this.root, file),
|
|
30
30
|
})
|
|
31
|
-
).Body!.transformToByteArray()
|
|
31
|
+
).Body!.transformToByteArray(),
|
|
32
32
|
);
|
|
33
|
-
} catch (e:
|
|
34
|
-
if (e.name === 'NoSuchKey') return undefined;
|
|
33
|
+
} catch (e: unknown) {
|
|
34
|
+
if (e instanceof Error && e.name === 'NoSuchKey') return undefined;
|
|
35
35
|
else throw e;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -42,8 +42,8 @@ export class S3Storage implements RegistryStorage {
|
|
|
42
42
|
{ client: this.client },
|
|
43
43
|
{
|
|
44
44
|
Bucket: this.bucket,
|
|
45
|
-
Prefix: listRoot
|
|
46
|
-
}
|
|
45
|
+
Prefix: listRoot,
|
|
46
|
+
},
|
|
47
47
|
);
|
|
48
48
|
const result: string[] = [];
|
|
49
49
|
for await (const page of paginator)
|
|
@@ -55,7 +55,7 @@ export class S3Storage implements RegistryStorage {
|
|
|
55
55
|
await this.client.putObject({
|
|
56
56
|
Bucket: this.bucket,
|
|
57
57
|
Key: pathPosix.join(this.root, file),
|
|
58
|
-
Body: buffer
|
|
58
|
+
Body: buffer,
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -65,12 +65,12 @@ export class S3Storage implements RegistryStorage {
|
|
|
65
65
|
Bucket: this.bucket,
|
|
66
66
|
Delete: {
|
|
67
67
|
Objects: files.map((file) => ({
|
|
68
|
-
Key: pathPosix.join(this.root, file)
|
|
69
|
-
}))
|
|
70
|
-
}
|
|
68
|
+
Key: pathPosix.join(this.root, file),
|
|
69
|
+
})),
|
|
70
|
+
},
|
|
71
71
|
});
|
|
72
72
|
if (results.Errors !== undefined && results.Errors.length > 0)
|
|
73
|
-
throw new Error(`Errors encountered while deleting files: ${results.Errors.join('\n')}`);
|
|
73
|
+
throw new Error(`Errors encountered while deleting files: ${results.Errors.map((e) => e.Message ?? e.Code ?? 'Unknown error').join('\n')}`);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -90,9 +90,9 @@ export class FSStorage implements RegistryStorage {
|
|
|
90
90
|
async getFile(address: string): Promise<Buffer | undefined> {
|
|
91
91
|
try {
|
|
92
92
|
return await fs.promises.readFile(this.toAbsolutePath(address));
|
|
93
|
-
} catch (err:
|
|
94
|
-
if (err.code
|
|
95
|
-
else throw
|
|
93
|
+
} catch (err: unknown) {
|
|
94
|
+
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') return undefined;
|
|
95
|
+
else throw err;
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -100,13 +100,13 @@ export class FSStorage implements RegistryStorage {
|
|
|
100
100
|
try {
|
|
101
101
|
const listRoot = this.toAbsolutePath(prefix);
|
|
102
102
|
return (await fs.promises.readdir(listRoot, { recursive: true, withFileTypes: true }))
|
|
103
|
-
.filter((e
|
|
104
|
-
.map((e
|
|
105
|
-
path.relative(listRoot, path.resolve(e.parentPath, e.name)).split(path.sep).join(pathPosix.sep)
|
|
103
|
+
.filter((e) => e.isFile())
|
|
104
|
+
.map((e) =>
|
|
105
|
+
path.relative(listRoot, path.resolve(e.parentPath, e.name)).split(path.sep).join(pathPosix.sep),
|
|
106
106
|
);
|
|
107
|
-
} catch (err:
|
|
108
|
-
if (err.code
|
|
109
|
-
else throw
|
|
107
|
+
} catch (err: unknown) {
|
|
108
|
+
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') return [];
|
|
109
|
+
else throw err;
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -125,15 +125,17 @@ export class FSStorage implements RegistryStorage {
|
|
|
125
125
|
export function storageByUrl(address: string): RegistryStorage {
|
|
126
126
|
const url = new URL(address, `file:${path.resolve('.').split(path.sep).join(pathPosix.sep)}/`);
|
|
127
127
|
switch (url.protocol) {
|
|
128
|
-
case 'file:':
|
|
128
|
+
case 'file:': {
|
|
129
129
|
const root = path.resolve(url.pathname);
|
|
130
130
|
return new FSStorage(root);
|
|
131
|
-
|
|
131
|
+
}
|
|
132
|
+
case 's3:': {
|
|
132
133
|
const options: NonNullable<ConstructorParameters<typeof S3>[0]> = {};
|
|
133
134
|
const region = url.searchParams.get('region');
|
|
134
135
|
if (region) options.region = region;
|
|
135
136
|
const bucket = url.hostname;
|
|
136
137
|
return new S3Storage(new S3(options), bucket, url.pathname.replace(/^\//, ''));
|
|
138
|
+
}
|
|
137
139
|
default:
|
|
138
140
|
throw new Error(`Unknown protocol: ${url.protocol}`);
|
|
139
141
|
}
|
|
@@ -4,35 +4,35 @@ import {
|
|
|
4
4
|
PlPackageJsonConfigFile,
|
|
5
5
|
PlPackageYamlConfigFile,
|
|
6
6
|
PlRegFullPackageConfigData,
|
|
7
|
-
PlRegPackageConfigDataShard
|
|
7
|
+
PlRegPackageConfigDataShard,
|
|
8
8
|
} from './config_schema';
|
|
9
9
|
import * as os from 'node:os';
|
|
10
10
|
import { BlockRegistry } from './registry';
|
|
11
11
|
import { storageByUrl } from '../io/storage';
|
|
12
|
-
import { FullBlockPackageName } from './v1_repo_schema';
|
|
13
|
-
import { MiLogger } from '@milaboratories/ts-helpers';
|
|
12
|
+
import type { FullBlockPackageName } from './v1_repo_schema';
|
|
13
|
+
import type { MiLogger } from '@milaboratories/ts-helpers';
|
|
14
14
|
|
|
15
15
|
function mergeConfigs(
|
|
16
16
|
c1: PlRegPackageConfigDataShard,
|
|
17
|
-
c2: PlRegPackageConfigDataShard | undefined
|
|
17
|
+
c2: PlRegPackageConfigDataShard | undefined,
|
|
18
18
|
): PlRegPackageConfigDataShard {
|
|
19
19
|
if (c2 === undefined) return c1;
|
|
20
20
|
return {
|
|
21
21
|
...c1,
|
|
22
22
|
...c2,
|
|
23
23
|
registries: { ...c1.registries, ...c2.registries },
|
|
24
|
-
files: { ...c1.files, ...c2.files }
|
|
24
|
+
files: { ...c1.files, ...c2.files },
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
async function tryLoadJsonConfigFromFile(
|
|
29
|
-
file: string
|
|
29
|
+
file: string,
|
|
30
30
|
): Promise<PlRegPackageConfigDataShard | undefined> {
|
|
31
31
|
return tryLoadFile(file, (buf) => PlRegPackageConfigDataShard.parse(JSON.parse(buf.toString())));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
async function tryLoadYamlConfigFromFile(
|
|
35
|
-
file: string
|
|
35
|
+
file: string,
|
|
36
36
|
): Promise<PlRegPackageConfigDataShard | undefined> {
|
|
37
37
|
return tryLoadFile(file, (buf) => PlRegPackageConfigDataShard.parse(YAML.parse(buf.toString())));
|
|
38
38
|
}
|
|
@@ -50,9 +50,10 @@ async function loadConfigShard(): Promise<PlRegPackageConfigDataShard> {
|
|
|
50
50
|
return conf;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
const conf: PlRegPackageConfigDataShard | undefined = undefined;
|
|
54
54
|
let confPromise: Promise<PlRegPackageConfigDataShard> | undefined = undefined;
|
|
55
55
|
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
56
57
|
async function getConfigShard() {
|
|
57
58
|
if (conf !== undefined) return conf;
|
|
58
59
|
if (confPromise !== undefined) return await confPromise;
|
|
@@ -77,7 +78,7 @@ export class PlRegPackageConfig {
|
|
|
77
78
|
return {
|
|
78
79
|
organization: this.conf.organization,
|
|
79
80
|
package: this.conf.package,
|
|
80
|
-
version: this.conf.version
|
|
81
|
+
version: this.conf.version,
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
84
|
}
|
|
@@ -85,6 +86,6 @@ export class PlRegPackageConfig {
|
|
|
85
86
|
export async function getConfig(finalShard: PlRegPackageConfigDataShard) {
|
|
86
87
|
const confShard = await loadConfigShard();
|
|
87
88
|
return new PlRegPackageConfig(
|
|
88
|
-
PlRegFullPackageConfigData.parse(mergeConfigs(confShard, finalShard))
|
|
89
|
+
PlRegFullPackageConfigData.parse(mergeConfigs(confShard, finalShard)),
|
|
89
90
|
);
|
|
90
91
|
}
|
|
@@ -6,23 +6,23 @@ export const PlPackageConfigData = z.object({
|
|
|
6
6
|
organization: z.string(),
|
|
7
7
|
package: z.string(),
|
|
8
8
|
version: SemVer.optional(),
|
|
9
|
-
files: z.record(z.string().regex(/^[
|
|
10
|
-
meta: z.object({}).passthrough()
|
|
9
|
+
files: z.record(z.string().regex(/^[^/]+$/), z.string()).default({}),
|
|
10
|
+
meta: z.object({}).passthrough(),
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
export const PlRegCommonConfigData = z.object({
|
|
14
14
|
registries: z.record(z.string(), PlRegAddress).default({}),
|
|
15
|
-
registry: z.string().optional()
|
|
15
|
+
registry: z.string().optional(),
|
|
16
16
|
});
|
|
17
17
|
export type PlRegCommonConfigData = z.infer<typeof PlRegCommonConfigData>;
|
|
18
18
|
|
|
19
19
|
export const PlRegFullPackageConfigData = PlRegCommonConfigData.merge(PlPackageConfigData).required(
|
|
20
|
-
{ registry: true, version: true }
|
|
20
|
+
{ registry: true, version: true },
|
|
21
21
|
);
|
|
22
22
|
export type PlRegFullPackageConfigData = z.infer<typeof PlRegFullPackageConfigData>;
|
|
23
23
|
export const PlRegPackageConfigDataShard = PlRegFullPackageConfigData.partial().required({
|
|
24
24
|
registries: true,
|
|
25
|
-
files: true
|
|
25
|
+
files: true,
|
|
26
26
|
});
|
|
27
27
|
export type PlRegPackageConfigDataShard = z.infer<typeof PlRegPackageConfigDataShard>;
|
|
28
28
|
|
package/src/registry_v1/flags.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface TargetFile {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function parseTargetFile(arg: string): TargetFile {
|
|
10
|
-
const match = arg.match(/(?<destName>[
|
|
10
|
+
const match = arg.match(/(?<destName>[^/\\]+)=(?<src>.*)/);
|
|
11
11
|
if (match) {
|
|
12
12
|
const { src, destName } = match.groups!;
|
|
13
13
|
return { src, destName };
|
|
@@ -19,5 +19,6 @@ function parseTargetFile(arg: string): TargetFile {
|
|
|
19
19
|
export const targetFile = Flags.custom<TargetFile>({
|
|
20
20
|
summary: 'target files to upload',
|
|
21
21
|
helpValue: 'file_path | package_name=file_path',
|
|
22
|
-
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- oclif requires async but parsing is sync
|
|
23
|
+
parse: async (arg) => parseTargetFile(arg),
|
|
23
24
|
});
|