@incajs/cli 0.0.3 → 0.0.4

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/README.md CHANGED
@@ -43,7 +43,7 @@ export default defineConfig({
43
43
  productName: "Click Counter",
44
44
  // macOS's CFBundleIdentifier or equivalent
45
45
  identifier: "com.example.click-counter",
46
- // the packaged app's icon file
46
+ // the app's icon file
47
47
  icon: "assets/icon.icns",
48
48
  });
49
49
  ```
@@ -51,6 +51,10 @@ export default defineConfig({
51
51
  An `identifier` should be world-unique, so `inca package` prints a note
52
52
  when it falls back to the generated one rather than using it silently.
53
53
 
54
+ On macOS, `inca dev` launches the app under its `productName`, `icon` and
55
+ `identifier`, so the Dock and the menu bar show the same app they will
56
+ once it is packaged.
57
+
54
58
  ## Requirements
55
59
 
56
60
  `inca`'s host binary is pulled in automatically as a platform-specific
@@ -9,6 +9,11 @@ export interface BundlerOptions {
9
9
  entry: string;
10
10
  /** Where the build's output is written. */
11
11
  outDir: string;
12
+ /**
13
+ * Values the built app carries for `inca-host` to read — its name, id
14
+ * and window. Any JSON-serializable object.
15
+ */
16
+ runtimeConfig?: unknown;
12
17
  /** `"development"` keeps a framework's own warnings; `"production"` strips them. */
13
18
  mode: "development" | "production";
14
19
  /** Called after each successful (re)build, with what it wrote. */
@@ -36,6 +41,11 @@ export interface BuildOptions {
36
41
  entry: string;
37
42
  /** Where the build's output is written. */
38
43
  outDir: string;
44
+ /**
45
+ * Values the built app carries for `inca-host` to read — its name, id
46
+ * and window. Any JSON-serializable object.
47
+ */
48
+ runtimeConfig?: unknown;
39
49
  /** Where the bundler's own output goes. Defaults to `process.stdout`. */
40
50
  stdout?: NodeJS.WritableStream;
41
51
  /** Where the bundler's warnings and errors go. Defaults to `process.stderr`. */
@@ -5,4 +5,4 @@ export type { BuildOptions, BuildOutput } from '../types.mts';
5
5
  * rejects on failure rather than reporting it through a callback. Never
6
6
  * starts or talks to `inca-host` — that's `dev.mts`'s job.
7
7
  */
8
- export declare function build({ entry, outDir, stdout, stderr, quiet, }: BuildOptions): Promise<BuildOutput>;
8
+ export declare function build({ entry, outDir, runtimeConfig, stdout, stderr, quiet, }: BuildOptions): Promise<BuildOutput>;
@@ -18,6 +18,8 @@ export interface ResolveConfigOptions {
18
18
  stderr: NodeJS.WritableStream;
19
19
  /** Silences the bundler's progress output — see the `quiet` option in `../types.mts`. */
20
20
  quiet: boolean;
21
+ /** Written beside the entry — see the `runtimeConfig` option in `../types.mts`. */
22
+ runtimeConfig?: unknown;
21
23
  }
22
24
  /**
23
25
  * Builds the Vite config shared by `watch` and `build`, compiling `.vue`
@@ -29,4 +31,4 @@ export interface ResolveConfigOptions {
29
31
  * the entry, named by `chunkFileNames`/`assetFileNames` below, rather than
30
32
  * failing the build.
31
33
  */
32
- export declare function resolveViteConfig({ entry, outDir, mode, watch, onOutput, stdout, stderr, quiet, }: ResolveConfigOptions): InlineConfig;
34
+ export declare function resolveViteConfig({ entry, outDir, mode, watch, onOutput, stdout, stderr, quiet, runtimeConfig, }: ResolveConfigOptions): InlineConfig;
@@ -0,0 +1,11 @@
1
+ import { Plugin } from 'vite';
2
+ /** The file a build writes its app's config to, beside the entry. */
3
+ export declare const CONFIG_FILE_NAME = "inca.json";
4
+ /**
5
+ * Writes `config` to `inca.json` beside the entry, for `inca-host` to read
6
+ * when it starts the app.
7
+ *
8
+ * @param config - any JSON-serializable value; no file is written for
9
+ * `undefined` or an object with no keys
10
+ */
11
+ export declare function emitConfig(config: unknown): Plugin;
package/dist/build.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Bundler, BuildOutput } from './adapter/types.mts';
2
- import { ResolvedBuildConfig } from './config/loader.mts';
2
+ import { ResolvedBuildConfig, RuntimeConfig } from './config/loader.mts';
3
3
  export interface BuildAppOptions {
4
4
  /** The app's root directory. Defaults to `process.cwd()`. */
5
5
  cwd?: string;
@@ -12,6 +12,8 @@ export interface BuildAppOptions {
12
12
  bundler?: Bundler;
13
13
  /** An already-resolved config — lets `packageApp` avoid loading it twice. */
14
14
  config?: ResolvedBuildConfig;
15
+ /** What the build carries for `inca-host` to read. Resolved from the app's config when absent. */
16
+ runtimeConfig?: RuntimeConfig;
15
17
  /** Where the bundler's own output goes. Defaults to `process.stdout`. */
16
18
  stdout?: NodeJS.WritableStream;
17
19
  /** Where the bundler's warnings and errors go. Defaults to `process.stderr`. */
@@ -1002,7 +1002,7 @@ async function Wt(e) {
1002
1002
  name: e.rcFile,
1003
1003
  dir: e.cwd
1004
1004
  })), e.globalRc) {
1005
- let { findWorkspaceDir: t } = await import("./dist-DZ5asakr.js"), r = await t(e.cwd).catch(() => {});
1005
+ let { findWorkspaceDir: t } = await import("./dist-BvTGFq3F.js"), r = await t(e.cwd).catch(() => {});
1006
1006
  r && n.push(Z({
1007
1007
  name: e.rcFile,
1008
1008
  dir: r
@@ -1014,7 +1014,7 @@ async function Wt(e) {
1014
1014
  r.rc = t({}, ...n);
1015
1015
  }
1016
1016
  if (e.packageJson) {
1017
- let n = (Array.isArray(e.packageJson) ? e.packageJson : [typeof e.packageJson == "string" ? e.packageJson : e.name]).filter((e) => e && typeof e == "string"), { readPackageJSON: i } = await import("./dist-DZ5asakr.js"), a = await i(e.cwd).catch(() => {});
1017
+ let n = (Array.isArray(e.packageJson) ? e.packageJson : [typeof e.packageJson == "string" ? e.packageJson : e.name]).filter((e) => e && typeof e == "string"), { readPackageJSON: i } = await import("./dist-BvTGFq3F.js"), a = await i(e.cwd).catch(() => {});
1018
1018
  r.packageJson = t({}, ...n.map((e) => a?.[e]));
1019
1019
  }
1020
1020
  let a = {};
@@ -1171,14 +1171,16 @@ function Qt(e) {
1171
1171
  let t = e.indexOf("/");
1172
1172
  return e.startsWith("@") && t !== -1 ? e.slice(t + 1) : e;
1173
1173
  }
1174
- function $t(e) {
1175
- return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1176
- }
1174
+ var $t = "app";
1177
1175
  function en(e) {
1178
- return e ? Qt(e) : void 0;
1176
+ let t = e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1177
+ return t === "" ? $t : t;
1179
1178
  }
1180
1179
  function tn(e) {
1181
- return `org.inca.${$t(e)}`;
1180
+ return e ? Qt(e) : void 0;
1181
+ }
1182
+ function nn(e) {
1183
+ return `org.inca.${en(e)}`;
1182
1184
  }
1183
1185
  //#endregion
1184
- export { Xt as a, T as c, x as d, C as f, $t as i, w as l, tn as n, Wt as o, en as r, at as s, Zt as t, S as u };
1186
+ export { Xt as a, T as c, x as d, C as f, en as i, w as l, nn as n, Wt as o, tn as r, at as s, Zt as t, S as u };
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./jsonc-BdzClvC8.js";
2
- import { c as t, d as n, f as r, l as i, s as a, u as o } from "./defaults-D_1rymg4.js";
2
+ import { c as t, d as n, f as r, l as i, s as a, u as o } from "./defaults-DNvHueCI.js";
3
3
  import { n as s, t as c } from "./_format-BKs7bsc4.js";
4
4
  import { promises as l, statSync as u } from "node:fs";
5
5
  import "node:fs/promises";
package/dist/cli.js CHANGED
@@ -1,15 +1,15 @@
1
- import { i as e, n as t, o as n, r, t as i } from "./chunks/defaults-D_1rymg4.js";
1
+ import { i as e, n as t, o as n, r, t as i } from "./chunks/defaults-DNvHueCI.js";
2
2
  import a from "node:path";
3
3
  import { existsSync as o } from "node:fs";
4
- import { chmod as s, cp as c, mkdir as l, readFile as u, readdir as d, rm as f, writeFile as p } from "node:fs/promises";
5
- import { styleText as m } from "node:util";
6
- import { build as h } from "vite";
7
- import g from "@vitejs/plugin-vue";
8
- import { createRequire as _ } from "node:module";
9
- import { spawn as v } from "node:child_process";
10
- import { once as y } from "node:events";
11
- import b from "node:readline";
12
- import { setTimeout as x } from "node:timers/promises";
4
+ import { chmod as s, cp as c, link as l, mkdir as u, readFile as d, readdir as f, rm as p, writeFile as m } from "node:fs/promises";
5
+ import { styleText as h } from "node:util";
6
+ import { build as g } from "vite";
7
+ import _ from "@vitejs/plugin-vue";
8
+ import { createRequire as v } from "node:module";
9
+ import { spawn as y } from "node:child_process";
10
+ import { once as b } from "node:events";
11
+ import x from "node:readline";
12
+ import { setTimeout as ee } from "node:timers/promises";
13
13
  //#region src/error.mts
14
14
  var S = class extends Error {
15
15
  code;
@@ -17,58 +17,86 @@ var S = class extends Error {
17
17
  constructor(e, t) {
18
18
  super(t), this.code = e;
19
19
  }
20
- };
21
- //#endregion
22
- //#region src/config/loader.mts
23
- async function C(e) {
24
- let { config: t } = await n({
20
+ }, te = {
21
+ name: "inca",
22
+ packageJson: "inca",
23
+ rcFile: !1,
24
+ globalRc: !1,
25
+ giget: !1,
26
+ extend: !1
27
+ }, ne = /[/\\:*?"<>|\0]/;
28
+ function re(e) {
29
+ return e === e.trim() && e !== "" && e !== "." && e !== ".." && !ne.test(e);
30
+ }
31
+ function C(e) {
32
+ if (!(typeof e == "string" && re(e))) throw new S("ERR_INCA_PRODUCT_NAME_INVALID", `${JSON.stringify(e)} can't name a directory — set a "productName" in inca.config.ts with no leading or trailing space, and none of \`/\\:*?"<>|\``);
33
+ }
34
+ async function w(e) {
35
+ let { config: t, layers: r } = await n({
25
36
  cwd: e,
26
- name: "inca",
27
- packageJson: "inca",
28
- rcFile: !1,
29
- globalRc: !1,
30
- giget: !1,
31
- extend: !1
32
- });
37
+ ...te
38
+ }), i = r?.find((e) => e.configFile === "package.json");
39
+ return {
40
+ config: t,
41
+ usedPackageJsonKey: Object.keys(i?.config ?? {}).length > 0
42
+ };
43
+ }
44
+ async function T(e) {
45
+ let { config: t } = await w(e);
33
46
  return {
34
47
  entry: t.entry ? a.resolve(e, t.entry) : void 0,
35
48
  outDir: a.resolve(e, t.outDir ?? i.outDir)
36
49
  };
37
50
  }
