@b9g/libuild 0.1.22 → 0.1.23

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": "@b9g/libuild",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "Zero-config library builds",
5
5
  "keywords": [
6
6
  "build",
@@ -22,18 +22,25 @@
22
22
  "libuild": "src/cli.js"
23
23
  },
24
24
  "dependencies": {
25
- "esbuild": "^0.19.0"
25
+ "commander": "^14.0.2",
26
+ "esbuild": "^0.19.0",
27
+ "expect": "^30.2.0",
28
+ "glob": "^13.0.0"
26
29
  },
27
30
  "devDependencies": {
28
31
  "@types/bun": "latest",
29
32
  "typescript": "^5.0.0"
30
33
  },
31
34
  "peerDependencies": {
32
- "typescript": "^5.0.0"
35
+ "typescript": "^5.0.0",
36
+ "playwright": "^1.40.0"
33
37
  },
34
38
  "peerDependenciesMeta": {
35
39
  "typescript": {
36
40
  "optional": true
41
+ },
42
+ "playwright": {
43
+ "optional": true
37
44
  }
38
45
  },
39
46
  "engines": {
@@ -47,34 +54,68 @@
47
54
  "CHANGELOG.md",
48
55
  "src/"
49
56
  ],
50
- "main": "src/libuild.cjs",
51
57
  "module": "src/libuild.js",
52
58
  "exports": {
53
59
  ".": {
54
60
  "types": "./src/libuild.d.ts",
55
- "import": "./src/libuild.js",
56
- "require": "./src/libuild.cjs"
61
+ "import": "./src/libuild.js"
57
62
  },
58
63
  "./cli": {
59
64
  "types": "./src/cli.d.ts",
60
- "import": "./src/cli.js",
61
- "require": "./src/cli.cjs"
65
+ "import": "./src/cli.js"
62
66
  },
63
67
  "./cli.js": {
64
68
  "types": "./src/cli.d.ts",
65
- "import": "./src/cli.js",
66
- "require": "./src/cli.cjs"
69
+ "import": "./src/cli.js"
67
70
  },
68
71
  "./libuild": {
69
72
  "types": "./src/libuild.d.ts",
70
- "import": "./src/libuild.js",
71
- "require": "./src/libuild.cjs"
73
+ "import": "./src/libuild.js"
72
74
  },
73
75
  "./libuild.js": {
74
76
  "types": "./src/libuild.d.ts",
75
- "import": "./src/libuild.js",
76
- "require": "./src/libuild.cjs"
77
+ "import": "./src/libuild.js"
78
+ },
79
+ "./package.json": "./package.json",
80
+ "./test": {
81
+ "types": "./src/test.d.ts",
82
+ "import": "./src/test.js"
83
+ },
84
+ "./test.js": {
85
+ "types": "./src/test.d.ts",
86
+ "import": "./src/test.js"
87
+ },
88
+ "./test-bun": {
89
+ "types": "./src/test-bun.d.ts",
90
+ "import": "./src/test-bun.js"
91
+ },
92
+ "./test-bun.js": {
93
+ "types": "./src/test-bun.d.ts",
94
+ "import": "./src/test-bun.js"
77
95
  },
78
- "./package.json": "./package.json"
96
+ "./test-node": {
97
+ "types": "./src/test-node.d.ts",
98
+ "import": "./src/test-node.js"
99
+ },
100
+ "./test-node.js": {
101
+ "types": "./src/test-node.d.ts",
102
+ "import": "./src/test-node.js"
103
+ },
104
+ "./test-browser": {
105
+ "types": "./src/test-browser.d.ts",
106
+ "import": "./src/test-browser.js"
107
+ },
108
+ "./test-browser.js": {
109
+ "types": "./src/test-browser.d.ts",
110
+ "import": "./src/test-browser.js"
111
+ },
112
+ "./test-runner": {
113
+ "types": "./src/test-runner.d.ts",
114
+ "import": "./src/test-runner.js"
115
+ },
116
+ "./test-runner.js": {
117
+ "types": "./src/test-runner.d.ts",
118
+ "import": "./src/test-runner.js"
119
+ }
79
120
  }
80
121
  }
