Skip to content

Commit 5f79b07

Browse files
committed
feat: enhance registry management with schema validation and improved error handling
1 parent 6df206e commit 5f79b07

4 files changed

Lines changed: 84 additions & 16 deletions

File tree

packages/project/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
"./fs": {
2424
"types": "./dist/src/fs/index.d.ts",
2525
"import": "./dist/src/fs/index.js"
26+
},
27+
"./registry": {
28+
"types": "./dist/src/project/registry.d.ts",
29+
"import": "./dist/src/project/registry.js"
2630
}
2731
},
2832
"files": [

packages/project/src/project/index.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
RegistryUris,
1111
Dependencies,
1212
Dependency,
13-
JacLyFiles,
1413
PackageJson,
1514
splitLibraryNameVersion,
1615
getPackagePath,
@@ -310,17 +309,30 @@ export class Project {
310309
const resolvedDeps = await this.resolveDependencies(pkg.dependencies);
311310
const jaclyFiles: string[] = [];
312311
for (const [libName] of Object.entries(resolvedDeps)) {
313-
const pkg = await loadPackageJson(this.fs, path.join(libName, "package.json"));
312+
const pkg = await loadPackageJson(this.fs, path.join(this.projectPath, "node_modules", libName, "package.json"));
314313
if (!pkg) {
315314
this.err.write(
316315
`Failed to load package.json for '${libName}'. Install dependencies before fetching JacLy files.\n`
317316
);
318317
continue;
319318
}
320319
if (pkg.jaculus && pkg.jaculus.blocks) {
321-
jaclyFiles.push(
322-
path.join(getPackagePath(this.projectPath, libName), pkg.jaculus.blocks)
323-
);
320+
const blockFilePath = path.join(this.projectPath, "node_modules", libName, pkg.jaculus.blocks);
321+
// read folder and add all .json file
322+
if (this.fs.existsSync(blockFilePath)) {
323+
const files = this.fs.readdirSync(blockFilePath);
324+
for (const file of files) {
325+
const justFilename = path.basename(file);
326+
if (file.endsWith(".json") && !justFilename.startsWith(".")) {
327+
const fullPath = path.join(blockFilePath, file);
328+
jaclyFiles.push(fullPath);
329+
}
330+
}
331+
} else {
332+
this.err.write(
333+
`JacLy blocks folder '${blockFilePath}' does not exist for library '${libName}'.\n`
334+
);
335+
}
324336
}
325337
}
326338
return jaclyFiles;
@@ -331,7 +343,6 @@ export {
331343
Registry,
332344
Dependency,
333345
Dependencies,
334-
JacLyFiles,
335346
RegistryUris,
336347
PackageJson,
337348
parsePackageJson,

packages/project/src/project/package.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,17 @@ const DescriptionSchema = z.string();
2525
// - in first version, only exact versions are supported
2626
const DependenciesSchema = z.record(NameSchema, VersionSchema);
2727

28-
const JacLyFilesSchema = z.array(z.string());
29-
3028
const RegistryUrisSchema = z.array(z.string());
3129

3230
const JaculusSchema = z.object({
3331
blocks: z.string().optional(),
3432
});
3533

3634
const PackageJsonSchema = z.object({
37-
name: NameSchema.optional(),
38-
version: VersionSchema.optional(),
35+
name: NameSchema,
36+
version: VersionSchema,
3937
description: DescriptionSchema.optional(),
4038
dependencies: DependenciesSchema.default({}),
41-
jacly: JacLyFilesSchema.optional(),
4239
registry: RegistryUrisSchema.optional(),
4340
jaculus: JaculusSchema.optional(),
4441
});
@@ -48,7 +45,6 @@ export type Dependency = {
4845
version: string;
4946
};
5047
export type Dependencies = z.infer<typeof DependenciesSchema>;
51-
export type JacLyFiles = z.infer<typeof JacLyFilesSchema>;
5248
export type RegistryUris = z.infer<typeof RegistryUrisSchema>;
5349
export type PackageJson = z.infer<typeof PackageJsonSchema>;
5450

packages/project/src/project/registry.ts

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,66 @@
11
import semver from "semver";
22
import { getRequestJson, RequestFunction } from "../fs/index.js";
33
import { PackageJson, parsePackageJson } from "./package.js";
4+
import * as z from "zod";
45

56
export const DefaultRegistryUrl = ["https://f.jaculus.org/libs"];
67

8+
9+
/**
10+
*
11+
* Registry dist structure:
12+
* outputRegistryDist/
13+
* |-- packageName/
14+
* | |-- version/
15+
* | | |-- package.tar.gz
16+
* | | |-- package.json (same as in package)
17+
* |-- versions.json (list of versions) [{"version":"0.0.24"},{"version":"0.0.25"}]
18+
* |-- list.json (list of packages) [{"id":"core"},{"id":"smart-led"}]
19+
*
20+
*
21+
* package.tar.gz contains:
22+
* package/
23+
* |-- dist/
24+
* |-- blocks/
25+
* |-- package.json
26+
* |-- README.md
27+
*/
28+
29+
30+
const RegistryListSchema = z.array(
31+
z.object({
32+
id: z.string(),
33+
})
34+
);
35+
36+
const RegistryVersionsSchema = z.array(
37+
z.object({
38+
version: z.string(),
39+
})
40+
);
41+
42+
export type RegistryList = z.infer<typeof RegistryListSchema>;
43+
export type RegistryVersions = z.infer<typeof RegistryVersionsSchema>;
44+
45+
export function parseRegistryList(json: object): RegistryList {
46+
const result = RegistryListSchema.safeParse(json);
47+
if (!result.success) {
48+
const pretty = z.prettifyError(result.error);
49+
throw new Error(`Invalid registry list format:\n${pretty}`);
50+
}
51+
return result.data;
52+
}
53+
54+
export function parseRegistryVersions(json: object): RegistryVersions {
55+
const result = RegistryVersionsSchema.safeParse(json);
56+
if (!result.success) {
57+
const pretty = z.prettifyError(result.error);
58+
throw new Error(`Invalid registry versions format:\n${pretty}`);
59+
}
60+
return result.data;
61+
}
62+
63+
764
export class Registry {
865
public registryUri: string[];
966

@@ -20,7 +77,7 @@ export class Registry {
2077
const allLibraries: Map<string, string> = new Map();
2178

2279
for (const uri of this.registryUri) {
23-
const libraries = await getRequestJson(this.getRequest, uri, "list.json");
80+
const libraries = parseRegistryList(await getRequestJson(this.getRequest, uri, "list.json"));
2481
for (const item of libraries) {
2582
if (allLibraries.has(item.id)) {
2683
throw new Error(
@@ -46,10 +103,10 @@ export class Registry {
46103
}
47104

48105
public async listVersions(library: string): Promise<string[]> {
49-
return this.retrieveSingleResultFromRegistries(async (uri) => {
50-
const data = await getRequestJson(this.getRequest, uri, `${library}/versions.json`);
51-
return data.map((item: any) => item.version).sort(semver.rcompare);
106+
const versions = await this.retrieveSingleResultFromRegistries(async (uri) => {
107+
return getRequestJson(this.getRequest, uri, `${library}/versions.json`);
52108
}, `Failed to fetch versions for library '${library}'`);
109+
return parseRegistryVersions(versions).map((item) => item.version).sort(semver.rcompare);
53110
}
54111

55112
public async getPackageJson(library: string, version: string): Promise<PackageJson> {

0 commit comments

Comments
 (0)