@cueloop/extension-api 0.1.0-alpha.101 → 0.1.0-alpha.103

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueloop/extension-api",
3
- "version": "0.1.0-alpha.101",
3
+ "version": "0.1.0-alpha.103",
4
4
  "description": "The typed contract for extending cueloop: renderers, commands, keybindings, exporters",
5
5
  "homepage": "https://github.com/mmurakaru/cueloop#readme",
6
6
  "bugs": {
@@ -26,7 +26,7 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@cueloop/schema": "0.1.0-alpha.101",
29
+ "@cueloop/schema": "0.1.0-alpha.103",
30
30
  "valibot": "^1.5.0"
31
31
  },
32
32
  "peerDependencies": {
@@ -45,14 +45,19 @@ function readPackageJson(path: string): v.InferOutput<typeof PackageJsonSchema>
45
45
 
46
46
  function packageEntry(root: string, entry: string | undefined): string | undefined {
47
47
  if (entry === undefined) return undefined;
48
+
48
49
  if (!entry.startsWith("./")) throw new Error("entry must start with ./");
50
+
49
51
  const absolute = resolve(root, entry);
50
52
  const lexicalWithin = relative(root, absolute);
51
53
 
52
54
  if (isAbsolute(lexicalWithin) || lexicalWithin === ".." || lexicalWithin.startsWith(`..${sep}`))
53
55
  throw new Error("entry escapes package root");
56
+
54
57
  if (!existsSync(absolute)) throw new Error(`entry missing: ${entry}`);
58
+
55
59
  if (!statSync(absolute).isFile()) throw new Error(`entry is not a file: ${entry}`);
60
+
56
61
  const within = relative(realpathSync(root), realpathSync(absolute));
57
62
 
58
63
  if (isAbsolute(within) || within === ".." || within.startsWith(`..${sep}`))
@@ -70,6 +75,7 @@ export function discoverInstalledExtensionPackages(
70
75
  const rootManifest = join(installRoot, "package.json");
71
76
 
72
77
  if (!existsSync(rootManifest)) return { packages, errors };
78
+
73
79
  let dependencies: Record<string, string>;
74
80
 
75
81
  try {
@@ -85,10 +91,12 @@ export function discoverInstalledExtensionPackages(
85
91
  const manifest = readPackageJson(join(root, "package.json")).cueloop;
86
92
 
87
93
  if (!manifest) throw new Error("package has no cueloop manifest");
94
+
88
95
  const clientEntry = packageEntry(root, manifest.client);
89
96
  const daemonEntry = packageEntry(root, manifest.daemon);
90
97
 
91
98
  if (!clientEntry && !daemonEntry) throw new Error("manifest declares no entry point");
99
+
92
100
  packages.push({ name, root, clientEntry, daemonEntry });
93
101
  } catch (error) {
94
102
  errors.push(`Extension package ${name}: ${String(error)}`);
package/src/registry.ts CHANGED
@@ -42,14 +42,17 @@ export class Registry {
42
42
  registerVcsAdapter: (adapter) => {
43
43
  if (adapter.id === "git" || adapter.id === "jj")
44
44
  throw new Error(`Invalid or duplicate VCS adapter ID: ${adapter.id}`);
45
+
45
46
  const parsed = v.safeParse(VcsAdapterSchema, adapter);
46
47
 
47
48
  if (!parsed.success) throw new Error(`Invalid VCS adapter contract: ${adapter.id}`);
49
+
48
50
  if (
49
51
  record.vcsAdapters.has(adapter.id) ||
50
52
  this.extensions.some((extension) => extension.vcsAdapters.has(adapter.id))
51
53
  )
52
54
  throw new Error(`Invalid or duplicate VCS adapter ID: ${adapter.id}`);
55
+
53
56
  record.vcsAdapters.set(adapter.id, adapter);
54
57
  },
55
58
  };