@platforma-sdk/block-tools 2.1.11 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cli.mjs +113 -71
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/cmd/index.d.ts +2 -0
  6. package/dist/cmd/index.d.ts.map +1 -1
  7. package/dist/cmd/publish.d.ts +11 -0
  8. package/dist/cmd/publish.d.ts.map +1 -0
  9. package/dist/config-B1U40s2a.js +3 -0
  10. package/dist/config-B1U40s2a.js.map +1 -0
  11. package/dist/config-YukCegnp.mjs +1587 -0
  12. package/dist/config-YukCegnp.mjs.map +1 -0
  13. package/dist/index.js +1 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +170 -38
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/io/folder_reader.d.ts +24 -0
  18. package/dist/io/folder_reader.d.ts.map +1 -0
  19. package/dist/io/index.d.ts +3 -0
  20. package/dist/io/index.d.ts.map +1 -0
  21. package/dist/io/storage.d.ts.map +1 -0
  22. package/dist/lib.d.ts +1 -0
  23. package/dist/lib.d.ts.map +1 -1
  24. package/dist/registry_v1/config_schema.d.ts +13 -13
  25. package/dist/registry_v1/registry.d.ts +1 -1
  26. package/dist/registry_v1/registry.d.ts.map +1 -1
  27. package/dist/registry_v1/v1_repo_schema.d.ts +1 -1
  28. package/dist/registry_v1/v1_repo_schema.d.ts.map +1 -1
  29. package/dist/v2/build_dist.d.ts +2 -1
  30. package/dist/v2/build_dist.d.ts.map +1 -1
  31. package/dist/v2/index.d.ts +1 -0
  32. package/dist/v2/index.d.ts.map +1 -1
  33. package/dist/v2/model/block_components.d.ts +170 -178
  34. package/dist/v2/model/block_components.d.ts.map +1 -1
  35. package/dist/v2/model/block_description.d.ts +2873 -0
  36. package/dist/v2/model/block_description.d.ts.map +1 -0
  37. package/dist/v2/model/{meta.d.ts → block_meta.d.ts} +555 -3
  38. package/dist/v2/model/block_meta.d.ts.map +1 -0
  39. package/dist/v2/model/content_conversion.d.ts +7 -2
  40. package/dist/v2/model/content_conversion.d.ts.map +1 -1
  41. package/dist/v2/model/index.d.ts +3 -2079
  42. package/dist/v2/model/index.d.ts.map +1 -1
  43. package/dist/v2/registry/index.d.ts +4 -0
  44. package/dist/v2/registry/index.d.ts.map +1 -0
  45. package/dist/v2/registry/registry.d.ts +16 -0
  46. package/dist/v2/registry/registry.d.ts.map +1 -0
  47. package/dist/v2/registry/registry_reader.d.ts +12 -0
  48. package/dist/v2/registry/registry_reader.d.ts.map +1 -0
  49. package/dist/v2/registry/schema_internal.d.ts +7 -0
  50. package/dist/v2/registry/schema_internal.d.ts.map +1 -0
  51. package/dist/v2/registry/schema_public.d.ts +4499 -0
  52. package/dist/v2/registry/schema_public.d.ts.map +1 -0
  53. package/package.json +8 -5
  54. package/src/cmd/build-meta.ts +2 -2
  55. package/src/cmd/index.ts +2 -0
  56. package/src/cmd/publish.ts +69 -0
  57. package/src/io/folder_reader.test.ts +21 -0
  58. package/src/io/folder_reader.ts +77 -0
  59. package/src/io/index.ts +2 -0
  60. package/src/lib.ts +1 -0
  61. package/src/registry_v1/config.ts +1 -1
  62. package/src/registry_v1/registry.test.ts +1 -1
  63. package/src/registry_v1/registry.ts +1 -1
  64. package/src/registry_v1/v1_repo_schema.ts +1 -1
  65. package/src/v2/build_dist.ts +16 -12
  66. package/src/v2/index.ts +1 -0
  67. package/src/v2/model/block_components.ts +14 -10
  68. package/src/v2/model/block_description.ts +49 -0
  69. package/src/v2/model/{meta.ts → block_meta.ts} +23 -5
  70. package/src/v2/model/content_conversion.ts +78 -10
  71. package/src/v2/model/index.ts +3 -44
  72. package/src/v2/registry/index.ts +3 -0
  73. package/src/v2/registry/registry.ts +240 -0
  74. package/src/v2/registry/registry_reader.ts +71 -0
  75. package/src/v2/registry/schema_internal.ts +13 -0
  76. package/src/v2/registry/schema_public.ts +112 -0
  77. package/dist/config-Br5DwFuM.mjs +0 -1317
  78. package/dist/config-Br5DwFuM.mjs.map +0 -1
  79. package/dist/config-DMAm68Pm.js +0 -3
  80. package/dist/config-DMAm68Pm.js.map +0 -1
  81. package/dist/lib/storage.d.ts.map +0 -1
  82. package/dist/v2/model/common.d.ts +0 -3
  83. package/dist/v2/model/common.d.ts.map +0 -1
  84. package/dist/v2/model/content_types.d.ts +0 -478
  85. package/dist/v2/model/content_types.d.ts.map +0 -1
  86. package/dist/v2/model/meta.d.ts.map +0 -1
  87. package/dist/v2/registry/schema.d.ts +0 -15
  88. package/dist/v2/registry/schema.d.ts.map +0 -1
  89. package/src/v2/model/common.ts +0 -2
  90. package/src/v2/model/content_types.ts +0 -233
  91. package/src/v2/registry/schema.ts +0 -29
  92. /package/dist/{lib → io}/storage.d.ts +0 -0
  93. /package/src/{lib → io}/storage.test.ts +0 -0
  94. /package/src/{lib → io}/storage.ts +0 -0
