create-zenbu-app 0.0.3 → 0.0.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/dist/index.mjs CHANGED
@@ -7,10 +7,67 @@ import { spawnSync } from "node:child_process";
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
  const TEMPLATE_DIR = path.resolve(__dirname, "..", "template");
9
9
  const argv = process.argv.slice(2);
10
- const flags = new Set(argv.filter((a) => a.startsWith("-")));
10
+ const flagsSet = new Set(argv.filter((a) => a.startsWith("-")));
11
11
  const positional = argv.filter((a) => !a.startsWith("-"));
12
- const yes = flags.has("--yes") || flags.has("-y");
12
+ const yes = flagsSet.has("--yes") || flagsSet.has("-y");
13
+ const noInstall = flagsSet.has("--no-install");
13
14
  const ZENBU_LOCAL_CORE = process.env.ZENBU_LOCAL_CORE;
15
+ /**
16
+ * Detect the PM that invoked `create-zenbu-app`. Order:
17
+ * 1. `process.versions.bun` → bun (covers `bunx create-zenbu-app`).
18
+ * 2. `npm_config_user_agent` → "<pm>/<version> ..." (set by all of npm,
19
+ * pnpm, yarn classic, yarn berry).
20
+ * 3. Shell out to `<detected-name> --version` if user_agent only carries
21
+ * the bare name without a parseable version.
22
+ * 4. Fallback to pnpm with a hardcoded sane default.
23
+ */
24
+ function detectPackageManager() {
25
+ if (process.versions.bun) return {
26
+ type: "bun",
27
+ version: process.versions.bun,
28
+ fallback: false
29
+ };
30
+ const ua = process.env.npm_config_user_agent;
31
+ if (ua) {
32
+ const first = ua.split(" ")[0];
33
+ if (first) {
34
+ const slash = first.indexOf("/");
35
+ const name = (slash >= 0 ? first.slice(0, slash) : first).toLowerCase();
36
+ const version = slash >= 0 ? first.slice(slash + 1) : "";
37
+ if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") {
38
+ if (version && /^\d/.test(version)) return {
39
+ type: name,
40
+ version,
41
+ fallback: false
42
+ };
43
+ const probed = probeVersion(name);
44
+ if (probed) return {
45
+ type: name,
46
+ version: probed,
47
+ fallback: false
48
+ };
49
+ }
50
+ }
51
+ }
52
+ return {
53
+ type: "pnpm",
54
+ version: "10.33.0",
55
+ fallback: true
56
+ };
57
+ }
58
+ function probeVersion(pm) {
59
+ const res = spawnSync(pm, ["--version"], {
60
+ encoding: "utf8",
61
+ stdio: [
62
+ "ignore",
63
+ "pipe",
64
+ "ignore"
65
+ ]
66
+ });
67
+ if (res.status !== 0) return null;
68
+ const match = (res.stdout ?? "").trim().match(/\d+\.\d+\.\d+(?:[-+][\w.]+)?/);
69
+ return match ? match[0] : null;
70
+ }
14
71
  function renderTemplate(value, projectName) {
15
72
  return value.replace(/\{\{projectName\}\}/g, projectName);
16
73
  }
@@ -27,6 +84,19 @@ function copyDirSync(src, dest, projectName) {
27
84
  }
28
85
  }
29
86
  }
87
+ /**
88
+ * Replace the `// {{packageManager}}` marker in the scaffolded
89
+ * `zenbu.config.ts` with a real `packageManager: { ... }` line. Idempotent
90
+ * — running this twice yields the same file.
91
+ */
92
+ function seedPackageManager(projectDir, pm) {
93
+ const configPath = path.join(projectDir, "zenbu.config.ts");
94
+ if (!fs.existsSync(configPath)) return;
95
+ const original = fs.readFileSync(configPath, "utf8");
96
+ const literal = `packageManager: { type: "${pm.type}", version: "${pm.version}" },`;
97
+ const replaced = original.replace(/\/\/\s*\{\{packageManager\}\}/, literal);
98
+ if (replaced !== original) fs.writeFileSync(configPath, replaced);
99
+ }
30
100
  function rewireToLocalCore(projectDir, corePath) {
31
101
  const pkgPath = path.join(projectDir, "package.json");
32
102
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
@@ -63,6 +133,19 @@ function gitInitWithInitialCommit(projectDir) {
63
133
  }
64
134
  });
