@relayfile/adapter-core 0.3.26 → 0.3.28

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 (41) hide show
  1. package/dist/src/cli.js +44 -0
  2. package/dist/src/cli.js.map +1 -1
  3. package/dist/src/index.d.ts +1 -0
  4. package/dist/src/index.d.ts.map +1 -1
  5. package/dist/src/index.js +1 -0
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/src/scope-keys/catalog-generator.d.ts.map +1 -1
  8. package/dist/src/scope-keys/catalog-generator.js +5 -1
  9. package/dist/src/scope-keys/catalog-generator.js.map +1 -1
  10. package/dist/src/triggers/catalog-generator.d.ts.map +1 -1
  11. package/dist/src/triggers/catalog-generator.js +5 -1
  12. package/dist/src/triggers/catalog-generator.js.map +1 -1
  13. package/dist/src/vfs-client/index.d.ts +113 -0
  14. package/dist/src/vfs-client/index.d.ts.map +1 -0
  15. package/dist/src/vfs-client/index.js +172 -0
  16. package/dist/src/vfs-client/index.js.map +1 -0
  17. package/dist/src/writeback-paths/catalog-generator.d.ts +51 -0
  18. package/dist/src/writeback-paths/catalog-generator.d.ts.map +1 -0
  19. package/dist/src/writeback-paths/catalog-generator.js +264 -0
  20. package/dist/src/writeback-paths/catalog-generator.js.map +1 -0
  21. package/dist/src/writeback-paths/catalog.generated.d.ts +470 -0
  22. package/dist/src/writeback-paths/catalog.generated.d.ts.map +1 -0
  23. package/dist/src/writeback-paths/catalog.generated.js +737 -0
  24. package/dist/src/writeback-paths/catalog.generated.js.map +1 -0
  25. package/dist/src/writeback-paths/index.d.ts +3 -0
  26. package/dist/src/writeback-paths/index.d.ts.map +1 -0
  27. package/dist/src/writeback-paths/index.js +3 -0
  28. package/dist/src/writeback-paths/index.js.map +1 -0
  29. package/dist/src/writeback-paths/resolver.d.ts +24 -0
  30. package/dist/src/writeback-paths/resolver.d.ts.map +1 -0
  31. package/dist/src/writeback-paths/resolver.js +59 -0
  32. package/dist/src/writeback-paths/resolver.js.map +1 -0
  33. package/dist/tests/vfs-client/vfs-client.test.d.ts +2 -0
  34. package/dist/tests/vfs-client/vfs-client.test.d.ts.map +1 -0
  35. package/dist/tests/vfs-client/vfs-client.test.js +49 -0
  36. package/dist/tests/vfs-client/vfs-client.test.js.map +1 -0
  37. package/dist/tests/writeback-paths/catalog-generator.test.d.ts +2 -0
  38. package/dist/tests/writeback-paths/catalog-generator.test.d.ts.map +1 -0
  39. package/dist/tests/writeback-paths/catalog-generator.test.js +56 -0
  40. package/dist/tests/writeback-paths/catalog-generator.test.js.map +1 -0
  41. package/package.json +9 -1
