create-vidra-app 0.4.0 → 0.5.1

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
@@ -1,53 +1,46 @@
1
1
  # create-vidra-app
2
2
 
3
- Scaffold a new [Vidra](https://vidra.build) application — a
4
- **React UI + .NET MAUI native host**, shipped from a single codebase.
3
+ Scaffold a [Vidra](https://vidra.build) desktop app with a web UI and a
4
+ C#/.NET native host.
5
5
 
6
- > **Alpha.** APIs and templates may change between 0.x releases.
6
+ > **Alpha:** APIs and templates may change between 0.x releases.
7
7
 
8
- ## Usage
8
+ ## Create an app
9
9
 
10
10
  ```bash
11
11
  npm create vidra-app@latest
12
12
  # or
13
13
  npx create-vidra-app my-app
14
- ```
15
-
16
- You'll be prompted for a project name and an app ID (reverse-domain). Then:
17
14
 
18
- ```bash
19
15
  cd my-app
20
- npm run dev # starts Vite + the native host together
16
+ npm run dev
21
17
  ```
22
18
 
23
- Scaffolded apps get the `vidra` CLI as a local dev dependency — there's no
24
- global `vidra` to install. Run it from inside your project via the npm scripts
25
- or `npx`:
19
+ The generated project depends on [`vidra-cli`](https://www.npmjs.com/package/vidra-cli),
20
+ which provides the `vidra` command. This package is only needed to create the
21
+ app; nothing depends on it afterwards. Use the provided npm scripts or run
22
+ `vidra` through `npx`; no global install is required.
26
23
 
27
- ```bash
28
- npm run dev # start Vite + native host
29
- npm run build # build + package for distribution
30
- npm run doctor # check your .NET / MAUI / Xcode setup
31
- npx vidra dev --target windows # run a specific desktop target
32
- npx vidra build --target macos # build + package a macOS .dmg
33
- ```
34
-
35
- ## Prerequisites
24
+ ## Requirements
36
25
 
37
26
  - .NET 10 SDK
38
- - The .NET MAUI workload: `dotnet workload install maui`
39
- - Node.js 18+
40
- - macOS targets require Xcode; Windows targets must be built on Windows
27
+ - .NET MAUI workload: `dotnet workload install maui`
28
+ - Node.js 22 or newer
29
+ - Xcode for macOS builds
30
+
31
+ Windows targets must be built on Windows.
41
32
 
42
- If the MAUI workload is missing, `create-vidra-app` will detect it after
43
- scaffolding and offer to install it for you. You can re-check at any time with
44
- `npm run doctor`.
33
+ ## Common commands
45
34
 
46
- ## Links
35
+ ```bash
36
+ npm run dev
37
+ npm run build
38
+ npm run doctor
39
+ npx vidra --help
40
+ ```
47
41
 
48
- - Website: [vidra.build](https://vidra.build)
49
- - GitHub: [rzamfiriu/vidra](https://github.com/rzamfiriu/vidra)
50
- - npm: [create-vidra-app](https://www.npmjs.com/package/create-vidra-app)
42
+ See the [getting started guide](https://vidra.build/docs/getting-started/) for
43
+ project structure, development, and build options.
51
44
 
52
45
  ## License
53
46
 
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // src/index.ts
2
2
  import prompts2 from "prompts";
3
- import fs9 from "fs-extra";
4
- import path10 from "path";
3
+ import fs2 from "fs-extra";
4
+ import path2 from "path";
5
5
  import { randomUUID } from "crypto";
6
6
  import { fileURLToPath } from "url";
7
7
 
8
- // src/utils.ts
8
+ // ../shared/src/utils.ts
9
9
  var toPascalCase = (str) => {
10
10
  return str.replace(
11
11
  /[-_]+(.)?/g,
@@ -42,11 +42,13 @@ var parseArgs = (argv) => {
42
42
  }
43
43
  return args;
44
44
  };
45
+ var splitLines = (text) => text.split(/\r?\n/);
46
+ var isInteractive = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
45
47
 
46
- // src/exec.ts
47
- import { execSync, spawn } from "child_process";
48
+ // ../shared/src/exec.ts
49
+ import { execFileSync, execSync, spawn } from "child_process";
48
50
 
49
- // src/theme.ts
51
+ // ../shared/src/theme.ts
50
52
  import chalk from "chalk";
51
53
  var lime = chalk.hex("#c8f751");
52
54
  var value = chalk.hex("#e8e8ec");
@@ -88,11 +90,28 @@ var row = (opts) => {
88
90
  var footer = (content) => ` ${content}`;
89
91
  var fixLine = (cmd, label = "fix:") => ` ${amber(label)} ${lime(cmd)}`;
90
92
 
91
- // src/exec.ts
93
+ // ../shared/src/exec.ts
92
94
  var toText = (value2) => {
93
95
  if (value2 == null) return "";
94
96
  return Buffer.isBuffer(value2) ? value2.toString() : value2;
95
97
  };
98
+ var run = (cmd, args) => {
99
+ try {
100
+ const stdout = execFileSync(cmd, args, {
101
+ encoding: "utf-8",
102
+ stdio: ["ignore", "pipe", "pipe"]
103
+ });
104
+ return { found: true, ok: true, stdout: stdout ?? "", stderr: "" };
105
+ } catch (e) {
106
+ const err = e;
107
+ return {
108
+ found: err.code !== "ENOENT",
109
+ ok: false,
110
+ stdout: toText(err.stdout),
111
+ stderr: toText(err.stderr)
112
+ };
113
+ }
114
+ };
96
115
  var formatProcessError = (error) => {
97
116
  const err = error;
98
117
  const combined = [toText(err.stderr), toText(err.stdout)].map((s) => s.trim()).filter((s) => s.length > 0).join("\n").trim();
@@ -169,69 +188,12 @@ var applyReplacements = (str, replacements) => {
169
188
  return str;
170
189
  };
171
190
 
172
- // src/doctor.ts
173
- import { execFileSync as execFileSync5 } from "child_process";
174
- import fs8 from "fs";
175
- import path9 from "path";
176
- import prompts from "prompts";
177
-
178
- // src/signing.ts
179
- import path2 from "path";
180
- import fs2 from "fs-extra";
181
- import { execFileSync, spawnSync } from "child_process";
182
-
183
- // src/notarize.ts
184
- import path3 from "path";
191
+ // ../shared/src/dotnet-toolchain.ts
185
192
  import { execFileSync as execFileSync2 } from "child_process";
186
-
187
- // src/windows-signing.ts
188
- import path4 from "path";
189
- import fs3 from "fs-extra";
190
- import { execFileSync as execFileSync3 } from "child_process";
191
-
192
- // src/velopack.ts
193
- import path5 from "path";
194
- import os from "os";
195
- import fs4 from "fs-extra";
196
- import { execFileSync as execFileSync4 } from "child_process";
197
-
198
- // src/update-config.ts
199
- import path6 from "path";
200
- import fs5 from "fs-extra";
201
-
202
- // src/project.ts
203
- import path8 from "path";
204
-
205
- // src/version.ts
206
- import fs6 from "fs-extra";
207
- import path7 from "path";
208
-
209
- // src/project.ts
210
- import fs7 from "fs-extra";
211
-
212
- // src/doctor.ts
193
+ import prompts from "prompts";
213
194
  var DOTNET = process.platform === "win32" ? "dotnet.exe" : "dotnet";
214
195
  var MAUI_DOCS = "https://learn.microsoft.com/dotnet/maui/get-started/installation";
215
196
  var INSTALL_NET_10_FIX = "Install the .NET 10 SDK \u2014 https://dotnet.microsoft.com/download";
216
- var bufToStr = (v) => v == null ? "" : Buffer.isBuffer(v) ? v.toString() : v;
217
- var run = (cmd, args) => {
218
- try {
219
- const stdout = execFileSync5(cmd, args, {
220
- encoding: "utf-8",
221
- stdio: ["ignore", "pipe", "pipe"]
222
- });
223
- return { found: true, ok: true, stdout: stdout ?? "", stderr: "" };
224
- } catch (e) {
225
- const err = e;
226
- return {
227
- found: err.code !== "ENOENT",
228
- ok: false,
229
- stdout: bufToStr(err.stdout),
230
- stderr: bufToStr(err.stderr)
231
- };
232
- }
233
- };
234
- var splitLines = (text) => text.split(/\r?\n/);
235
197
  var NET_10_VERSION = /^10\./;
236
198
  var MAUI_WORKLOAD = /\bmaui\b/i;
237
199
  var hasNet10Sdk = (listSdksOutput) => splitLines(listSdksOutput).some((line) => NET_10_VERSION.test(line.trim()));
@@ -265,7 +227,6 @@ var checkDotnetSdk = () => {
265
227
  };
266
228
  };
267
229
  var isMauiWorkloadInstalled = () => outputMentionsMaui(run(DOTNET, ["workload", "list"]).stdout);
268
- var isInteractive = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
269
230
  var installWorkload = (csprojPath) => {
270
231
  const args = csprojPath ? ["workload", "restore", csprojPath] : ["workload", "install", "maui"];
271
232
  console.log();
@@ -282,7 +243,7 @@ var installWorkload = (csprojPath) => {
282
243
  );
283
244
  console.log();
284
245
  try {
285
- execFileSync5(DOTNET, args, { stdio: "inherit" });
246
+ execFileSync2(DOTNET, args, { stdio: "inherit" });
286
247
  return true;
287
248
  } catch {
288
249
  console.error();
@@ -360,15 +321,15 @@ var ensureMauiWorkload = async (opts = {}) => {
360
321
 
361
322
  // src/index.ts
362
323
  var note = (label, body) => ` ${dim(label.padEnd(7))} ${body}`;
363
- var __dirname = path10.dirname(fileURLToPath(import.meta.url));
364
- var CLI_ROOT = path10.resolve(__dirname, "..");
365
- var TEMPLATES_DIR = path10.join(CLI_ROOT, "templates");
366
- var VIDRA_REPO_ROOT = path10.resolve(CLI_ROOT, "..", "..", "..");
367
- var LOCAL_FEED_DIR = path10.join(VIDRA_REPO_ROOT, "dist", "packages");
368
- var LOCAL_CLI_DIR = CLI_ROOT;
369
- var LOCAL_SDK_DIR = path10.join(VIDRA_REPO_ROOT, "src", "sdk", "vidra-js");
324
+ var __dirname = path2.dirname(fileURLToPath(import.meta.url));
325
+ var CLI_ROOT = path2.resolve(__dirname, "..");
326
+ var TEMPLATES_DIR = path2.join(CLI_ROOT, "templates");
327
+ var VIDRA_REPO_ROOT = path2.resolve(CLI_ROOT, "..", "..", "..");
328
+ var LOCAL_FEED_DIR = path2.join(VIDRA_REPO_ROOT, "dist", "packages");
329
+ var LOCAL_CLI_DIR = path2.join(VIDRA_REPO_ROOT, "src", "cli", "vidra-cli");
330
+ var LOCAL_SDK_DIR = path2.join(VIDRA_REPO_ROOT, "src", "sdk", "vidra-js");
370
331
  var VIDRA_VERSION = JSON.parse(
371
- fs9.readFileSync(path10.join(CLI_ROOT, "package.json"), "utf-8")
332
+ fs2.readFileSync(path2.join(CLI_ROOT, "package.json"), "utf-8")
372
333
  ).version;
373
334
  var SDK_VERSION = VIDRA_VERSION;
374
335
  var main = async () => {
@@ -409,8 +370,8 @@ var main = async () => {
409
370
  );
410
371
  appId = res.appId;
411
372
  }
412
- const root = path10.resolve(projectDir);
413
- if (fs9.existsSync(root) && fs9.readdirSync(root).length > 0) {
373
+ const root = path2.resolve(projectDir);
374
+ if (fs2.existsSync(root) && fs2.readdirSync(root).length > 0) {
414
375
  console.error();
415
376
  console.error(
416
377
  row({
@@ -426,8 +387,8 @@ var main = async () => {
426
387
  console.log(kv("directory", root));
427
388
  console.log(kv("app id", appId));
428
389
  console.log();
429
- const isMonorepo = fs9.existsSync(path10.join(LOCAL_SDK_DIR, "package.json"));
430
- const localFeedExists = isMonorepo && fs9.existsSync(LOCAL_FEED_DIR);
390
+ const isMonorepo = fs2.existsSync(path2.join(LOCAL_SDK_DIR, "package.json"));
391
+ const localFeedExists = isMonorepo && fs2.existsSync(LOCAL_FEED_DIR);
431
392
  const localFeedSource = localFeedExists ? ` <add key="vidra-local" value="${toTextPath(LOCAL_FEED_DIR)}" />` : "";
432
393
  const cliRef = isMonorepo ? `file:${toTextPath(LOCAL_CLI_DIR)}` : `^${VIDRA_VERSION}`;
433
394
  const sdkRef = isMonorepo ? `file:${toTextPath(LOCAL_SDK_DIR)}` : `^${SDK_VERSION}`;
@@ -442,17 +403,17 @@ var main = async () => {
442
403
  "{{sdkVersion}}": sdkRef,
443
404
  "{{localFeedSource}}": localFeedSource
444
405
  };
445
- const templateDir = path10.join(TEMPLATES_DIR, "react-vite");
406
+ const templateDir = path2.join(TEMPLATES_DIR, "react-vite");
446
407
  await scaffoldDir(templateDir, root, replacements);
447
408
  console.log(row({ glyph: "active", detail: dim("creating solution\u2026") }));
448
409
  exec(`dotnet new sln -n ${projectName} --force`, root);
449
- const slnFile = fs9.existsSync(path10.join(root, `${projectName}.slnx`)) ? `${projectName}.slnx` : `${projectName}.sln`;
410
+ const slnFile = fs2.existsSync(path2.join(root, `${projectName}.slnx`)) ? `${projectName}.slnx` : `${projectName}.sln`;
450
411
  exec(
451
412
  `dotnet sln ${slnFile} add src/${projectName}.Host/${projectName}.Host.csproj`,
452
413
  root
453
414
  );
454
415
  console.log(row({ glyph: "active", detail: dim("installing dependencies\u2026") }));
455
- const uiDir = path10.join(root, "ui");
416
+ const uiDir = path2.join(root, "ui");
456
417
  const [rootNpmOk, uiNpmOk] = await Promise.all([
457
418
  tryExecAsync("npm install", root),
458
419
  tryExecAsync("npm install", uiDir)
@@ -478,7 +439,7 @@ var main = async () => {
478
439
  }
479
440
  if (isMonorepo) {
480
441
  console.log(note("npm", `${dim("@vidra-dev/sdk \u2192")} ${value(LOCAL_SDK_DIR)}`));
481
- console.log(note("npm", `${dim("create-vidra-app \u2192")} ${value(LOCAL_CLI_DIR)}`));
442
+ console.log(note("npm", `${dim("vidra-cli \u2192")} ${value(LOCAL_CLI_DIR)}`));
482
443
  }
483
444
  console.log();
484
445
  if (!npmOk) {
@@ -490,7 +451,7 @@ var main = async () => {
490
451
  );
491
452
  console.log();
492
453
  }
493
- const hostCsproj = path10.join(
454
+ const hostCsproj = path2.join(
494
455
  root,
495
456
  "src",
496
457
  `${projectName}.Host`,
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "create-vidra-app",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Scaffold a new Vidra application (React + .NET MAUI)",
5
5
  "type": "module",
6
6
  "bin": {
7
- "create-vidra-app": "./bin/create-vidra-app.mjs",
8
- "vidra": "./bin/vidra.mjs"
7
+ "create-vidra-app": "bin/create-vidra-app.mjs"
9
8
  },
10
9
  "files": [
11
10
  "bin/",
@@ -15,6 +14,7 @@
15
14
  "scripts": {
16
15
  "build": "tsup",
17
16
  "dev": "tsup --watch",
17
+ "typecheck": "tsc --noEmit",
18
18
  "test": "vitest run",
19
19
  "test:watch": "vitest",
20
20
  "prepublishOnly": "npm run build"
@@ -33,8 +33,7 @@
33
33
  "desktop",
34
34
  "electron-alternative",
35
35
  "tauri-alternative",
36
- "scaffold",
37
- "cli"
36
+ "scaffold"
38
37
  ],
39
38
  "repository": {
40
39
  "type": "git",
@@ -47,19 +46,23 @@
47
46
  },
48
47
  "license": "MIT",
49
48
  "engines": {
50
- "node": ">=18"
49
+ "node": ">=22"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
51
53
  },
52
54
  "dependencies": {
53
- "chalk": "^5.4.1",
55
+ "chalk": "^6.0.0",
54
56
  "fs-extra": "^11.2.0",
55
57
  "prompts": "^2.4.2"
56
58
  },
57
59
  "devDependencies": {
60
+ "@vidra-dev/cli-shared": "*",
58
61
  "@types/fs-extra": "^11.0.4",
59
- "@types/node": "^22.9.0",
62
+ "@types/node": "^22.20.0",
60
63
  "@types/prompts": "^2.4.9",
61
64
  "tsup": "^8.5.1",
62
- "typescript": "^6.0.2",
63
- "vitest": "^2.1.4"
65
+ "typescript": "^7.0.2",
66
+ "vitest": "^4.1.10"
64
67
  }
65
68
  }
@@ -1,97 +1,45 @@
1
1
  # {{appTitle}}
2
2
 
3
- A cross-platform application built with [Vidra](https://vidra.build) — React UI + .NET MAUI native host.
3
+ A desktop application built with [Vidra](https://vidra.build): a React UI and a
4
+ C#/.NET native host.
4
5
 
5
- ## Getting Started
6
-
7
- ### Prerequisites
6
+ ## Requirements
8
7
 
9
8
  - [.NET 10 SDK](https://dotnet.microsoft.com/download)
10
- - The .NET MAUI workload: `dotnet workload install maui`
11
- - [Node.js](https://nodejs.org/) 18+
12
- - macOS targets require Xcode; Windows targets must be built on Windows
13
-
14
- Not sure if you're set up? Run:
15
-
16
- ```bash
17
- npm run doctor
18
- ```
9
+ - .NET MAUI workload: `dotnet workload install maui`
10
+ - [Node.js](https://nodejs.org/) 22 or newer
11
+ - Xcode for macOS builds
19
12
 
20
- It checks your .NET SDK, the MAUI workload, and (on macOS) Xcode, and prints the
21
- exact command to fix anything that's missing.
13
+ Windows targets must be built on Windows.
22
14
 
23
- > The `vidra` CLI ships as a local dev dependency of this project, so run it
24
- > through npm (`npm run dev`, `npm run doctor`) or with `npx vidra <command>` —
25
- > there is no global `vidra` command to install.
26
-
27
- ### Development
15
+ ## Development
28
16
 
29
17
  ```bash
18
+ npm run doctor
30
19
  npm run dev
31
20
  ```
32
21
 
33
- This starts the Vite dev server and launches the native host for the current OS
34
- under `dotnet watch`. Both sides of the app pick up your edits:
35
-
36
- - **UI**: edit anything in `ui/src` — Vite HMR updates the WebView instantly.
37
- - **C#**: edit the host (for example `OnTickAsync` in `MainPage.cs`) and save —
38
- the session puts the change in front of you in seconds. *How* depends on the
39
- platform:
40
- - **Windows**: supported edits apply to the *running* app and the UI flashes a
41
- "C# reloaded" badge. Edits hot reload can't express (new fields, changed
42
- signatures, …) trigger an automatic rebuild and relaunch.
43
- - **macOS**: the same, when the toolchain cooperates. Mac Catalyst's
44
- hot-reload agent often drops its connection mid-session (dotnet/sdk#55488);
45
- a dropped agent applies nothing while `dotnet watch` still reports success,
46
- so `vidra dev` watches for it and switches the session to rebuild +
47
- relaunch on save. You'll see it say so — after that, edits arrive with a
48
- restart and no badge.
49
- `npm run doctor` says which loop you get.
50
-
51
- To skip `dotnet watch` entirely and do a single build and launch:
52
-
53
- ```bash
54
- npx vidra dev --no-hot-reload
55
- ```
56
-
57
- To target a specific desktop platform explicitly:
58
-
59
- ```bash
60
- npx vidra dev --target macos
61
- npx vidra dev --target windows
62
- ```
63
-
64
- If you want to run the pieces separately:
22
+ `npm run dev` starts Vite and the native host together. Changes to the web UI
23
+ reload through Vite; supported C# changes reload through the .NET development
24
+ loop.
65
25
 
66
- ```bash
67
- npm run dev:ui
68
- npm run dev:host:macos
69
- npm run dev:host:windows
70
- ```
71
-
72
- ### Production Build
26
+ ## Build
73
27
 
74
28
  ```bash
75
29
  npm run build
76
30
  ```
77
31
 
78
- ## Project Structure
32
+ The `vidra` CLI is a local project dependency. Run `npx vidra --help` to see
33
+ target, packaging, and update options.
79
34
 
80
- ```
35
+ ## Project structure
36
+
37
+ ```text
81
38
  {{projectNameKebab}}/
82
39
  ├── src/
83
- │ └── {{projectName}}.Host/ # .NET MAUI native host
84
- │ ├── MauiProgram.cs # App configuration + Vidra setup
85
- │ ├── MainPage.cs # Main page (extends VidraPage)
86
- │ └── Platforms/ # Platform-specific code
87
- └── ui/ # React frontend
88
- ├── src/
89
- │ ├── App.tsx # Main React component
90
- │ └── main.tsx # Entry point
91
- ├── vite.config.ts
92
- └── package.json
40
+ │ └── {{projectName}}.Host/ # .NET MAUI host and C# contracts
41
+ └── ui/ # React application and generated TypeScript
93
42
  ```
94
43
 
95
- ---
96
-
97
- Built with [Vidra](https://vidra.build) — a C#/.NET native core with a web UI.
44
+ Read the [Vidra documentation](https://vidra.build/docs/) for bridge guides,
45
+ capabilities, distribution, and updates.
@@ -1,6 +1,8 @@
1
1
  # Build artifacts
2
2
  dist/
3
3
  src/*/Resources/Raw/wwwroot/
4
+ src/*/Resources/Raw/vidra-bridge-policy.json
5
+ ui/src/generated/vidra-access-policy.ts
4
6
  *.tsbuildinfo
5
7
 
6
8
  # .NET
@@ -11,6 +11,7 @@
11
11
  "doctor": "vidra doctor"
12
12
  },
13
13
  "devDependencies": {
14
- "create-vidra-app": "{{cliVersion}}"
14
+ "@vidra-dev/sdk": "{{sdkVersion}}",
15
+ "vidra-cli": "{{cliVersion}}"
15
16
  }
16
17
  }
@@ -23,11 +23,22 @@ public class MainPage : VidraPage
23
23
  try
24
24
  {
25
25
  var count = await Bridge.Js().Counter.IncrementAsync();
26
- System.Diagnostics.Debug.WriteLine($"[MainPage] Counter is now {count}");
26
+ Console.WriteLine($"[MainPage] Counter is now {count}");
27
27
  }
28
28
  catch (Exception ex)
29
29
  {
30
- System.Diagnostics.Debug.WriteLine($"[MainPage] Counter increment failed: {ex.Message}");
30
+ // Console, which is what Vidra.Hosting itself logs through, and the
31
+ // only one of the three that a Release build actually emits.
32
+ // Debug.WriteLine is compiled out of Release entirely, and Release is
33
+ // exactly the build where someone is looking at a counter stuck at
34
+ // zero. Trace.TraceError survives the compile but goes to
35
+ // DefaultTraceListener, which writes nothing unless a debugger is
36
+ // attached, and this template registers no listener.
37
+ //
38
+ // The whole exception, not ex.Message: the bridge's answer to "why"
39
+ // is the error code on it, and JS_HANDLER_NOT_FOUND, JS_HANDLER_ERROR
40
+ // and JS_RESPONSE_INVALID are three different problems.
41
+ Console.Error.WriteLine($"[MainPage] Counter increment failed: {ex}");
31
42
  }
32
43
  }
33
44
  }
@@ -9,28 +9,32 @@ public static class MauiProgram
9
9
  {
10
10
  var builder = MauiApp.CreateBuilder();
11
11
 
12
- // Updates come in two tiers. Both are opt-in and both read one
13
- // `vidra.updates` block in package.json.
12
+ // Updates are wired up and doing nothing, which is the intended state
13
+ // until this app has a feed to check. The switch is already in
14
+ // vidra.config.ts, empty — filling it in is the whole opt-in:
14
15
  //
15
- // Web bundle: fast, no reinstall. Add `.UseVidraUpdates()` below and
16
+ // updates: { feed: "https://updates.example.com/notes/" }
16
17
  //
17
- // "vidra": { "updates": { "feedUrl": "https://example.com/bundles.json" } }
18
+ // Type a URL there, or run `npx vidra updates init --feed <url>`, then
19
+ // publish with `npx vidra build` (both tiers) or `npx vidra build --web`
20
+ // (just the UI, no compile).
18
21
  //
19
- // then publish with `npx vidra bundle`. A bundle only installs when its
20
- // contract fingerprints match this build, so JS can never call a bridge
21
- // the installed binary lacks.
22
+ // One directory serves both tiers. To split them across two hosts:
22
23
  //
23
- // Whole app: native code included. Reference Vidra.Updates.Native, add
24
- // `.UseVidraNativeUpdates()`, uncomment the line in Platforms/*/Program.cs,
25
- // and add
24
+ // "feed": { "web": "https://cdn/notes/", "app": "https://dl/notes/" }
26
25
  //
27
- // "vidra": { "updates": { "native": { "feedUrl": "https://example.com/app/" } } }
26
+ // Web bundle: your `ui/` build, applied on the next launch, no reinstall.
27
+ // A bundle only installs when its contract fingerprints match this build,
28
+ // so JS can never call a bridge the installed binary lacks.
28
29
  //
29
- // then build with `npx vidra build --target <target> --native-update`.
30
- // `npx vidra doctor` names whichever half is missing.
30
+ // Whole app: native code included, via Velopack. Its other half is the
31
+ // `VelopackApp` line in Platforms/*/Program.cs, which has to run before
32
+ // the UI framework starts.
31
33
  builder
32
34
  .UseMauiApp<App>()
33
35
  .UseVidra()
36
+ .UseVidraUpdates()
37
+ .UseVidraNativeUpdates()
34
38
  .ConfigureFonts(fonts =>
35
39
  {
36
40
  fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
@@ -6,20 +6,17 @@
6
6
  // also inspects the assembly statically and warns when
7
7
  // `VelopackApp.Build()...Run()` is anywhere other than the entry point.
8
8
  //
9
+ // It is live from the first scaffold and does nothing at all until this app is
10
+ // installed from a Velopack release — which it is not, until `vidra.config.ts`
11
+ // names an updates feed and `vidra build` packs
12
+ // a release into it. Filling in that URL is the whole opt-in.
13
+ //
9
14
  // `UseVidraLocator()` is the Mac Catalyst part. Velopack's client picks its
10
15
  // locator from `RuntimeInformation.IsOSPlatform`, which answers false for OSX
11
16
  // here, so without it, `Run()` throws before any update logic executes.
12
- //
13
- // To turn native updates on:
14
- // 1. add the Vidra.Updates.Native package reference to this project
15
- // 2. uncomment the two lines below, and the ones in MauiProgram.cs
16
- // 3. add a `vidra.updates.native.feedUrl` to package.json
17
- // 4. build with `npx vidra build --target macos --native-update`
18
- //
19
- // `npx vidra doctor` checks all four and names whichever is missing.
20
17
 
21
- // using Velopack;
22
- // using Vidra.Hosting;
18
+ using Velopack;
19
+ using Vidra.Hosting;
23
20
  using UIKit;
24
21
 
25
22
  namespace {{projectName}};
@@ -28,7 +25,7 @@ public static class Program
28
25
  {
29
26
  static void Main(string[] args)
30
27
  {
31
- // VelopackApp.Build().UseVidraLocator().Run();
28
+ VelopackApp.Build().UseVidraLocator().Run();
32
29
 
33
30
  UIApplication.Main(args, null, typeof(AppDelegate));
34
31
  }
@@ -9,19 +9,15 @@
9
9
  // `--veloapp-*` argument and expects it to do that work and exit without ever
10
10
  // showing a window. `VelopackApp.Build()...Run()` is what handles those launches,
11
11
  // and `vpk pack` statically inspects the assembly and warns when it finds the
12
- // call anywhere other than the entry point. Putting it here costs nothing and
13
- // means an app that later enables updates needs no migration into generated code.
12
+ // call anywhere other than the entry point.
14
13
  //
15
- // To turn native updates on:
16
- // 1. add the Vidra.Updates.Native package reference to this project
17
- // 2. uncomment the two lines below, and the ones in MauiProgram.cs
18
- // 3. add a `vidra.updates.native.feedUrl` to package.json
19
- // 4. build with `npx vidra build --target windows --native-update`
20
- //
21
- // `npx vidra doctor` checks all four and names whichever is missing.
14
+ // It is live from the first scaffold and does nothing at all until this app is
15
+ // installed from a Velopack release — which it is not, until `vidra.config.ts`
16
+ // names an updates feed and `vidra build` packs
17
+ // a release into it. Filling in that URL is the whole opt-in.
22
18
 
23
- // using Velopack;
24
- // using Vidra.Hosting;
19
+ using Velopack;
20
+ using Vidra.Hosting;
25
21
 
26
22
  namespace {{projectName}}.WinUI;
27
23
 
@@ -30,7 +26,7 @@ public static class Program
30
26
  [STAThread]
31
27
  static void Main(string[] args)
32
28
  {
33
- // VelopackApp.Build().UseVidraLocator().Run();
29
+ VelopackApp.Build().UseVidraLocator().Run();
34
30
 
35
31
  WinRT.ComWrappersSupport.InitializeComWrappers();
36
32