@@ -0,0 +1,11 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ export {
10
+ __require
11
+ };
package/src/cli.js CHANGED
@@ -3,160 +3,51 @@
3
3
  /// <reference types="./cli.d.ts" />
4
4
 
5
5
  // src/cli.ts
6
- import { parseArgs } from "util";
6
+ import { Command } from "commander";
7
7
  import * as Path from "path";
8
8
  import { build, publish } from "./libuild.js";
9
- var { values, positionals } = parseArgs({
10
- args: process.argv.slice(2),
11
- options: {
12
- help: { type: "boolean", short: "h" },
13
- version: { type: "boolean", short: "v" },
14
- save: { type: "boolean" },
15
- "no-save": { type: "boolean" }
16
- },
17
- allowPositionals: true,
18
- strict: false
19
- // Allow unknown options to be passed through
9
+ import { runTests } from "./test-runner.js";
10
+ var program = new Command();
11
+ program.name("libuild").description("Zero-config library builds").version("0.1.22");
12
+ program.command("build", { isDefault: true }).description("Build the library").argument("[directory]", "Directory to build", ".").option("--save", "Update root package.json to point to dist files").action(async (directory, options) => {
13
+ const cwd = Path.resolve(directory);
14
+ await build(cwd, options.save || false);
20
15
  });
21
- var HELP_TEXT = `
22
- libuild - Zero-config library builds
23
-
24
- Usage:
25
- libuild [command] [directory] [options]
26
-
27
- Commands:
28
- build Build the library (default command)
29
- publish Build and publish the library
30
-
31
- Arguments:
32
- directory Optional directory to build (defaults to current directory)
33
-
34
- Options:
35
- --save Update root package.json to point to dist files
36
- --no-save Skip package.json updates (for publish command)
37
-
38
- IMPORTANT:
39
- \u2022 libuild is zero-config - there is NO libuild.config.js file
40
- \u2022 Configuration comes from your package.json (main, module, exports, etc.)
41
- \u2022 Use --save to regenerate package.json fields based on built files
42
- \u2022 Invalid bin/exports paths are automatically cleaned up with --save
43
-
44
- For publish command, all additional flags are forwarded to npm publish.
45
-
46
- Examples:
47
- libuild # Build the library in current directory
48
- libuild build # Same as above
49
- libuild ../other-proj # Build library in ../other-proj
50
- libuild build --save # Build and update package.json for npm link
51
- libuild publish ../lib # Build and publish library in ../lib
52
- libuild publish --dry-run --tag beta # Build and publish with npm flags
53
- `;
54
- async function main() {
55
- if (values.help) {
56
- console.log(HELP_TEXT);
57
- process.exit(0);
58
- }
59
- if (values.version) {
60
- const pkg = await import("../package.json");
61
- console.log(pkg.version);
62
- process.exit(0);
63
- }
64
- const command = positionals[0] || "build";
65
- let targetDir;
66
- for (let i = 1; i < positionals.length; i++) {
67
- const arg = positionals[i];
68
- const flagValueFlags = ["--tag", "--access", "--registry", "--otp", "--workspace"];
69
- const isValueForFlag = flagValueFlags.some((flag) => {
70
- const flagIndex = process.argv.indexOf(flag);
71
- const argIndex = process.argv.indexOf(arg);
72
- return flagIndex !== -1 && argIndex === flagIndex + 1;
73
- });
74
- if (isValueForFlag) {
75
- continue;
76
- }
77
- if (!arg.startsWith("--")) {
78
- try {
79
- const isSystemPath = Path.isAbsolute(arg) && (arg.startsWith("/bin/") || arg.startsWith("/usr/") || arg.startsWith("/etc/") || arg.startsWith("/var/") || arg.startsWith("/opt/") || arg.startsWith("/tmp/") || arg.startsWith("/System/") || arg.startsWith("/Applications/"));
80
- if (isSystemPath) {
81
- continue;
82
- }
83
- const resolvedPath = Path.resolve(arg);
84
- if (arg.includes("/") || arg.includes("\\") || arg === "." || arg === ".." || arg.startsWith("./") || arg.startsWith("../")) {
85
- targetDir = arg;
86
- break;
87
- }
88
- const fs = await import("fs/promises");
89
- try {
90
- const stat = await fs.stat(resolvedPath);
91
- if (stat.isDirectory() && !Path.isAbsolute(arg)) {
92
- targetDir = arg;
93
- break;
94
- }
95
- } catch {
96
- }
97
- } catch {
98
- }
99
- }
100
- }
101
- const cwd = targetDir ? Path.resolve(targetDir) : process.cwd();
102
- const shouldSave = values.save || command === "publish" && !values["no-save"];
103
- const allowedNpmFlags = [
104
- "--dry-run",
105
- "--tag",
106
- "--access",
107
- "--registry",
108
- "--otp",
109
- "--provenance",
110
- "--workspace",
111
- "--workspaces",
112
- "--include-workspace-root"
113
- ];
114
- const rawExtraArgs = process.argv.slice(2).filter(
115
- (arg) => !["build", "publish"].includes(arg) && !["--save", "--no-save", "--help", "-h", "--version", "-v"].includes(arg) && arg !== targetDir
116
- // Don't filter out the target directory
117
- );
118
- const extraArgs = [];
119
- for (let i = 0; i < rawExtraArgs.length; i++) {
120
- const arg = rawExtraArgs[i];
121
- if (arg.startsWith("--")) {
122
- const flagName = arg.split("=")[0];
123
- if (allowedNpmFlags.includes(flagName)) {
124
- extraArgs.push(arg);
125
- if (!arg.includes("=") && ["--tag", "--access", "--registry", "--otp", "--workspace"].includes(flagName)) {
126
- if (i + 1 < rawExtraArgs.length && !rawExtraArgs[i + 1].startsWith("--")) {
127
- extraArgs.push(rawExtraArgs[i + 1]);
128
- i++;
129
- }
130
- }
131
- } else {
132
- console.warn(`Warning: Ignoring unknown/unsafe npm flag: ${arg}`);
133
- }
134
- } else {
135
- const prevArg = i > 0 ? rawExtraArgs[i - 1] : "";
136
- const isPrevArgValueFlag = ["--tag", "--access", "--registry", "--otp", "--workspace"].includes(prevArg) && !prevArg.includes("=");
137
- if (isPrevArgValueFlag && extraArgs.includes(prevArg)) {
138
- extraArgs.push(arg);
139
- } else {
140
- console.warn(`Warning: Ignoring unexpected argument: ${arg}`);
141
- }
142
- }
143
- }
144
- try {
145
- switch (command) {
146
- case "build":
147
- await build(cwd, shouldSave);
148
- break;
149
- case "publish":
150
- await publish(cwd, shouldSave, extraArgs);
151
- break;
152
- default:
153
- console.error(`Unknown command: ${command}`);
154
- console.log(HELP_TEXT);
155
- process.exit(1);
156
- }
157
- } catch (error) {
158
- console.error("Error:", error.message);
16
+ program.command("publish").description("Build and publish the library").argument("[directory]", "Directory to build and publish", ".").option("--no-save", "Skip package.json updates").option("--dry-run", "Perform a dry run").option("--tag <tag>", "Publish with a specific tag").option("--access <access>", "Set access level (public/restricted)").option("--registry <url>", "Use a specific registry").option("--otp <code>", "One-time password for 2FA").option("--provenance", "Generate provenance statement").action(async (directory, options) => {
17
+ const cwd = Path.resolve(directory);
18
+ const shouldSave = options.save !== false;
19
+ const npmArgs = [];
20
+ if (options.dryRun)
21
+ npmArgs.push("--dry-run");
22
+ if (options.tag)
23
+ npmArgs.push("--tag", options.tag);
24
+ if (options.access)
25
+ npmArgs.push("--access", options.access);
26
+ if (options.registry)
27
+ npmArgs.push("--registry", options.registry);
28
+ if (options.otp)
29
+ npmArgs.push("--otp", options.otp);
30
+ if (options.provenance)
31
+ npmArgs.push("--provenance");
32
+ await publish(cwd, shouldSave, npmArgs);
33
+ });
34
+ program.command("test").description("Run tests across platforms").argument("[directory]", "Directory containing tests", ".").option("-p, --platform <platforms...>", "Platforms to test on (bun, node, chromium, firefox, webkit)").option("--debug", "Keep browser open for debugging").option("-w, --watch", "Watch mode - re-run tests on file changes").option("--timeout <ms>", "Test timeout in milliseconds", "60000").action(async (directory, options) => {
35
+ const cwd = Path.resolve(directory);
36
+ const validPlatforms = ["bun", "node", "chromium", "firefox", "webkit"];
37
+ const platforms = options.platform?.length ? options.platform.filter((p) => validPlatforms.includes(p)) : ["bun"];
38
+ if (options.platform?.length && platforms.length !== options.platform.length) {
39
+ const invalid = options.platform.filter((p) => !validPlatforms.includes(p));
40
+ console.error(`Invalid platform(s): ${invalid.join(", ")}`);
41
+ console.error(`Valid platforms: ${validPlatforms.join(", ")}`);
159
42
  process.exit(1);
160
43
  }
161
- }
162
- main();
44
+ const success = await runTests({
45
+ cwd,
46
+ platforms,
47
+ debug: options.debug || false,
48
+ watch: options.watch || false,
49
+ timeout: parseInt(options.timeout || "60000", 10)
50
+ });
51
+ process.exit(success ? 0 : 1);
52
+ });
53
+ program.parse();
package/src/libuild.js CHANGED
@@ -1,4 +1,6 @@
1
1
  /// <reference types="./libuild.d.ts" />
2
+ import "./_chunks/chunk-IBOCQ33F.js";
3
+
2
4
  // src/libuild.ts
3
5
  import * as FS3 from "fs/promises";
4
6
  import * as Path3 from "path";
@@ -1025,8 +1027,10 @@ async function build2(cwd, save = false) {
1025
1027
  const externalDeps = [
1026
1028
  "*.json",
1027
1029
  // Let Node.js handle JSON imports natively
1028
- "esbuild"
1030
+ "esbuild",
1029
1031
  // Explicit external to suppress require.resolve warning from esbuild's own code
1032
+ "bun:*"
1033
+ // Bun built-ins (bun:test, bun:sqlite, etc.)
1030
1034
  ];
1031
1035
  const entryPoints = [];
1032
1036
  const umdEntries = [];
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Browser test shim for @b9g/libuild/test
3
+ *
4
+ * Implements a minimal test runner that works in browsers.
5
+ * Results are exposed via globalThis.__LIBUILD_TEST__ for Playwright to poll.
6
+ */
7
+ interface Matchers {
8
+ toBe(expected: unknown): void;
9
+ toEqual(expected: unknown): void;
10
+ toStrictEqual(expected: unknown): void;
11
+ toBeTruthy(): void;
12
+ toBeFalsy(): void;
13
+ toBeNull(): void;
14
+ toBeUndefined(): void;
15
+ toBeDefined(): void;
16
+ toBeNaN(): void;
17
+ toBeGreaterThan(expected: number): void;
18
+ toBeGreaterThanOrEqual(expected: number): void;
19
+ toBeLessThan(expected: number): void;
20
+ toBeLessThanOrEqual(expected: number): void;
21
+ toContain(expected: unknown): void;
22
+ toHaveLength(expected: number): void;
23
+ toMatch(expected: RegExp | string): void;
24
+ toThrow(expected?: string | RegExp | Error): void;
25
+ toBeInstanceOf(expected: new (...args: any[]) => any): void;
26
+ not: Matchers;
27
+ }
28
+ export declare function expect(actual: unknown): Matchers;
29
+ declare global {
30
+ var __LIBUILD_TEST__: {
31
+ ended: boolean;
32
+ failed: number;
33
+ passed: number;
34
+ errors: Array<{
35
+ name: string;
36
+ error: string;
37
+ }>;
38
+ };
39
+ }
40
+ type TestFn = () => void | Promise<void>;
41
+ type HookFn = () => void | Promise<void>;
42
+ export declare function describe(name: string, fn: () => void): void;
43
+ export declare function test(name: string, fn: TestFn): void;
44
+ export declare const it: typeof test;
45
+ export declare function beforeEach(fn: HookFn): void;
46
+ export declare function afterEach(fn: HookFn): void;
47
+ export declare function beforeAll(fn: HookFn): void;
48
+ export declare function afterAll(fn: HookFn): void;
49
+ export {};