@@ -0,0 +1,240 @@
1
+ import { MiLogger } from '@milaboratories/ts-helpers';
2
+ import { compare as compareSemver, satisfies } from 'semver';
3
+ import { RegistryStorage } from '../../io/storage';
4
+ import { BlockPackIdNoVersion, BlockPackManifest } from '@milaboratories/pl-model-middle-layer';
5
+ import {
6
+ GlobalUpdateSeedInFile,
7
+ GlobalUpdateSeedOutFile,
8
+ PackageUpdatePattern,
9
+ packageUpdateSeedPath,
10
+ VersionUpdatesPrefix
11
+ } from './schema_internal';
12
+ import {
13
+ GlobalOverviewReg,
14
+ GlobalOverviewPath,
15
+ ManifestSuffix,
16
+ packageContentPrefix,
17
+ PackageOverview,
18
+ packageOverviewPath,
19
+ ManifestFileName
20
+ } from './schema_public';
21
+ import { BlockPackDescriptionManifestAddRelativePathPrefix, RelativeContentReader } from '../model';
22
+ import { randomUUID } from 'node:crypto';
23
+
24
+ type PackageUpdateInfo = {
25
+ package: BlockPackIdNoVersion;
26
+ versions: Set<String>;
27
+ };
28
+
29
+ export class BlockRegistryV2 {
30
+ constructor(
31
+ private readonly storage: RegistryStorage,
32
+ private readonly logger?: MiLogger
33
+ ) {}
34
+
35
+ private async updateRegistry() {
36
+ this.logger?.info('Initiating registry refresh...');
37
+
38
+ // reading update requests
39
+ const packagesToUpdate = new Map<string, PackageUpdateInfo>();
40
+ const seedPaths: string[] = [];
41
+ const rawSeedPaths = await this.storage.listFiles(VersionUpdatesPrefix);
42
+ this.logger?.info('Packages to be updated:');
43
+ for (const seedPath of rawSeedPaths) {
44
+ const match = seedPath.match(PackageUpdatePattern);
45
+ if (!match) continue;
46
+ seedPaths.push(seedPath);
47
+ const { packageKeyWithoutVersion, organization, name, version, seed } = match.groups!;
48
+
49
+ let update = packagesToUpdate.get(packageKeyWithoutVersion);
50
+ let added = false;
51
+ if (!update) {
52
+ packagesToUpdate.set(packageKeyWithoutVersion, {
53
+ package: { organization, name },
54
+ versions: new Set([version])
55
+ });
56
+ added = true;
57
+ } else if (!update.versions.has(version)) {
58
+ update.versions.add(version);
59
+ added = true;
60
+ }
61
+ this.logger?.info(` - ${organization}:${name}:${version} added:${added}`);
62
+ }
63
+
64
+ // loading global overview
65
+ const overviewContent = await this.storage.getFile(GlobalOverviewPath);
66
+ const overview: GlobalOverviewReg =
67
+ overviewContent === undefined
68
+ ? { schema: 'v2', packages: [] }
69
+ : GlobalOverviewReg.parse(JSON.parse(overviewContent.toString()));
70
+ let overviewPackages = overview.packages;
71
+ this.logger?.info(`Global overview loaded, ${overviewPackages.length} records`);
72
+
73
+ // updating packages
74
+ for (const [, packageInfo] of packagesToUpdate.entries()) {
75
+ // reading existing overview
76
+ const overviewFile = packageOverviewPath(packageInfo.package);
77
+ const pOverviewContent = await this.storage.getFile(overviewFile);
78
+ const packageOverview: PackageOverview =
79
+ pOverviewContent === undefined
80
+ ? { schema: 'v2', versions: [] }
81
+ : PackageOverview.parse(JSON.parse(pOverviewContent.toString()));
82
+ this.logger?.info(
83
+ `Updating ${packageInfo.package.organization}:${packageInfo.package.name} overview, ${packageOverview.versions.length} records`
84
+ );
85
+
86
+ // removing versions that we will update
87
+ const newVersions = packageOverview.versions.filter(
88
+ (e) => !packageInfo.versions.has(e.description.id.version)
89
+ );
90
+
91
+ // reading new entries
92
+ for (const [v] of packageInfo.versions.entries()) {
93
+ const version = v.toString();
94
+ const manifestContent = await this.storage.getFile(
95
+ packageContentPrefix({
96
+ ...packageInfo.package,
97
+ version
98
+ }) + ManifestSuffix
99
+ );
100
+ if (!manifestContent) continue; // absent package
101
+ const sha256 = Buffer.from(await crypto.subtle.digest('sha-256', manifestContent))
102
+ .toString('hex')
103
+ .toUpperCase();
104
+ newVersions.push({
105
+ description: BlockPackDescriptionManifestAddRelativePathPrefix(version).parse(
106
+ BlockPackManifest.parse(JSON.parse(manifestContent.toString('utf8'))).description
107
+ ),
108
+ manifestSha256: sha256
109
+ });
110
+ }
111
+
112
+ // sorting entries according to version
113
+ newVersions.sort((e1, e2) =>
114
+ compareSemver(e2.description.id.version, e1.description.id.version)
115
+ );
116
+
117
+ // write package overview back
118
+ await this.storage.putFile(
119
+ overviewFile,
120
+ Buffer.from(
121
+ JSON.stringify({ schema: 'v2', versions: newVersions } satisfies PackageOverview)
122
+ )
123
+ );
124
+ this.logger?.info(`Done (${newVersions.length} records)`);
125
+
126
+ // patching corresponding entry in overview
127
+ overviewPackages = overviewPackages.filter(
128
+ (e) =>
129
+ e.id.organization !== packageInfo.package.organization ||
130
+ e.id.name !== packageInfo.package.name
131
+ );
132
+ overviewPackages.push({
133
+ id: {
134
+ organization: packageInfo.package.organization,
135
+ name: packageInfo.package.name
136
+ },
137
+ allVersions: newVersions.map((e) => e.description.id.version).reverse(),
138
+ latest: BlockPackDescriptionManifestAddRelativePathPrefix(
139
+ `${packageInfo.package.organization}/${packageInfo.package.name}`
140
+ ).parse(newVersions[0].description),
141
+ latestManifestSha256: newVersions[0].manifestSha256
142
+ });
143
+ }
144
+
145
+ // writing global overview
146
+ await this.storage.putFile(
147
+ GlobalOverviewPath,
148
+ Buffer.from(
149
+ JSON.stringify({ schema: 'v2', packages: overviewPackages } satisfies GlobalOverviewReg)
150
+ )
151
+ );
152
+ this.logger?.info(`Global overview updated (${overviewPackages.length} records)`);
153
+
154
+ // deleting seeds
155
+ await this.storage.deleteFiles(...seedPaths.map((sp) => `${VersionUpdatesPrefix}${sp}`));
156
+ this.logger?.info(`Version update requests cleared`);
157
+ }
158
+
159
+ public async updateIfNeeded(force: boolean = false): Promise<void> {
160
+ // implementation of main convergence algorithm
161
+
162
+ this.logger?.info(`Checking if registry requires refresh...`);
163
+ const updateRequestSeed = await this.storage.getFile(GlobalUpdateSeedInFile);
164
+ const currentUpdatedSeed = await this.storage.getFile(GlobalUpdateSeedOutFile);
165
+ if (!force && updateRequestSeed === undefined && currentUpdatedSeed === undefined) return;
166
+ if (
167
+ !force &&
168
+ updateRequestSeed !== undefined &&
169
+ currentUpdatedSeed !== undefined &&
170
+ updateRequestSeed.equals(currentUpdatedSeed)
171
+ )
172
+ return;
173
+
174
+ await this.updateRegistry();
175
+
176
+ if (updateRequestSeed) {
177
+ await this.storage.putFile(GlobalUpdateSeedOutFile, updateRequestSeed);
178
+ this.logger?.info(`Refresh finished`);
179
+ }
180
+ }
181
+
182
+ public async getPackageOverview(
183
+ name: BlockPackIdNoVersion
184
+ ): Promise<undefined | PackageOverview> {
185
+ const content = await this.storage.getFile(packageOverviewPath(name));
186
+ if (content === undefined) return undefined;
187
+ return PackageOverview.parse(JSON.parse(content.toString()));
188
+ }
189
+
190
+ public async getGlobalOverview(): Promise<undefined | GlobalOverviewReg> {
191
+ const content = await this.storage.getFile(GlobalOverviewPath);
192
+ if (content === undefined) return undefined;
193
+ return GlobalOverviewReg.parse(JSON.parse(content.toString()));
194
+ }
195
+
196
+ // public async getGlobalOverviewExplicitBytes(): Promise<undefined | GlobalOverviewReg> {
197
+ // const content = await this.storage.getFile(GlobalOverviewPath);
198
+ // if (content === undefined) return undefined;
199
+ // return GlobalOverviewReg.parse(JSON.parse(content.toString()));
200
+ // }
201
+
202
+ public async publishPackage(
203
+ manifest: BlockPackManifest,
204
+ fileReader: RelativeContentReader
205
+ ): Promise<void> {
206
+ const prefix = packageContentPrefix(manifest.description.id);
207
+ // uploading content files
208
+ for (const f of manifest.files) {
209
+ const bytes = await fileReader(f.name);
210
+ if (bytes.length !== f.size)
211
+ throw new Error(
212
+ `Actual file size don't match file size from the manifest file for ${f.name} (actual = ${bytes.length}; manifest = ${f.size})`
213
+ );
214
+ const sha256 = Buffer.from(await crypto.subtle.digest('sha-256', bytes))
215
+ .toString('hex')
216
+ .toUpperCase();
217
+ if (sha256 !== f.sha256.toUpperCase())
218
+ throw new Error(
219
+ `Actual file SHA-256 don't match the checksum from the manifest file for ${f.name} (actual = ${sha256}; manifest = ${f.sha256.toUpperCase()})`
220
+ );
221
+
222
+ const dst = prefix + '/' + f.name;
223
+ this.logger?.info(`Uploading ${f.name} -> ${dst} ...`);
224
+ await this.storage.putFile(dst, bytes);
225
+ }
226
+
227
+ // uploading manifest as the last upload action
228
+ const manifestDst = prefix + '/' + ManifestFileName;
229
+ this.logger?.info(`Uploading manifest to ${manifestDst} ...`);
230
+ await this.storage.putFile(manifestDst, Buffer.from(JSON.stringify(manifest)));
231
+
232
+ // adding update seed
233
+ const seed = randomUUID();
234
+ const seedPath = packageUpdateSeedPath(manifest.description.id, seed);
235
+ this.logger?.info(`Creating update seed at ${seedPath} ...`);
236
+ await this.storage.putFile(seedPath, Buffer.from(seed));
237
+ this.logger?.info(`Touching global update seed ${GlobalUpdateSeedInFile} ...`);
238
+ await this.storage.putFile(GlobalUpdateSeedInFile, Buffer.from(seed));
239
+ }
240
+ }
@@ -0,0 +1,71 @@
1
+ import {
2
+ BlockPackDescriptionManifest,
3
+ BlockPackMetaEmbeddedBytes,
4
+ BlockPackMetaManifest,
5
+ BlockPackOverview
6
+ } from '@milaboratories/pl-model-middle-layer';
7
+ import { FolderReader } from '../../io';
8
+ import canonicalize from 'canonicalize';
9
+ import {
10
+ GlobalOverview,
11
+ GlobalOverviewEntryReg,
12
+ GlobalOverviewFileName,
13
+ GlobalOverviewReg,
14
+ MainPrefix,
15
+ ManifestFileName
16
+ } from './schema_public';
17
+ import { BlockPackMetaEmbedBytes } from '../model';
18
+
19
+ export type BlockPackOverviewNoRegLabel = Omit<BlockPackOverview, 'registryId'>;
20
+
21
+ export class RegistryV2Reader {
22
+ private readonly metaCache = new Map<
23
+ string,
24
+ { sha256: string; meta: BlockPackMetaEmbeddedBytes }
25
+ >();
26
+
27
+ private readonly rootFolderReader: FolderReader;
28
+
29
+ constructor(
30
+ private readonly url: string,
31
+ reader: FolderReader
32
+ ) {
33
+ this.rootFolderReader = reader.relativeReader(MainPrefix);
34
+ }
35
+
36
+ private async embedMetaContent(
37
+ entry: GlobalOverviewEntryReg
38
+ ): Promise<BlockPackMetaEmbeddedBytes> {
39
+ const id = canonicalize(entry.id)!;
40
+ const fromCache = this.metaCache.get(id);
41
+ if (fromCache && fromCache.sha256 === entry.latestManifestSha256) return fromCache.meta;
42
+ const rootContentReader = this.rootFolderReader.getContentReader();
43
+ const meta = await BlockPackMetaEmbedBytes(rootContentReader).parseAsync(entry.latest.meta);
44
+ this.metaCache.set(id, { sha256: entry.latestManifestSha256, meta });
45
+ return meta;
46
+ }
47
+
48
+ public async listBlockPacks(): Promise<BlockPackOverviewNoRegLabel[]> {
49
+ const rootContentReader = this.rootFolderReader.getContentReader();
50
+ const globalOverview = GlobalOverviewReg.parse(
51
+ JSON.parse(
52
+ Buffer.from(await this.rootFolderReader.readFile(GlobalOverviewFileName)).toString()
53
+ )
54
+ );
55
+ return await Promise.all(
56
+ globalOverview.packages.map(
57
+ async (p) =>
58
+ ({
59
+ id: p.latest.id,
60
+ meta: await this.embedMetaContent(p),
61
+ spec: {
62
+ type: 'from-registry-v2',
63
+ id: p.latest.id,
64
+ registryUrl: this.url
65
+ },
66
+ otherVersions: p.allVersions
67
+ }) satisfies BlockPackOverviewNoRegLabel
68
+ )
69
+ );
70
+ }
71
+ }
@@ -0,0 +1,13 @@
1
+ import { BlockPackId } from '@milaboratories/pl-model-middle-layer';
2
+
3
+ export const VersionUpdatesPrefix = '_updates_v2/per_package_version/';
4
+
5
+ export function packageUpdateSeedPath(bp: BlockPackId, seed: string): string {
6
+ return `${VersionUpdatesPrefix}${bp.organization}/${bp.name}/${bp.version}/${seed}`;
7
+ }
8
+
9
+ export const PackageUpdatePattern =
10
+ /(?<packageKeyWithoutVersion>(?<organization>[^\/]+)\/(?<name>[^\/]+))\/(?<version>[^\/]+)\/(?<seed>[^\/]+)$/;
11
+
12
+ export const GlobalUpdateSeedInFile = '_updates_v2/_global_update_in';
13
+ export const GlobalUpdateSeedOutFile = '_updates_v2/_global_update_out';
@@ -0,0 +1,112 @@
1
+ import {
2
+ BlockComponentsManifest,
3
+ BlockPackDescriptionManifest,
4
+ BlockPackId,
5
+ BlockPackIdNoVersion,
6
+ BlockPackMeta,
7
+ ContentRelativeBinary,
8
+ ContentRelativeText,
9
+ CreateBlockPackDescriptionSchema,
10
+ SemVer,
11
+ Sha256Schema
12
+ } from '@milaboratories/pl-model-middle-layer';
13
+ import { z } from 'zod';
14
+ import { RelativeContentReader, relativeToExplicitBytes, relativeToExplicitString } from '../model';
15
+
16
+ export const MainPrefix = 'v2/';
17
+
18
+ export const GlobalOverviewFileName = 'overview.json';
19
+ export const PackageOverviewFileName = 'overview.json';
20
+ export const ManifestFileName = 'manifest.json';
21
+
22
+ export function packageContentPrefix(bp: BlockPackId): string {
23
+ return `${MainPrefix}${bp.organization}/${bp.name}/${bp.version}`;
24
+ }
25
+
26
+ export const ManifestSuffix = '/' + ManifestFileName;
27
+
28
+ // export function payloadFilePath(bp: BlockPackId, file: string): string {
29
+ // return `${MainPrefix}${bp.organization}/${bp.name}/${bp.version}/${file}`;
30
+ // }
31
+
32
+ export const PackageOverviewVersionEntry = z.object({
33
+ description: BlockPackDescriptionManifest,
34
+ manifestSha256: Sha256Schema
35
+ });
36
+ export type PackageOverviewVersionEntry = z.infer<typeof PackageOverviewVersionEntry>;
37
+
38
+ export const PackageOverview = z.object({
39
+ schema: z.literal('v2'),
40
+ versions: z.array(PackageOverviewVersionEntry)
41
+ });
42
+ export type PackageOverview = z.infer<typeof PackageOverview>;
43
+
44
+ export function packageOverviewPath(bp: BlockPackIdNoVersion): string {
45
+ return `${MainPrefix}${bp.organization}/${bp.name}/${PackageOverviewFileName}`;
46
+ }
47
+
48
+ export const GlobalOverviewPath = `${MainPrefix}${GlobalOverviewFileName}`;
49
+
50
+ export function GlobalOverviewEntry<const Description extends z.ZodTypeAny>(
51
+ descriptionType: Description
52
+ ) {
53
+ return z.object({
54
+ id: BlockPackIdNoVersion,
55
+ allVersions: z.array(z.string()),
56
+ latest: descriptionType,
57
+ latestManifestSha256: Sha256Schema
58
+ });
59
+ }
60
+ export const GlobalOverviewEntryReg = GlobalOverviewEntry(BlockPackDescriptionManifest);
61
+ export type GlobalOverviewEntryReg = z.infer<typeof GlobalOverviewEntryReg>;
62
+
63
+ export function GlobalOverview<const Description extends z.ZodTypeAny>(
64
+ descriptionType: Description
65
+ ) {
66
+ return z.object({
67
+ schema: z.literal('v2'),
68
+ packages: z.array(GlobalOverviewEntry(descriptionType))
69
+ });
70
+ }
71
+
72
+ export const GlobalOverviewReg = GlobalOverview(BlockPackDescriptionManifest);
73
+ export type GlobalOverviewReg = z.infer<typeof GlobalOverviewReg>;
74
+
75
+ export function BlockDescriptionToExplicitBinaryBytes(reader: RelativeContentReader) {
76
+ return CreateBlockPackDescriptionSchema(
77
+ BlockComponentsManifest,
78
+ BlockPackMeta(
79
+ ContentRelativeText.transform(relativeToExplicitString(reader)),
80
+ ContentRelativeBinary.transform(relativeToExplicitBytes(reader))
81
+ )
82
+ );
83
+ }
84
+ export function GlobalOverviewToExplicitBinaryBytes(reader: RelativeContentReader) {
85
+ return GlobalOverview(
86
+ CreateBlockPackDescriptionSchema(
87
+ BlockComponentsManifest,
88
+ BlockPackMeta(
89
+ ContentRelativeText.transform(relativeToExplicitString(reader)),
90
+ ContentRelativeBinary.transform(relativeToExplicitBytes(reader))
91
+ )
92
+ )
93
+ );
94
+ }
95
+ export type GlobalOverviewExplicitBinaryBytes = z.infer<
96
+ ReturnType<typeof GlobalOverviewToExplicitBinaryBytes>
97
+ >;
98
+
99
+ export function GlobalOverviewToExplicitBinaryBase64(reader: RelativeContentReader) {
100
+ return GlobalOverview(
101
+ CreateBlockPackDescriptionSchema(
102
+ BlockComponentsManifest,
103
+ BlockPackMeta(
104
+ ContentRelativeText.transform(relativeToExplicitString(reader)),
105
+ ContentRelativeBinary.transform(relativeToExplicitBytes(reader))
106
+ )
107
+ )
108
+ );
109
+ }
110
+ export type GlobalOverviewExplicitBinaryBase64 = z.infer<
111
+ ReturnType<typeof GlobalOverviewToExplicitBinaryBase64>
112
+ >;