@burakboduroglu/nors 0.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/LICENSE +21 -0
- package/README.md +154 -0
- package/bin/nors.js +86 -0
- package/package.json +48 -0
- package/pb_migrations/1789000000_nors_notes.js +47 -0
- package/pb_public/nors/assets/abnfDiagram-VCTEODGH-72Hc1HpF.js +1 -0
- package/pb_public/nors/assets/arc-BEvzHx4o.js +1 -0
- package/pb_public/nors/assets/architecture-7GRP2DOG-HrDOEF9a.js +1 -0
- package/pb_public/nors/assets/architectureDiagram-5GKGNRK7-Dyvym86p.js +36 -0
- package/pb_public/nors/assets/array-BifhSqXX.js +1 -0
- package/pb_public/nors/assets/blockDiagram-I7D4REHJ-CDUU8dVT.js +129 -0
- package/pb_public/nors/assets/c4Diagram-7LVT6UL2-DO3ezHBq.js +38 -0
- package/pb_public/nors/assets/channel-Df8EOoqr.js +1 -0
- package/pb_public/nors/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/pb_public/nors/assets/chunk-4HAMMTFA-1EqQyQU7.js +62 -0
- package/pb_public/nors/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/pb_public/nors/assets/chunk-75Z2AOVW-Cwc7WThs.js +2 -0
- package/pb_public/nors/assets/chunk-DU6HZSFF-B5Wb9e-Z.js +127 -0
- package/pb_public/nors/assets/chunk-F27PBJKO-Bab3aPrd.js +1 -0
- package/pb_public/nors/assets/chunk-FOHPRMQF-DzxwRta7.js +161 -0
- package/pb_public/nors/assets/chunk-GMAD6QVW-BvxprKvk.js +72 -0
- package/pb_public/nors/assets/chunk-GVQU2GXP-CsbitBlJ.js +1 -0
- package/pb_public/nors/assets/chunk-IMKFNOWR-CPLySese.js +231 -0
- package/pb_public/nors/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/pb_public/nors/assets/chunk-L3NEJ4N5-CFPB-We8.js +1 -0
- package/pb_public/nors/assets/chunk-OSK3NFVY-BAJO2owD.js +10 -0
- package/pb_public/nors/assets/chunk-P2QGCYS3-f8ck-xGx.js +1 -0
- package/pb_public/nors/assets/chunk-POPQ4Y6H-B_VDFlEk.js +1 -0
- package/pb_public/nors/assets/chunk-PWAF6VOD-B32HYusP.js +1 -0
- package/pb_public/nors/assets/chunk-SHT3W25Y-CfjlZPrR.js +168 -0
- package/pb_public/nors/assets/chunk-SVP7TREG-DT0H529z.js +88 -0
- package/pb_public/nors/assets/chunk-TICWLB2K-BD3m0b83.js +206 -0
- package/pb_public/nors/assets/chunk-XXDRQBXY-DFBUG-OT.js +1 -0
- package/pb_public/nors/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/pb_public/nors/assets/classDiagram-ZZMXUADV-B17tfBoX.js +1 -0
- package/pb_public/nors/assets/classDiagram-v2-VYDZK3BY-B17tfBoX.js +1 -0
- package/pb_public/nors/assets/cose-bilkent-JH36ORCC-BiZdMhTY.js +1 -0
- package/pb_public/nors/assets/cynefin-OW5HDTMX-Bts7NCEe.js +1 -0
- package/pb_public/nors/assets/cynefinDiagram-5FMLGOSQ-DQtWZ8b_.js +62 -0
- package/pb_public/nors/assets/cytoscape.esm-Yq6u8L66.js +321 -0
- package/pb_public/nors/assets/dagre-C-rnJpZF.js +1 -0
- package/pb_public/nors/assets/dagre-GXQ25YYZ-9KsnELcz.js +4 -0
- package/pb_public/nors/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/pb_public/nors/assets/diagram-S7CK7UJ4-BH9UWoqn.js +30 -0
- package/pb_public/nors/assets/diagram-UQ7AKVKN-CxwLdAs_.js +41 -0
- package/pb_public/nors/assets/diagram-VSXAHHWV-CZ09vgYE.js +3 -0
- package/pb_public/nors/assets/diagram-VX7I27RA-BOR_eKl1.js +24 -0
- package/pb_public/nors/assets/diagram-Z3DM3KII-CNxcZIX5.js +24 -0
- package/pb_public/nors/assets/dist-DTg6UBE_.js +1 -0
- package/pb_public/nors/assets/ebnfDiagram-PWID7BFC-Bd6A_szT.js +1 -0
- package/pb_public/nors/assets/erDiagram-RLTQ6QDP-Cg1LC0U7.js +99 -0
- package/pb_public/nors/assets/eventmodeling-NTZA5JFV-04EdYz80.js +1 -0
- package/pb_public/nors/assets/flowDiagram-HODETNUW-D2i1JVc0.js +1 -0
- package/pb_public/nors/assets/ganttDiagram-EL5Y4UJY-DvZJpWfe.js +292 -0
- package/pb_public/nors/assets/gitGraph-4MIJSDKK-CsEbmQD4.js +1 -0
- package/pb_public/nors/assets/gitGraphDiagram-WWUBYQGX-CVlXu2Qq.js +106 -0
- package/pb_public/nors/assets/graphlib-DS17s2tU.js +1 -0
- package/pb_public/nors/assets/index-BZ_XOI9a.js +71 -0
- package/pb_public/nors/assets/index-DpLWWzac.css +1 -0
- package/pb_public/nors/assets/info-A6RAGUB7-Cr_1btt8.js +1 -0
- package/pb_public/nors/assets/infoDiagram-27XIBGKW-B5T1nV5L.js +2 -0
- package/pb_public/nors/assets/init-C-OQMol4.js +1 -0
- package/pb_public/nors/assets/ishikawaDiagram-5VMMS53U-CBxNSCVW.js +70 -0
- package/pb_public/nors/assets/journeyDiagram-3NMN7TZE-Cr3ECa1U.js +139 -0
- package/pb_public/nors/assets/kanban-definition-UXKFOSKX-DePsUrbx.js +89 -0
- package/pb_public/nors/assets/katex-ZlcWpGUi.js +257 -0
- package/pb_public/nors/assets/line-DcGZsAWh.js +1 -0
- package/pb_public/nors/assets/linear-B6A2FQ2q.js +1 -0
- package/pb_public/nors/assets/mermaid-parser.core-BR6xQvT6.js +7 -0
- package/pb_public/nors/assets/mermaid.core-FEPUjAo_.js +44 -0
- package/pb_public/nors/assets/mindmap-definition-YA3MSWOX-7sU4YIM1.js +96 -0
- package/pb_public/nors/assets/ordinal-BDEzSJ7C.js +1 -0
- package/pb_public/nors/assets/packet-AYTQ26CC-TYEYjIA7.js +1 -0
- package/pb_public/nors/assets/path-fybaL0A-.js +1 -0
- package/pb_public/nors/assets/pegDiagram-XKGWAZYB-BGzYtGBp.js +1 -0
- package/pb_public/nors/assets/pie-WAS4IAKB-BAuhAqOa.js +1 -0
- package/pb_public/nors/assets/pieDiagram-E7YTZNPT-Dc1PZDwl.js +39 -0
- package/pb_public/nors/assets/quadrantDiagram-AXDQQJYC-D-d3azLW.js +7 -0
- package/pb_public/nors/assets/radar-RG4KPBEZ-CWKhbiay.js +1 -0
- package/pb_public/nors/assets/railroad-74A4TZTK-Cm0h6b91.js +1 -0
- package/pb_public/nors/assets/railroad-abnf-HS5TGJTU-DAMHMau8.js +1 -0
- package/pb_public/nors/assets/railroad-ebnf-LZEXJU2U-CqJSrz-5.js +1 -0
- package/pb_public/nors/assets/railroad-peg-WCYAUIDC-CjgiTUIW.js +1 -0
- package/pb_public/nors/assets/railroadDiagram-O6MQD6OU-nzjXgwpW.js +1 -0
- package/pb_public/nors/assets/requirementDiagram-BXWQKSXE-v6B3lGir.js +84 -0
- package/pb_public/nors/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/pb_public/nors/assets/sankeyDiagram-P5KCCOFB-CuyMtFNE.js +40 -0
- package/pb_public/nors/assets/sequenceDiagram-WJ2MYXX4-C2LyM7bh.js +162 -0
- package/pb_public/nors/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/pb_public/nors/assets/src-BH-TyZbA.js +1 -0
- package/pb_public/nors/assets/stateDiagram-D77RDMKH-D1A2WBer.js +1 -0
- package/pb_public/nors/assets/stateDiagram-v2-MP3YSRHH-4A_XCUQM.js +1 -0
- package/pb_public/nors/assets/swimlanes-42K2YHIH-sCNSWX_N.js +1 -0
- package/pb_public/nors/assets/swimlanesDiagram-VR7AAH4N-D7VxXsS9.js +8 -0
- package/pb_public/nors/assets/timeline-definition-24CTP7MA-DCxtDLFB.js +120 -0
- package/pb_public/nors/assets/treeView-Q6P3EWNA-Bnjs5jw6.js +1 -0
- package/pb_public/nors/assets/treemap-WGGIJYW6-C5ajpoq6.js +1 -0
- package/pb_public/nors/assets/vennDiagram-4TSXK5OY-B5S6LN3U.js +34 -0
- package/pb_public/nors/assets/wardley-WFR3VGLG-zH3dSKZv.js +1 -0
- package/pb_public/nors/assets/wardleyDiagram-VM6X3IG4-BffSe1Zn.js +78 -0
- package/pb_public/nors/assets/xychartDiagram-S5SC5T6Z-zb3OjZUW.js +7 -0
- package/pb_public/nors/index.html +15 -0
- package/pb_public/nors/nors-mark.svg +8 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Burak Boduroğlu
|
|
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,154 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="assets/nors-mark-512.png" alt="Nors mark" width="112">
|
|
4
|
+
|
|
5
|
+
# Nors
|
|
6
|
+
|
|
7
|
+
**Personal ops notes that ride a PocketBase instance you already run.**
|
|
8
|
+
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://www.npmjs.com/package/@burakboduroglu/nors)
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
Nors is not an application you deploy. It is one migration and one static
|
|
21
|
+
page, copied into a PocketBase directory you already have. The database,
|
|
22
|
+
auth, HTTP server and backups are already running — a dedicated notes app
|
|
23
|
+
would duplicate all of them.
|
|
24
|
+
|
|
25
|
+
<div align="center">
|
|
26
|
+
|
|
27
|
+
<img src="assets/screenshot-dash.png" alt="Nors dashboard — note cards with kind tabs" width="760">
|
|
28
|
+
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
## What it is
|
|
32
|
+
|
|
33
|
+
Notes live as cards on a dashboard, filed under four kinds: Diagram, Runbook,
|
|
34
|
+
Reference, Scratch. An agent drafts in markdown, you publish from the panel —
|
|
35
|
+
paste a blob, fix the title, pick a kind, done. Bodies render as markdown and
|
|
36
|
+
Mermaid fences become diagrams in the reader.
|
|
37
|
+
|
|
38
|
+
Writing stays minimal on purpose: title, kind, pinned, body. The slug grows
|
|
39
|
+
out of the title and the summary out of the first clean body line, so there
|
|
40
|
+
is nothing else to fill in.
|
|
41
|
+
|
|
42
|
+
## Highlights
|
|
43
|
+
|
|
44
|
+
| | Feature | How it works |
|
|
45
|
+
| --- | ------- | ------------ |
|
|
46
|
+
| 🧩 | **No infrastructure of its own** | Files copied into an existing PocketBase. No container, no second database, no extra port. |
|
|
47
|
+
| 📝 | **Write four things, nothing else** | Title, kind, pinned, body. Slug and summary derive themselves. |
|
|
48
|
+
| 📊 | **Diagrams without a plugin** | Mermaid loads only on pages that hold a fence; everything else never downloads it. |
|
|
49
|
+
| ↔️ | **Order by dragging** | Native HTML5 drag-and-drop renumbers `sort`; pinned cards stay first by construction. No DnD library. |
|
|
50
|
+
| 📥 | **Seeds are upserts** | `bun run import-seeds` matches by slug — re-running updates instead of duplicating. |
|
|
51
|
+
| 🛡️ | **Unsaved work asks first** | Leaving the editor with edits pops a guard instead of silently dropping the draft. |
|
|
52
|
+
| 📵 | **No telemetry** | Zero outbound requests. The page talks to your PocketBase and nothing else. |
|
|
53
|
+
|
|
54
|
+
<div align="center">
|
|
55
|
+
|
|
56
|
+
<img src="assets/screenshot-reader.png" alt="Nors reader — CLI shelf note with rendered Mermaid diagrams" width="760">
|
|
57
|
+
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
## Footprint
|
|
61
|
+
|
|
62
|
+
Measured with `du`:
|
|
63
|
+
|
|
64
|
+
| | |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| Installed files | **3.5 MB** — migration 4 KB, page the rest |
|
|
67
|
+
| First visit | **~87 KB** — entry JS ~79 KB (gzip ~24 KB), CSS ~7.5 KB |
|
|
68
|
+
| The other 3.4 MB | Mermaid diagram chunks, fetched only when a reader page holds a fence |
|
|
69
|
+
| Database growth | one `nors_notes` row per note, inside the existing `pb_data` |
|
|
70
|
+
| Extra processes | none |
|
|
71
|
+
| Extra ports | none |
|
|
72
|
+
|
|
73
|
+
If PocketBase is already running, the marginal cost of Nors is the file sizes.
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
Install into a PocketBase directory with the packaged CLI:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
bunx @burakboduroglu/nors install /path/to/pocketbase
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This copies the migration and built page; it never touches `pb_data`. Then
|
|
84
|
+
restart PocketBase so the migration runs. **If it was already running, stop it
|
|
85
|
+
before copying and start it afterwards** — PocketBase watches its directories
|
|
86
|
+
and can race a service manager doing the same.
|
|
87
|
+
|
|
88
|
+
For a source checkout and remote host, the `deploy/` installer performs the
|
|
89
|
+
stop → copy → start sequence:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
scp -r pb_migrations pb_public deploy/install.sh host:/tmp/nors-stage/
|
|
93
|
+
ssh host
|
|
94
|
+
sudo /tmp/nors-stage/install.sh /tmp/nors-stage
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The page is served at `/nors/`. Gate `/nors` and
|
|
98
|
+
`/api/collections/nors_notes` in Cloudflare Access the way `/subs/` is gated
|
|
99
|
+
(see `deploy/access-caddy.md`). Then load the three seed notes through the API:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
NORS_PB_URL=https://your.host NORS_PB_EMAIL=... NORS_PB_PASSWORD=... \
|
|
103
|
+
bun run import-seeds
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## How it works
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
browser ──▶ /nors/ static page, superuser login
|
|
110
|
+
browser ──▶ /api/collections/nors_notes/* superuser only, CRUD + reorder
|
|
111
|
+
agent ──▶ drafts markdown ──▶ editor ──▶ publish
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Routes are hashes: `#/` dashboard, `#/n/<slug>` reader,
|
|
115
|
+
`#/edit/<slug|$new>` editor. `/nors/?new=1` is the stable external entry point
|
|
116
|
+
for a new note; it consumes the query and opens the `$new` editor route.
|
|
117
|
+
|
|
118
|
+
## Security
|
|
119
|
+
|
|
120
|
+
The `nors_notes` collection has null API rules, which in PocketBase means
|
|
121
|
+
superuser only. The dashboard holds a superuser token in localStorage — anyone
|
|
122
|
+
with the browser profile has the keys, documented rather than hidden. There is
|
|
123
|
+
no audit log and no second user; this is a single-operator surface behind
|
|
124
|
+
Cloudflare Access, not a multi-user app.
|
|
125
|
+
|
|
126
|
+
## What it deliberately does not do
|
|
127
|
+
|
|
128
|
+
No in-app LLM calls. No public notes or team sharing. No wiki search, tag
|
|
129
|
+
graph, or version history UI. No reminders. It does not replace a vault or a
|
|
130
|
+
knowledge base — it is the live dashboard above them.
|
|
131
|
+
|
|
132
|
+
## Stack
|
|
133
|
+
|
|
134
|
+
PocketBase for storage, auth and HTTP. SolidJS + Vite UI compiled to static
|
|
135
|
+
files under `pb_public/nors/`. `marked` for markdown, Mermaid on demand, no
|
|
136
|
+
CSS library, no UI server. Bun as the package manager.
|
|
137
|
+
|
|
138
|
+
## Develop the UI
|
|
139
|
+
|
|
140
|
+
Source lives in `web/`. The shipped page is built output:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
bun --cwd web install
|
|
144
|
+
bun run build # root script — emits pb_public/nors/
|
|
145
|
+
bun run dev # local UI; /api proxied to :8090 (NORS_PB_PORT to move it)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Against a tunneled production box: `ssh -N -L 8090:127.0.0.1:8090 host`,
|
|
149
|
+
then `bun run dev` — the browser stays on localhost, so neither CORS nor
|
|
150
|
+
Cloudflare Access is in the path.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT — see [LICENSE](LICENSE).
|
package/bin/nors.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Nors's installer. It copies files into a PocketBase directory and prints the
|
|
3
|
+
// steps that cannot be copied for you. It never touches pb_data, never starts
|
|
4
|
+
// or stops anything, and never talks to the network.
|
|
5
|
+
|
|
6
|
+
import { readFile, mkdir, cp, access } from "node:fs/promises"
|
|
7
|
+
import { constants } from "node:fs"
|
|
8
|
+
import { join, dirname, resolve } from "node:path"
|
|
9
|
+
import { fileURLToPath } from "node:url"
|
|
10
|
+
|
|
11
|
+
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..")
|
|
12
|
+
const pkg = JSON.parse(await readFile(join(ROOT, "package.json"), "utf8"))
|
|
13
|
+
|
|
14
|
+
const exists = async (p) => access(p, constants.F_OK).then(() => true, () => false)
|
|
15
|
+
|
|
16
|
+
const HELP = `
|
|
17
|
+
nors ${pkg.version} — personal ops notes on PocketBase
|
|
18
|
+
|
|
19
|
+
nors install <pocketbase-dir> copy the migration and the page into place
|
|
20
|
+
Options
|
|
21
|
+
--force install even if the target does not look like a PocketBase directory
|
|
22
|
+
-h, --help this
|
|
23
|
+
-v, --version
|
|
24
|
+
|
|
25
|
+
The install step only writes pb_migrations/ and pb_public/nors/.
|
|
26
|
+
Your data lives in pb_data/ and is never read or written.
|
|
27
|
+
`
|
|
28
|
+
|
|
29
|
+
// A PocketBase directory is recognised by the binary or by pb_data beside it.
|
|
30
|
+
// Getting this wrong would scatter files into an unrelated folder, so the check
|
|
31
|
+
// is a refusal rather than a warning.
|
|
32
|
+
async function assertPocketBase(dir, force) {
|
|
33
|
+
if (force) return
|
|
34
|
+
const looksRight =
|
|
35
|
+
(await exists(join(dir, "pocketbase"))) ||
|
|
36
|
+
(await exists(join(dir, "pocketbase.exe"))) ||
|
|
37
|
+
(await exists(join(dir, "pb_data")))
|
|
38
|
+
if (!looksRight) {
|
|
39
|
+
console.error(
|
|
40
|
+
`Refusing to install: ${dir} holds no pocketbase binary and no pb_data.\n` +
|
|
41
|
+
`Point at the directory the PocketBase executable lives in, or pass --force.`
|
|
42
|
+
)
|
|
43
|
+
process.exit(1)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function install(dir, force) {
|
|
48
|
+
if (!dir) { console.error("Usage: nors install <pocketbase-dir>"); process.exit(1) }
|
|
49
|
+
const target = resolve(dir)
|
|
50
|
+
if (!(await exists(target))) { console.error(`No such directory: ${target}`); process.exit(1) }
|
|
51
|
+
await assertPocketBase(target, force)
|
|
52
|
+
|
|
53
|
+
const parts = [
|
|
54
|
+
["pb_migrations", "pb_migrations"],
|
|
55
|
+
[join("pb_public", "nors"), join("pb_public", "nors")]
|
|
56
|
+
]
|
|
57
|
+
for (const [from, to] of parts) {
|
|
58
|
+
const dest = join(target, to)
|
|
59
|
+
await mkdir(dirname(dest), { recursive: true })
|
|
60
|
+
await cp(join(ROOT, from), dest, { recursive: true })
|
|
61
|
+
console.log(` wrote ${to}/`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(`
|
|
65
|
+
Installed into ${target}
|
|
66
|
+
|
|
67
|
+
Next, and none of it is automatic:
|
|
68
|
+
1. Restart PocketBase so the migration runs. If it was already running, stop
|
|
69
|
+
it before copying and start it after.
|
|
70
|
+
2. Serve the page. It is at /nors/ once PocketBase is serving pb_public.
|
|
71
|
+
3. Put an auth layer in front of /nors and
|
|
72
|
+
/api/collections/nors_notes. The collection is superuser-only on its own;
|
|
73
|
+
the page is a login form anyone could reach.
|
|
74
|
+
4. A source checkout includes optional seed notes and the import-seeds script.
|
|
75
|
+
`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const [cmd, ...rest] = process.argv.slice(2)
|
|
79
|
+
const force = rest.includes("--force")
|
|
80
|
+
|
|
81
|
+
if (cmd === "-v" || cmd === "--version") { console.log(pkg.version); process.exit(0) }
|
|
82
|
+
if (!cmd || cmd === "-h" || cmd === "--help") { console.log(HELP); process.exit(0) }
|
|
83
|
+
if (cmd === "install") { await install(rest.find((a) => !a.startsWith("--")), force); process.exit(0) }
|
|
84
|
+
|
|
85
|
+
console.error(`Unknown command: ${cmd}\n${HELP}`)
|
|
86
|
+
process.exit(1)
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@burakboduroglu/nors",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Personal ops notes dashboard on PocketBase — Norse-named, Solid UI at /nors/",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Burak Boduroğlu",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "bun --cwd web dev",
|
|
10
|
+
"build": "bun --cwd web build",
|
|
11
|
+
"prepack": "bun --cwd web build",
|
|
12
|
+
"preview": "bun --cwd web preview",
|
|
13
|
+
"import-seeds": "bun scripts/import-seeds.ts"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"nors": "bin/nors.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin",
|
|
20
|
+
"pb_migrations",
|
|
21
|
+
"pb_public",
|
|
22
|
+
"LICENSE",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"notes",
|
|
27
|
+
"ops-notes",
|
|
28
|
+
"pocketbase",
|
|
29
|
+
"self-hosted",
|
|
30
|
+
"dashboard",
|
|
31
|
+
"mermaid",
|
|
32
|
+
"no-telemetry"
|
|
33
|
+
],
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/burakboduroglu/nors.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/burakboduroglu/nors#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/burakboduroglu/nors/issues"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/// <reference path="../pb_data/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
// Nors: personal ops notes. Superuser-only (null API rules).
|
|
4
|
+
// Served as a Solid app from pb_public/nors/ behind Caddy + Access.
|
|
5
|
+
migrate((app) => {
|
|
6
|
+
const notes = new Collection({
|
|
7
|
+
name: "nors_notes",
|
|
8
|
+
type: "base",
|
|
9
|
+
fields: [
|
|
10
|
+
{ name: "title", type: "text", required: true, max: 160 },
|
|
11
|
+
{ name: "slug", type: "text", required: true, max: 80 },
|
|
12
|
+
{ name: "summary", type: "text", max: 400 },
|
|
13
|
+
{ name: "body", type: "editor", required: false },
|
|
14
|
+
{
|
|
15
|
+
name: "kind",
|
|
16
|
+
type: "select",
|
|
17
|
+
required: true,
|
|
18
|
+
maxSelect: 1,
|
|
19
|
+
values: ["diagram", "runbook", "reference", "scratch"],
|
|
20
|
+
},
|
|
21
|
+
{ name: "tags", type: "json", maxSize: 8000 },
|
|
22
|
+
{ name: "pinned", type: "bool" },
|
|
23
|
+
{
|
|
24
|
+
name: "status",
|
|
25
|
+
type: "select",
|
|
26
|
+
required: true,
|
|
27
|
+
maxSelect: 1,
|
|
28
|
+
values: ["draft", "published", "archived"],
|
|
29
|
+
},
|
|
30
|
+
{ name: "sort", type: "number" },
|
|
31
|
+
{ name: "created", type: "autodate", onCreate: true, onUpdate: false },
|
|
32
|
+
{ name: "updated", type: "autodate", onCreate: true, onUpdate: true },
|
|
33
|
+
],
|
|
34
|
+
indexes: [
|
|
35
|
+
"CREATE UNIQUE INDEX idx_nors_notes_slug ON nors_notes (slug)",
|
|
36
|
+
"CREATE INDEX idx_nors_notes_status ON nors_notes (status)",
|
|
37
|
+
"CREATE INDEX idx_nors_notes_sort ON nors_notes (sort)",
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
app.save(notes)
|
|
41
|
+
}, (app) => {
|
|
42
|
+
try {
|
|
43
|
+
app.delete(app.findCollectionByNameOrId("nors_notes"))
|
|
44
|
+
} catch (_) {
|
|
45
|
+
// already gone
|
|
46
|
+
}
|
|
47
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{m as e}from"./src-BH-TyZbA.js";import{m as t,t as n}from"./mermaid-parser.core-BR6xQvT6.js";import{n as r}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import"./chunk-DU6HZSFF-B5Wb9e-Z.js";import{n as i,r as a,t as o}from"./chunk-SVP7TREG-DT0H529z.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-FEPUjAo_.js";var c=t().RailroadAbnf.parser.LangiumParser,l=r(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=r(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=r(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=r(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=r(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=r(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=r(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:r(t=>{o.clear(),e.debug(`[ABNF Parser] Starting Langium parse`);let r=c.parse(t);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new n(r);let i=r.value;e.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),e.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-DTg6UBE_.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-FOHPRMQF-DzxwRta7.js";import{M as e}from"./mermaid-parser.core-BR6xQvT6.js";export{e as createArchitectureServices};
|