@platforma-sdk/block-tools 2.6.44 → 2.6.45
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/README.md +16 -9
- package/bin/dev.js +4 -4
- package/bin/run.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +16 -6
- package/dist/cli.mjs.map +1 -1
- package/dist/cmd/index.d.ts +8 -8
- package/dist/cmd/mark-stable.d.ts +1 -1
- package/dist/cmd/publish.d.ts +1 -1
- package/dist/cmd/restore-overview-from-snapshot.d.ts +1 -1
- package/dist/{config-DKBY0B2u.mjs → config-Cc8_zV3b.mjs} +48 -17
- package/dist/config-Cc8_zV3b.mjs.map +1 -0
- package/dist/config-Ycas5fbX.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -4
- package/dist/index.mjs.map +1 -1
- package/dist/registry_v1/config_schema.d.ts +7 -7
- package/dist/registry_v1/v1_repo_schema.d.ts +1 -1
- package/dist/v2/model/block_components.d.ts +19 -19
- package/dist/v2/model/block_description.d.ts +102 -102
- package/dist/v2/model/block_meta.d.ts +20 -20
- package/dist/v2/model/content_conversion.d.ts +2 -2
- package/dist/v2/registry/registry.d.ts +1 -1
- package/dist/v2/source_package.d.ts +1 -1
- package/package.json +31 -29
- package/src/cmd/build-meta.ts +15 -15
- package/src/cmd/build-model.ts +23 -26
- package/src/cmd/index.ts +20 -20
- package/src/cmd/list-overview-snapshots.ts +12 -12
- package/src/cmd/mark-stable.ts +30 -33
- package/src/cmd/pack.ts +15 -15
- package/src/cmd/publish.ts +46 -34
- package/src/cmd/refresh-registry.ts +15 -15
- package/src/cmd/restore-overview-from-snapshot.ts +27 -25
- package/src/cmd/update-deps.ts +8 -8
- package/src/cmd/upload-package-v1.ts +33 -33
- package/src/common_types.ts +1 -1
- package/src/io/folder_reader.test.ts +13 -13
- package/src/io/folder_reader.ts +18 -20
- package/src/io/index.ts +2 -2
- package/src/io/storage.test.ts +48 -48
- package/src/io/storage.ts +20 -15
- package/src/lib.ts +3 -3
- package/src/registry_v1/config.ts +11 -11
- package/src/registry_v1/config_schema.ts +5 -5
- package/src/registry_v1/flags.ts +4 -4
- package/src/registry_v1/index.ts +3 -3
- package/src/registry_v1/registry.test.ts +54 -54
- package/src/registry_v1/registry.ts +29 -25
- package/src/registry_v1/v1_repo_schema.ts +3 -3
- package/src/util.ts +6 -9
- package/src/v2/build_dist.test.ts +8 -9
- package/src/v2/build_dist.ts +10 -13
- package/src/v2/index.ts +4 -4
- package/src/v2/model/block_components.ts +5 -5
- package/src/v2/model/block_description.ts +12 -8
- package/src/v2/model/block_meta.ts +4 -5
- package/src/v2/model/content_conversion.ts +44 -44
- package/src/v2/model/index.ts +4 -4
- package/src/v2/registry/index.ts +3 -3
- package/src/v2/registry/registry.test.ts +223 -197
- package/src/v2/registry/registry.ts +93 -66
- package/src/v2/registry/registry_reader.test.ts +15 -15
- package/src/v2/registry/registry_reader.ts +29 -27
- package/src/v2/registry/schema_internal.ts +11 -10
- package/src/v2/registry/schema_public.ts +56 -47
- package/src/v2/source_package.test.ts +15 -15
- package/src/v2/source_package.ts +33 -26
- package/dist/config-DKBY0B2u.mjs.map +0 -1
package/src/io/folder_reader.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Dispatcher } from
|
|
2
|
-
import { request } from
|
|
3
|
-
import type { RelativeContentReader } from
|
|
4
|
-
import path from
|
|
5
|
-
import pathPosix from
|
|
6
|
-
import fsp from
|
|
7
|
-
import { defaultHttpDispatcher } from
|
|
1
|
+
import type { Dispatcher } from "undici";
|
|
2
|
+
import { request } from "undici";
|
|
3
|
+
import type { RelativeContentReader } from "../v2";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import pathPosix from "node:path/posix";
|
|
6
|
+
import fsp from "node:fs/promises";
|
|
7
|
+
import { defaultHttpDispatcher } from "@milaboratories/pl-http";
|
|
8
8
|
|
|
9
9
|
export interface FolderReader {
|
|
10
10
|
readonly rootUrl: URL;
|
|
@@ -28,14 +28,13 @@ class HttpFolderReader implements FolderReader {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
public relativeReader(relativePath: string): HttpFolderReader {
|
|
31
|
-
if (!relativePath.endsWith(
|
|
31
|
+
if (!relativePath.endsWith("/")) relativePath = relativePath + "/";
|
|
32
32
|
return new HttpFolderReader(new URL(relativePath, this.rootUrl), this.httpDispatcher);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
public getContentReader(relativePath?: string): RelativeContentReader {
|
|
36
|
-
const reader: HttpFolderReader =
|
|
37
|
-
? this.relativeReader(relativePath)
|
|
38
|
-
: this;
|
|
36
|
+
const reader: HttpFolderReader =
|
|
37
|
+
relativePath !== undefined ? this.relativeReader(relativePath) : this;
|
|
39
38
|
return (path) => reader.readFile(path);
|
|
40
39
|
}
|
|
41
40
|
}
|
|
@@ -52,7 +51,7 @@ class FSFolderReader implements FolderReader {
|
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
public relativeReader(relativePath: string): FSFolderReader {
|
|
55
|
-
if (!relativePath.endsWith(
|
|
54
|
+
if (!relativePath.endsWith("/")) relativePath = relativePath + "/";
|
|
56
55
|
return new FSFolderReader(
|
|
57
56
|
new URL(relativePath, this.rootUrl),
|
|
58
57
|
path.join(this.root, ...relativePath.split(pathPosix.sep)),
|
|
@@ -60,9 +59,8 @@ class FSFolderReader implements FolderReader {
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
public getContentReader(relativePath?: string): RelativeContentReader {
|
|
63
|
-
const reader: FSFolderReader =
|
|
64
|
-
? this.relativeReader(relativePath)
|
|
65
|
-
: this;
|
|
62
|
+
const reader: FSFolderReader =
|
|
63
|
+
relativePath !== undefined ? this.relativeReader(relativePath) : this;
|
|
66
64
|
return (path) => reader.readFile(path);
|
|
67
65
|
}
|
|
68
66
|
}
|
|
@@ -76,15 +74,15 @@ function localToPosix(p: string): string {
|
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
export function folderReaderByUrl(address: string, httpDispatcher?: Dispatcher): FolderReader {
|
|
79
|
-
if (!address.endsWith(
|
|
80
|
-
const url = new URL(address, `file:${localToPosix(path.resolve(
|
|
77
|
+
if (!address.endsWith("/")) address = address + "/";
|
|
78
|
+
const url = new URL(address, `file:${localToPosix(path.resolve("."))}/`);
|
|
81
79
|
switch (url.protocol) {
|
|
82
|
-
case
|
|
80
|
+
case "file:": {
|
|
83
81
|
const rootPath = posixToLocalPath(url.pathname);
|
|
84
82
|
return new FSFolderReader(url, rootPath);
|
|
85
83
|
}
|
|
86
|
-
case
|
|
87
|
-
case
|
|
84
|
+
case "https:":
|
|
85
|
+
case "http:":
|
|
88
86
|
return new HttpFolderReader(url, httpDispatcher ?? defaultHttpDispatcher());
|
|
89
87
|
default:
|
|
90
88
|
throw new Error(`Unknown protocol: ${url.protocol}`);
|
package/src/io/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./folder_reader";
|
|
2
|
+
export * from "./storage";
|
package/src/io/storage.test.ts
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { randomUUID } from
|
|
2
|
-
import { test, expect } from
|
|
3
|
-
import { S3Storage, storageByUrl } from
|
|
4
|
-
import path from
|
|
5
|
-
import * as fs from
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { test, expect } from "vitest";
|
|
3
|
+
import { S3Storage, storageByUrl } from "./storage";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
6
|
|
|
7
|
-
test(
|
|
8
|
-
const url = new URL(
|
|
9
|
-
expect(url.pathname).toEqual(path.resolve(
|
|
7
|
+
test("file url test #1", async () => {
|
|
8
|
+
const url = new URL("file:./local/path", "file://" + path.resolve(".") + "/");
|
|
9
|
+
expect(url.pathname).toEqual(path.resolve("./local/path"));
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
test(
|
|
13
|
-
const url = new URL(
|
|
14
|
-
expect(url.toString()).toEqual(
|
|
12
|
+
test("file url test #2", async () => {
|
|
13
|
+
const url = new URL("http://a/b/c", "file://" + path.resolve(".") + "/");
|
|
14
|
+
expect(url.toString()).toEqual("http://a/b/c");
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test(
|
|
17
|
+
test("test local fs read write", async () => {
|
|
18
18
|
const uuid = randomUUID().toString();
|
|
19
|
-
const tmp = path.resolve(
|
|
19
|
+
const tmp = path.resolve("tmp");
|
|
20
20
|
const storagePath = path.resolve(tmp, uuid);
|
|
21
|
-
const storage = storageByUrl(
|
|
22
|
-
expect(await storage.getFile(
|
|
23
|
-
await storage.putFile(
|
|
24
|
-
expect((await storage.getFile(
|
|
21
|
+
const storage = storageByUrl("file://" + storagePath);
|
|
22
|
+
expect(await storage.getFile("some/deep/file.txt")).toBeUndefined();
|
|
23
|
+
await storage.putFile("some/deep/file.txt", Buffer.from("test1"));
|
|
24
|
+
expect((await storage.getFile("some/deep/file.txt"))?.toString()).toEqual("test1");
|
|
25
25
|
await fs.promises.rm(storagePath, { recursive: true });
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
test(
|
|
28
|
+
test("test local fs list", async () => {
|
|
29
29
|
const uuid = randomUUID().toString();
|
|
30
|
-
const tmp = path.resolve(
|
|
30
|
+
const tmp = path.resolve("tmp");
|
|
31
31
|
const storagePath = path.resolve(tmp, uuid);
|
|
32
|
-
const storage = storageByUrl(
|
|
33
|
-
await storage.putFile(
|
|
34
|
-
await storage.putFile(
|
|
35
|
-
await storage.putFile(
|
|
36
|
-
const result = await storage.listFiles(
|
|
32
|
+
const storage = storageByUrl("file://" + storagePath);
|
|
33
|
+
await storage.putFile("some/deep1/file_1.txt", Buffer.from("test1"));
|
|
34
|
+
await storage.putFile("some/deep1/file_2.txt", Buffer.from("test1"));
|
|
35
|
+
await storage.putFile("some/deep2/file_1.txt", Buffer.from("test1"));
|
|
36
|
+
const result = await storage.listFiles("some");
|
|
37
37
|
result.sort();
|
|
38
|
-
const expected = [
|
|
38
|
+
const expected = ["deep2/file_1.txt", "deep1/file_1.txt", "deep1/file_2.txt"];
|
|
39
39
|
expected.sort();
|
|
40
40
|
expect(result).toEqual(expected);
|
|
41
|
-
await storage.deleteFiles(
|
|
42
|
-
expected.splice(expected.indexOf(
|
|
43
|
-
const result1 = await storage.listFiles(
|
|
41
|
+
await storage.deleteFiles("some/deep2/file_1.txt");
|
|
42
|
+
expected.splice(expected.indexOf("some/deep2/file_1.txt"), 1);
|
|
43
|
+
const result1 = await storage.listFiles("some");
|
|
44
44
|
result1.sort();
|
|
45
45
|
expect(result1).toEqual(expected);
|
|
46
46
|
await fs.promises.rm(storagePath, { recursive: true });
|
|
@@ -48,38 +48,38 @@ test('test local fs list', async () => {
|
|
|
48
48
|
|
|
49
49
|
const testS3Address = process.env.TEST_S3_ADDRESS;
|
|
50
50
|
if (testS3Address) {
|
|
51
|
-
test(
|
|
51
|
+
test("test s3 read write", async () => {
|
|
52
52
|
const uuid = randomUUID().toString();
|
|
53
53
|
const testS3AddressURL = new URL(testS3Address);
|
|
54
|
-
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/,
|
|
54
|
+
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/, "")}/${uuid}`;
|
|
55
55
|
const storage = storageByUrl(testS3AddressURL.toString()) as S3Storage;
|
|
56
|
-
expect(await storage.getFile(
|
|
57
|
-
await storage.putFile(
|
|
58
|
-
expect((await storage.getFile(
|
|
56
|
+
expect(await storage.getFile("some/deep/file.txt")).toBeUndefined();
|
|
57
|
+
await storage.putFile("some/deep/file.txt", Buffer.from("test1"));
|
|
58
|
+
expect((await storage.getFile("some/deep/file.txt"))?.toString()).toEqual("test1");
|
|
59
59
|
await storage.deleteFiles(`some/deep/file.txt`);
|
|
60
|
-
expect(await storage.getFile(
|
|
60
|
+
expect(await storage.getFile("some/deep/file.txt")).toBeUndefined();
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
test(
|
|
63
|
+
test("test s3 fs list", async () => {
|
|
64
64
|
const uuid = randomUUID().toString();
|
|
65
65
|
const testS3AddressURL = new URL(testS3Address);
|
|
66
|
-
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/,
|
|
66
|
+
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/, "")}/${uuid}`;
|
|
67
67
|
const storage = storageByUrl(testS3AddressURL.toString()) as S3Storage;
|
|
68
68
|
|
|
69
|
-
const nonExistingFolderListing = await storage.listFiles(
|
|
69
|
+
const nonExistingFolderListing = await storage.listFiles("not_existing_folder");
|
|
70
70
|
expect(nonExistingFolderListing).toEqual([]);
|
|
71
71
|
|
|
72
|
-
await storage.putFile(
|
|
73
|
-
await storage.putFile(
|
|
74
|
-
await storage.putFile(
|
|
75
|
-
const result = await storage.listFiles(
|
|
72
|
+
await storage.putFile("some/deep1/file_1.txt", Buffer.from("test1"));
|
|
73
|
+
await storage.putFile("some/deep1/file_2.txt", Buffer.from("test1"));
|
|
74
|
+
await storage.putFile("some/deep2/file_1.txt", Buffer.from("test1"));
|
|
75
|
+
const result = await storage.listFiles("some");
|
|
76
76
|
result.sort();
|
|
77
|
-
const expected = [
|
|
77
|
+
const expected = ["deep2/file_1.txt", "deep1/file_1.txt", "deep1/file_2.txt"];
|
|
78
78
|
expected.sort();
|
|
79
79
|
expect(result).toEqual(expected);
|
|
80
|
-
await storage.deleteFiles(
|
|
81
|
-
expected.splice(expected.indexOf(
|
|
82
|
-
const result1 = await storage.listFiles(
|
|
80
|
+
await storage.deleteFiles("some/deep2/file_1.txt");
|
|
81
|
+
expected.splice(expected.indexOf("some/deep2/file_1.txt"), 1);
|
|
82
|
+
const result1 = await storage.listFiles("some");
|
|
83
83
|
result1.sort();
|
|
84
84
|
expect(result1).toEqual(expected);
|
|
85
85
|
await storage.client.deleteObjects({
|
|
@@ -88,9 +88,9 @@ if (testS3Address) {
|
|
|
88
88
|
Objects: [
|
|
89
89
|
{ Key: `${storage.root}/some/deep1/file_1.txt` },
|
|
90
90
|
{ Key: `${storage.root}/some/deep1/file_2.txt` },
|
|
91
|
-
{ Key: `${storage.root}/some/deep2/file_1.txt` }
|
|
92
|
-
]
|
|
93
|
-
}
|
|
91
|
+
{ Key: `${storage.root}/some/deep2/file_1.txt` },
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
94
|
});
|
|
95
95
|
});
|
|
96
96
|
}
|
package/src/io/storage.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import pathPosix from
|
|
2
|
-
import path from
|
|
3
|
-
import { paginateListObjectsV2, S3 } from
|
|
4
|
-
import * as fs from
|
|
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
5
|
|
|
6
6
|
export interface RegistryStorage {
|
|
7
7
|
putFile(file: string, buffer: Buffer): Promise<void>;
|
|
@@ -31,7 +31,7 @@ export class S3Storage implements RegistryStorage {
|
|
|
31
31
|
).Body!.transformToByteArray(),
|
|
32
32
|
);
|
|
33
33
|
} catch (e: unknown) {
|
|
34
|
-
if (e instanceof Error && e.name ===
|
|
34
|
+
if (e instanceof Error && e.name === "NoSuchKey") return undefined;
|
|
35
35
|
else throw e;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -70,7 +70,9 @@ export class S3Storage implements RegistryStorage {
|
|
|
70
70
|
},
|
|
71
71
|
});
|
|
72
72
|
if (results.Errors !== undefined && results.Errors.length > 0)
|
|
73
|
-
throw new Error(
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Errors encountered while deleting files: ${results.Errors.map((e) => e.Message ?? e.Code ?? "Unknown error").join("\n")}`,
|
|
75
|
+
);
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -83,7 +85,7 @@ export class FSStorage implements RegistryStorage {
|
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
private toAbsolutePath(localPath: string): string {
|
|
86
|
-
if (pathPosix.isAbsolute(localPath)) throw new Error(
|
|
88
|
+
if (pathPosix.isAbsolute(localPath)) throw new Error("absolute path");
|
|
87
89
|
return path.resolve(this.root, localPath.split(pathPosix.sep).join(path.sep));
|
|
88
90
|
}
|
|
89
91
|
|
|
@@ -91,7 +93,7 @@ export class FSStorage implements RegistryStorage {
|
|
|
91
93
|
try {
|
|
92
94
|
return await fs.promises.readFile(this.toAbsolutePath(address));
|
|
93
95
|
} catch (err: unknown) {
|
|
94
|
-
if (err instanceof Error &&
|
|
96
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") return undefined;
|
|
95
97
|
else throw err;
|
|
96
98
|
}
|
|
97
99
|
}
|
|
@@ -102,10 +104,13 @@ export class FSStorage implements RegistryStorage {
|
|
|
102
104
|
return (await fs.promises.readdir(listRoot, { recursive: true, withFileTypes: true }))
|
|
103
105
|
.filter((e) => e.isFile())
|
|
104
106
|
.map((e) =>
|
|
105
|
-
path
|
|
107
|
+
path
|
|
108
|
+
.relative(listRoot, path.resolve(e.parentPath, e.name))
|
|
109
|
+
.split(path.sep)
|
|
110
|
+
.join(pathPosix.sep),
|
|
106
111
|
);
|
|
107
112
|
} catch (err: unknown) {
|
|
108
|
-
if (err instanceof Error &&
|
|
113
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") return [];
|
|
109
114
|
else throw err;
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -123,18 +128,18 @@ export class FSStorage implements RegistryStorage {
|
|
|
123
128
|
}
|
|
124
129
|
|
|
125
130
|
export function storageByUrl(address: string): RegistryStorage {
|
|
126
|
-
const url = new URL(address, `file:${path.resolve(
|
|
131
|
+
const url = new URL(address, `file:${path.resolve(".").split(path.sep).join(pathPosix.sep)}/`);
|
|
127
132
|
switch (url.protocol) {
|
|
128
|
-
case
|
|
133
|
+
case "file:": {
|
|
129
134
|
const root = path.resolve(url.pathname);
|
|
130
135
|
return new FSStorage(root);
|
|
131
136
|
}
|
|
132
|
-
case
|
|
137
|
+
case "s3:": {
|
|
133
138
|
const options: NonNullable<ConstructorParameters<typeof S3>[0]> = {};
|
|
134
|
-
const region = url.searchParams.get(
|
|
139
|
+
const region = url.searchParams.get("region");
|
|
135
140
|
if (region) options.region = region;
|
|
136
141
|
const bucket = url.hostname;
|
|
137
|
-
return new S3Storage(new S3(options), bucket, url.pathname.replace(/^\//,
|
|
142
|
+
return new S3Storage(new S3(options), bucket, url.pathname.replace(/^\//, ""));
|
|
138
143
|
}
|
|
139
144
|
default:
|
|
140
145
|
throw new Error(`Unknown protocol: ${url.protocol}`);
|
package/src/lib.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * as RegistryV1 from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * as RegistryV1 from "./registry_v1";
|
|
2
|
+
export * from "./io";
|
|
3
|
+
export * from "./v2";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import YAML from
|
|
2
|
-
import { tryLoadFile } from
|
|
1
|
+
import YAML from "yaml";
|
|
2
|
+
import { tryLoadFile } from "../util";
|
|
3
3
|
import {
|
|
4
4
|
PlPackageJsonConfigFile,
|
|
5
5
|
PlPackageYamlConfigFile,
|
|
6
6
|
PlRegFullPackageConfigData,
|
|
7
7
|
PlRegPackageConfigDataShard,
|
|
8
|
-
} from
|
|
9
|
-
import * as os from
|
|
10
|
-
import { BlockRegistry } from
|
|
11
|
-
import { storageByUrl } from
|
|
12
|
-
import type { FullBlockPackageName } from
|
|
13
|
-
import type { MiLogger } from
|
|
8
|
+
} from "./config_schema";
|
|
9
|
+
import * as os from "node:os";
|
|
10
|
+
import { BlockRegistry } from "./registry";
|
|
11
|
+
import { storageByUrl } from "../io/storage";
|
|
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,
|
|
@@ -40,8 +40,8 @@ async function tryLoadYamlConfigFromFile(
|
|
|
40
40
|
async function loadConfigShard(): Promise<PlRegPackageConfigDataShard> {
|
|
41
41
|
let conf = PlRegPackageConfigDataShard.parse({});
|
|
42
42
|
|
|
43
|
-
conf = mergeConfigs(conf, await tryLoadJsonConfigFromFile(
|
|
44
|
-
conf = mergeConfigs(conf, await tryLoadYamlConfigFromFile(
|
|
43
|
+
conf = mergeConfigs(conf, await tryLoadJsonConfigFromFile("./.pl.reg.json"));
|
|
44
|
+
conf = mergeConfigs(conf, await tryLoadYamlConfigFromFile("./.pl.reg.yaml"));
|
|
45
45
|
conf = mergeConfigs(conf, await tryLoadJsonConfigFromFile(`${os.homedir()}/.pl.reg.json`));
|
|
46
46
|
conf = mergeConfigs(conf, await tryLoadYamlConfigFromFile(`${os.homedir()}/.pl.reg.yaml`));
|
|
47
47
|
conf = mergeConfigs(conf, await tryLoadJsonConfigFromFile(PlPackageJsonConfigFile));
|
|
@@ -66,7 +66,7 @@ export class PlRegPackageConfig {
|
|
|
66
66
|
|
|
67
67
|
createRegistry(logger?: MiLogger): BlockRegistry {
|
|
68
68
|
let address = this.conf.registry;
|
|
69
|
-
if (!address.startsWith(
|
|
69
|
+
if (!address.startsWith("file:") && !address.startsWith("s3:")) {
|
|
70
70
|
const regByAlias = this.conf.registries[address];
|
|
71
71
|
if (!regByAlias) throw new Error(`Registry with alias "${address}" not found`);
|
|
72
72
|
address = regByAlias;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import { PlRegAddress } from
|
|
3
|
-
import { SemVer } from
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { PlRegAddress } from "../common_types";
|
|
3
|
+
import { SemVer } from "@milaboratories/pl-model-middle-layer";
|
|
4
4
|
|
|
5
5
|
export const PlPackageConfigData = z.object({
|
|
6
6
|
organization: z.string(),
|
|
@@ -26,5 +26,5 @@ export const PlRegPackageConfigDataShard = PlRegFullPackageConfigData.partial().
|
|
|
26
26
|
});
|
|
27
27
|
export type PlRegPackageConfigDataShard = z.infer<typeof PlRegPackageConfigDataShard>;
|
|
28
28
|
|
|
29
|
-
export const PlPackageJsonConfigFile =
|
|
30
|
-
export const PlPackageYamlConfigFile =
|
|
29
|
+
export const PlPackageJsonConfigFile = "pl.package.json";
|
|
30
|
+
export const PlPackageYamlConfigFile = "pl.package.yaml";
|
package/src/registry_v1/flags.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Flags } from
|
|
2
|
-
import path from
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
export interface TargetFile {
|
|
5
5
|
src: string;
|
|
@@ -17,8 +17,8 @@ function parseTargetFile(arg: string): TargetFile {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const targetFile = Flags.custom<TargetFile>({
|
|
20
|
-
summary:
|
|
21
|
-
helpValue:
|
|
20
|
+
summary: "target files to upload",
|
|
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
23
|
parse: async (arg) => parseTargetFile(arg),
|
|
24
24
|
});
|
package/src/registry_v1/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export { PlRegPackageConfig } from
|
|
1
|
+
export * from "./v1_repo_schema";
|
|
2
|
+
export * from "./config_schema";
|
|
3
|
+
export { PlRegPackageConfig } from "./config";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { expect, test } from
|
|
2
|
-
import { ConsoleLoggerAdapter } from
|
|
3
|
-
import { randomUUID } from
|
|
4
|
-
import fs from
|
|
5
|
-
import path from
|
|
6
|
-
import { RegistryStorage, storageByUrl } from
|
|
7
|
-
import { BlockRegistry } from
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { ConsoleLoggerAdapter } from "@milaboratories/ts-helpers";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { RegistryStorage, storageByUrl } from "../io";
|
|
7
|
+
import { BlockRegistry } from "./registry";
|
|
8
8
|
|
|
9
9
|
type TestStorageInstance = {
|
|
10
10
|
storage: RegistryStorage;
|
|
@@ -16,108 +16,108 @@ type TestStorageTarget = {
|
|
|
16
16
|
};
|
|
17
17
|
const testStorages: TestStorageTarget[] = [
|
|
18
18
|
{
|
|
19
|
-
name:
|
|
19
|
+
name: "local",
|
|
20
20
|
storageProvider: () => {
|
|
21
21
|
const uuid = randomUUID().toString();
|
|
22
|
-
const tmp = path.resolve(
|
|
22
|
+
const tmp = path.resolve("tmp");
|
|
23
23
|
const storagePath = path.resolve(tmp, uuid);
|
|
24
|
-
const storage = storageByUrl(
|
|
24
|
+
const storage = storageByUrl("file://" + storagePath);
|
|
25
25
|
return {
|
|
26
26
|
storage,
|
|
27
27
|
teardown: async () => {
|
|
28
28
|
await fs.promises.rm(storagePath, { recursive: true, force: true });
|
|
29
|
-
}
|
|
29
|
+
},
|
|
30
30
|
};
|
|
31
|
-
}
|
|
32
|
-
}
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
33
|
];
|
|
34
34
|
|
|
35
35
|
const testS3Address = process.env.TEST_S3_ADDRESS;
|
|
36
36
|
if (testS3Address !== undefined) {
|
|
37
37
|
testStorages.push({
|
|
38
|
-
name:
|
|
38
|
+
name: "s3",
|
|
39
39
|
storageProvider: () => {
|
|
40
40
|
const uuid = randomUUID().toString();
|
|
41
41
|
const testS3AddressURL = new URL(testS3Address!);
|
|
42
|
-
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/,
|
|
42
|
+
testS3AddressURL.pathname = `${testS3AddressURL.pathname.replace(/\/$/, "")}/${uuid}`;
|
|
43
43
|
const storage = storageByUrl(testS3AddressURL.toString());
|
|
44
44
|
return {
|
|
45
45
|
storage,
|
|
46
46
|
teardown: async () => {
|
|
47
|
-
const allFiles = await storage.listFiles(
|
|
48
|
-
console.log(
|
|
47
|
+
const allFiles = await storage.listFiles("");
|
|
48
|
+
console.log("Deleting: ", allFiles);
|
|
49
49
|
await storage.deleteFiles(...allFiles);
|
|
50
|
-
}
|
|
50
|
+
},
|
|
51
51
|
};
|
|
52
|
-
}
|
|
52
|
+
},
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
test.each(testStorages)(
|
|
56
|
+
test.each(testStorages)("basic registry test with $name", async ({ storageProvider }) => {
|
|
57
57
|
const { storage, teardown } = storageProvider();
|
|
58
58
|
const registry = new BlockRegistry(storage, new ConsoleLoggerAdapter());
|
|
59
59
|
await registry.updateIfNeeded();
|
|
60
60
|
const constructor1 = registry.constructNewPackage({
|
|
61
|
-
organization:
|
|
62
|
-
package:
|
|
63
|
-
version:
|
|
61
|
+
organization: "org1",
|
|
62
|
+
package: "pkg1",
|
|
63
|
+
version: "1.1.0",
|
|
64
64
|
});
|
|
65
|
-
await constructor1.writeMeta({ some:
|
|
65
|
+
await constructor1.writeMeta({ some: "value1" });
|
|
66
66
|
await constructor1.finish();
|
|
67
67
|
await registry.updateIfNeeded();
|
|
68
68
|
const constructor2 = registry.constructNewPackage({
|
|
69
|
-
organization:
|
|
70
|
-
package:
|
|
71
|
-
version:
|
|
69
|
+
organization: "org1",
|
|
70
|
+
package: "pkg1",
|
|
71
|
+
version: "1.2.0",
|
|
72
72
|
});
|
|
73
|
-
await constructor2.writeMeta({ some:
|
|
73
|
+
await constructor2.writeMeta({ some: "value2" });
|
|
74
74
|
await constructor2.finish();
|
|
75
75
|
await registry.updateIfNeeded();
|
|
76
|
-
expect(await registry.getPackageOverview({ organization:
|
|
77
|
-
{ version:
|
|
78
|
-
{ version:
|
|
76
|
+
expect(await registry.getPackageOverview({ organization: "org1", package: "pkg1" })).toEqual([
|
|
77
|
+
{ version: "1.2.0", meta: { some: "value2" } },
|
|
78
|
+
{ version: "1.1.0", meta: { some: "value1" } },
|
|
79
79
|
]);
|
|
80
80
|
expect(await registry.getGlobalOverview()).toEqual([
|
|
81
81
|
{
|
|
82
|
-
organization:
|
|
83
|
-
package:
|
|
84
|
-
allVersions: [
|
|
85
|
-
latestVersion:
|
|
86
|
-
latestMeta: { some:
|
|
87
|
-
}
|
|
82
|
+
organization: "org1",
|
|
83
|
+
package: "pkg1",
|
|
84
|
+
allVersions: ["1.1.0", "1.2.0"],
|
|
85
|
+
latestVersion: "1.2.0",
|
|
86
|
+
latestMeta: { some: "value2" },
|
|
87
|
+
},
|
|
88
88
|
]);
|
|
89
89
|
await teardown();
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
test.each(testStorages)(
|
|
92
|
+
test.each(testStorages)("package modification test with $name", async ({ storageProvider }) => {
|
|
93
93
|
const { storage, teardown } = storageProvider();
|
|
94
94
|
const registry = new BlockRegistry(storage, new ConsoleLoggerAdapter());
|
|
95
95
|
const constructor1 = registry.constructNewPackage({
|
|
96
|
-
organization:
|
|
97
|
-
package:
|
|
98
|
-
version:
|
|
96
|
+
organization: "org1",
|
|
97
|
+
package: "pkg1",
|
|
98
|
+
version: "1.1.0",
|
|
99
99
|
});
|
|
100
|
-
await constructor1.writeMeta({ some:
|
|
100
|
+
await constructor1.writeMeta({ some: "value1" });
|
|
101
101
|
await constructor1.finish();
|
|
102
102
|
const constructor2 = registry.constructNewPackage({
|
|
103
|
-
organization:
|
|
104
|
-
package:
|
|
105
|
-
version:
|
|
103
|
+
organization: "org1",
|
|
104
|
+
package: "pkg1",
|
|
105
|
+
version: "1.1.0",
|
|
106
106
|
});
|
|
107
|
-
await constructor2.writeMeta({ some:
|
|
107
|
+
await constructor2.writeMeta({ some: "value2" });
|
|
108
108
|
await constructor2.finish();
|
|
109
109
|
await registry.updateIfNeeded();
|
|
110
|
-
expect(await registry.getPackageOverview({ organization:
|
|
111
|
-
{ version:
|
|
110
|
+
expect(await registry.getPackageOverview({ organization: "org1", package: "pkg1" })).toEqual([
|
|
111
|
+
{ version: "1.1.0", meta: { some: "value2" } },
|
|
112
112
|
]);
|
|
113
113
|
expect(await registry.getGlobalOverview()).toEqual([
|
|
114
114
|
{
|
|
115
|
-
organization:
|
|
116
|
-
package:
|
|
117
|
-
allVersions: [
|
|
118
|
-
latestVersion:
|
|
119
|
-
latestMeta: { some:
|
|
120
|
-
}
|
|
115
|
+
organization: "org1",
|
|
116
|
+
package: "pkg1",
|
|
117
|
+
allVersions: ["1.1.0"],
|
|
118
|
+
latestVersion: "1.1.0",
|
|
119
|
+
latestMeta: { some: "value2" },
|
|
120
|
+
},
|
|
121
121
|
]);
|
|
122
122
|
await teardown();
|
|
123
123
|
});
|