@@ -0,0 +1,172 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdir, readFile, readdir, rename, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ export class RelayfileWritebackError extends Error {
5
+ provider;
6
+ operation;
7
+ cause;
8
+ retryable;
9
+ constructor(options) {
10
+ super(`${options.provider}.${options.operation} failed${options.cause instanceof Error ? `: ${options.cause.message}` : ""}`);
11
+ this.name = "RelayfileWritebackError";
12
+ this.provider = options.provider;
13
+ this.operation = options.operation;
14
+ if (options.cause !== undefined)
15
+ this.cause = options.cause;
16
+ this.retryable = options.retryable ?? false;
17
+ }
18
+ }
19
+ const DEFAULT_WRITEBACK_TIMEOUT_MS = 3_000;
20
+ function isRecord(value) {
21
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22
+ }
23
+ /** Percent-encode a path segment so identifiers safely round-trip. */
24
+ export function encodeSegment(value) {
25
+ return encodeURIComponent(String(value));
26
+ }
27
+ /**
28
+ * Allocate a unique draft filename for a new resource. The Relayfile writeback
29
+ * worker renames the file to the canonical id on receipt.
30
+ */
31
+ export function draftFile(prefix) {
32
+ return `${prefix} ${randomUUID()}.json`;
33
+ }
34
+ /**
35
+ * Resolve the absolute Relayfile mount root, honoring (in order) the
36
+ * client-supplied option, the `RELAYFILE_MOUNT_ROOT` / `RELAYFILE_ROOT` env
37
+ * vars, and finally `workspaceCwd` / `process.cwd()`.
38
+ */
39
+ export function resolveMountRoot(client) {
40
+ return path.resolve(client.relayfileMountRoot ??
41
+ client.relayfileRoot ??
42
+ client.mountRoot ??
43
+ process.env.RELAYFILE_MOUNT_ROOT ??
44
+ process.env.RELAYFILE_ROOT ??
45
+ client.workspaceCwd ??
46
+ process.cwd());
47
+ }
48
+ function toAbsolutePath(client, relayPath) {
49
+ const root = resolveMountRoot(client);
50
+ const normalized = relayPath.startsWith("/") ? relayPath.slice(1) : relayPath;
51
+ const absolute = path.resolve(root, normalized);
52
+ const relative = path.relative(root, absolute);
53
+ // `startsWith("..")` alone would also reject a legit in-mount name like
54
+ // `..foo.json`; only an exact `..` or a `../`-prefixed segment escapes.
55
+ if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
56
+ throw new Error(`Relayfile path escapes mount root: ${relayPath}`);
57
+ }
58
+ return absolute;
59
+ }
60
+ export async function readJsonFile(client, provider, operation, relayPath) {
61
+ try {
62
+ const absolutePath = toAbsolutePath(client, relayPath);
63
+ return JSON.parse(await readFile(absolutePath, "utf8"));
64
+ }
65
+ catch (cause) {
66
+ throw new RelayfileWritebackError({ provider, operation, cause, retryable: false });
67
+ }
68
+ }
69
+ export async function readTextFile(client, provider, operation, relayPath) {
70
+ try {
71
+ return await readFile(toAbsolutePath(client, relayPath), "utf8");
72
+ }
73
+ catch (cause) {
74
+ throw new RelayfileWritebackError({ provider, operation, cause, retryable: false });
75
+ }
76
+ }
77
+ export async function listJsonFiles(client, provider, operation, relayDir) {
78
+ try {
79
+ const absoluteDir = toAbsolutePath(client, relayDir);
80
+ const entries = await readdirIfPresent(absoluteDir);
81
+ const out = [];
82
+ for (const entry of entries) {
83
+ if (!entry.endsWith(".json"))
84
+ continue;
85
+ const relayPath = `${relayDir.replace(/\/+$/, "")}/${entry}`;
86
+ const value = JSON.parse(await readFile(path.join(absoluteDir, entry), "utf8"));
87
+ out.push({ path: relayPath, value });
88
+ }
89
+ return out;
90
+ }
91
+ catch (cause) {
92
+ throw new RelayfileWritebackError({ provider, operation, cause, retryable: false });
93
+ }
94
+ }
95
+ export async function listDirectoryEntries(client, provider, operation, relayDir) {
96
+ try {
97
+ return await readdirIfPresent(toAbsolutePath(client, relayDir));
98
+ }
99
+ catch (cause) {
100
+ throw new RelayfileWritebackError({ provider, operation, cause, retryable: false });
101
+ }
102
+ }
103
+ async function readdirIfPresent(absoluteDir) {
104
+ try {
105
+ return await readdir(absoluteDir);
106
+ }
107
+ catch (error) {
108
+ if (isNoEntryError(error)) {
109
+ return [];
110
+ }
111
+ throw error;
112
+ }
113
+ }
114
+ function isNoEntryError(error) {
115
+ return isRecord(error) && error.code === "ENOENT";
116
+ }
117
+ /**
118
+ * Write a draft JSON payload atomically (write-then-rename) so the writeback
119
+ * worker never sees a partial file. Waits for a receipt by default; pass
120
+ * `writebackTimeoutMs: 0` to return immediately.
121
+ */
122
+ export async function writeJsonFile(client, provider, operation, relayPath, body) {
123
+ try {
124
+ const absolutePath = toAbsolutePath(client, relayPath);
125
+ await mkdir(path.dirname(absolutePath), { recursive: true });
126
+ const tempPath = `${absolutePath}.tmp-${randomUUID()}`;
127
+ await writeFile(tempPath, `${JSON.stringify(body, null, 2)}\n`, "utf8");
128
+ await rename(tempPath, absolutePath);
129
+ const receipt = await waitForReceipt(absolutePath, client, body);
130
+ return { path: relayPath, absolutePath, ...(receipt ? { receipt } : {}) };
131
+ }
132
+ catch (cause) {
133
+ throw new RelayfileWritebackError({ provider, operation, cause, retryable: false });
134
+ }
135
+ }
136
+ async function waitForReceipt(absolutePath, client, draft) {
137
+ const timeoutMs = client.writebackTimeoutMs ?? DEFAULT_WRITEBACK_TIMEOUT_MS;
138
+ if (timeoutMs <= 0)
139
+ return undefined;
140
+ // Never reinterpret the just-written draft as a receipt. The draft payload may
141
+ // legitimately carry top-level `id` / `path` / `created` fields (e.g. an
142
+ // upsert update writing back the canonical issue), so the first poll could
143
+ // otherwise return the draft itself and surface a bogus identifier. Only
144
+ // accept a file whose content has changed from the draft we wrote.
145
+ const draftJson = JSON.stringify(draft);
146
+ const deadline = Date.now() + timeoutMs;
147
+ do {
148
+ const parsed = await readCurrentJson(absolutePath);
149
+ if (parsed !== undefined &&
150
+ JSON.stringify(parsed) !== draftJson &&
151
+ isRecord(parsed) &&
152
+ (typeof parsed.created === "string" ||
153
+ typeof parsed.path === "string" ||
154
+ typeof parsed.id === "string" ||
155
+ typeof parsed.externalId === "string" ||
156
+ typeof parsed.merged === "boolean" ||
157
+ typeof parsed.merged === "string")) {
158
+ return parsed;
159
+ }
160
+ await new Promise((resolve) => setTimeout(resolve, client.writebackPollMs ?? 250));
161
+ } while (Date.now() < deadline);
162
+ return undefined;
163
+ }
164
+ async function readCurrentJson(absolutePath) {
165
+ try {
166
+ return JSON.parse(await readFile(absolutePath, "utf8"));
167
+ }
168
+ catch {
169
+ return undefined;
170
+ }
171
+ }
172
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/vfs-client/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Per-provider **writeback path** templates — the canonical Relayfile-mount
3
+ * paths an agent writes a draft JSON file to in order to trigger a provider
4
+ * mutation (create issue, comment, post message). Each adapter's
5
+ * `resources.ts` is the source of truth: the same `{ name, path }` data the
6
+ * writeback worker's `classifyWrite` matches incoming drafts against. This
7
+ * catalog harvests it cross-provider so a single consumer dependency
8
+ * (`@relayfile/adapter-core/writeback-paths`) can resolve a draft path from
9
+ * `(provider, resource, params)` without taking a dependency on every
10
+ * `@relayfile/adapter-<provider>` package.
11
+ */
12
+ export interface WritebackResourcePath {
13
+ /** Path template with `{param}` placeholders, e.g. `/linear/issues/{issueId}/comments`. */
14
+ path: string;
15
+ /** Placeholder names in template order, e.g. `["issueId"]`. */
16
+ params: string[];
17
+ }
18
+ /**
19
+ * provider → resource name → path template variants.
20
+ *
21
+ * A resource `name` is NOT unique within an adapter: the same entity is mounted
22
+ * at several paths (e.g. notion `pages` →
23
+ * `/notion/databases/{databaseId}/pages`, `/notion/pages/{pageId}.json`, …).
24
+ * Every distinct template is kept; the resolver disambiguates by the exact set
25
+ * of params supplied. Collapsing to one path per name would silently drop valid
26
+ * writeback targets.
27
+ */
28
+ export type WritebackPathCatalog = Record<string, Record<string, WritebackResourcePath[]>>;
29
+ export interface AdapterWithoutWritebackPaths {
30
+ packageName: string;
31
+ packagePath: string;
32
+ provider: string;
33
+ reason: string;
34
+ }
35
+ export interface WritebackPathCatalogGeneration {
36
+ catalog: WritebackPathCatalog;
37
+ adaptersWithoutWritebackPaths: AdapterWithoutWritebackPaths[];
38
+ }
39
+ export interface WriteWritebackPathCatalogOptions {
40
+ check?: boolean;
41
+ repoRoot?: string;
42
+ }
43
+ export declare function generateWritebackPathCatalog(repoRoot?: string): Promise<WritebackPathCatalogGeneration>;
44
+ export declare function writeWritebackPathCatalog(options?: WriteWritebackPathCatalogOptions): Promise<WritebackPathCatalogGeneration>;
45
+ export declare function writebackPathCatalogPaths(repoRoot: string): {
46
+ catalogJson: string;
47
+ withoutJson: string;
48
+ catalogTs: string;
49
+ };
50
+ export declare function renderWritebackPathCatalogModule(generation: WritebackPathCatalogGeneration): string;
51
+ //# sourceMappingURL=catalog-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-generator.d.ts","sourceRoot":"","sources":["../../../src/writeback-paths/catalog-generator.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACpC,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC;AAE3F,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,oBAAoB,CAAC;IAC9B,6BAA6B,EAAE,4BAA4B,EAAE,CAAC;CAC/D;AAED,MAAM,WAAW,gCAAgC;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA8BD,wBAAsB,4BAA4B,CAChD,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,8BAA8B,CAAC,CAwBzC;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE,gCAAqC,GAC7C,OAAO,CAAC,8BAA8B,CAAC,CAwCzC;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAOA;AAED,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,8BAA8B,GAAG,MAAM,CAanG"}
@@ -0,0 +1,264 @@
1
+ import { access, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, join, relative, resolve } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import { findRepoRoot } from "../triggers/catalog-generator.js";
5
+ const GENERATED_HEADER = `/**
6
+ * Generated by \`adapter-core writeback-paths generate\`.
7
+ *
8
+ * Writeback path templates are emitted verbatim from each adapter's
9
+ * \`resources.ts\` (\`{ name, path }\`) — the same source the writeback worker's
10
+ * \`classifyWrite\` routes drafts against. A consumer resolves a concrete draft
11
+ * path with \`writebackPath(provider, resource, params)\`.
12
+ */
13
+ `;
14
+ const NON_ADAPTER_PACKAGES = new Set([
15
+ "@relayfile/adapter-core",
16
+ "@relayfile/webhook-server",
17
+ "@relayfile/relay-helpers"
18
+ ]);
19
+ export async function generateWritebackPathCatalog(repoRoot) {
20
+ repoRoot = repoRoot ? resolve(repoRoot) : await findRepoRoot();
21
+ const packages = await listAdapterPackages(repoRoot);
22
+ const entries = [];
23
+ const adaptersWithoutWritebackPaths = [];
24
+ for (const adapterPackage of packages) {
25
+ const { resources, error } = await readAdapterResources(adapterPackage);
26
+ if (resources.length > 0) {
27
+ entries.push({ provider: adapterPackage.provider, resources });
28
+ continue;
29
+ }
30
+ adaptersWithoutWritebackPaths.push({
31
+ packageName: adapterPackage.packageName,
32
+ packagePath: adapterPackage.relativePath,
33
+ provider: adapterPackage.provider,
34
+ reason: error ?? "No resources.ts with writeback path templates",
35
+ });
36
+ }
37
+ return {
38
+ catalog: sortCatalog(entries),
39
+ adaptersWithoutWritebackPaths: adaptersWithoutWritebackPaths.sort(compareByPackagePath),
40
+ };
41
+ }
42
+ export async function writeWritebackPathCatalog(options = {}) {
43
+ const repoRoot = options.repoRoot ? resolve(options.repoRoot) : await findRepoRoot();
44
+ const generation = await generateWritebackPathCatalog(repoRoot);
45
+ const paths = writebackPathCatalogPaths(repoRoot);
46
+ const expectedFiles = new Map([
47
+ [paths.catalogJson, renderJson(generation.catalog)],
48
+ [paths.withoutJson, renderJson(generation.adaptersWithoutWritebackPaths)],
49
+ [paths.catalogTs, renderWritebackPathCatalogModule(generation)],
50
+ ]);
51
+ if (options.check) {
52
+ const mismatches = [];
53
+ for (const [filePath, expected] of expectedFiles) {
54
+ let actual = "";
55
+ try {
56
+ actual = await readFile(filePath, "utf8");
57
+ }
58
+ catch {
59
+ mismatches.push(relative(repoRoot, filePath));
60
+ continue;
61
+ }
62
+ // Normalize line endings: a CRLF checkout (Windows, no enforced
63
+ // `.gitattributes`) must not read as a false out-of-sync mismatch.
64
+ if (normalizeEol(actual) !== normalizeEol(expected)) {
65
+ mismatches.push(relative(repoRoot, filePath));
66
+ }
67
+ }
68
+ if (mismatches.length > 0) {
69
+ throw new Error(`Writeback-path catalog is out of sync. Run \`adapter-core writeback-paths generate\`. Stale files: ${mismatches.join(", ")}`);
70
+ }
71
+ return generation;
72
+ }
73
+ for (const [filePath, contents] of expectedFiles) {
74
+ await mkdir(dirname(filePath), { recursive: true });
75
+ await writeFile(filePath, contents);
76
+ }
77
+ return generation;
78
+ }
79
+ export function writebackPathCatalogPaths(repoRoot) {
80
+ const dir = join(repoRoot, "packages", "core", "src", "writeback-paths");
81
+ return {
82
+ catalogJson: join(dir, "catalog.generated.json"),
83
+ withoutJson: join(dir, "adapters-without-writeback-paths.generated.json"),
84
+ catalogTs: join(dir, "catalog.generated.ts"),
85
+ };
86
+ }
87
+ export function renderWritebackPathCatalogModule(generation) {
88
+ return `${GENERATED_HEADER}
89
+ export const WRITEBACK_PATH_CATALOG = ${renderInlineJson(generation.catalog)} as const satisfies Record<
90
+ string,
91
+ Record<string, readonly { path: string; params: readonly string[] }[]>
92
+ >;
93
+
94
+ export const ADAPTERS_WITHOUT_WRITEBACK_PATHS = ${renderInlineJson(generation.adaptersWithoutWritebackPaths)} as const;
95
+
96
+ export type WritebackProvider = keyof typeof WRITEBACK_PATH_CATALOG;
97
+ export type WritebackResource<P extends WritebackProvider> =
98
+ keyof (typeof WRITEBACK_PATH_CATALOG)[P];
99
+ `;
100
+ }
101
+ /**
102
+ * Read an adapter's writeback resources. Prefers the built `resources.js`
103
+ * (a plain `{ name, path }[]` array — the same module `classifyWrite`
104
+ * consumes); falls back to regex-parsing the `resources.ts` source so the
105
+ * catalog still generates when an adapter is unbuilt.
106
+ */
107
+ async function readAdapterResources(adapterPackage) {
108
+ const builtEntryPoint = await firstExistingPath([
109
+ join(adapterPackage.dir, "dist", "resources.js"),
110
+ join(adapterPackage.dir, "dist", "src", "resources.js"),
111
+ ]);
112
+ let importError;
113
+ if (builtEntryPoint) {
114
+ try {
115
+ const moduleExports = (await import(pathToFileURL(builtEntryPoint).href));
116
+ const resources = normalizeResources(moduleExports.resources);
117
+ if (resources.length > 0) {
118
+ return { resources };
119
+ }
120
+ }
121
+ catch (error) {
122
+ // Remember the import failure so it surfaces as the adapter's reason
123
+ // instead of a generic "no resources" message — a swallowed import
124
+ // error otherwise hides a real build/runtime problem.
125
+ importError = `Could not import built adapter resources: ${errorMessage(error)}`;
126
+ }
127
+ }
128
+ const sourceResources = await readResourcesFromSource(join(adapterPackage.dir, "src", "resources.ts"));
129
+ if (sourceResources.length > 0) {
130
+ return { resources: sourceResources };
131
+ }
132
+ return { resources: [], error: importError };
133
+ }
134
+ function normalizeResources(value) {
135
+ if (!Array.isArray(value)) {
136
+ return [];
137
+ }
138
+ const out = [];
139
+ for (const entry of value) {
140
+ if (!isRecord(entry))
141
+ continue;
142
+ const { name, path } = entry;
143
+ if (typeof name === "string" && name.length > 0 && typeof path === "string" && path.length > 0) {
144
+ out.push({ name, path });
145
+ }
146
+ }
147
+ return out;
148
+ }
149
+ async function readResourcesFromSource(entryPoint) {
150
+ let contents;
151
+ try {
152
+ contents = await readFile(entryPoint, "utf8");
153
+ }
154
+ catch {
155
+ return [];
156
+ }
157
+ // Match `name: "x"` immediately followed by `path: "/y"` within each
158
+ // resource literal. `name` always precedes `path` in the generated file.
159
+ const pattern = /name:\s*["']([^"']+)["']\s*,\s*path:\s*["']([^"']+)["']/gu;
160
+ const out = [];
161
+ let match;
162
+ while ((match = pattern.exec(contents)) !== null) {
163
+ out.push({ name: match[1], path: match[2] });
164
+ }
165
+ return out;
166
+ }
167
+ function sortCatalog(entries) {
168
+ // provider → name → (path → variant). The inner map dedupes by path so an
169
+ // exact (name, path) repeat collapses, while genuinely distinct templates
170
+ // sharing a name are all retained (notion `pages`, asana `sections`, …).
171
+ const catalog = new Map();
172
+ for (const entry of entries) {
173
+ const byName = catalog.get(entry.provider) ?? new Map();
174
+ for (const resource of entry.resources) {
175
+ const byPath = byName.get(resource.name) ?? new Map();
176
+ if (!byPath.has(resource.path)) {
177
+ byPath.set(resource.path, { path: resource.path, params: extractParams(resource.path) });
178
+ }
179
+ byName.set(resource.name, byPath);
180
+ }
181
+ catalog.set(entry.provider, byName);
182
+ }
183
+ return Object.fromEntries([...catalog.entries()]
184
+ .sort(([left], [right]) => left.localeCompare(right))
185
+ .map(([provider, byName]) => [
186
+ provider,
187
+ Object.fromEntries([...byName.entries()]
188
+ .sort(([left], [right]) => left.localeCompare(right))
189
+ .map(([name, byPath]) => [
190
+ name,
191
+ [...byPath.values()].sort((left, right) => left.path.localeCompare(right.path)),
192
+ ])),
193
+ ]));
194
+ }
195
+ function normalizeEol(value) {
196
+ return value.replace(/\r\n/gu, "\n");
197
+ }
198
+ /** Placeholder names in template order, e.g. `/x/{a}/y/{b}` → `["a","b"]`. */
199
+ function extractParams(template) {
200
+ return [...template.matchAll(/\{([^}]+)\}/gu)].map((match) => match[1]);
201
+ }
202
+ async function listAdapterPackages(repoRoot) {
203
+ const packagesDir = join(repoRoot, "packages");
204
+ const names = await readdir(packagesDir);
205
+ const packages = [];
206
+ for (const name of names.sort()) {
207
+ const dir = join(packagesDir, name);
208
+ const packageJsonPath = join(dir, "package.json");
209
+ let packageJson;
210
+ try {
211
+ packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
212
+ }
213
+ catch {
214
+ continue;
215
+ }
216
+ if (!packageJson.name || NON_ADAPTER_PACKAGES.has(packageJson.name)) {
217
+ continue;
218
+ }
219
+ packages.push({
220
+ dir,
221
+ packageName: packageJson.name,
222
+ provider: inferProviderSlug(packageJson.name, name),
223
+ relativePath: relative(repoRoot, dir),
224
+ });
225
+ }
226
+ return packages;
227
+ }
228
+ function inferProviderSlug(packageName, directoryName) {
229
+ if (packageName.startsWith("@relayfile/adapter-")) {
230
+ return packageName.slice("@relayfile/adapter-".length);
231
+ }
232
+ if (packageName.startsWith("@relayfile/")) {
233
+ return packageName.slice("@relayfile/".length);
234
+ }
235
+ return directoryName;
236
+ }
237
+ async function firstExistingPath(paths) {
238
+ for (const path of paths) {
239
+ try {
240
+ await access(path);
241
+ return path;
242
+ }
243
+ catch {
244
+ // Try the next candidate.
245
+ }
246
+ }
247
+ return undefined;
248
+ }
249
+ function compareByPackagePath(left, right) {
250
+ return left.packagePath.localeCompare(right.packagePath) || left.provider.localeCompare(right.provider);
251
+ }
252
+ function renderJson(value) {
253
+ return `${JSON.stringify(value, null, 2)}\n`;
254
+ }
255
+ function renderInlineJson(value) {
256
+ return JSON.stringify(value, null, 2);
257
+ }
258
+ function isRecord(value) {
259
+ return value !== null && typeof value === "object";
260
+ }
261
+ function errorMessage(error) {
262
+ return error instanceof Error ? error.message : String(error);
263
+ }
264
+ //# sourceMappingURL=catalog-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-generator.js","sourceRoot":"","sources":["../../../src/writeback-paths/catalog-generator.ts"],"names":[],"mappings":"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"}