Skip to content

Commit 6e90b73

Browse files
authored
fix: make kit Bazel package consumer-safe
Make the scheduling-kit Bazel package target build correctly when consumed as an external Bzlmod module, and prepare the 0.7.6 release metadata.
1 parent cdbbb61 commit 6e90b73

7 files changed

Lines changed: 234 additions & 27 deletions

File tree

AGENTS.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ The package should be reusable across multiple businesses. Avoid app-specific as
3838

3939
## Current Tracking
4040

41-
As of `2026-04-25`, the active structural work is no longer just downstream
41+
As of `2026-05-02`, the active structural work is no longer just downstream
4242
contract cleanup. It is release-authority, artifact-truth, and runner-contract
4343
convergence.
4444

@@ -49,17 +49,20 @@ Active threads:
4949
- `TIN-165` bazel-registry generation from standalone package truth
5050
- release, tag, npm, and GitHub release authority cleanup tracked in GitHub
5151
issue `#73`
52+
- downstream Bzlmod consumer builds of `//:pkg` from the active registry
5253
- runner reachability and shared-runner proof before treating package CI as a
5354
stable public workflow contract
5455

5556
Current operational truth:
5657

5758
- local development should default to `jesssullivan/main`
5859
- that branch is the current functional release line
59-
- current package metadata on `main` is `@tummycrypt/scheduling-kit` `0.7.2`
60-
- as of `2026-04-25`, npm `latest` is `0.7.2`; the matching GitHub release
61-
was not present when checked, so keep `#73` open until tag/release authority
62-
is reconciled
60+
- current published package truth is `@tummycrypt/scheduling-kit` `0.7.5`
61+
on npm, GitHub Releases, and the active tinyland Bazel registry
62+
- the `0.7.6` lane fixes downstream Bzlmod `//:pkg` consumption by making the
63+
Svelte package build independent of main-workspace-relative `src` paths
64+
- keep `#73` open until the next package release/tag/registry pass proves the
65+
updated Bazel consumer path end to end
6366
- `tinyland-inc/origin/main` is now a downstream mirror/validation surface,
6467
not an equally authoritative release surface
6568
- package metadata, git tags, npm dist-tags, and GitHub releases are separate

