@solcreek/cli 0.4.5 → 0.4.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @solcreek/cli
2
2
 
3
+ ## 0.4.6
4
+
5
+ ### Features
6
+
7
+ - **`creek deploy gh:owner/repo` shorthand** — a shorter alias for
8
+ `https://github.com/owner/repo`. Matches the GitHub CLI convention.
9
+ `gh:`, `gl:` (GitLab), and `bb:` (Bitbucket) are now all registered
10
+ alongside the longer `github:` / `gitlab:` / `bitbucket:` forms.
11
+ Example: `npx creek deploy gh:jiseeeh/serene-ink`.
12
+
13
+ ### Fixes / DX
14
+
15
+ - **Install size cut from ~170MB to ~25MB** by moving `miniflare` out of
16
+ runtime dependencies entirely. Miniflare plus its transitive deps
17
+ (workerd, sharp) was adding ~146MB to every `npm install creek` — a
18
+ pure penalty on the `creek deploy` flow, which never touches
19
+ miniflare. `miniflare` is now listed in `devDependencies` only, so
20
+ the published package is free of it. First-time `npx creek deploy`
21
+ goes from ~20s install to ~3–5s, and the postinstall warnings that
22
+ used to appear on systems without build tools (sharp's node-gyp
23
+ fallback) are gone entirely.
24
+
25
+ - **`creek dev` loads miniflare from multiple locations** via
26
+ `createRequire` — the user's current project (`npm install --save-dev
27
+ miniflare`), a creek-managed cache directory at `~/.creek/deps`, or
28
+ the global npm root (`npm install -g miniflare`). If none of those
29
+ have it, a jargon-free error explains what to install and where.
30
+ Users who only want to deploy never see this error because
31
+ `creek deploy` doesn't load the local runtime at all.
32
+
3
33
  ## 0.4.5
4
34
 
5
35
  ### Features
@@ -1,4 +1,14 @@
1
1
  import type { BindingDeclaration } from "@solcreek/sdk";
2
+ /**
3
+ * Thrown by `creek dev` when no local runtime package can be resolved from
4
+ * the user's project, global npm root, or creek's dep cache. The message
5
+ * is deliberately jargon-free: it talks about "a local runtime" instead of
6
+ * naming miniflare in the explanation, and only mentions the package name
7
+ * as part of the exact npm command the user needs to run.
8
+ */
9
+ export declare class MiniflareNotInstalledError extends Error {
10
+ constructor();
11
+ }
2
12
  export interface WorkerRunnerOptions {
3
13
  /** User's worker entry point (e.g. "worker/index.ts"). */
4
14
  entryPoint: string;
@@ -1,11 +1,93 @@
1
- // Worker execution for `creek dev` — bundles user code and runs it via Miniflare.
1
+ // Worker execution for `creek dev` — bundles user code and runs it via
2
+ // Miniflare for local D1 / KV / R2 / Queues / Durable Objects simulation.
2
3
  //
3
- // Uses esbuild watch mode for hot reload and Miniflare for D1/KV/R2 simulation.
4
+ // `miniflare` is intentionally NOT in @solcreek/cli's runtime dependencies
5
+ // it (plus its transitive deps workerd and sharp) adds ~146MB to every
6
+ // install of `creek`. Since `creek deploy` never touches miniflare, it's
7
+ // a pure penalty on the aha-moment flow: paste a command, see a live URL.
8
+ //
9
+ // Instead, `creek dev` resolves miniflare at runtime from the caller's
10
+ // project (npm install --save-dev miniflare in their own package.json),
11
+ // the global npm root, or a creek-managed cache dir. If none of those
12
+ // have miniflare, we throw a zero-jargon error that tells the user
13
+ // exactly one command to run.
4
14
  import { writeFileSync, mkdirSync } from "node:fs";
5
15
  import { join, resolve } from "node:path";
16
+ import { createRequire } from "node:module";
17
+ import { homedir } from "node:os";
18
+ import { execSync } from "node:child_process";
6
19
  import { context } from "esbuild";
7
- import { Miniflare } from "miniflare";
8
20
  import { generateWorkerWrapper } from "../utils/worker-bundle.js";
21
+ /**
22
+ * Thrown by `creek dev` when no local runtime package can be resolved from
23
+ * the user's project, global npm root, or creek's dep cache. The message
24
+ * is deliberately jargon-free: it talks about "a local runtime" instead of
25
+ * naming miniflare in the explanation, and only mentions the package name
26
+ * as part of the exact npm command the user needs to run.
27
+ */
28
+ export class MiniflareNotInstalledError extends Error {
29
+ constructor() {
30
+ super([
31
+ "`creek dev` needs a local runtime to simulate the edge environment,",
32
+ "and it isn't installed yet.",
33
+ "",
34
+ " One-time setup — run this in your project directory:",
35
+ " npm install --save-dev miniflare",
36
+ "",
37
+ " This downloads ~150MB but only needs to happen once per project.",
38
+ " `creek deploy` already works without it — you can skip this step",
39
+ " entirely if you only want to deploy.",
40
+ ].join("\n"));
41
+ this.name = "MiniflareNotInstalledError";
42
+ }
43
+ }
44
+ /**
45
+ * Try to load miniflare from several plausible locations, in order of
46
+ * preference:
47
+ *
48
+ * 1. The user's current project (npm install --save-dev miniflare)
49
+ * 2. Creek-managed dep cache at ~/.creek/deps/miniflare (for future
50
+ * auto-install support — not wired up yet but already searched here
51
+ * so a future `creek dev install` command can drop files there)
52
+ * 3. Global npm root (for users who `npm install -g miniflare`)
53
+ *
54
+ * Each location is attempted with a fresh `createRequire` rooted at a
55
+ * dummy file in that directory, then `require.resolve("miniflare")` is
56
+ * used to find the package. If all three fail, throws
57
+ * MiniflareNotInstalledError with a zero-jargon explanation.
58
+ */
59
+ async function loadMiniflare() {
60
+ const searchRoots = [];
61
+ // 1. User's current project
62
+ searchRoots.push(process.cwd());
63
+ // 2. Creek-managed cache
64
+ searchRoots.push(join(homedir(), ".creek", "deps"));
65
+ // 3. Global npm root (best-effort — may be slow on first call)
66
+ try {
67
+ const globalRoot = execSync("npm root -g", {
68
+ encoding: "utf-8",
69
+ stdio: ["ignore", "pipe", "ignore"],
70
+ }).trim();
71
+ if (globalRoot)
72
+ searchRoots.push(globalRoot);
73
+ }
74
+ catch {
75
+ // No npm on PATH, or command failed — skip this search path silently.
76
+ }
77
+ for (const root of searchRoots) {
78
+ try {
79
+ // createRequire needs a file path — use a dummy file inside the root
80
+ // (the file doesn't have to exist for node_modules lookup to work).
81
+ const req = createRequire(join(root, "__creek_resolver__.js"));
82
+ const resolved = req.resolve("miniflare");
83
+ return (await import(resolved));
84
+ }
85
+ catch {
86
+ // Try the next root.
87
+ }
88
+ }
89
+ throw new MiniflareNotInstalledError();
90
+ }
9
91
  const NODE_BUILTINS = [
10
92
  "node:async_hooks",
11
93
  "node:stream",
@@ -52,9 +134,14 @@ export class WorkerRunner {
52
134
  writeFileSync(wrapperPath, wrapper);
53
135
  // 2. Initial bundle with esbuild
54
136
  const bundledScript = await this.bundle(wrapperPath);
55
- // 3. Start Miniflare
137
+ // 3. Start Miniflare — loaded from the user's project / cache / global
138
+ // so `creek deploy` can ship without miniflare in @solcreek/cli's
139
+ // runtime dependencies. See loadMiniflare() above for the search
140
+ // order and the MiniflareNotInstalledError message.
141
+ const miniflareModule = await loadMiniflare();
142
+ const MiniflareCtor = miniflareModule.Miniflare;
56
143
  this.mfOptions = this.buildMiniflareOptions(bundledScript, persistDir);
57
- this.mf = new Miniflare(this.mfOptions);
144
+ this.mf = new MiniflareCtor(this.mfOptions);
58
145
  // Wait for Miniflare to be ready and get the port
59
146
  const readyUrl = await this.mf.ready;
60
147
  // mf.ready returns a URL object
@@ -28,8 +28,11 @@ export declare function isRepoUrl(input: string): boolean;
28
28
  * https://github.com/owner/repo.git
29
29
  * https://github.com/owner/repo#branch
30
30
  * https://github.com/owner/repo/tree/branch
31
- * github:owner/repo
32
- * github:owner/repo#branch
31
+ * github:owner/repo (long-form shorthand)
32
+ * gh:owner/repo (short alias — matches gh CLI convention)
33
+ * gh:owner/repo#branch
34
+ * gitlab:owner/repo gl:owner/repo
35
+ * bitbucket:owner/repo bb:owner/repo
33
36
  */
34
37
  export declare function parseRepoUrl(input: string): ParsedRepoUrl;
35
38
  /**
@@ -17,10 +17,17 @@ const PROVIDER_HOSTS = {
17
17
  "bitbucket.org": "bitbucket",
18
18
  "www.bitbucket.org": "bitbucket",
19
19
  };
20
+ // Shorthand prefixes. Short aliases (gh:/gl:/bb:) match the conventions
21
+ // established by the GitHub CLI, GitLab CLI, and other tooling — they're
22
+ // the shortest safe way to reference a repo without colliding with local
23
+ // path syntax (local paths never have ':' before any '/').
20
24
  const SHORTHAND_PREFIXES = {
21
25
  "github:": "github",
26
+ "gh:": "github",
22
27
  "gitlab:": "gitlab",
28
+ "gl:": "gitlab",
23
29
  "bitbucket:": "bitbucket",
30
+ "bb:": "bitbucket",
24
31
  };
25
32
  // Strict character set for owner and repo names
26
33
  const SAFE_NAME = /^[a-zA-Z0-9._-]+$/;
@@ -53,8 +60,11 @@ export function isRepoUrl(input) {
53
60
  * https://github.com/owner/repo.git
54
61
  * https://github.com/owner/repo#branch
55
62
  * https://github.com/owner/repo/tree/branch
56
- * github:owner/repo
57
- * github:owner/repo#branch
63
+ * github:owner/repo (long-form shorthand)
64
+ * gh:owner/repo (short alias — matches gh CLI convention)
65
+ * gh:owner/repo#branch
66
+ * gitlab:owner/repo gl:owner/repo
67
+ * bitbucket:owner/repo bb:owner/repo
58
68
  */
59
69
  export function parseRepoUrl(input) {
60
70
  if (!input || typeof input !== "string") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solcreek/cli",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "CLI for the Creek deployment platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,6 @@
31
31
  "citty": "^0.1.6",
32
32
  "consola": "^3.4.2",
33
33
  "esbuild": "^0.25.0",
34
- "miniflare": "^4.20260317.3",
35
34
  "smol-toml": "^1.3.1",
36
35
  "ws": "^8.20.0",
37
36
  "@solcreek/sdk": "0.4.2"
@@ -44,6 +43,7 @@
44
43
  "@types/ws": "^8.18.1",
45
44
  "hono": "^4.7.4",
46
45
  "jsdom": "^29.0.1",
46
+ "miniflare": "^4.20260317.3",
47
47
  "react": "^19.2.4",
48
48
  "react-dom": "^19.2.4",
49
49
  "typescript": "^5.8.2",