@platforma-sdk/block-tools 2.1.5
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 +82 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +6 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +7 -0
- package/dist/cli.cjs +786 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +58 -0
- package/dist/cli.d.ts +58 -0
- package/dist/cli.js +757 -0
- package/dist/cli.js.map +1 -0
- package/dist/lib.cjs +629 -0
- package/dist/lib.cjs.map +1 -0
- package/dist/lib.d.cts +2637 -0
- package/dist/lib.d.ts +2637 -0
- package/dist/lib.js +577 -0
- package/dist/lib.js.map +1 -0
- package/package.json +61 -0
package/dist/lib.js
ADDED
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SemVer, BlockPackMeta, ContentAbsoluteTextLocal, ContentAbsoluteBinaryLocal, BlockPackMetaEmbeddedContent, CreateBlockPackDescriptionSchema, BlockComponentsManifest, BlockPackMetaManifest, BlockComponents, ContentAbsoluteFolder, ContentRelativeBinary, BlockPackDescriptionFromPackageJsonRaw, DescriptionContentText, DescriptionContentBinary } from '@milaboratories/pl-model-middle-layer';
|
|
3
|
+
import 'yaml';
|
|
4
|
+
import fsp2 from 'node:fs/promises';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import semver from 'semver/preload';
|
|
7
|
+
import pathPosix from 'node:path/posix';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { S3, paginateListObjectsV2 } from '@aws-sdk/client-s3';
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import path2 from 'path';
|
|
12
|
+
import * as mime from 'mime-types';
|
|
13
|
+
import * as tar from 'tar';
|
|
14
|
+
import { notEmpty } from '@milaboratories/ts-helpers';
|
|
15
|
+
|
|
16
|
+
var __defProp = Object.defineProperty;
|
|
17
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
18
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
19
|
+
}) : x)(function(x) {
|
|
20
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
21
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
22
|
+
});
|
|
23
|
+
var __export = (target, all) => {
|
|
24
|
+
for (var name in all)
|
|
25
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/registry_v1/index.ts
|
|
29
|
+
var registry_v1_exports = {};
|
|
30
|
+
__export(registry_v1_exports, {
|
|
31
|
+
GlobalOverviewPath: () => GlobalOverviewPath,
|
|
32
|
+
MetaFile: () => MetaFile,
|
|
33
|
+
PlPackageConfigData: () => PlPackageConfigData,
|
|
34
|
+
PlPackageJsonConfigFile: () => PlPackageJsonConfigFile,
|
|
35
|
+
PlPackageYamlConfigFile: () => PlPackageYamlConfigFile,
|
|
36
|
+
PlRegCommonConfigData: () => PlRegCommonConfigData,
|
|
37
|
+
PlRegFullPackageConfigData: () => PlRegFullPackageConfigData,
|
|
38
|
+
PlRegPackageConfig: () => PlRegPackageConfig,
|
|
39
|
+
PlRegPackageConfigDataShard: () => PlRegPackageConfigDataShard,
|
|
40
|
+
packageContentPrefix: () => packageContentPrefix,
|
|
41
|
+
packageOverviewPath: () => packageOverviewPath,
|
|
42
|
+
payloadFilePath: () => payloadFilePath
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// src/registry_v1/v1_repo_schema.ts
|
|
46
|
+
var MainPrefix = "v1/";
|
|
47
|
+
function packageContentPrefix(bp) {
|
|
48
|
+
return `${MainPrefix}${bp.organization}/${bp.package}/${bp.version}`;
|
|
49
|
+
}
|
|
50
|
+
function payloadFilePath(bp, file) {
|
|
51
|
+
return `${MainPrefix}${bp.organization}/${bp.package}/${bp.version}/${file}`;
|
|
52
|
+
}
|
|
53
|
+
function packageOverviewPath(bp) {
|
|
54
|
+
return `${MainPrefix}${bp.organization}/${bp.package}/overview.json`;
|
|
55
|
+
}
|
|
56
|
+
var GlobalOverviewPath = `${MainPrefix}overview.json`;
|
|
57
|
+
var MetaFile = "meta.json";
|
|
58
|
+
var PlRegAddress = z.string().regex(/^(?:s3:|file:)/);
|
|
59
|
+
var PlPackageConfigData = z.object({
|
|
60
|
+
organization: z.string(),
|
|
61
|
+
package: z.string(),
|
|
62
|
+
version: SemVer.optional(),
|
|
63
|
+
files: z.record(z.string().regex(/^[^\/]+$/), z.string()).default({}),
|
|
64
|
+
meta: z.object({}).passthrough()
|
|
65
|
+
});
|
|
66
|
+
var PlRegCommonConfigData = z.object({
|
|
67
|
+
registries: z.record(z.string(), PlRegAddress).default({}),
|
|
68
|
+
registry: z.string().optional()
|
|
69
|
+
});
|
|
70
|
+
var PlRegFullPackageConfigData = PlRegCommonConfigData.merge(PlPackageConfigData).required(
|
|
71
|
+
{ registry: true, version: true }
|
|
72
|
+
);
|
|
73
|
+
var PlRegPackageConfigDataShard = PlRegFullPackageConfigData.partial().required({
|
|
74
|
+
registries: true,
|
|
75
|
+
files: true
|
|
76
|
+
});
|
|
77
|
+
var PlPackageJsonConfigFile = "pl.package.json";
|
|
78
|
+
var PlPackageYamlConfigFile = "pl.package.yaml";
|
|
79
|
+
async function tryLoadFile(file, map) {
|
|
80
|
+
try {
|
|
81
|
+
return map(await fsp2.readFile(file));
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (err.code == "ENOENT") return void 0;
|
|
84
|
+
else throw new Error("", { cause: err });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
var VersionUpdatesPrefix = "_updates_v1/per_package_version/";
|
|
88
|
+
function packageUpdatePath(bp, seed) {
|
|
89
|
+
return `${VersionUpdatesPrefix}${bp.organization}/${bp.package}/${bp.version}/${seed}`;
|
|
90
|
+
}
|
|
91
|
+
var PackageUpdatePattern = /(?<packageKeyWithoutVersion>(?<organization>[^\/]+)\/(?<pkg>[^\/]+))\/(?<version>[^\/]+)\/(?<seed>[^\/]+)$/;
|
|
92
|
+
var GlobalUpdateSeedInFile = "_updates_v1/_global_update_in";
|
|
93
|
+
var GlobalUpdateSeedOutFile = "_updates_v1/_global_update_out";
|
|
94
|
+
var BlockRegistry = class {
|
|
95
|
+
constructor(storage, logger) {
|
|
96
|
+
this.storage = storage;
|
|
97
|
+
this.logger = logger;
|
|
98
|
+
}
|
|
99
|
+
constructNewPackage(pack) {
|
|
100
|
+
return new BlockRegistryPackConstructor(this.storage, pack);
|
|
101
|
+
}
|
|
102
|
+
async updateRegistry() {
|
|
103
|
+
this.logger?.info("Initiating registry refresh...");
|
|
104
|
+
const packagesToUpdate = /* @__PURE__ */ new Map();
|
|
105
|
+
const seedPaths = [];
|
|
106
|
+
const rawSeedPaths = await this.storage.listFiles(VersionUpdatesPrefix);
|
|
107
|
+
this.logger?.info("Packages to be updated:");
|
|
108
|
+
for (const seedPath of rawSeedPaths) {
|
|
109
|
+
const match = seedPath.match(PackageUpdatePattern);
|
|
110
|
+
if (!match) continue;
|
|
111
|
+
seedPaths.push(seedPath);
|
|
112
|
+
const { packageKeyWithoutVersion, organization, pkg, version, seed } = match.groups;
|
|
113
|
+
let update = packagesToUpdate.get(packageKeyWithoutVersion);
|
|
114
|
+
if (!update) {
|
|
115
|
+
packagesToUpdate.set(packageKeyWithoutVersion, {
|
|
116
|
+
package: { organization, package: pkg },
|
|
117
|
+
versions: /* @__PURE__ */ new Set([version])
|
|
118
|
+
});
|
|
119
|
+
} else if (!update.versions.has(version)) {
|
|
120
|
+
update.versions.add(version);
|
|
121
|
+
}
|
|
122
|
+
this.logger?.info(` - ${organization}:${pkg}:${version}`);
|
|
123
|
+
}
|
|
124
|
+
const overviewContent = await this.storage.getFile(GlobalOverviewPath);
|
|
125
|
+
let overview = overviewContent === void 0 ? [] : JSON.parse(overviewContent.toString());
|
|
126
|
+
this.logger?.info(`Global overview loaded, ${overview.length} records`);
|
|
127
|
+
for (const [, packageInfo] of packagesToUpdate.entries()) {
|
|
128
|
+
const overviewFile = packageOverviewPath(packageInfo.package);
|
|
129
|
+
const pOverviewContent = await this.storage.getFile(overviewFile);
|
|
130
|
+
let packageOverview = pOverviewContent === void 0 ? [] : JSON.parse(pOverviewContent.toString());
|
|
131
|
+
this.logger?.info(
|
|
132
|
+
`Updating ${packageInfo.package.organization}:${packageInfo.package.package} overview, ${packageOverview.length} records`
|
|
133
|
+
);
|
|
134
|
+
packageOverview = packageOverview.filter((e) => !packageInfo.versions.has(e.version));
|
|
135
|
+
for (const [v] of packageInfo.versions.entries()) {
|
|
136
|
+
const version = v.toString();
|
|
137
|
+
const metaContent = await this.storage.getFile(
|
|
138
|
+
payloadFilePath(
|
|
139
|
+
{
|
|
140
|
+
...packageInfo.package,
|
|
141
|
+
version
|
|
142
|
+
},
|
|
143
|
+
MetaFile
|
|
144
|
+
)
|
|
145
|
+
);
|
|
146
|
+
if (!metaContent) continue;
|
|
147
|
+
packageOverview.push({ version, meta: JSON.parse(metaContent.toString()) });
|
|
148
|
+
}
|
|
149
|
+
packageOverview.sort((e1, e2) => semver.compare(e2.version, e1.version));
|
|
150
|
+
await this.storage.putFile(overviewFile, Buffer.from(JSON.stringify(packageOverview)));
|
|
151
|
+
this.logger?.info(`Done (${packageOverview.length} records)`);
|
|
152
|
+
overview = overview.filter(
|
|
153
|
+
(e) => e.organization !== packageInfo.package.organization || e.package !== packageInfo.package.package
|
|
154
|
+
);
|
|
155
|
+
overview.push({
|
|
156
|
+
organization: packageInfo.package.organization,
|
|
157
|
+
package: packageInfo.package.package,
|
|
158
|
+
allVersions: packageOverview.map((e) => e.version).reverse(),
|
|
159
|
+
latestVersion: packageOverview[0].version,
|
|
160
|
+
latestMeta: packageOverview[0].meta
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
await this.storage.putFile(GlobalOverviewPath, Buffer.from(JSON.stringify(overview)));
|
|
164
|
+
this.logger?.info(`Global overview updated (${overview.length} records)`);
|
|
165
|
+
await this.storage.deleteFiles(...seedPaths.map((sp) => `${VersionUpdatesPrefix}${sp}`));
|
|
166
|
+
this.logger?.info(`Version update requests cleared`);
|
|
167
|
+
}
|
|
168
|
+
async updateIfNeeded(force = false) {
|
|
169
|
+
this.logger?.info(`Checking if registry requires refresh...`);
|
|
170
|
+
const updateRequestSeed = await this.storage.getFile(GlobalUpdateSeedInFile);
|
|
171
|
+
const currentUpdatedSeed = await this.storage.getFile(GlobalUpdateSeedOutFile);
|
|
172
|
+
if (!force && updateRequestSeed === void 0 && currentUpdatedSeed === void 0) return;
|
|
173
|
+
if (!force && updateRequestSeed !== void 0 && currentUpdatedSeed !== void 0 && updateRequestSeed.equals(currentUpdatedSeed))
|
|
174
|
+
return;
|
|
175
|
+
await this.updateRegistry();
|
|
176
|
+
if (updateRequestSeed) {
|
|
177
|
+
await this.storage.putFile(GlobalUpdateSeedOutFile, updateRequestSeed);
|
|
178
|
+
this.logger?.info(`Refresh finished`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async getPackageOverview(name) {
|
|
182
|
+
const content = await this.storage.getFile(packageOverviewPath(name));
|
|
183
|
+
if (content === void 0) return void 0;
|
|
184
|
+
return JSON.parse(content.toString());
|
|
185
|
+
}
|
|
186
|
+
async getGlobalOverview() {
|
|
187
|
+
const content = await this.storage.getFile(GlobalOverviewPath);
|
|
188
|
+
if (content === void 0) return void 0;
|
|
189
|
+
return JSON.parse(content.toString());
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var BlockRegistryPackConstructor = class {
|
|
193
|
+
constructor(storage, name) {
|
|
194
|
+
this.storage = storage;
|
|
195
|
+
this.name = name;
|
|
196
|
+
}
|
|
197
|
+
metaAdded = false;
|
|
198
|
+
seed = randomUUID();
|
|
199
|
+
async addFile(file, content) {
|
|
200
|
+
await this.storage.putFile(payloadFilePath(this.name, file), content);
|
|
201
|
+
}
|
|
202
|
+
async writeMeta(meta) {
|
|
203
|
+
await this.addFile(MetaFile, Buffer.from(JSON.stringify(meta)));
|
|
204
|
+
this.metaAdded = true;
|
|
205
|
+
}
|
|
206
|
+
async finish() {
|
|
207
|
+
if (!this.metaAdded) throw new Error("meta not added");
|
|
208
|
+
await this.storage.putFile(packageUpdatePath(this.name, this.seed), Buffer.of(0));
|
|
209
|
+
await this.storage.putFile(GlobalUpdateSeedInFile, Buffer.from(this.seed));
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
var S3Storage = class {
|
|
213
|
+
constructor(client, bucket, root) {
|
|
214
|
+
this.client = client;
|
|
215
|
+
this.bucket = bucket;
|
|
216
|
+
this.root = root;
|
|
217
|
+
}
|
|
218
|
+
async getFile(file) {
|
|
219
|
+
try {
|
|
220
|
+
return Buffer.from(
|
|
221
|
+
await (await this.client.getObject({
|
|
222
|
+
Bucket: this.bucket,
|
|
223
|
+
Key: pathPosix.join(this.root, file)
|
|
224
|
+
})).Body.transformToByteArray()
|
|
225
|
+
);
|
|
226
|
+
} catch (e) {
|
|
227
|
+
if (e.name === "NoSuchKey") return void 0;
|
|
228
|
+
else throw e;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async listFiles(prefix) {
|
|
232
|
+
const listRoot = pathPosix.join(this.root, prefix);
|
|
233
|
+
const paginator = paginateListObjectsV2(
|
|
234
|
+
{ client: this.client },
|
|
235
|
+
{
|
|
236
|
+
Bucket: this.bucket,
|
|
237
|
+
Prefix: listRoot
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
const result = [];
|
|
241
|
+
for await (const page of paginator)
|
|
242
|
+
result.push(...page.Contents.map((e) => pathPosix.relative(listRoot, e.Key)));
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
async putFile(file, buffer) {
|
|
246
|
+
await this.client.putObject({
|
|
247
|
+
Bucket: this.bucket,
|
|
248
|
+
Key: pathPosix.join(this.root, file),
|
|
249
|
+
Body: buffer
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async deleteFiles(...files) {
|
|
253
|
+
const results = await this.client.deleteObjects({
|
|
254
|
+
Bucket: this.bucket,
|
|
255
|
+
Delete: {
|
|
256
|
+
Objects: files.map((file) => ({
|
|
257
|
+
Key: pathPosix.join(this.root, file)
|
|
258
|
+
}))
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
if (results.Errors !== void 0 && results.Errors.length > 0)
|
|
262
|
+
throw new Error(`Errors encountered while deleting files: ${results.Errors.join("\n")}`);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
var FSStorage = class {
|
|
266
|
+
/** Absolute path */
|
|
267
|
+
root;
|
|
268
|
+
constructor(_root) {
|
|
269
|
+
this.root = path.resolve(_root);
|
|
270
|
+
}
|
|
271
|
+
toAbsolutePath(localPath) {
|
|
272
|
+
if (pathPosix.isAbsolute(localPath)) throw new Error("absolute path");
|
|
273
|
+
return path.resolve(this.root, localPath.split(pathPosix.sep).join(path.sep));
|
|
274
|
+
}
|
|
275
|
+
async getFile(address) {
|
|
276
|
+
try {
|
|
277
|
+
return await fs.promises.readFile(this.toAbsolutePath(address));
|
|
278
|
+
} catch (err) {
|
|
279
|
+
if (err.code == "ENOENT") return void 0;
|
|
280
|
+
else throw new Error("", { cause: err });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async listFiles(prefix) {
|
|
284
|
+
try {
|
|
285
|
+
const listRoot = this.toAbsolutePath(prefix);
|
|
286
|
+
return (await fs.promises.readdir(listRoot, { recursive: true, withFileTypes: true })).filter((e) => e.isFile()).map(
|
|
287
|
+
(e) => path.relative(listRoot, path.resolve(e.path, e.name)).split(path.sep).join(pathPosix.sep)
|
|
288
|
+
);
|
|
289
|
+
} catch (err) {
|
|
290
|
+
if (err.code == "ENOENT") return [];
|
|
291
|
+
else throw new Error("", { cause: err });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
async putFile(address, buffer) {
|
|
295
|
+
const absoluteAddress = this.toAbsolutePath(address);
|
|
296
|
+
await fs.promises.mkdir(path.dirname(absoluteAddress), { recursive: true });
|
|
297
|
+
await fs.promises.writeFile(absoluteAddress, buffer);
|
|
298
|
+
}
|
|
299
|
+
async deleteFiles(...files) {
|
|
300
|
+
for (const file of files) await fs.promises.rm(this.toAbsolutePath(file));
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
function storageByUrl(address) {
|
|
304
|
+
const url = new URL(address, `file:${path.resolve(".").split(path.sep).join(pathPosix.sep)}/`);
|
|
305
|
+
switch (url.protocol) {
|
|
306
|
+
case "file:":
|
|
307
|
+
const root = path.resolve(url.pathname);
|
|
308
|
+
return new FSStorage(root);
|
|
309
|
+
case "s3:":
|
|
310
|
+
const options = {};
|
|
311
|
+
const region = url.searchParams.get("region");
|
|
312
|
+
if (region) options.region = region;
|
|
313
|
+
const bucket = url.hostname;
|
|
314
|
+
return new S3Storage(new S3(options), bucket, url.pathname.replace(/^\//, ""));
|
|
315
|
+
default:
|
|
316
|
+
throw new Error(`Unknown protocol: ${url.protocol}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/registry_v1/config.ts
|
|
321
|
+
var PlRegPackageConfig = class {
|
|
322
|
+
constructor(conf) {
|
|
323
|
+
this.conf = conf;
|
|
324
|
+
}
|
|
325
|
+
createRegistry(logger) {
|
|
326
|
+
let address = this.conf.registry;
|
|
327
|
+
if (!address.startsWith("file:") && !address.startsWith("s3:")) {
|
|
328
|
+
const regByAlias = this.conf.registries[address];
|
|
329
|
+
if (!regByAlias) throw new Error(`Registry with alias "${address}" not found`);
|
|
330
|
+
address = regByAlias;
|
|
331
|
+
}
|
|
332
|
+
return new BlockRegistry(storageByUrl(address), logger);
|
|
333
|
+
}
|
|
334
|
+
get fullPackageName() {
|
|
335
|
+
return {
|
|
336
|
+
organization: this.conf.organization,
|
|
337
|
+
package: this.conf.package,
|
|
338
|
+
version: this.conf.version
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
function tryResolve(root, request) {
|
|
343
|
+
try {
|
|
344
|
+
return __require.resolve(request, {
|
|
345
|
+
paths: [root]
|
|
346
|
+
});
|
|
347
|
+
} catch (err) {
|
|
348
|
+
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
|
349
|
+
}
|
|
350
|
+
return void 0;
|
|
351
|
+
}
|
|
352
|
+
function ResolvedModuleFile(moduleRoot) {
|
|
353
|
+
return z.string().transform((request, ctx) => {
|
|
354
|
+
const result = tryResolve(moduleRoot, request);
|
|
355
|
+
if (result === void 0) {
|
|
356
|
+
ctx.addIssue({
|
|
357
|
+
code: z.ZodIssueCode.custom,
|
|
358
|
+
message: `Can't resolve ${request} against ${moduleRoot}`
|
|
359
|
+
});
|
|
360
|
+
return z.NEVER;
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
type: "absolute-file",
|
|
364
|
+
file: result
|
|
365
|
+
};
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function ResolvedModuleFolder(moduleRoot, ...indexFilesToLookFor) {
|
|
369
|
+
return z.string().transform((request, ctx) => {
|
|
370
|
+
const requestWithSlash = request.endsWith("/") ? request : `${request}/`;
|
|
371
|
+
for (const idxFile of indexFilesToLookFor) {
|
|
372
|
+
const result = tryResolve(moduleRoot, requestWithSlash + idxFile);
|
|
373
|
+
if (result !== void 0) {
|
|
374
|
+
if (!result.endsWith(idxFile))
|
|
375
|
+
throw new Error(`Unexpected resolve result ${result} with index file ${idxFile}`);
|
|
376
|
+
return {
|
|
377
|
+
type: "absolute-folder",
|
|
378
|
+
folder: result.slice(0, result.length - idxFile.length)
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
ctx.addIssue({
|
|
383
|
+
code: z.ZodIssueCode.custom,
|
|
384
|
+
message: `Can't resolve ${request} folder against ${moduleRoot}, no index file found (${indexFilesToLookFor.join(", ")})`
|
|
385
|
+
});
|
|
386
|
+
return z.NEVER;
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
function mapLocalToAbsolute(root) {
|
|
390
|
+
return (value) => value.type === "relative" ? { type: "absolute-file", file: path2.resolve(root, value.path) } : value;
|
|
391
|
+
}
|
|
392
|
+
function absoluteToString() {
|
|
393
|
+
return async (value) => {
|
|
394
|
+
if (value.type === "absolute-file")
|
|
395
|
+
return await fsp2.readFile(value.file, { encoding: "utf-8" });
|
|
396
|
+
else return value.content;
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function absoluteToBase64() {
|
|
400
|
+
return async (value) => {
|
|
401
|
+
if (value.type === "absolute-file") {
|
|
402
|
+
const mimeType = mime.lookup(value.file);
|
|
403
|
+
if (!mimeType) throw new Error(`Can't recognize mime type of the file: ${value.file}.`);
|
|
404
|
+
return {
|
|
405
|
+
type: "explicit-base64",
|
|
406
|
+
mimeType,
|
|
407
|
+
content: await fsp2.readFile(value.file, { encoding: "base64" })
|
|
408
|
+
};
|
|
409
|
+
} else return value;
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function cpAbsoluteToRelative(dstFolder, fileAccumulator) {
|
|
413
|
+
return async (value) => {
|
|
414
|
+
if (value.type === "absolute-file") {
|
|
415
|
+
const fileName = path2.basename(value.file);
|
|
416
|
+
const dst = path2.resolve(dstFolder, fileName);
|
|
417
|
+
fileAccumulator?.push(fileName);
|
|
418
|
+
await fsp2.cp(value.file, dst);
|
|
419
|
+
return { type: "relative", path: fileName };
|
|
420
|
+
} else return value;
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function packFolderToRelativeTgz(dstFolder, tgzName, fileAccumulator) {
|
|
424
|
+
if (!tgzName.endsWith(".tgz")) throw new Error(`Unexpected tgz file name: ${tgzName}`);
|
|
425
|
+
return async (value) => {
|
|
426
|
+
const dst = path2.resolve(dstFolder, tgzName);
|
|
427
|
+
await tar.create(
|
|
428
|
+
{
|
|
429
|
+
gzip: true,
|
|
430
|
+
file: dst,
|
|
431
|
+
cwd: value.folder
|
|
432
|
+
},
|
|
433
|
+
[value.folder]
|
|
434
|
+
);
|
|
435
|
+
fileAccumulator?.push(tgzName);
|
|
436
|
+
return { type: "relative", path: tgzName };
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function mapRemoteToAbsolute(rootUrl) {
|
|
440
|
+
const rootWithSlash = rootUrl.endsWith("/") ? rootUrl : `${rootUrl}/`;
|
|
441
|
+
return (value) => value.type === "relative" ? { type: "absolute-url", url: rootWithSlash + value.path } : value;
|
|
442
|
+
}
|
|
443
|
+
function BlockComponentsDescription(moduleRoot) {
|
|
444
|
+
return BlockComponents(
|
|
445
|
+
ResolvedModuleFile(moduleRoot),
|
|
446
|
+
ResolvedModuleFolder(moduleRoot, "index.html")
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
function BlockComponentsConsolidate(dstFolder, fileAccumulator) {
|
|
450
|
+
return BlockComponents(
|
|
451
|
+
ContentAbsoluteBinaryLocal.transform(cpAbsoluteToRelative(dstFolder, fileAccumulator)),
|
|
452
|
+
ContentAbsoluteFolder.transform(packFolderToRelativeTgz(dstFolder, "ui.tgz", fileAccumulator))
|
|
453
|
+
).pipe(BlockComponentsManifest);
|
|
454
|
+
}
|
|
455
|
+
function BlockComponentsAbsoluteUrl(prefix) {
|
|
456
|
+
return BlockComponents(
|
|
457
|
+
ContentRelativeBinary.transform(mapRemoteToAbsolute(prefix)),
|
|
458
|
+
ContentRelativeBinary.transform(mapRemoteToAbsolute(prefix))
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
function BlockPackMetaDescription(root) {
|
|
462
|
+
return BlockPackMeta(
|
|
463
|
+
DescriptionContentText.transform(mapLocalToAbsolute(root)),
|
|
464
|
+
DescriptionContentBinary.transform(mapLocalToAbsolute(root))
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
function BlockPackMetaConsolidate(dstFolder, fileAccumulator) {
|
|
468
|
+
return BlockPackMeta(
|
|
469
|
+
ContentAbsoluteTextLocal.transform(cpAbsoluteToRelative(dstFolder, fileAccumulator)),
|
|
470
|
+
ContentAbsoluteBinaryLocal.transform(cpAbsoluteToRelative(dstFolder, fileAccumulator))
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
BlockPackMeta(
|
|
474
|
+
ContentAbsoluteTextLocal.transform(absoluteToString()),
|
|
475
|
+
ContentAbsoluteBinaryLocal.transform(absoluteToBase64())
|
|
476
|
+
).pipe(BlockPackMetaEmbeddedContent);
|
|
477
|
+
|
|
478
|
+
// src/v2/model/index.ts
|
|
479
|
+
function ResolvedBlockPackDescriptionFromPackageJson(root) {
|
|
480
|
+
return CreateBlockPackDescriptionSchema(
|
|
481
|
+
BlockComponentsDescription(root),
|
|
482
|
+
BlockPackMetaDescription(root)
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
function BlockPackDescriptionConsolidateToFolder(dstFolder, fileAccumulator) {
|
|
486
|
+
return CreateBlockPackDescriptionSchema(
|
|
487
|
+
BlockComponentsConsolidate(dstFolder, fileAccumulator),
|
|
488
|
+
//BlockPackMetaToExplicit
|
|
489
|
+
BlockPackMetaConsolidate(dstFolder, fileAccumulator)
|
|
490
|
+
).pipe(BlockPackDescriptionManifest);
|
|
491
|
+
}
|
|
492
|
+
var BlockPackDescriptionManifest = CreateBlockPackDescriptionSchema(
|
|
493
|
+
BlockComponentsManifest,
|
|
494
|
+
BlockPackMetaManifest
|
|
495
|
+
);
|
|
496
|
+
var BlockPackManifest = BlockPackDescriptionManifest.extend({
|
|
497
|
+
schema: z.literal("v1"),
|
|
498
|
+
files: z.array(z.string())
|
|
499
|
+
});
|
|
500
|
+
var BlockPackManifestFile = "manifest.json";
|
|
501
|
+
async function buildBlockPackDist(description, dst) {
|
|
502
|
+
await fsp2.mkdir(dst, { recursive: true });
|
|
503
|
+
const files = [];
|
|
504
|
+
const descriptionRelative = await BlockPackDescriptionConsolidateToFolder(dst, files).parseAsync(
|
|
505
|
+
description
|
|
506
|
+
);
|
|
507
|
+
const manifest = BlockPackManifest.parse({
|
|
508
|
+
schema: "v1",
|
|
509
|
+
...descriptionRelative,
|
|
510
|
+
files
|
|
511
|
+
});
|
|
512
|
+
await fsp2.writeFile(path.resolve(dst, BlockPackManifestFile), JSON.stringify(manifest));
|
|
513
|
+
return manifest;
|
|
514
|
+
}
|
|
515
|
+
var BlockDescriptionPackageJsonField = "block";
|
|
516
|
+
var ConventionPackageNamePattern = /(?:@[a-zA-Z0-9-.]+\/)?(?<organization>[a-zA-Z0-9-]+)\.(?<name>[a-zA-Z0-9-]+)/;
|
|
517
|
+
function parsePackageName(packageName) {
|
|
518
|
+
const match = packageName.match(ConventionPackageNamePattern);
|
|
519
|
+
if (!match)
|
|
520
|
+
throw new Error(
|
|
521
|
+
`Malformed package name (${packageName}), can't infer organization and block pack name.`
|
|
522
|
+
);
|
|
523
|
+
const { name, organization } = match.groups;
|
|
524
|
+
return { name, organization };
|
|
525
|
+
}
|
|
526
|
+
async function tryLoadPackDescription(moduleRoot) {
|
|
527
|
+
const fullPackageJsonPath = path2.resolve(moduleRoot, "package.json");
|
|
528
|
+
try {
|
|
529
|
+
const packageJson = await tryLoadFile(
|
|
530
|
+
fullPackageJsonPath,
|
|
531
|
+
(buf) => JSON.parse(buf.toString("utf-8"))
|
|
532
|
+
);
|
|
533
|
+
if (packageJson === void 0) return void 0;
|
|
534
|
+
const descriptionNotParsed = packageJson[BlockDescriptionPackageJsonField];
|
|
535
|
+
if (descriptionNotParsed === void 0) return void 0;
|
|
536
|
+
const descriptionRaw = {
|
|
537
|
+
...BlockPackDescriptionFromPackageJsonRaw.parse(descriptionNotParsed),
|
|
538
|
+
id: {
|
|
539
|
+
...parsePackageName(
|
|
540
|
+
notEmpty(packageJson["name"], `"name" not found in ${fullPackageJsonPath}`)
|
|
541
|
+
),
|
|
542
|
+
version: SemVer.parse(packageJson["version"])
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
const descriptionParsingResult = await ResolvedBlockPackDescriptionFromPackageJson(moduleRoot).safeParseAsync(descriptionRaw);
|
|
546
|
+
if (descriptionParsingResult.success) return descriptionParsingResult.data;
|
|
547
|
+
return void 0;
|
|
548
|
+
} catch (e) {
|
|
549
|
+
return void 0;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
async function loadPackDescriptionRaw(moduleRoot) {
|
|
553
|
+
const fullPackageJsonPath = path2.resolve(moduleRoot, "package.json");
|
|
554
|
+
const packageJson = JSON.parse(await fsp2.readFile(fullPackageJsonPath, { encoding: "utf-8" }));
|
|
555
|
+
const descriptionNotParsed = packageJson[BlockDescriptionPackageJsonField];
|
|
556
|
+
if (descriptionNotParsed === void 0)
|
|
557
|
+
throw new Error(
|
|
558
|
+
`Block description (field ${BlockDescriptionPackageJsonField}) not found in ${fullPackageJsonPath}.`
|
|
559
|
+
);
|
|
560
|
+
return {
|
|
561
|
+
...BlockPackDescriptionFromPackageJsonRaw.parse(descriptionNotParsed),
|
|
562
|
+
id: {
|
|
563
|
+
...parsePackageName(
|
|
564
|
+
notEmpty(packageJson["name"], `"name" not found in ${fullPackageJsonPath}`)
|
|
565
|
+
),
|
|
566
|
+
version: SemVer.parse(packageJson["version"])
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
async function loadPackDescription(moduleRoot) {
|
|
571
|
+
const descriptionRaw = await loadPackDescriptionRaw(moduleRoot);
|
|
572
|
+
return await ResolvedBlockPackDescriptionFromPackageJson(moduleRoot).parseAsync(descriptionRaw);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
export { BlockComponentsAbsoluteUrl, BlockComponentsConsolidate, BlockComponentsDescription, BlockDescriptionPackageJsonField, BlockPackDescriptionConsolidateToFolder, BlockPackDescriptionManifest, BlockPackManifest, BlockPackManifestFile, registry_v1_exports as RegistryV1, ResolvedBlockPackDescriptionFromPackageJson, ResolvedModuleFile, ResolvedModuleFolder, absoluteToBase64, absoluteToString, buildBlockPackDist, cpAbsoluteToRelative, loadPackDescription, loadPackDescriptionRaw, mapLocalToAbsolute, mapRemoteToAbsolute, packFolderToRelativeTgz, parsePackageName, tryLoadPackDescription };
|
|
576
|
+
//# sourceMappingURL=lib.js.map
|
|
577
|
+
//# sourceMappingURL=lib.js.map
|