BUILD.bazel

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Subpackage structure:
1616
//src/testing - Mock helpers, MSW handlers
1717
"""
1818

19-
load("@aspect_rules_js//js:defs.bzl", "js_library", "js_run_binary")
19+
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
20+
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_library", "js_run_binary")
2021
load("@aspect_rules_js//npm:defs.bzl", "npm_package")
2122
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
2223
load("@tummycrypt_scheduling_kit_npm//:defs.bzl", "npm_link_all_packages")
@@ -46,12 +47,23 @@ svelte_kit.svelte_kit_binary(
4647
visibility = ["//visibility:public"],
4748
)
4849

50+
js_binary(
51+
name = "bazel_svelte_package",
52+
entry_point = "scripts/svelte-package-bazel-wrapper.mjs",
53+
data = [
54+
":node_modules/@sveltejs/package",
55+
":node_modules/svelte",
56+
":node_modules/typescript",
57+
],
58+
)
59+
4960
# svelte-check and Vitest both read tsconfig.json, which extends the generated
5061
# .svelte-kit/tsconfig.json. Mirror the pnpm scripts' required sync step.
5162
js_run_binary(
5263
name = "svelte_kit_sync",
5364
tags = ["manual"],
5465
tool = ":svelte_kit",
66+
chdir = ".",
5567
srcs = glob([
5668
"src/**/*.ts",
5769
"src/**/*.svelte",
@@ -74,22 +86,32 @@ js_run_binary(
7486
# components, .svelte.ts stores, and plain .ts files in one pass.
7587
# =============================================================================
7688

89+
SCHEDULING_KIT_PACKAGE_SOURCES = glob(
90+
[
91+
"src/**/*.ts",
92+
"src/**/*.svelte",
93+
"src/**/*.svelte.ts",
94+
],
95+
exclude = [
96+
"src/**/*.test.ts",
97+
"src/**/*.spec.ts",
98+
"src/tests/**",
99+
],
100+
)
101+
102+
copy_to_directory(
103+
name = "scheduling_kit_src",
104+
srcs = SCHEDULING_KIT_PACKAGE_SOURCES,
105+
out = "scheduling_kit_src",
106+
root_paths = ["src"],
107+
)
108+
77109
js_run_binary(
78110
name = "scheduling_kit_build",
79111
tags = ["manual"],
80-
tool = ":svelte_package",
81-
srcs = glob(
82-
[
83-
"src/**/*.ts",
84-
"src/**/*.svelte",
85-
"src/**/*.svelte.ts",
86-
],
87-
exclude = [
88-
"src/**/*.test.ts",
89-
"src/**/*.spec.ts",
90-
"src/tests/**",
91-
],
92-
) + [
112+
tool = ":bazel_svelte_package",
113+
srcs = [
114+
":scheduling_kit_src",
93115
"package.json",
94116
"svelte.config.js",
95117
"tsconfig.json",
@@ -98,7 +120,7 @@ js_run_binary(
98120
],
99121
args = [
100122
"-i",
101-
"src",
123+
"$(execpath :scheduling_kit_src)",
102124
"-o",
103125
"dist",
104126
],
@@ -127,7 +149,7 @@ npm_package(
127149
],
128150
package = "@tummycrypt/scheduling-kit",
129151
tags = ["manual"],
130-
version = "0.7.5",
152+
version = "0.7.6",
131153
visibility = ["//visibility:public"],
132154
)
133155

@@ -283,6 +305,7 @@ js_run_binary(
283305
name = "typecheck",
284306
tags = ["manual"],
285307
tool = ":svelte_check",
308+
chdir = ".",
286309
srcs = glob(
287310
[
288311
"src/**/*.ts",

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Subpackage targets (finer-grained caching):
2222

2323
module(
2424
name = "tummycrypt_scheduling_kit",
25-
version = "0.7.5",
25+
version = "0.7.6",
2626
compatibility_level = 1,
2727
)
2828

docs/generated/package-surface.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Generated from `package.json` and the current `src/` tree.
1111
| Field | Value |
1212
| --- | --- |
1313
| Package | `@tummycrypt/scheduling-kit` |
14-
| Version | `0.7.5` |
14+
| Version | `0.7.6` |
1515
| Description | Backend-agnostic scheduling components with alternative payment support |
1616
| Node range | `>=20 <25` |
1717
| Repository | https://github.com/Jesssullivan/scheduling-kit.git |

docs/generated/release-metadata.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ Generated from `package.json`, `MODULE.bazel`, `BUILD.bazel`,
1111

1212
| Surface | Value |
1313
| --- | --- |
14-
| package.json version | `0.7.5` |
15-
| MODULE.bazel version | `0.7.5` |
16-
| BUILD.bazel npm_package version | `0.7.5` |
14+
| package.json version | `0.7.6` |
15+
| MODULE.bazel version | `0.7.6` |
16+
| BUILD.bazel npm_package version | `0.7.6` |
1717
| BUILD.bazel package name | `@tummycrypt/scheduling-kit` |
1818
| .bazelversion | `8.1.1` |
1919
| pnpm packageManager | `pnpm@9.15.9` |

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tummycrypt/scheduling-kit",
3-
"version": "0.7.5",
3+
"version": "0.7.6",
44
"description": "Backend-agnostic scheduling components with alternative payment support",
55
"type": "module",
66
"packageManager": "pnpm@9.15.9",
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#!/usr/bin/env node
2+
import { spawnSync } from "node:child_process";
3+
import {
4+
chmodSync,
5+
cpSync,
6+
existsSync,
7+
mkdtempSync,
8+
mkdirSync,
9+
readdirSync,
10+
rmSync,
11+
statSync,
12+
symlinkSync,
13+
} from "node:fs";
14+
import os from "node:os";
15+
import path from "node:path";
16+
import { fileURLToPath } from "node:url";
17+
import process from "node:process";
18+
19+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
20+
const packageRoot = path.resolve(scriptDir, "..");
21+
const originalCwd = process.cwd();
22+
23+
function resolveExistingPath(value) {
24+
if (path.isAbsolute(value)) {
25+
return value;
26+
}
27+
28+
const candidates = [
29+
path.join(packageRoot, value),
30+
value,
31+
path.join(originalCwd, value),
32+
process.env.JS_BINARY__EXECROOT
33+
? path.join(process.env.JS_BINARY__EXECROOT, value)
34+
: undefined,
35+
path.resolve(value),
36+
].filter(Boolean);
37+
38+
return candidates.find((candidate) => existsSync(candidate)) ?? value;
39+
}
40+
41+
function resolvePackageCli() {
42+
const candidates = [
43+
path.join(
44+
packageRoot,
45+
"node_modules",
46+
"@sveltejs",
47+
"package",
48+
"src",
49+
"cli.js",
50+
),
51+
path.join(
52+
originalCwd,
53+
"node_modules",
54+
"@sveltejs",
55+
"package",
56+
"src",
57+
"cli.js",
58+
),
59+
process.env.JS_BINARY__EXECROOT
60+
? path.join(
61+
process.env.JS_BINARY__EXECROOT,
62+
"node_modules",
63+
"@sveltejs",
64+
"package",
65+
"src",
66+
"cli.js",
67+
)
68+
: undefined,
69+
].filter(Boolean);
70+
71+
const cli = candidates.find((candidate) => existsSync(candidate));
72+
if (!cli) {
73+
throw new Error("Unable to locate @sveltejs/package CLI in Bazel runfiles");
74+
}
75+
return cli;
76+
}
77+
78+
function linkOrCopy(source, destination, copy = false) {
79+
rmSync(destination, { recursive: true, force: true });
80+
if (copy) {
81+
cpSync(source, destination, { recursive: true });
82+
return;
83+
}
84+
symlinkSync(source, destination);
85+
}
86+
87+
function makeWritable(target) {
88+
const stats = statSync(target);
89+
chmodSync(target, stats.isDirectory() ? 0o700 : 0o600);
90+
91+
if (!stats.isDirectory()) {
92+
return;
93+
}
94+
95+
for (const entry of readdirSync(target)) {
96+
makeWritable(path.join(target, entry));
97+
}
98+
}
99+
100+
function prepareWritableProject(inputDir) {
101+
const tempRoot = mkdtempSync(
102+
path.join(os.tmpdir(), "scheduling-kit-package-"),
103+
);
104+
const workDir = mkdirSync(path.join(tempRoot, "work"), { recursive: true });
105+
106+
linkOrCopy(inputDir, path.join(workDir, "src"));
107+
for (const file of ["package.json", "svelte.config.js", "tsconfig.json"]) {
108+
linkOrCopy(resolveExistingPath(file), path.join(workDir, file));
109+
}
110+
111+
const svelteKitDir = resolveExistingPath(".svelte-kit");
112+
if (existsSync(svelteKitDir)) {
113+
linkOrCopy(svelteKitDir, path.join(workDir, ".svelte-kit"), true);
114+
makeWritable(path.join(workDir, ".svelte-kit"));
115+
}
116+
117+
const nodeModulesDir = resolveExistingPath("node_modules");
118+
if (existsSync(nodeModulesDir)) {
119+
linkOrCopy(nodeModulesDir, path.join(workDir, "node_modules"));
120+
}
121+
122+
return { tempRoot, workDir };
123+
}
124+
125+
const forwardedArgs = [];
126+
let resolvedInput;
127+
let outputDir = "dist";
128+
for (let index = 0; index < process.argv.length - 2; index += 1) {
129+
const arg = process.argv[index + 2];
130+
131+
if (arg === "-i" || arg === "--input") {
132+
resolvedInput = resolveExistingPath(process.argv[index + 3]);
133+
forwardedArgs.push(arg, "src");
134+
index += 1;
135+
continue;
136+
}
137+
138+
if (arg.startsWith("--input=")) {
139+
resolvedInput = resolveExistingPath(arg.slice("--input=".length));
140+
forwardedArgs.push("--input=src");
141+
continue;
142+
}
143+
144+
if (arg === "-o" || arg === "--output") {
145+
outputDir = process.argv[index + 3];
146+
forwardedArgs.push(arg, path.resolve(originalCwd, outputDir));
147+
index += 1;
148+
continue;
149+
}
150+
151+
if (arg.startsWith("--output=")) {
152+
outputDir = arg.slice("--output=".length);
153+
forwardedArgs.push(`--output=${path.resolve(originalCwd, outputDir)}`);
154+
continue;
155+
}
156+
157+
forwardedArgs.push(arg);
158+
}
159+
160+
if (!resolvedInput) {
161+
throw new Error("Missing required svelte-package input directory");
162+
}
163+
164+
const { tempRoot, workDir } = prepareWritableProject(resolvedInput);
165+
const result = spawnSync(
166+
process.execPath,
167+
[resolvePackageCli(), ...forwardedArgs],
168+
{
169+
cwd: workDir,
170+
stdio: "inherit",
171+
env: process.env,
172+
},
173+
);
174+
rmSync(tempRoot, { recursive: true, force: true });
175+
176+
if (result.error) {
177+
console.error(result.error.message);
178+
process.exit(1);
179+
}
180+
181+
process.exit(result.status ?? 1);

0 commit comments

Comments
 (0)