65
135
  }
136
+ /**
137
+ * Run `<pm> install` in the freshly-scaffolded project so the user can go
138
+ * straight to `pnpm dev`/`bun dev`/etc. without the extra step. We run with
139
+ * the user's globally-installed PM (which is what they used to invoke us in
140
+ * the first place), so this won't hit the bundled toolchain — that only
141
+ * matters at the .app's first launch on the consumer's machine.
142
+ */
143
+ function runInstall(projectDir, pm) {
144
+ return spawnSync(pm.type, ["install"], {
145
+ cwd: projectDir,
146
+ stdio: "inherit"
147
+ }).status === 0;
148
+ }
66
149
  function main() {
67
150
  const projectName = positional[0] ?? ".";
68
151
  if (projectName === "." && !yes) {
@@ -70,7 +153,7 @@ function main() {
70
153
  process.exit(1);
71
154
  }
72
155
  const projectDir = path.resolve(process.cwd(), projectName);
73
- const displayName = projectName === "." ? path.basename(projectDir) : projectName;
156
+ const displayName = path.basename(projectDir);
74
157
  if (fs.existsSync(projectDir)) {
75
158
  const entries = fs.readdirSync(projectDir).filter((e) => e !== ".git");
76
159
  const allowedExisting = projectName === "." && fs.existsSync(path.join(projectDir, "package.json"));
@@ -79,19 +162,30 @@ function main() {
79
162
  process.exit(1);
80
163
  }
81
164
  }
82
- console.log(`\nScaffolding Zenbu app in "${displayName}"...\n`);
165
+ const pm = detectPackageManager();
166
+ console.log(`\nScaffolding Zenbu app in "${displayName}"...`);
167
+ if (pm.fallback) console.log(` → couldn't detect invoking package manager; defaulting to ${pm.type}@${pm.version}.`);
168
+ else console.log(` → detected ${pm.type}@${pm.version} as the invoking package manager`);
169
+ console.log("");
83
170
  copyDirSync(TEMPLATE_DIR, projectDir, displayName);
84
171
  const gi = path.join(projectDir, "_gitignore");
85
172
  if (fs.existsSync(gi)) fs.renameSync(gi, path.join(projectDir, ".gitignore"));
173
+ seedPackageManager(projectDir, pm);
86
174
  if (ZENBU_LOCAL_CORE) {
87
175
  const corePath = path.resolve(ZENBU_LOCAL_CORE);
88
176
  rewireToLocalCore(projectDir, corePath);
89
177
  console.log(` → linked @zenbujs/core -> ${corePath}`);
90
178
  }
179
+ let installed = false;
180
+ if (!noInstall) {
181
+ console.log(` → running ${pm.type} install\n`);
182
+ installed = runInstall(projectDir, pm);
183
+ if (!installed) console.warn(` → ${pm.type} install failed; you can retry manually after the scaffold completes.\n`);
184
+ }
91
185
  if (!fs.existsSync(path.join(projectDir, ".git"))) gitInitWithInitialCommit(projectDir);
92
186
  const cdHint = projectName === "." ? "" : `cd ${displayName} && `;
93
- console.log(`Done. Next:\n\n ${cdHint}pnpm install\n pnpm dev\n`);
94
- console.log(`Note: Zenbu currently requires pnpm 10+.\n`);
187
+ if (installed) console.log(`Done. Next:\n\n ${cdHint}${pm.type} dev\n`);
188
+ else console.log(`Done. Next:\n\n ${cdHint}${pm.type} install\n ${pm.type} dev\n`);
95
189
  }
96
190
  try {
97
191
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-zenbu-app",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "description": "Scaffold a new Zenbu app",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -3,3 +3,6 @@ dist/
3
3
  .zenbu/
4
4
  node_modules/.zenbujs/
5
5
  tsconfig.local.json
6
+ .env
7
+ .env.*
8
+ !.env.example
@@ -12,10 +12,12 @@
12
12
  "db:generate": "zen db generate"
13
13
  },
14
14
  "dependencies": {
15
- "@zenbujs/core": "0.0.5",
15
+ "@zenbujs/core": "^0.0.9",
16
+ "@tailwindcss/vite": "^4.2.0",
16
17
  "@vitejs/plugin-react": "^5.0.0",
17
18
  "react": "^19.0.0",
18
19
  "react-dom": "^19.0.0",
20
+ "tailwindcss": "^4.2.0",
19
21
  "vite": "^6.0.0",
20
22
  "zod": "^4.0.0"
21
23
  },
@@ -0,0 +1,16 @@
1
+ import { createSchema, InferRoot, InferSchema, z } from "@zenbujs/core/db"
2
+
3
+ export const schema = createSchema({
4
+ issues: z
5
+ .array(
6
+ z.object({
7
+ id: z.string(),
8
+ title: z.string(),
9
+ createdAt: z.number(),
10
+ }),
11
+ )
12
+ .default([]),
13
+ })
14
+
15
+ export type AppSchema = InferSchema<typeof schema>
16
+ export type SchemaRoot = InferRoot<AppSchema>
@@ -1,14 +1,11 @@
1
- import { runtime, serviceWithDeps } from "@zenbujs/core/runtime"
1
+ import { Service } from "@zenbujs/core/runtime"
2
2
  import { WindowService } from "@zenbujs/core/services"
3
3
 
4
- export class AppService extends serviceWithDeps({
5
- window: WindowService,
4
+ export class AppService extends Service.create({
5
+ key: "app",
6
+ deps: { window: WindowService },
6
7
  }) {
7
- static key = "app"
8
-
9
8
  async evaluate() {
10
- await this.ctx.window.openView({ scope: "app" })
9
+ await this.ctx.window.openView({ type: "app" })
11
10
  }
12
11
  }
13
-
14
- runtime.register(AppService, import.meta)
@@ -0,0 +1,11 @@
1
+ import { Service } from "@zenbujs/core/runtime"
2
+
3
+ /**
4
+ * Sample RPC service. Methods on the class are callable from the renderer
5
+ * via `useRpc()` — see `src/renderer/App.tsx`.
6
+ */
7
+ export class Repo extends Service.create({ key: "repo" }) {
8
+ async getCwd() {
9
+ return process.cwd()
10
+ }
11
+ }
@@ -1,43 +1,102 @@
1
+ import { ZenbuProvider, useDb, useDbClient, useRpc } from "@zenbujs/core/react"
2
+ import { useState } from "react"
3
+
1
4
  function Titlebar() {
2
5
  return (
3
6
  <div
4
- style={{
5
- height: 40,
6
- display: "flex",
7
- alignItems: "center",
8
- justifyContent: "flex-end",
9
- padding: "0 12px 0 72px",
10
- // @ts-expect-error webkit property
11
- WebkitAppRegion: "drag",
12
- flexShrink: 0,
13
- }}
7
+ className="h-10 flex items-center justify-end px-3 pl-[72px] shrink-0"
8
+ // @ts-expect-error webkit property
9
+ style={{ WebkitAppRegion: "drag" }}
14
10
  />
15
11
  )
16
12
  }
17
13
 
18
14
  function Home() {
15
+ const db = useDb()
16
+ const client = useDbClient()
17
+ const rpc = useRpc()
18
+ const [cwd, setCwd] = useState<string | null>(null)
19
+
20
+ const issues = db.plugin.app.issues
21
+
19
22
  return (
20
- <main
21
- style={{
22
- flex: 1,
23
- padding: "0 32px 32px",
24
- fontFamily: "system-ui, -apple-system, sans-serif",
25
- color: "var(--foreground, #e5e5e5)",
26
- }}
27
- >
28
- <h1>Welcome to Zenbu</h1>
29
- <p style={{ color: "var(--muted-foreground, #999)", marginTop: 8 }}>
23
+ <main className="flex-1 px-8 pb-8 font-sans text-[#e5e5e5]">
24
+ <h1 className="text-2xl font-bold mb-2">Welcome to Zenbu</h1>
25
+ <p className="text-[#888] mb-6">
30
26
  Edit <code>src/renderer/App.tsx</code> to get started.
31
27
  </p>
28
+
29
+ <form
30
+ className="flex flex-col gap-3 bg-[#18181b] rounded-xl p-4 max-w-md mb-6"
31
+ onSubmit={(e) => {
32
+ e.preventDefault()
33
+ const form = e.currentTarget
34
+ const title = (form.elements.namedItem("title") as HTMLInputElement).value
35
+ if (!title.trim()) return
36
+ client.update((db) => {
37
+ db.plugin.app.issues.push({
38
+ id: crypto.randomUUID(),
39
+ title,
40
+ createdAt: Date.now(),
41
+ })
42
+ })
43
+ form.reset()
44
+ }}
45
+ >
46
+ <input
47
+ name="title"
48
+ placeholder="New issue title"
49
+ autoComplete="off"
50
+ className="px-3 py-2 rounded bg-[#222] border border-[#333] outline-none focus:border-indigo-500"
51
+ />
52
+ <button
53
+ type="submit"
54
+ className="bg-indigo-600 hover:bg-indigo-700 transition text-white font-semibold px-4 py-2 rounded"
55
+ >
56
+ + add
57
+ </button>
58
+ </form>
59
+
60
+ <div className="max-w-md mb-6">
61
+ {issues.length === 0 ? (
62
+ <div className="text-[#888] italic">No issues yet — try adding one.</div>
63
+ ) : (
64
+ issues.map((issue) => (
65
+ <div
66
+ key={issue.id}
67
+ className="mb-2 p-3 rounded-lg bg-[#222] border border-[#2a2a2a] flex items-center justify-between"
68
+ >
69
+ <span>{issue.title}</span>
70
+ <span className="text-xs text-[#666]">
71
+ {new Date(issue.createdAt).toLocaleTimeString()}
72
+ </span>
73
+ </div>
74
+ ))
75
+ )}
76
+ </div>
77
+
78
+ <button
79
+ className="bg-zinc-800 hover:bg-zinc-700 px-4 py-2 rounded text-sm"
80
+ onClick={async () => setCwd(await rpc.repo.getCwd())}
81
+ >
82
+ rpc → main process cwd
83
+ </button>
84
+ {cwd && (
85
+ <div className="mt-2 p-2 rounded bg-[#232328] text-[#b0b0b0] w-fit text-xs">
86
+ {cwd}
87
+ </div>
88
+ )}
32
89
  </main>
33
90
  )
34
91
  }
35
92
 
36
93
  export function App() {
37
94
  return (
38
- <div style={{ display: "flex", flexDirection: "column", minHeight: "100vh" }}>
39
- <Titlebar />
40
- <Home />
41
- </div>
95
+ <ZenbuProvider>
96
+ <div className="flex flex-col min-h-screen">
97
+ <Titlebar />
98
+ <Home />
99
+ </div>
100
+ </ZenbuProvider>
42
101
  )
43
102
  }
@@ -1,3 +1,5 @@
1
+ @import "tailwindcss";
2
+
1
3
  * {
2
4
  box-sizing: border-box;
3
5
  }
@@ -5,4 +7,5 @@
5
7
  body {
6
8
  margin: 0;
7
9
  background: #111;
10
+ color: #e5e5e5;
8
11
  }
@@ -0,0 +1,118 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="zenbu-bg" content="#111">
6
+ <title>Installing</title>
7
+ <style>
8
+ html, body {
9
+ height: 100%;
10
+ margin: 0;
11
+ padding: 0;
12
+ background: #111;
13
+ color: #ddd;
14
+ font: 13px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
15
+ -webkit-app-region: drag;
16
+ user-select: none;
17
+ }
18
+ body {
19
+ display: flex;
20
+ flex-direction: column;
21
+ align-items: center;
22
+ justify-content: center;
23
+ gap: 18px;
24
+ padding: 32px;
25
+ box-sizing: border-box;
26
+ }
27
+ .label {
28
+ font-size: 14px;
29
+ color: #f0f0f0;
30
+ letter-spacing: 0.2px;
31
+ min-height: 1.4em;
32
+ text-align: center;
33
+ }
34
+ .bar {
35
+ width: min(360px, 70%);
36
+ height: 4px;
37
+ background: #2a2a2a;
38
+ border-radius: 2px;
39
+ overflow: hidden;
40
+ position: relative;
41
+ }
42
+ .bar-fill {
43
+ position: absolute;
44
+ inset: 0 auto 0 0;
45
+ width: 0%;
46
+ background: #f0f0f0;
47
+ transition: width 180ms ease-out;
48
+ }
49
+ .bar.indeterminate .bar-fill {
50
+ width: 30%;
51
+ animation: slide 1.2s ease-in-out infinite;
52
+ }
53
+ @keyframes slide {
54
+ 0% { transform: translateX(-100%); }
55
+ 100% { transform: translateX(366%); }
56
+ }
57
+ .message {
58
+ font-size: 11px;
59
+ color: #888;
60
+ font-family: "SF Mono", Menlo, Consolas, monospace;
61
+ max-width: min(420px, 90%);
62
+ text-align: center;
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ white-space: nowrap;
66
+ min-height: 1.4em;
67
+ }
68
+ </style>
69
+ </head>
70
+ <body>
71
+ <div class="label" id="label">Starting&hellip;</div>
72
+ <div class="bar indeterminate" id="bar"><div class="bar-fill" id="fill"></div></div>
73
+ <div class="message" id="message"></div>
74
+ <script>
75
+ // The framework's built-in preload exposes `window.zenbuInstall` with
76
+ // `.on(event, cb)` returning an unsubscribe function. Events:
77
+ // step: { id: "clone" | "fetch" | "install" | "handoff", label }
78
+ // message: { text }
79
+ // progress: { phase?, loaded?, total?, ratio? }
80
+ // done: { id }
81
+ // error: { id?, message }
82
+ const api = window.zenbuInstall;
83
+ const labelEl = document.getElementById("label");
84
+ const messageEl = document.getElementById("message");
85
+ const barEl = document.getElementById("bar");
86
+ const fillEl = document.getElementById("fill");
87
+ if (api) {
88
+ api.on("step", (p) => {
89
+ if (p && p.label) labelEl.textContent = p.label;
90
+ barEl.classList.add("indeterminate");
91
+ fillEl.style.width = "";
92
+ });
93
+ api.on("message", (p) => {
94
+ if (p && p.text) messageEl.textContent = p.text;
95
+ });
96
+ api.on("progress", (p) => {
97
+ const ratio = p && typeof p.ratio === "number" ? p.ratio : null;
98
+ if (ratio != null && ratio >= 0) {
99
+ barEl.classList.remove("indeterminate");
100
+ fillEl.style.width = Math.max(2, Math.min(100, ratio * 100)) + "%";
101
+ } else {
102
+ barEl.classList.add("indeterminate");
103
+ }
104
+ });
105
+ api.on("done", () => {
106
+ messageEl.textContent = "";
107
+ });
108
+ api.on("error", (p) => {
109
+ labelEl.textContent = "Failed";
110
+ if (p && p.message) messageEl.textContent = p.message;
111
+ barEl.classList.remove("indeterminate");
112
+ fillEl.style.width = "100%";
113
+ fillEl.style.background = "#d04444";
114
+ });
115
+ }
116
+ </script>
117
+ </body>
118
+ </html>
@@ -2,50 +2,21 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <meta name="zenbu-bg" content="#F4F4F4">
5
+ <meta name="zenbu-bg" content="#111">
6
6
  <style>
7
- * { margin: 0; padding: 0; box-sizing: border-box; }
8
- html, body { height: 100%; overflow: hidden; }
9
- body {
10
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
11
- background: #F4F4F4;
12
- -webkit-app-region: drag;
13
- user-select: none;
14
- padding: 52px 48px 32px;
15
- display: flex;
16
- flex-direction: column;
17
- gap: 16px;
7
+ html, body {
8
+ height: 100%;
9
+ margin: 0;
10
+ padding: 0;
11
+ background: #111;
18
12
  }
19
13
  @media (prefers-color-scheme: dark) {
20
- body { background: #1a1a1a; }
21
- .skeleton { background: #2a2a2a; }
22
- .skeleton::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,0.03), transparent); }
14
+ html, body {
15
+ background: #111;
16
+ }
23
17
  }
24
- .skeleton {
25
- background: #e5e5e5;
26
- border-radius: 6px;
27
- position: relative;
28
- overflow: hidden;
29
- }
30
- .skeleton::after {
31
- content: "";
32
- position: absolute;
33
- inset: 0;
34
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
35
- animation: shimmer 1.5s infinite;
36
- }
37
- @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
38
- .title { height: 28px; width: 35%; }
39
- .line { height: 14px; }
40
- .line:nth-child(2) { width: 90%; }
41
- .line:nth-child(3) { width: 70%; }
42
- .line:nth-child(4) { width: 80%; }
43
18
  </style>
44
19
  </head>
45
20
  <body>
46
- <div class="skeleton title"></div>
47
- <div class="skeleton line"></div>
48
- <div class="skeleton line"></div>
49
- <div class="skeleton line"></div>
50
21
  </body>
51
22
  </html>
@@ -2,12 +2,13 @@ import path from "node:path"
2
2
  import { fileURLToPath } from "node:url"
3
3
  import { defineConfig } from "vite"
4
4
  import react from "@vitejs/plugin-react"
5
+ import tailwindcss from "@tailwindcss/vite"
5
6
 
6
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
8
 
8
9
  export default defineConfig({
9
10
  root: path.resolve(__dirname, "src", "renderer"),
10
- plugins: [react()],
11
+ plugins: [react(), tailwindcss()],
11
12
  resolve: {
12
13
  alias: {
13
14
  "@": path.resolve(__dirname, "src", "renderer"),
@@ -2,9 +2,7 @@ import {
2
2
  defineConfig,
3
3
  definePlugin,
4
4
  defineBuildConfig,
5
- stripIfDisabled,
6
- dropFiles,
7
- } from "@zenbujs/core/config";
5
+ } from "@zenbujs/core/config"
8
6
 
9
7
  export default defineConfig({
10
8
  // Where the kyju database lives (relative to this file).
@@ -19,6 +17,7 @@ export default defineConfig({
19
17
  definePlugin({
20
18
  name: "app",
21
19
  services: ["./src/main/services/*.ts"],
20
+ schema: "./src/main/schema.ts",
22
21
  }),
23
22
  ],
24
23
 
@@ -26,10 +25,18 @@ export default defineConfig({
26
25
  // `zen build:electron` (signed .app via electron-builder). Set
27
26
  // `mirror.target` to "<owner>/<repo>" before shipping.
28
27
  build: defineBuildConfig({
28
+ // {{packageManager}}
29
+ // The .app's "host version" — bump every time you ship a new
30
+ // .app build. Each commit's `package.json#zenbu.host` semver range
31
+ // is checked against this value at launch (and from
32
+ // `UpdaterService.update()`); incompatible commits are skipped, so
33
+ // older .apps stay pinned to source they can actually run.
34
+ hostVersion: "0.0.1",
29
35
  source: ".",
30
36
  out: ".zenbu/build/source",
31
37
  include: [
32
38
  "src/**/*",
39
+ ".gitignore",
33
40
  "package.json",
34
41
  "pnpm-lock.yaml",
35
42
  "tsconfig.json",
@@ -43,10 +50,6 @@ export default defineConfig({
43
50
  "src/**/*.spec.tsx",
44
51
  "src/dev-only/**",
45
52
  ],
46
- transforms: [
47
- stripIfDisabled({ FLAG_BETA: false }),
48
- dropFiles(/\.stories\.tsx?$/),
49
- ],
50
53
  // mirror: { target: "{{owner}}/{{repo}}", branch: "main" },
51
54
  }),
52
- });
55
+ })