@naru-pub/dev 0.0.0-stage → 1.1.0

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,3 +1,170 @@
1
- # Temporary Holding Version
1
+ # @naru-pub/dev
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Run and test a [Naru](https://naru.pub) site on your own machine: its pages,
4
+ the Data SDK, and its site code (`_naru/` migrations, queries, mutations,
5
+ routes, live queries) on the same edge Worker that serves `sdk.naru.pub`,
6
+ with one-click owner and member sign-in. No Naru account or checkout is
7
+ needed, and once installed it runs offline.
8
+
9
+ ```bash
10
+ npx @naru-pub/dev ./site --site demo
11
+ # naru-dev: demo at http://localhost:4000/
12
+ ```
13
+
14
+ Requires Node.js 20 or later, on macOS or Linux (arm64 or x64) or Windows
15
+ (x64): the platforms [workerd](https://www.npmjs.com/package/workerd), which
16
+ it runs, ships a binary for, and where naru-dev is tested.
17
+
18
+ ## Install
19
+
20
+ Run it once with `npx @naru-pub/dev`, or add it to a project:
21
+
22
+ ```bash
23
+ npm install --save-dev @naru-pub/dev
24
+ npx naru-dev ./site --site demo
25
+ ```
26
+
27
+ ## The command
28
+
29
+ ```
30
+ naru-dev [site folder] [options]
31
+
32
+ --site <name> the site's Naru name (<name>.naru.pub); default localsite
33
+ --port <port> default 4000; 0 picks a free one
34
+ --state <dir> where data is kept; default <site folder>/.naru-dev
35
+ --quiet print only the address
36
+ --version print the version and exit
37
+ ```
38
+
39
+ It prints its version, the Naru commit it was built from and the SDK
40
+ versions it serves, then serves the folder on `http://localhost:<port>`:
41
+
42
+ - **Pages** as they are, with an import map added to each HTML page, so
43
+ `import ... from "https://sdk.naru.pub/sdk/1.1.0/naru.js"` (and `/sdk/1/`,
44
+ `/sdk/1.0.0/`) loads this machine's SDK, pointed at this server. Keep the
45
+ real URLs in your pages; they work unchanged on Naru.
46
+ - **`_naru/`**: every file is published at start and again whenever one
47
+ changes, migrations applied; `_naru/collections.json` is installed,
48
+ changes included. After each publication it writes
49
+ `_naru/types/database.d.ts`, the site's tables as interfaces for `ctx.sql`
50
+ and query builders.
51
+ - **Sign-in**: `naru.auth.signIn()` signs the owner in on one click
52
+ (collections it asks for are made private if missing, as on Naru);
53
+ `naru.members.signIn()` opens a page to pick or name a test member and
54
+ their status (approved, pending, banned).
55
+ - **Uploads** keep their `https://media.naru.pub/...` addresses; a service
56
+ worker on your pages serves them from `<state>/media/`.
57
+
58
+ Data, uploads, members and sign-ins are kept in `<site folder>/.naru-dev/`
59
+ (add it to `.gitignore`) and survive restarts. Delete the folder to start
60
+ over.
61
+
62
+ ## Testing
63
+
64
+ `@naru-pub/dev/testing` starts the same server inside your test, on a free
65
+ port with a temporary state, and signs people in without clicking:
66
+
67
+ ```js
68
+ import { startNaru } from "@naru-pub/dev/testing";
69
+ import { chromium } from "playwright";
70
+
71
+ const naru = await startNaru({ site: "./site", name: "demo", quiet: true });
72
+ const browser = await chromium.launch();
73
+ try {
74
+ const owner = await browser.newContext();
75
+ await naru.signIn(owner, "owner");
76
+ const page = await owner.newPage();
77
+ await page.goto(naru.url("/admin/"));
78
+ // ...the page finds the owner's session, as after a real sign-in.
79
+
80
+ const alice = await browser.newContext();
81
+ await naru.signIn(alice, "alice");
82
+
83
+ // Or call the data API yourself:
84
+ const { headers } = await naru.signIn(null, "bob");
85
+ await fetch(naru.url("/api/data/v1/demo/_mutate/notes:add"), {
86
+ method: "POST",
87
+ headers: { ...headers, "content-type": "application/json" },
88
+ body: JSON.stringify({ args: { text: "hi" } }),
89
+ });
90
+
91
+ await naru.reset(); // an empty site again, migrations applied
92
+ } finally {
93
+ await browser.close();
94
+ await naru.stop();
95
+ }
96
+ ```
97
+
98
+ `startNaru(options)` resolves once the site answers. Options:
99
+
100
+ | Option | Default | What |
101
+ | ------- | ----------------- | -------------------------------------------------------- |
102
+ | `site` | (required) | The site's folder |
103
+ | `name` | `localsite` | The site's Naru name |
104
+ | `port` | `0` (a free port) | Where to serve |
105
+ | `state` | a new temp folder | Where data is kept; a temp folder is removed by `stop()` |
106
+ | `quiet` | `false` | Print nothing (`log` still has it) |
107
+
108
+ It returns:
109
+
110
+ - `origin`, such as `http://localhost:53412`, and `url(path)`;
111
+ - `signIn(target, who, { status, collections })`: `who` is `"owner"` or a
112
+ member's name (made if new, `status` kept). Given a Playwright `Page` or
113
+ `BrowserContext` (anything with `addInitScript`; Playwright is not a
114
+ dependency), its pages on this origin find the session where the SDK keeps
115
+ it from their next navigation, and at once for a page already there.
116
+ Resolves `{ accessToken, expiresAt, memberId, headers }` either way;
117
+ - `reset()`: empties the site's collections, tables and uploads and
118
+ publishes `_naru/` again; members and sign-ins stay;
119
+ - `stop()`; `log`, everything it printed; `name`; `state`.
120
+
121
+ ## What's emulated, and what isn't
122
+
123
+ The site's data runs on Naru's own edge Worker (the code that serves
124
+ `sdk.naru.pub`) under workerd, with SQLite-backed Durable Objects: the
125
+ collections and their rules, the site's tables, queries, mutations, routes
126
+ and live queries, the QuickJS runtime and its limits, revision conditions
127
+ and batches, behave as on Naru. A process in front stands in for naru.pub's
128
+ part.
129
+
130
+ Not emulated: payments and supporter plans (every member may sign in),
131
+ the control plane's quotas and checks on media (size, counts, types),
132
+ custom domains, Naru's sign-in and consent pages, the media library, the
133
+ daily restore points, and the per-statement SQLite time budget of Naru's
134
+ own workerd build. The per-address read limit is lifted, since every
135
+ tab on your machine is one address. The site is always served at its own
136
+ origin, as on `<name>.naru.pub`.
137
+
138
+ ## Versioning
139
+
140
+ The package's major and minor follow the Data SDK's newest version it
141
+ serves: 1.1.x serves SDK 1.0.0 and 1.1.0. Patch releases follow Naru's
142
+ server; `naru-dev --version` names the Naru commit a release was built from.
143
+
144
+ ## Publishing
145
+
146
+ From the Naru repository (maintainers): set `version` in
147
+ `naru-dev/package.json`, commit, and push a tag `dev-v<version>`;
148
+ `.github/workflows/publish-naru-dev.yml` builds, checks and stages it with
149
+ the `NPM_TOKEN` secret, and it goes live once approved with 2FA (`npm stage
150
+ approve <stage-id>`, or the Staged Packages tab on npmjs.com).
151
+ `scripts/check-package.sh <dir>` does the same check locally.
152
+
153
+ ## License
154
+
155
+ [AGPL-3.0-only](LICENSE), as Naru. The SDK files it serves are Naru's; your
156
+ site is your own.
157
+
158
+ ## 한국어
159
+
160
+ `@naru-pub/dev`는 나루 사이트를 내 컴퓨터에서 실행하고 시험하는 도구입니다.
161
+ `npx @naru-pub/dev ./site --site demo`를 실행하면 http://localhost:4000 에서
162
+ 사이트 파일과 데이터 SDK, `_naru/`의 마이그레이션·쿼리·뮤테이션·라우트·실시간
163
+ 쿼리를 `sdk.naru.pub`과 같은 엣지 Worker로 제공합니다. 운영자와 회원
164
+ 로그인은 한 번의 클릭으로 끝나고, `_naru/`를 고치면 바로 다시 게시합니다.
165
+ 데이터는 사이트 폴더의 `.naru-dev/`에 남습니다.
166
+
167
+ 테스트에서는 `@naru-pub/dev/testing`의 `startNaru()`로 빈 포트와 임시 폴더에
168
+ 서버를 띄우고, `signIn(page, "owner")`나 `signIn(page, "회원이름")`으로 클릭
169
+ 없이 로그인합니다. 결제, 미디어 용량 제한, 커스텀 도메인, 나루의 로그인·동의
170
+ 화면은 흉내 내지 않습니다. 라이선스는 AGPL-3.0-only입니다.
@@ -0,0 +1,4 @@
1
+ {
2
+ "version": "1.1.0",
3
+ "commit": "7305d60c9403"
4
+ }