38
- async function ee(e) {
39
- let s = a.join(e, "package.json"), c;
51
+ async function E(e) {
52
+ let n = a.join(e, "package.json"), s;
40
53
  try {
41
- c = await u(s, "utf8");
54
+ s = await d(n, "utf8");
42
55
  } catch {
43
- throw new S("ERR_INCA_PACKAGE_JSON_NOT_FOUND", `no package.json found at ${s}`);
56
+ throw new S("ERR_INCA_PACKAGE_JSON_NOT_FOUND", `no package.json found at ${n}`);
44
57
  }
45
- let l = JSON.parse(c), { config: d, layers: f } = await n({
46
- cwd: e,
47
- name: "inca",
48
- packageJson: "inca",
49
- rcFile: !1,
50
- globalRc: !1,
51
- giget: !1,
52
- extend: !1
53
- }), p = f?.find((e) => e.configFile === "package.json"), m = Object.keys(p?.config ?? {}).length > 0, h = d.productName ?? r(l.name);
54
- if (!h) throw new S("ERR_INCA_PRODUCT_NAME_MISSING", `${s} needs a "name", or "productName" in inca.config.ts`);
55
- let g = d.version ?? l.version ?? i.version, _ = d.identifier ?? t(h), v;
56
- if (d.icon && (v = a.resolve(e, d.icon), !o(v))) throw new S("ERR_INCA_ICON_NOT_FOUND", `"icon" points to ${v}, which doesn't exist`);
57
- let y = d.entry ? a.resolve(e, d.entry) : void 0, b = a.resolve(e, d.outDir ?? i.outDir);
58
+ let c = JSON.parse(s), { config: l, usedPackageJsonKey: u } = await w(e), f = l.productName ?? r(c.name);
59
+ if (!f) throw new S("ERR_INCA_PRODUCT_NAME_MISSING", `${n} needs a "name", or "productName" in inca.config.ts`);
60
+ C(f);
61
+ let p = l.version ?? c.version ?? i.version, m = l.identifier ?? t(f), h;
62
+ if (l.icon && (h = a.resolve(e, l.icon), !o(h))) throw new S("ERR_INCA_ICON_NOT_FOUND", `"icon" points to ${h}, which doesn't exist`);
63
+ let g = l.entry ? a.resolve(e, l.entry) : void 0, _ = a.resolve(e, l.outDir ?? i.outDir);
58
64
  return {
59
- productName: h,
60
- identifier: _,
61
- identifierIsDefault: d.identifier === void 0,
62
- version: g,
63
- icon: v,
64
- entry: y,
65
- outDir: b,
66
- usedPackageJsonKey: m
65
+ productName: f,
66
+ identifier: m,
67
+ identifierIsDefault: l.identifier === void 0,
68
+ version: p,
69
+ icon: h,
70
+ window: l.window,
71
+ entry: g,
72
+ outDir: _,
73
+ usedPackageJsonKey: u
67
74
  };
68
75
  }
76
+ function D(e) {
77
+ return {
78
+ name: e.productName,
79
+ identifier: e.identifier,
80
+ window: e.window
81
+ };
82
+ }
83
+ async function O(e) {
84
+ let { config: n } = await w(e), i = {};
85
+ try {
86
+ i = JSON.parse(await d(a.join(e, "package.json"), "utf8"));
87
+ } catch {}
88
+ let o = n.productName ?? r(i.name);
89
+ o && C(o);
90
+ let s = {
91
+ name: o,
92
+ identifier: n.identifier ?? (o ? t(o) : void 0),
93
+ window: n.window
94
+ };
95
+ return Object.values(s).some((e) => e !== void 0) ? s : void 0;
96
+ }
69
97
  //#endregion
70
98
  //#region src/adapter/vite/captureOutput.mts
71
- function te(e) {
99
+ function ie(e) {
72
100
  return {
73
101
  name: "inca:capture-output",
74
102
  writeBundle(t, n) {
@@ -82,9 +110,25 @@ function te(e) {
82
110
  };
83
111
  }
84
112
  //#endregion
113
+ //#region src/adapter/vite/emitConfig.mts
114
+ var ae = "inca.json";
115
+ function oe(e) {
116
+ let t = JSON.stringify(e, void 0, 2), n = t === void 0 || t === "{}";
117
+ return {
118
+ name: "inca:emit-config",
119
+ generateBundle() {
120
+ n || this.emitFile({
121
+ type: "asset",
122
+ fileName: ae,
123
+ source: `${t}\n`
124
+ });
125
+ }
126
+ };
127
+ }
128
+ //#endregion
85
129
  //#region src/adapter/vite/logger.mts
86
- var ne = "Build failed with ";
87
- function re(e, t) {
130
+ var se = "Build failed with ";
131
+ function k(e, t) {
88
132
  let n = /* @__PURE__ */ new WeakSet(), r = /* @__PURE__ */ new Set(), i = {
89
133
  hasWarned: !1,
90
134
  info(t) {
@@ -97,7 +141,7 @@ function re(e, t) {
97
141
  r.has(e) || (r.add(e), i.warn(e));
98
142
  },
99
143
  error(e, r) {
100
- i.hasWarned = !0, r?.error && n.add(r.error), !e.includes(ne) && t.write(`${e.replace(/\n\s+at .*/g, "")}\n`);
144
+ i.hasWarned = !0, r?.error && n.add(r.error), !e.includes(se) && t.write(`${e.replace(/\n\s+at .*/g, "")}\n`);
101
145
  },
102
146
  clearScreen() {},
103
147
  hasErrorLogged(e) {
@@ -108,7 +152,7 @@ function re(e, t) {
108
152
  }
109
153
  //#endregion
110
154
  //#region src/adapter/vite/unsupported.mts
111
- var w = /\.(?:css|pcss|postcss|sass|scss|less|styl|stylus)(?:\?|$)/, T = [{
155
+ var ce = /\.(?:css|pcss|postcss|sass|scss|less|styl|stylus)(?:\?|$)/, le = [{
112
156
  code: "ERR_INCA_UNSUPPORTED_STYLE",
113
157
  name: "a <style> block",
114
158
  matches: (e) => e.includes("vue&type=style"),
@@ -116,10 +160,10 @@ var w = /\.(?:css|pcss|postcss|sass|scss|less|styl|stylus)(?:\?|$)/, T = [{
116
160
  }, {
117
161
  code: "ERR_INCA_UNSUPPORTED_STYLESHEET",
118
162
  name: "a stylesheet import",
119
- matches: (e) => w.test(e),
163
+ matches: (e) => ce.test(e),
120
164
  hint: "the renderer applies no stylesheet — use a :style binding instead"
121
165
  }];
122
- function E(e = T) {
166
+ function ue(e = le) {
123
167
  return {
124
168
  name: "inca:reject-unsupported",
125
169
  enforce: "pre",
@@ -133,26 +177,27 @@ function E(e = T) {
133
177
  }
134
178
  //#endregion
135
179
  //#region src/adapter/vite/config.mts
136
- var D = "bundle.js";
137
- function O({ entry: e, outDir: t, mode: n, watch: r, onOutput: i, stdout: o, stderr: s, quiet: c }) {
180
+ var de = "bundle.js";
181
+ function A({ entry: e, outDir: t, mode: n, watch: r, onOutput: i, stdout: o, stderr: s, quiet: c, runtimeConfig: l }) {
138
182
  return {
139
183
  configFile: !1,
140
184
  root: a.dirname(e),
141
185
  mode: n,
142
186
  clearScreen: !1,
143
187
  logLevel: c ? "silent" : "info",
144
- customLogger: re(o, s),
188
+ customLogger: k(o, s),
145
189
  define: { "process.env.NODE_ENV": JSON.stringify(n) },
146
190
  plugins: [
147
- g({ template: { compilerOptions: { runtimeModuleName: "@vue/runtime-core" } } }),
148
- E(),
149
- te(i)
191
+ _({ template: { compilerOptions: { runtimeModuleName: "@vue/runtime-core" } } }),
192
+ ue(),
193
+ oe(l),
194
+ ie(i)
150
195
  ],
151
196
  build: {
152
197
  lib: {
153
198
  entry: e,
154
199
  formats: ["es"],
155
- fileName: () => D
200
+ fileName: () => de
156
201
  },
157
202
  outDir: t,
158
203
  emptyOutDir: n === "production",
@@ -167,48 +212,49 @@ function O({ entry: e, outDir: t, mode: n, watch: r, onOutput: i, stdout: o, std
167
212
  }
168
213
  //#endregion
169
214
  //#region src/adapter/vite/build.mts
170
- async function k({ entry: e, outDir: t, stdout: n = process.stdout, stderr: r = process.stderr, quiet: i = !1 }) {
171
- let o;
172
- if (await h(O({
215
+ async function fe({ entry: e, outDir: t, runtimeConfig: n, stdout: r = process.stdout, stderr: i = process.stderr, quiet: o = !1 }) {
216
+ let s;
217
+ if (await g(A({
173
218
  entry: e,
174
219
  outDir: t,
220
+ runtimeConfig: n,
175
221
  mode: "production",
176
222
  watch: !1,
177
- stdout: n,
178
- stderr: r,
179
- quiet: i,
223
+ stdout: r,
224
+ stderr: i,
225
+ quiet: o,
180
226
  onOutput: (e) => {
181
- o = {
227
+ s = {
182
228
  outDir: t,
183
229
  entryFile: a.join(t, e.entryFile),
184
230
  files: e.files
185
231
  };
186
232
  }
187
- })), !o) throw new S("ERR_INCA_BUILD_NO_OUTPUT", "build produced no output");
188
- return o;
233
+ })), !s) throw new S("ERR_INCA_BUILD_NO_OUTPUT", "build produced no output");
234
+ return s;
189
235
  }
190
236
  //#endregion
191
237
  //#region src/dev-client/hostBin.mts
192
- var A = "INCA_HOST_BIN";
193
- function j() {
238
+ var j = "INCA_HOST_BIN";
239
+ function M() {
194
240
  let e = process.platform === "darwin" || process.platform === "linux" ? process.platform : void 0, t = process.arch === "arm64" || process.arch === "x64" ? process.arch : void 0;
195
241
  return e && t ? `@incajs/host-${e}-${t}` : void 0;
196
242
  }
197
- function M() {
198
- let e = j();
243
+ function pe() {
244
+ let e = M();
199
245
  if (e) try {
200
- return _(import.meta.url).resolve(`${e}/bin/inca-host`);
246
+ return v(import.meta.url).resolve(`${e}/bin/inca-host`);
201
247
  } catch {
202
248
  return;
203
249
  }
204
250
  }
205
251
  function N() {
206
- let e = process.env[A];
252
+ let e = process.env[j];
207
253
  if (e) return e;
208
- let t = M();
254
+ let t = pe();
209
255
  if (t) return t;
210
- let n = j();
211
- throw new S("ERR_INCA_HOST_BIN_UNRESOLVED", `no inca-host binary found — ${n ? `no ${n} package is installed for it` : `this platform (${process.platform}/${process.arch}) has no published package`}, and ${A} isn't set to one`);
256
+ let n = M();
257
+ throw new S("ERR_INCA_HOST_BIN_UNRESOLVED", `no inca-host binary found — ${n ? `no ${n} package is installed for it` : `this platform (${process.platform}/${process.arch}) has no published package`}, and ${j} isn't set to one`);
212
258
  }
213
259
  //#endregion
214
260
  //#region src/dev-client/hostError.mts
@@ -219,14 +265,14 @@ var P = class extends Error {
219
265
  super(e), this.code = t, this.hostStack = n, this.name = "HostError";
220
266
  }
221
267
  };
222
- function ie(e) {
268
+ function F(e) {
223
269
  return typeof e == "object" && !!e && e.jsonrpc === "2.0";
224
270
  }
225
271
  //#endregion
226
272
  //#region src/dev-client/hostClient.mts
227
- var ae = (e) => {
273
+ var I = (e) => {
228
274
  process.stderr.write(e.endsWith("\n") ? e : `${e}\n`);
229
- }, oe = class {
275
+ }, L = class {
230
276
  #e;
231
277
  #t;
232
278
  #n = 1;
@@ -236,22 +282,22 @@ var ae = (e) => {
236
282
  this.#e = e;
237
283
  }
238
284
  async start() {
239
- let e = this.#e.hostBin ?? N(), t = v(e, ["--dev", this.#e.entryFile], { stdio: [
285
+ let e = this.#e.hostBin ?? N(), t = y(e, ["--dev", this.#e.entryFile], { stdio: [
240
286
  "pipe",
241
287
  "pipe",
242
288
  "pipe"
243
289
  ] });
244
290
  this.#t = t;
245
- let n = this.#e.onStderr ?? ae;
291
+ let n = this.#e.onStderr ?? I;
246
292
  t.stderr.setEncoding("utf8"), t.stderr.on("data", (e) => n(e)), t.stdin.on("error", (e) => {
247
293
  e.code !== "EPIPE" && n(`inca-host stdin: ${e.message}\n`);
248
- }), b.createInterface({ input: t.stdout }).on("line", (e) => {
294
+ }), x.createInterface({ input: t.stdout }).on("line", (e) => {
249
295
  this.#a(e, n);
250
296
  }), t.on("exit", (e, t) => {
251
297
  let n = /* @__PURE__ */ Error(`inca-host exited (code=${String(e)}, signal=${String(t)}) before answering`);
252
298
  for (let { reject: e } of this.#r.values()) e(n);
253
299
  this.#r.clear(), this.#i || this.#e.onExit?.(e, t);
254
- }), await y(t, "spawn");
300
+ }), await b(t, "spawn");
255
301
  }
256
302
  #a(e, t) {
257
303
  let n;
@@ -261,7 +307,7 @@ var ae = (e) => {
261
307
  t(`[stray stdout] ${e}`);
262
308
  return;
263
309
  }
264
- if (!ie(n)) {
310
+ if (!F(n)) {
265
311
  t(`[stray stdout] ${e}`);
266
312
  return;
267
313
  }
@@ -294,7 +340,7 @@ var ae = (e) => {
294
340
  }
295
341
  async #s(e) {
296
342
  this.#i = !0;
297
- let t = y(e, "exit");
343
+ let t = b(e, "exit");
298
344
  e.kill(), await t;
299
345
  }
300
346
  async call(e, t) {
@@ -319,35 +365,35 @@ var ae = (e) => {
319
365
  let t = this.#t;
320
366
  if (!t || t.exitCode !== null || t.signalCode !== null) return;
321
367
  this.#i = !0;
322
- let n = y(t, "exit");
323
- this.call("shutdown").catch(() => {}), await Promise.race([n.then(() => "exited"), x(e).then(() => "timeout")]) === "timeout" && (t.kill(), await n);
368
+ let n = b(t, "exit");
369
+ this.call("shutdown").catch(() => {}), await Promise.race([n.then(() => "exited"), ee(e).then(() => "timeout")]) === "timeout" && (t.kill(), await n);
324
370
  }
325
- }, F = "[inca]", I = new Intl.DateTimeFormat(void 0, {
371
+ }, R = "[inca]", z = new Intl.DateTimeFormat(void 0, {
326
372
  hour: "numeric",
327
373
  minute: "numeric",
328
374
  second: "numeric"
329
375
  });
330
- function L(e, t, n) {
331
- let r = m(["bold", n], F, { stream: e });
332
- return t.timestamp ? `${m("dim", I.format(/* @__PURE__ */ new Date()), { stream: e })} ${r}` : r;
376
+ function B(e, t, n) {
377
+ let r = h(["bold", n], R, { stream: e });
378
+ return t.timestamp ? `${h("dim", z.format(/* @__PURE__ */ new Date()), { stream: e })} ${r}` : r;
333
379
  }
334
- function R(e, t, n = {}) {
335
- e.write(`${L(e, n, "cyan")} ${t}\n`);
380
+ function V(e, t, n = {}) {
381
+ e.write(`${B(e, n, "cyan")} ${t}\n`);
336
382
  }
337
- function z(e) {
383
+ function H(e) {
338
384
  let t = e.code;
339
385
  return typeof t == "string" ? t : null;
340
386
  }
341
- function B(e) {
387
+ function me(e) {
342
388
  return /\bERR_INCA_[A-Z0-9_]+/.exec(e)?.[0] ?? null;
343
389
  }
344
- function V(e) {
390
+ function he(e) {
345
391
  let t = e.stack;
346
392
  if (!t) return null;
347
393
  for (let n of [`${e.name}: ${e.message}`, e.message]) if (t.startsWith(n)) return t.slice(n.length).replace(/^\r?\n/, "") || null;
348
394
  return t;
349
395
  }
350
- function H(e) {
396
+ function ge(e) {
351
397
  let t = /^(?:\w*Error: )?(ERR_INCA_[A-Z0-9_]+): /.exec(e);
352
398
  return t ? {
353
399
  message: e.slice(t[0].length),
@@ -363,11 +409,11 @@ function U(e) {
363
409
  return e instanceof P ? {
364
410
  message: e.message,
365
411
  stack: e.hostStack,
366
- code: z(e)
412
+ code: H(e)
367
413
  } : e instanceof Error ? {
368
414
  message: e.message,
369
- stack: V(e),
370
- code: z(e) ?? B(e.message)
415
+ stack: he(e),
416
+ code: H(e) ?? me(e.message)
371
417
  } : {
372
418
  message: String(e),
373
419
  stack: null,
@@ -375,13 +421,13 @@ function U(e) {
375
421
  };
376
422
  }
377
423
  function W(e, t, n, r = {}) {
378
- let i = n.code ? ` (${m("bold", n.code, { stream: e })})` : "";
379
- e.write(`${L(e, r, "red")} ${t}${i}: ${n.message}\n`), n.stack && e.write(`${n.stack}\n`);
424
+ let i = n.code ? ` (${h("bold", n.code, { stream: e })})` : "";
425
+ e.write(`${B(e, r, "red")} ${t}${i}: ${n.message}\n`), n.stack && e.write(`${n.stack}\n`);
380
426
  }
381
427
  //#endregion
382
428
  //#region src/adapter/vite/watch.mts
383
- async function G({ onBuild: e, onError: t, stdout: n = process.stdout, stderr: r = process.stderr, quiet: i = !1, ...o }) {
384
- let { outDir: s } = o, c, l = await h(O({
429
+ async function _e({ onBuild: e, onError: t, stdout: n = process.stdout, stderr: r = process.stderr, quiet: i = !1, ...o }) {
430
+ let { outDir: s } = o, c, l = await g(A({
385
431
  ...o,
386
432
  watch: !0,
387
433
  stdout: n,
@@ -405,204 +451,248 @@ async function G({ onBuild: e, onError: t, stdout: n = process.stdout, stderr: r
405
451
  if (e.code !== "ERROR") return;
406
452
  c = void 0;
407
453
  let { errors: n } = e.error;
408
- t(H(n?.[0]?.message ?? e.error.message));
454
+ t(ge(n?.[0]?.message ?? e.error.message));
409
455
  }), { close: () => l.close() };
410
456
  }
411
457
  //#endregion
412
458
  //#region src/defaultBundler.mts
413
- var K = {
414
- watch: G,
415
- build: k
459
+ var G = {
460
+ watch: _e,
461
+ build: fe
416
462
  };
417
463
  //#endregion
418
464
  //#region src/entry.mts
419
- async function q(e) {
465
+ async function K(e) {
420
466
  let t = a.join(e, "src/main.mts");
421
467
  if (o(t)) return t;
422
468
  let n = a.join(e, "src/App.vue");
423
- if (o(n)) return se(n, e);
469
+ if (o(n)) return ve(n, e);
424
470
  throw new S("ERR_INCA_ENTRY_NOT_FOUND", `no app entry found — expected ${t} or ${n}`);
425
471
  }
426
- async function se(e, t) {
472
+ async function ve(e, t) {
427
473
  let n = a.join(t, "node_modules/.inca");
428
- await l(n, { recursive: !0 });
474
+ await u(n, { recursive: !0 });
429
475
  let r = a.join(n, "entry.mts"), i = JSON.stringify(e.split(a.sep).join("/"));
430
- return await p(r, `import { createIncaApp } from "incajs/vue";\nimport App from ${i};\ncreateIncaApp(App).mount();\n`), r;
476
+ return await m(r, `import { createIncaApp } from "incajs/vue";\nimport App from ${i};\ncreateIncaApp(App).mount();\n`), r;
431
477
  }
432
478
  //#endregion
433
479
  //#region src/build.mts
434
- async function J(e = {}) {
435
- let t = e.cwd ?? process.cwd(), n = e.config ?? await C(t), r = n.outDir, i = e.bundler ?? K, a = e.entry ?? n.entry ?? await q(t);
480
+ async function q(e = {}) {
481
+ let t = e.cwd ?? process.cwd(), n = e.config ?? await T(t), r = n.outDir, i = e.bundler ?? G, a = e.entry ?? n.entry ?? await K(t), o = e.runtimeConfig ?? await O(t);
436
482
  return i.build({
437
483
  entry: a,
438
484
  outDir: r,
485
+ runtimeConfig: o,
439
486
  stdout: e.stdout,
440
487
  stderr: e.stderr
441
488
  });
442
489
  }
443
490
  //#endregion
444
491
  //#region src/dev-lock.mts
445
- function ce(e) {
492
+ function J(e) {
446
493
  return a.join(e, "node_modules/.inca/dev.pid");
447
494
  }
448
- function le(e) {
495
+ function ye(e) {
449
496
  try {
450
497
  return process.kill(e, 0), !0;
451
498
  } catch (e) {
452
499
  return e.code === "EPERM";
453
500
  }
454
501
  }
455
- async function ue(e) {
456
- let t = ce(e), n = Number.parseInt(await u(t, "utf8").catch(() => ""), 10);
457
- if (Number.isInteger(n) && le(n)) throw new S("ERR_INCA_DEV_RUNNING", `inca dev is already running for this app (pid ${String(n)})`);
458
- return await l(a.dirname(t), { recursive: !0 }), await p(t, String(process.pid)), () => f(t, { force: !0 });
502
+ async function be(e) {
503
+ let t = J(e), n = Number.parseInt(await d(t, "utf8").catch(() => ""), 10);
504
+ if (Number.isInteger(n) && ye(n)) throw new S("ERR_INCA_DEV_RUNNING", `inca dev is already running for this app (pid ${String(n)})`);
505
+ return await u(a.dirname(t), { recursive: !0 }), await m(t, String(process.pid)), () => p(t, { force: !0 });
506
+ }
507
+ //#endregion
508
+ //#region src/plist.mts
509
+ function Y(e) {
510
+ return e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
511
+ }
512
+ function xe(e) {
513
+ return typeof e == "boolean" ? e ? "<true/>" : "<false/>" : `<string>${Y(e)}</string>`;
514
+ }
515
+ function Se(e) {
516
+ return `<?xml version="1.0" encoding="UTF-8"?>
517
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
518
+ <plist version="1.0">
519
+ <dict>
520
+ ${Object.entries(e).map(([e, t]) => `\t<key>${Y(e)}</key>\n\t${xe(t)}`).join("\n")}\n</dict>
521
+ </plist>
522
+ `;
523
+ }
524
+ //#endregion
525
+ //#region src/macos-app.mts
526
+ async function X(e) {
527
+ let { appPath: t, metadata: n, hostBin: r } = e;
528
+ await p(t, {
529
+ recursive: !0,
530
+ force: !0
531
+ });
532
+ let i = a.join(t, "Contents"), o = a.join(i, "MacOS"), d = a.join(i, "Resources");
533
+ await u(o, { recursive: !0 }), await u(d, { recursive: !0 });
534
+ let f = a.join(o, n.productName);
535
+ e.link ? await l(r, f).catch(() => c(r, f)) : await c(r, f), await s(f, 493);
536
+ let h = {
537
+ CFBundleName: n.productName,
538
+ CFBundleDisplayName: n.productName,
539
+ CFBundleExecutable: n.productName,
540
+ CFBundleIdentifier: n.identifier,
541
+ CFBundleVersion: n.version,
542
+ CFBundleShortVersionString: n.version,
543
+ CFBundlePackageType: "APPL",
544
+ CFBundleInfoDictionaryVersion: "6.0",
545
+ NSHighResolutionCapable: !0
546
+ };
547
+ if (n.icon) {
548
+ let e = a.basename(n.icon);
549
+ await c(n.icon, a.join(d, e)), h.CFBundleIconFile = e;
550
+ }
551
+ return await m(a.join(i, "Info.plist"), Se(h)), await m(a.join(i, "PkgInfo"), "APPL????"), {
552
+ appPath: t,
553
+ executablePath: f,
554
+ resourcesDir: d
555
+ };
459
556
  }
460
557
  //#endregion
461
558
  //#region src/dev.mts
462
- var Y = { timestamp: !0 };
463
- async function de(e, t) {
559
+ var Z = { timestamp: !0 }, Ce = ["ERR_INCA_PACKAGE_JSON_NOT_FOUND", "ERR_INCA_PRODUCT_NAME_MISSING"];
560
+ async function we(e, t) {
561
+ try {
562
+ return await E(e);
563
+ } catch (e) {
564
+ if (!(e instanceof S) || !Ce.includes(e.code)) throw e;
565
+ V(t, `running unnamed — ${e.message}`, Z);
566
+ return;
567
+ }
568
+ }
569
+ async function Te(e, t, n, r) {
570
+ if (process.platform === "darwin" && t) try {
571
+ return (await X({
572
+ appPath: a.join(e, "node_modules/.inca", `${t.productName}.app`),
573
+ metadata: t,
574
+ hostBin: n ?? N(),
575
+ link: !0
576
+ })).executablePath;
577
+ } catch (e) {
578
+ V(r, `running unbundled — ${U(e).message}`, Z);
579
+ return;
580
+ }
581
+ }
582
+ async function Ee(e, t) {
464
583
  let n = new Set(t), r;
465
584
  try {
466
- r = await d(e, {
585
+ r = await f(e, {
467
586
  recursive: !0,
468
587
  withFileTypes: !0
469
588
  });
470
589
  } catch {
471
590
  return;
472
591
  }
473
- await Promise.all(r.filter((e) => e.isFile()).map((t) => a.relative(e, a.join(t.parentPath, t.name))).filter((e) => !n.has(e)).map((t) => f(a.join(e, t), { force: !0 })));
592
+ await Promise.all(r.filter((e) => e.isFile()).map((t) => a.relative(e, a.join(t.parentPath, t.name))).filter((e) => !n.has(e)).map((t) => p(a.join(e, t), { force: !0 })));
474
593
  }
475
- async function fe(e) {
476
- let t = e.cwd ?? process.cwd(), n = await C(t), r = await ue(t), i = n.outDir, o = e.bundler ?? K, s = e.stdout ?? process.stdout, c = e.stderr ?? process.stderr, l = e.entry ?? n.entry ?? await q(t), u, d = !1, f = !1, p = Promise.resolve(), h = () => {}, g = new Promise((e) => {
477
- h = e;
478
- });
479
- async function _() {
480
- try {
481
- return await u?.call("reload"), !0;
482
- } catch (e) {
483
- return W(c, "reload failed", U(e), Y), !1;
484
- }
485
- }
486
- async function v(n) {
487
- if (await de(n.outDir, n.files), !u) {
488
- let t = new oe({
489
- entryFile: n.entryFile,
490
- hostBin: e.hostBin,
491
- onStderr: (e) => c.write(e),
492
- onReady: () => {
493
- d = !0, R(s, "ready", Y), f && (f = !1, _());
494
- },
495
- onAppError: (e) => W(c, "app error", e, Y),
496
- onExit: () => {
497
- R(s, "host exited — stopping", Y), h();
498
- }
499
- });
594
+ async function De(e) {
595
+ let t = e.cwd ?? process.cwd(), n = await T(t), r = await be(t);
596
+ try {
597
+ let r = n.outDir, i = e.bundler ?? G, o = e.stdout ?? process.stdout, s = e.stderr ?? process.stderr, c = e.entry ?? n.entry ?? await K(t), l = await we(t, o), u = l ? D(l) : await O(t), d = await Te(t, l, e.hostBin, o) ?? e.hostBin, f, p = !1, m = !1, g = Promise.resolve(), _ = () => {}, v = new Promise((e) => {
598
+ _ = e;
599
+ });
600
+ async function y() {
500
601
  try {
501
- await t.start();
602
+ return await f?.call("reload"), !0;
502
603
  } catch (e) {
503
- W(c, "failed to start inca-host", U(e), Y);
504
- return;
604
+ return W(s, "reload failed", U(e), Z), !1;
505
605
  }
506
- u = t;
507
- return;
508
606
  }
509
- if (!d) {
510
- f = !0;
511
- return;
512
- }
513
- if (await _() && n.changed) {
514
- let e = m("dim", a.relative(t, n.changed.file), { stream: s }), r = Date.now() - n.changed.at;
515
- R(s, `${m("green", "reload")} ${e} (${r}ms)`, Y);
607
+ async function b(e) {
608
+ if (await Ee(e.outDir, e.files), !f) {
609
+ let t = new L({
610
+ entryFile: e.entryFile,
611
+ hostBin: d,
612
+ onStderr: (e) => s.write(e),
613
+ onReady: () => {
614
+ p = !0, V(o, "ready", Z), m && (m = !1, y());
615
+ },
616
+ onAppError: (e) => W(s, "app error", e, Z),
617
+ onExit: () => {
618
+ V(o, "host exited — stopping", Z), _();
619
+ }
620
+ });
621
+ try {
622
+ await t.start();
623
+ } catch (e) {
624
+ W(s, "failed to start inca-host", U(e), Z);
625
+ return;
626
+ }
627
+ f = t;
628
+ return;
629
+ }
630
+ if (!p) {
631
+ m = !0;
632
+ return;
633
+ }
634
+ if (await y() && e.changed) {
635
+ let n = h("dim", a.relative(t, e.changed.file), { stream: o }), r = Date.now() - e.changed.at;
636
+ V(o, `${h("green", "reload")} ${n} (${r}ms)`, Z);
637
+ }
516
638
  }
639
+ let x = await i.watch({
640
+ entry: c,
641
+ outDir: r,
642
+ runtimeConfig: u,
643
+ mode: "development",
644
+ stdout: o,
645
+ stderr: s,
646
+ onBuild: (e) => {
647
+ g = g.then(() => b(e));
648
+ },
649
+ onError: (e) => {
650
+ W(s, "build failed", e, Z);
651
+ }
652
+ });
653
+ e.signal.aborted ? _() : e.signal.addEventListener("abort", () => _(), { once: !0 }), await v, await g, await f?.stop(), await x.close();
654
+ } finally {
655
+ await r();
517
656
  }
518
- let y = await o.watch({
519
- entry: l,
520
- outDir: i,
521
- mode: "development",
522
- stdout: s,
523
- stderr: c,
524
- onBuild: (e) => {
525
- p = p.then(() => v(e));
526
- },
527
- onError: (e) => {
528
- W(c, "build failed", e, Y);
529
- }
530
- });
531
- e.signal.aborted ? h() : e.signal.addEventListener("abort", () => h(), { once: !0 }), await g, await p, await u?.stop(), await y.close(), await r();
532
- }
533
- //#endregion
534
- //#region src/plist.mts
535
- function X(e) {
536
- return e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
537
- }
538
- function pe(e) {
539
- return typeof e == "boolean" ? e ? "<true/>" : "<false/>" : `<string>${X(e)}</string>`;
540
- }
541
- function me(e) {
542
- return `<?xml version="1.0" encoding="UTF-8"?>
543
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
544
- <plist version="1.0">
545
- <dict>
546
- ${Object.entries(e).map(([e, t]) => `\t<key>${X(e)}</key>\n\t${pe(t)}`).join("\n")}\n</dict>
547
- </plist>
548
- `;
549
657
  }
550
658
  //#endregion
551
659
  //#region src/package.mts
552
- function he() {
660
+ function Oe() {
553
661
  if (process.platform === "darwin") return "macos";
554
662
  if (process.platform === "linux") return "linux";
555
663
  throw new S("ERR_INCA_PLATFORM_UNSUPPORTED", `inca package doesn't support ${process.platform} yet`);
556
664
  }
557
- async function Z(e, t) {
665
+ async function Q(e, t) {
558
666
  await Promise.all(e.files.map(async (n) => {
559
667
  let r = a.join(t, n);
560
- await l(a.dirname(r), { recursive: !0 }), await c(a.join(e.outDir, n), r);
668
+ await u(a.dirname(r), { recursive: !0 }), await c(a.join(e.outDir, n), r);
561
669
  }));
562
670
  }
563
- async function Q({ metadata: e, output: t, hostBin: n }) {
564
- let r = a.join(t.outDir, `${e.productName}.app`);
565
- await f(r, {
566
- recursive: !0,
567
- force: !0
671
+ async function ke({ metadata: e, output: t, hostBin: n }) {
672
+ let { appPath: r, resourcesDir: i } = await X({
673
+ appPath: a.join(t.outDir, `${e.productName}.app`),
674
+ metadata: e,
675
+ hostBin: n
568
676
  });
569
- let i = a.join(r, "Contents"), o = a.join(i, "MacOS"), u = a.join(i, "Resources");
570
- await l(o, { recursive: !0 }), await l(u, { recursive: !0 });
571
- let d = a.join(o, e.productName);
572
- await c(n, d), await s(d, 493), await Z(t, u);
573
- let m = {
574
- CFBundleName: e.productName,
575
- CFBundleDisplayName: e.productName,
576
- CFBundleExecutable: e.productName,
577
- CFBundleIdentifier: e.identifier,
578
- CFBundleVersion: e.version,
579
- CFBundleShortVersionString: e.version,
580
- CFBundlePackageType: "APPL",
581
- CFBundleInfoDictionaryVersion: "6.0",
582
- NSHighResolutionCapable: !0
583
- };
584
- if (e.icon) {
585
- let t = a.basename(e.icon);
586
- await c(e.icon, a.join(u, t)), m.CFBundleIconFile = t;
587
- }
588
- return await p(a.join(i, "Info.plist"), me(m)), await p(a.join(i, "PkgInfo"), "APPL????"), r;
677
+ return await Q(t, i), r;
589
678
  }
590
- async function ge({ metadata: t, output: n, hostBin: r }) {
679
+ async function Ae({ metadata: t, output: n, hostBin: r }) {
591
680
  let i = e(t.productName), o = a.join(n.outDir, i);
592
- await f(o, {
681
+ await p(o, {
593
682
  recursive: !0,
594
683
  force: !0
595
- }), await l(o, { recursive: !0 });
596
- let u = a.join(o, i);
597
- return await c(r, u), await s(u, 493), await Z(n, o), o;
598
- }
599
- async function _e(e = {}) {
600
- let t = e.cwd ?? process.cwd(), n = e.stdout ?? process.stdout, r = e.target ?? he(), i = await ee(t);
601
- i.usedPackageJsonKey && R(n, "the \"inca\" key in package.json is deprecated — move these settings to inca.config.ts"), i.identifierIsDefault && R(n, `no "identifier" set in inca.config.ts — using generated identifier ${i.identifier}`);
602
- let a = await J({
684
+ }), await u(o, { recursive: !0 });
685
+ let l = a.join(o, i);
686
+ return await c(r, l), await s(l, 493), await Q(n, o), o;
687
+ }
688
+ async function je(e = {}) {
689
+ let t = e.cwd ?? process.cwd(), n = e.stdout ?? process.stdout, r = e.target ?? Oe(), i = await E(t);
690
+ i.usedPackageJsonKey && V(n, "the \"inca\" key in package.json is deprecated — move these settings to inca.config.ts"), i.identifierIsDefault && V(n, `no "identifier" set in inca.config.ts — using generated identifier ${i.identifier}`);
691
+ let a = await q({
603
692
  cwd: t,
604
693
  entry: e.entry,
605
694
  config: i,
695
+ runtimeConfig: D(i),
606
696
  bundler: e.bundler,
607
697
  stdout: n,
608
698
  stderr: e.stderr
@@ -613,20 +703,20 @@ async function _e(e = {}) {
613
703
  output: a,
614
704
  hostBin: s
615
705
  };
616
- return { appPath: r === "macos" ? await Q(c) : await ge(c) };
706
+ return { appPath: r === "macos" ? await ke(c) : await Ae(c) };
617
707
  }
618
708
  //#endregion
619
709
  //#region src/cli.mts
620
- var ve = "Usage: inca <dev|build|package>";
710
+ var Me = "Usage: inca <dev|build|package>";
621
711
  function $(e) {
622
712
  return a.relative(process.cwd(), e);
623
713
  }
624
- async function ye(e = process.argv) {
714
+ async function Ne(e = process.argv) {
625
715
  let t = e[2];
626
716
  if (t === "build") {
627
717
  try {
628
- let e = await J();
629
- R(process.stdout, `built ${$(e.entryFile)}`);
718
+ let e = await q();
719
+ V(process.stdout, `built ${$(e.entryFile)}`);
630
720
  } catch (e) {
631
721
  W(process.stderr, "build failed", U(e)), process.exitCode = 1;
632
722
  }
@@ -634,26 +724,26 @@ async function ye(e = process.argv) {
634
724
  }
635
725
  if (t === "package") {
636
726
  try {
637
- let { appPath: e } = await _e();
638
- R(process.stdout, `packaged ${$(e)}`);
727
+ let { appPath: e } = await je();
728
+ V(process.stdout, `packaged ${$(e)}`);
639
729
  } catch (e) {
640
730
  W(process.stderr, "package failed", U(e)), process.exitCode = 1;
641
731
  }
642
732
  return;
643
733
  }
644
734
  if (t !== "dev") {
645
- process.stderr.write(`${ve}\n`), process.exitCode = 1;
735
+ process.stderr.write(`${Me}\n`), process.exitCode = 1;
646
736
  return;
647
737
  }
648
738
  let n = new AbortController(), r = () => {
649
- n.signal.aborted || (R(process.stderr, "shutting down", { timestamp: !0 }), n.abort());
739
+ n.signal.aborted || (V(process.stderr, "shutting down", { timestamp: !0 }), n.abort());
650
740
  };
651
741
  process.on("SIGINT", r), process.on("SIGTERM", r);
652
742
  try {
653
- await fe({ signal: n.signal });
743
+ await De({ signal: n.signal });
654
744
  } catch (e) {
655
745
  W(process.stderr, "dev failed", U(e), { timestamp: !0 }), process.exitCode = 1;
656
746
  }
657
747
  }
658
748
  //#endregion
659
- export { ye as run };
749
+ export { Ne as run };
@@ -28,7 +28,8 @@ export declare function unscopedName(name: string): string;
28
28
  *
29
29
  * @param name - e.g. a `productName`
30
30
  * @returns `name` lowercased, with runs of non-`[a-z0-9]` collapsed to a
31
- * single `-` and trimmed from both ends
31
+ * single `-` and trimmed from both ends; `"app"` for a name that holds
32
+ * none of those characters
32
33
  */
33
34
  export declare function slugify(name: string): string;
34
35
  /**
@@ -1,3 +1,4 @@
1
+ import { WindowConfig } from './types.mts';
1
2
  /** `entry`/`outDir` only — what `build()`/`dev()` need, with no `package.json` requirement. */
2
3
  export interface ResolvedBuildConfig {
3
4
  /** Absolute path, if `inca.config.ts` set one. */
@@ -14,9 +15,21 @@ export interface ResolvedAppConfig extends ResolvedBuildConfig {
14
15
  version: string;
15
16
  /** Absolute path, if the app declared one. */
16
17
  icon?: string;
18
+ /** What the app declared about its window, if anything. */
19
+ window?: WindowConfig;
17
20
  /** package.json's `"inca"` key is deprecated; callers warn when this is true. */
18
21
  usedPackageJsonKey: boolean;
19
22
  }
23
+ /**
24
+ * What a built app carries for its host to read: the name the platform
25
+ * shows it under, the id it is known by, and its window. Each field is
26
+ * absent unless the app's config sets it.
27
+ */
28
+ export interface RuntimeConfig {
29
+ name?: string;
30
+ identifier?: string;
31
+ window?: WindowConfig;
32
+ }
20
33
  /**
21
34
  * Loads just `entry`/`outDir` from `inca.config.ts`, with derived defaults.
22
35
  * Never touches `package.json`.
@@ -35,3 +48,19 @@ export declare function resolveBuildConfig(cwd: string): Promise<ResolvedBuildCo
35
48
  * `productName`, or an `icon` doesn't resolve to a real file
36
49
  */
37
50
  export declare function resolveAppConfig(cwd: string): Promise<ResolvedAppConfig>;
51
+ /**
52
+ * Narrows a full config down to what a build carries for the host.
53
+ *
54
+ * @param config - a config {@link resolveAppConfig} returned
55
+ * @returns its name, id and window
56
+ */
57
+ export declare function runtimeConfigOf(config: ResolvedAppConfig): RuntimeConfig;
58
+ /**
59
+ * Loads {@link RuntimeConfig} for an app that may name itself nowhere.
60
+ * An app with no `package.json`, or none that gives it a name, still gets
61
+ * whatever window settings it declared.
62
+ *
63
+ * @param cwd - the app's root directory
64
+ * @returns the config, or `undefined` when the app declares none of it
65
+ */
66
+ export declare function resolveRuntimeConfig(cwd: string): Promise<RuntimeConfig | undefined>;
@@ -32,4 +32,35 @@ export interface IncaConfig {
32
32
  * @default "dist"
33
33
  */
34
34
  outDir?: string;
35
+ /** The window the app opens in. */
36
+ window?: WindowConfig;
37
+ }
38
+ /** What an app declares about its window — see {@link IncaConfig.window}. */
39
+ export interface WindowConfig {
40
+ /**
41
+ * Initial width, in pixels. Falls back to the width the app's root
42
+ * element declares, then to this default.
43
+ * @default 800
44
+ */
45
+ width?: number;
46
+ /**
47
+ * Initial height, in pixels. Falls back to the height the app's root
48
+ * element declares, then to this default.
49
+ * @default 600
50
+ */
51
+ height?: number;
52
+ /**
53
+ * The window's title.
54
+ * @default the app's productName
55
+ */
56
+ title?: string;
57
+ /**
58
+ * Whether a user can resize the window.
59
+ * @default false
60
+ */
61
+ resizable?: boolean;
62
+ /** Smallest width the window can be, in pixels. It opens at least this wide. */
63
+ minWidth?: number;
64
+ /** Smallest height the window can be, in pixels. It opens at least this tall. */
65
+ minHeight?: number;
35
66
  }
package/dist/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, t } from "./chunks/defaults-D_1rymg4.js";
1
+ import { a as e, t } from "./chunks/defaults-DNvHueCI.js";
2
2
  //#region src/config/index.mts
3
3
  var n = e();
4
4
  //#endregion
package/dist/dev.d.mts CHANGED
@@ -9,7 +9,10 @@ export interface DevOptions {
9
9
  entry?: string;
10
10
  /** Overrides the bundler — see {@link defaultBundler} for what's wired in by default. */
11
11
  bundler?: Bundler;
12
- /** Overrides host binary resolution — passed straight through to `HostClient`. */
12
+ /**
13
+ * Overrides host binary resolution. On macOS this is the binary the
14
+ * app bundle wraps; elsewhere it is launched directly.
15
+ */
13
16
  hostBin?: string;
14
17
  /** Defaults to `process.stdout`. */
15
18
  stdout?: NodeJS.WritableStream;
@@ -0,0 +1,47 @@
1
+ /** The app metadata a `.app` bundle's `Info.plist` carries. */
2
+ export interface MacosAppMetadata {
3
+ /** The name macOS shows in the Dock, the menu bar and the Finder. */
4
+ productName: string;
5
+ /** A reverse-DNS-style unique id, written as `CFBundleIdentifier`. */
6
+ identifier: string;
7
+ /** The app's version, written as both `CFBundleVersion` and `CFBundleShortVersionString`. */
8
+ version: string;
9
+ /** Absolute path to an icon file, copied into `Contents/Resources`. */
10
+ icon?: string;
11
+ }
12
+ /** Options for {@link writeMacosApp}. */
13
+ export interface WriteMacosAppOptions {
14
+ /** Where the `.app` directory is written. An existing one there is replaced. */
15
+ appPath: string;
16
+ /** What the bundle's `Info.plist` describes. */
17
+ metadata: MacosAppMetadata;
18
+ /** The `inca-host` binary the bundle's executable is made from. */
19
+ hostBin: string;
20
+ /**
21
+ * Hard-links the executable to `hostBin` rather than copying it, and
22
+ * copies when the two paths are on different filesystems. Set it where
23
+ * the bundle is rebuilt often and holds no files of its own.
24
+ */
25
+ link?: boolean;
26
+ }
27
+ /** The paths {@link writeMacosApp} created. */
28
+ export interface MacosApp {
29
+ /** The `.app` directory itself. */
30
+ appPath: string;
31
+ /** The bundle's executable, at `Contents/MacOS/<productName>`. */
32
+ executablePath: string;
33
+ /** `Contents/Resources`, where an app's own files belong. */
34
+ resourcesDir: string;
35
+ }
36
+ /**
37
+ * Writes a macOS `.app` bundle around the `inca-host` binary:
38
+ * `Contents/MacOS` holding the executable, `Contents/Resources` left empty
39
+ * apart from the icon, and `Info.plist`/`PkgInfo` beside them. macOS reads
40
+ * the app's name, icon and identifier from the bundle, so an executable
41
+ * launched from one carries them wherever the platform shows an app.
42
+ *
43
+ * @param options - where to write, what to describe, and which binary to use
44
+ * @returns the bundle's own path, its executable, and its resources directory
45
+ * @throws if any part of the bundle can't be written
46
+ */
47
+ export declare function writeMacosApp(options: WriteMacosAppOptions): Promise<MacosApp>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@incajs/cli",
3
- "version": "0.0.3",
4
- "description": "The inca CLI: watches an app's entry point through a bundler adapter, starts inca-host once the first bundle lands, and reloads it on every rebuild.",
3
+ "version": "0.0.4",
4
+ "description": "Dev server, bundler, and packager for Incarnative.js apps.",
5
5
  "keywords": [
6
6
  "bundler",
7
7
  "cli",
@@ -68,9 +68,9 @@
68
68
  }
69
69
  },
70
70
  "optionalDependencies": {
71
- "@incajs/host-darwin-arm64": "0.0.3",
72
- "@incajs/host-linux-arm64": "0.0.3",
73
- "@incajs/host-linux-x64": "0.0.3"
71
+ "@incajs/host-darwin-arm64": "0.0.4",
72
+ "@incajs/host-linux-arm64": "0.0.4",
73
+ "@incajs/host-linux-x64": "0.0.4"
74
74
  },
75
75
  "engines": {
76
76
  "node": ">=22.18"