@noy-db/create 0.5.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vLannaAi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # @noy-db/create
2
+
3
+ Wizard + CLI tool for [noy-db](https://github.com/vLannaAi/noy-db) — scaffold a fresh Nuxt 4 + Pinia encrypted store, augment an existing Nuxt project, or run operational commands (add user, rotate keys, backup) from the command line.
4
+
5
+ Two bins ship in this package:
6
+
7
+ - **`create`** — invoked by `npm create @noy-db`. Fresh-project wizard OR in-place augmenter for an existing Nuxt 4 project, depending on where you run it.
8
+ - **`noy-db`** — ongoing CLI tool. Invoked via `pnpm exec noy-db <cmd>` or `npx noy-db <cmd>` from inside a project. Five subcommands: `add`, `add user`, `verify`, `rotate`, `backup`.
9
+
10
+ ---
11
+
12
+ ## `create @noy-db` — the wizard
13
+
14
+ The wizard auto-detects whether your current directory is an existing Nuxt 4 project:
15
+
16
+ - If `nuxt.config.{ts,js,mjs}` **and** a `package.json` listing `nuxt` are both present, the wizard enters **augment mode** (patches the existing config in-place)
17
+ - Otherwise it enters **fresh mode** (creates a new subdirectory with a full Nuxt 4 starter)
18
+
19
+ ### Fresh mode — new project
20
+
21
+ ```bash
22
+ # In an empty directory
23
+ npm create @noy-db my-app
24
+ pnpm create @noy-db my-app
25
+ yarn create @noy-db my-app
26
+ bun create @noy-db my-app
27
+ ```
28
+
29
+ The wizard asks at most 3 questions (project name, adapter, include sample data) and writes a complete Nuxt 4 + Pinia + `@noy-db/nuxt` starter into `./my-app/`. Nothing is installed automatically — pick your package manager and run it yourself.
30
+
31
+ Skip the prompts with `--yes`:
32
+
33
+ ```bash
34
+ npm create @noy-db my-app --yes
35
+ npm create @noy-db my-app --yes --adapter file --no-sample-data
36
+ ```
37
+
38
+ ### Augment mode — existing Nuxt 4 project
39
+
40
+ ```bash
41
+ # From inside an existing Nuxt 4 project root
42
+ cd ~/my-existing-app
43
+ npm create @noy-db
44
+ ```
45
+
46
+ The wizard will:
47
+
48
+ 1. **Detect** the existing `nuxt.config.ts` via the detection rule above
49
+ 2. **Prompt** for the adapter (`browser` / `file` / `memory`)
50
+ 3. **Patch** the config in-memory via [magicast](https://github.com/unjs/magicast):
51
+ - Add `'@noy-db/nuxt'` to the `modules` array (creating the array if missing)
52
+ - Add `noydb: { adapter, pinia: true, devtools: true }` (only if not already present)
53
+ 4. **Show** a colored unified diff of the proposed changes
54
+ 5. **Ask** for confirmation (`y/n`) — your config is only written if you confirm
55
+ 6. **Print** the `pnpm add …` command for the packages the patched config now depends on
56
+
57
+ #### Safe behaviors
58
+
59
+ - **Idempotent**: re-running on an already-augmented project is a no-op. You'll see `Nothing to do — already configured`.
60
+ - **Preserves custom config**: a pre-existing `noydb:` key in your config is left untouched. The wizard only fills in what's missing.
61
+ - **Preserves unrelated keys, comments, and formatting**: magicast walks a real Babel AST, not a regex.
62
+ - **Unsupported shapes are rejected cleanly**: if your config uses an opaque export (`export default someVar`) or a non-array `modules` field, the wizard bails with a clear error message telling you to edit manually.
63
+
64
+ #### Dry run
65
+
66
+ Preview the diff without writing anything:
67
+
68
+ ```bash
69
+ npm create @noy-db --dry-run
70
+ ```
71
+
72
+ Prints the unified diff and exits. Useful in CI, code review, and "what would this do to my config?" exploration.
73
+
74
+ #### Force fresh mode inside an existing project
75
+
76
+ If you're inside a Nuxt workspace but want to create a **new** sub-project rather than augment the root, pass `--force-fresh`:
77
+
78
+ ```bash
79
+ cd ~/my-monorepo-with-nuxt
80
+ npm create @noy-db my-sub-app --force-fresh
81
+ ```
82
+
83
+ ### All flags
84
+
85
+ | Flag | Effect |
86
+ |---|---|
87
+ | `<project-name>` (positional) | Target directory name (fresh mode only) |
88
+ | `-y`, `--yes` | Skip every prompt; use defaults |
89
+ | `--adapter <name>` | Pre-select adapter: `browser` (default) / `file` / `memory` |
90
+ | `--no-sample-data` | (fresh mode) Skip the seed invoice records |
91
+ | `--dry-run` | (augment mode) Show the diff without writing |
92
+ | `--force-fresh` | Force fresh-project mode even in an existing Nuxt dir |
93
+ | `--lang <code>` | UI language: `en` (default) / `th`. Auto-detected from `LC_ALL` / `LANG` when omitted |
94
+ | `-h`, `--help` | Show usage and exit |
95
+
96
+ #### Languages
97
+
98
+ The wizard's prompts and notes are available in **English** (default) and **Thai** (`th`). Pick a language explicitly with `--lang`:
99
+
100
+ ```bash
101
+ npm create @noy-db my-app --lang th
102
+ ```
103
+
104
+ When `--lang` is omitted, the wizard reads the standard POSIX locale env vars (`LC_ALL`, `LC_MESSAGES`, `LANG`, `LANGUAGE`) and auto-selects Thai when they point to a Thai locale, e.g.:
105
+
106
+ ```bash
107
+ LANG=th_TH.UTF-8 npm create @noy-db my-app
108
+ ```
109
+
110
+ Validation errors and stack traces stay in English regardless of language so bug reports look the same in any locale.
111
+
112
+ ---
113
+
114
+ ## `noy-db` — the CLI tool
115
+
116
+ The `noy-db` bin ships inside the same `@noy-db/create` package. Install it as a dev dependency and it's available via `pnpm exec` / `npx`:
117
+
118
+ ```bash
119
+ pnpm add -D @noy-db/create
120
+ pnpm exec noy-db <command>
121
+ ```
122
+
123
+ ### Commands at a glance
124
+
125
+ | Command | Purpose |
126
+ |---|---|
127
+ | `noy-db add <collection>` | Scaffold a new Pinia store + Vue page for a collection |
128
+ | `noy-db add user <id> <role>` | Grant a new user access to a compartment |
129
+ | `noy-db verify` | In-memory crypto round-trip integrity check |
130
+ | `noy-db rotate` | Rotate DEKs for one or more collections |
131
+ | `noy-db backup <target>` | Dump a compartment to an encrypted file |
132
+
133
+ All commands that touch real compartments use the **file adapter** and require these flags:
134
+
135
+ - `--dir <path>` — the data directory. Defaults to `./data`.
136
+ - `--compartment <name>` — the compartment (tenant) name. Required.
137
+ - `--user <id>` — your own user id in the compartment. Required.
138
+
139
+ You'll be prompted for your passphrase at runtime. Passphrases are never echoed, never logged, never written to disk, and cleared from process memory when the command exits.
140
+
141
+ ### `noy-db add <collection>`
142
+
143
+ Scaffolds two new files in your project:
144
+
145
+ - `app/stores/<name>.ts` — a `defineNoydbStore<Name>()` call with a placeholder interface
146
+ - `app/pages/<name>.vue` — a minimal CRUD page that lists, adds, and deletes records
147
+
148
+ ```bash
149
+ pnpm exec noy-db add clients
150
+ ```
151
+
152
+ Refuses to overwrite existing files — if either target already exists, the command exits non-zero without touching anything. There's no `--force` flag; delete the old files manually if you want to regenerate.
153
+
154
+ ### `noy-db add user <userId> <role> [options]`
155
+
156
+ Grants a new user access to a compartment. Two passphrase prompts: yours (caller), then the new user's (with confirmation).
157
+
158
+ ```bash
159
+ pnpm exec noy-db add user accountant-ann operator \
160
+ --dir ./data \
161
+ --compartment demo-co \
162
+ --user owner-alice \
163
+ --collections invoices:rw,clients:ro
164
+ ```
165
+
166
+ Roles:
167
+
168
+ | Role | Permissions | Requires `--collections`? |
169
+ |---|---|:---:|
170
+ | `owner` | All collections, all operations | No |
171
+ | `admin` | All collections, all operations (except grant owner) | No |
172
+ | `viewer` | All collections, read-only | No |
173
+ | `operator` | Per-collection `rw` or `ro` explicitly | **Yes** |
174
+ | `client` | Per-collection `ro` explicitly | **Yes** |
175
+
176
+ For `operator` and `client`, the `--collections` flag is required. Format: `name1:rw,name2:ro,name3:rw`.
177
+
178
+ ### `noy-db verify`
179
+
180
+ Runs an end-to-end crypto round-trip against an in-memory adapter. No real data is touched; the command creates a throwaway compartment, writes a record, reads it back, and verifies it decrypts correctly. Useful as a sanity check that `@noy-db/core`, `@noy-db/memory`, and your local Node version all agree on Web Crypto.
181
+
182
+ ```bash
183
+ pnpm exec noy-db verify
184
+ # ✔ noy-db integrity check passed (126ms)
185
+ ```
186
+
187
+ Exits non-zero if anything diverges.
188
+
189
+ ### `noy-db rotate [options]`
190
+
191
+ Rotate the DEKs for one or more collections in a compartment. Generates fresh keys, re-encrypts every record with the new keys, and re-wraps the new keys into every user's keyring. Nobody is revoked — everyone keeps their current permissions with fresh key material.
192
+
193
+ ```bash
194
+ # Rotate every collection in the compartment
195
+ pnpm exec noy-db rotate --dir ./data --compartment demo-co --user owner-alice
196
+
197
+ # Rotate specific collections only
198
+ pnpm exec noy-db rotate --dir ./data --compartment demo-co --user owner-alice \
199
+ --collections invoices,clients
200
+ ```
201
+
202
+ Use cases:
203
+
204
+ - **Suspected key leak**: an operator lost a laptop, a developer accidentally pasted a passphrase into a Slack channel, a USB stick went missing. Rotating is cheap insurance.
205
+ - **Scheduled rotation**: some compliance regimes require periodic key rotation regardless of exposure. This command makes rotation scriptable from cron or a CI job.
206
+
207
+ Different from `noydb.revoke({ rotateKeys: true })` in that it doesn't kick anyone out — it's the "just rotate" path.
208
+
209
+ ### `noy-db backup <target> [options]`
210
+
211
+ Dump a compartment to a local file. The dump is a **verifiable backup**: it includes the chain head and the full `_ledger` / `_ledger_deltas` snapshots, so `compartment.load()` on the receiving side will reject any tampering between dump and restore.
212
+
213
+ ```bash
214
+ pnpm exec noy-db backup ./backups/demo-2026-04-07.json \
215
+ --dir ./data --compartment demo-co --user owner-alice
216
+ ```
217
+
218
+ Target paths:
219
+
220
+ - **Plain filesystem path** — `./backups/demo.json` or `/absolute/path.json`
221
+ - **`file://` URI** — `file:///absolute/path.json` or `file://./relative.json`
222
+
223
+ Parent directories are created on demand, so `./backups/2026/04/demo.json` works even if `./backups/2026/04/` doesn't exist yet.
224
+
225
+ Unsupported schemes (`s3://`, `https://`, etc.) are rejected **before** the passphrase prompt so a typo doesn't waste a passphrase entry.
226
+
227
+ ### `noy-db help`
228
+
229
+ Prints the full usage message for all subcommands.
230
+
231
+ ---
232
+
233
+ ## Security invariants
234
+
235
+ Every command that touches real compartments follows these rules:
236
+
237
+ 1. **Passphrase via `@clack/prompts` `password()`** — never echoes to the terminal, never logged.
238
+ 2. **Passphrase never leaves the local closure** — no file writes, no error messages, no telemetry.
239
+ 3. **Ctrl-C at the prompt aborts before any I/O happens** — cancelling doesn't leave the system in a half-mutated state.
240
+ 4. **`finally { db.close() }`** — KEK is cleared from process memory on exit, success or failure.
241
+ 5. **Unsupported backup schemes are rejected before the prompt** — a typo doesn't waste a passphrase entry.
242
+
243
+ ---
244
+
245
+ ## What's in the fresh-project template
246
+
247
+ ```
248
+ my-app/
249
+ ├── nuxt.config.ts ← @noy-db/nuxt wired up with your chosen adapter
250
+ ├── package.json ← @noy-db/* deps at ^0.5.0
251
+ ├── tsconfig.json
252
+ ├── README.md
253
+ ├── .gitignore
254
+ └── app/
255
+ ├── app.vue
256
+ ├── stores/
257
+ │ └── invoices.ts ← defineNoydbStore<Invoice>
258
+ └── pages/
259
+ ├── index.vue
260
+ └── invoices.vue ← CRUD page with reactive query DSL
261
+ ```
262
+
263
+ Everything stored is encrypted with AES-256-GCM before it touches the adapter. The adapter only ever sees ciphertext.
264
+
265
+ ---
266
+
267
+ ## Deferred to a future release
268
+
269
+ These are explicit non-goals:
270
+
271
+ - **Thai i18n** of the wizard prompts ([#36](https://github.com/vLannaAi/noy-db/issues/36))
272
+ - **Non-Nuxt templates** — no Vite/Vue standalone, no Electron, no vanilla ([#39](https://github.com/vLannaAi/noy-db/issues/39))
273
+ - **`noy-db seed`** — needs a design decision about how seed scripts authenticate
274
+ - **S3 backup targets** — would bundle `@aws-sdk` into this package and break the zero-runtime-deps story; lives in a companion package instead
275
+ - **`noy-db restore <file>`** — paired with the existing `compartment.load()` + integrity check; deferred so it can be designed alongside future identity/session work
276
+
277
+ Open an issue if you need one of these sooner.
278
+
279
+ ---
280
+
281
+ ## License
282
+
283
+ MIT
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node