@homeflare/alchemy 0.58.0 → 0.60.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.
@@ -0,0 +1,118 @@
1
+ /**
2
+ * A consuming stack's own `check` calls `checkAlchemyPatch` to assert it actually carries the
3
+ * duplicate-resource-id fix — not just that SOME version of `alchemy` is installed, but that
4
+ * THIS install carries the patch, for the alchemy version it was cut against.
5
+ *
6
+ * ★ WHY A BUMP CAN OTHERWISE DROP IT SILENTLY. `patchedDependencies` keys a patch to an EXACT
7
+ * version string (`alchemy@2.0.0-beta.81`). `bun add alchemy@2.0.0-beta.82` leaves that key
8
+ * pointing at a version nothing installs anymore — `bun install` neither errors nor warns,
9
+ * it just stops applying the patch, and the stack is back to the original silent collision
10
+ * with every other gate still green. This check is what turns that bump into a failing
11
+ * `check`, the same way `tests/dist.test.ts` turns a build regression into a failing test
12
+ * instead of a surprise three repos downstream (this package's own AGENTS.md, "the smoke
13
+ * test is not optional").
14
+ * ★ A STATIC CHECK, mirroring `@homeflare/config/check`'s `checkCopy`/`checkOxfmt` — not a
15
+ * functional probe that spins up a `Stack`/`Resource`/`Effect` harness on every `check` run.
16
+ * The functional proof that the patch's LOGIC works lives in this package's own
17
+ * `duplicate-id.test.ts`, against the exact pinned version; a consumer's `check` only needs
18
+ * to know whether ITS install carries that same patch, applied — three file reads, no
19
+ * `effect` runtime pulled into every repo's check step.
20
+ * ⛔ IT REPORTS, IT DOES NOT REPAIR, same as `checkProject` in `@homeflare/config/check` — this
21
+ * never edits `package.json` or re-runs `bun install` for the caller.
22
+ */
23
+ import { PATCHED_ALCHEMY_VERSION } from './duplicate-id.ts';
24
+
25
+ /** One thing wrong with a consuming stack's alchemy patch, in the imperative. */
26
+ export type PatchProblem = string;
27
+
28
+ const patchKey = (version: string) => `alchemy@${version}`;
29
+
30
+ /** Where THIS package's own shipped copy of the patch lives, however it was installed. */
31
+ const shippedPatchPath = (version: string): string =>
32
+ new URL(`../../patches/${patchKey(version)}.patch`, import.meta.url).pathname;
33
+
34
+ type PackageJson = {
35
+ readonly patchedDependencies?: Readonly<Record<string, string>>;
36
+ };
37
+
38
+ /**
39
+ * @param projectDir The consuming stack's OWN repo root (where its `package.json` and
40
+ * `patches/` directory live) — never this kit's own.
41
+ * @param alchemyVersion The version to check for — defaults to the version this package's
42
+ * own shipped patch targets ({@link PATCHED_ALCHEMY_VERSION}); a caller only overrides it to
43
+ * test a different pin.
44
+ */
45
+ export const checkAlchemyPatch = async (
46
+ projectDir: string,
47
+ alchemyVersion: string = PATCHED_ALCHEMY_VERSION,
48
+ ): Promise<readonly PatchProblem[]> => {
49
+ const problems: PatchProblem[] = [];
50
+ const key = patchKey(alchemyVersion);
51
+
52
+ const installedPkg = Bun.file(`${projectDir}/node_modules/alchemy/package.json`);
53
+ if (!(await installedPkg.exists())) {
54
+ problems.push('node_modules/alchemy: not installed — nothing to check the patch against');
55
+ return problems;
56
+ }
57
+ const installedVersion = ((await installedPkg.json()) as { version?: string }).version;
58
+ if (installedVersion !== alchemyVersion) {
59
+ problems.push(
60
+ `node_modules/alchemy is ${installedVersion ?? 'unknown'}, but the duplicate-resource-id ` +
61
+ `patch targets ${alchemyVersion} — bump the patch (@homeflare/alchemy's own ` +
62
+ 'patches/) before bumping alchemy, or this install has no protection at all',
63
+ );
64
+ return problems;
65
+ }
66
+
67
+ const pkgFile = Bun.file(`${projectDir}/package.json`);
68
+ if (!(await pkgFile.exists())) {
69
+ problems.push('package.json: missing');
70
+ return problems;
71
+ }
72
+ const pkg = (await pkgFile.json()) as PackageJson;
73
+ const declaredPath = pkg.patchedDependencies?.[key];
74
+ if (declaredPath === undefined) {
75
+ problems.push(
76
+ `package.json: patchedDependencies has no entry for "${key}" — this stack has no ` +
77
+ 'duplicate-resource-id protection at all; see @homeflare/alchemy/docs/duplicate-resource-id.md',
78
+ );
79
+ return problems;
80
+ }
81
+
82
+ const theirs = Bun.file(`${projectDir}/${declaredPath}`);
83
+ if (!(await theirs.exists())) {
84
+ problems.push(`package.json declares "${key}" at ${declaredPath}, but that file is missing`);
85
+ return problems;
86
+ }
87
+ const ours = Bun.file(shippedPatchPath(alchemyVersion));
88
+ if (!(await ours.exists())) {
89
+ // The kit's own tarball is missing its patch — a packaging bug, not the consumer's.
90
+ problems.push(`@homeflare/alchemy ships no patches/${key}.patch to compare against`);
91
+ return problems;
92
+ }
93
+ if ((await theirs.text()) !== (await ours.text())) {
94
+ problems.push(
95
+ `${declaredPath}: differs from @homeflare/alchemy's shipped patch — re-copy it, ` +
96
+ 'or say why it differs',
97
+ );
98
+ }
99
+
100
+ // Declared and byte-identical is not yet APPLIED: a hand-edited patchedDependencies entry,
101
+ // or an install under a package manager that does not support bun's patch format, leaves
102
+ // node_modules unpatched with nothing above noticing. One cheap textual proof it landed.
103
+ const resourceSrc = Bun.file(`${projectDir}/node_modules/alchemy/src/Resource.ts`);
104
+ const resourceLib = Bun.file(`${projectDir}/node_modules/alchemy/lib/Resource.js`);
105
+ const marker = 'DuplicateResourceIdError';
106
+ const [srcText, libText] = await Promise.all([
107
+ resourceSrc.exists().then((ok) => (ok ? resourceSrc.text() : '')),
108
+ resourceLib.exists().then((ok) => (ok ? resourceLib.text() : '')),
109
+ ]);
110
+ if (!srcText.includes(marker) && !libText.includes(marker)) {
111
+ problems.push(
112
+ 'node_modules/alchemy/{src/Resource.ts,lib/Resource.js}: neither contains the patch — ' +
113
+ 'declared in package.json but not applied; re-run `bun install`',
114
+ );
115
+ }
116
+
117
+ return problems;
118
+ };