@human-synthesis/norns 0.0.7 → 0.0.8

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  **AI-driven software architecture and development framework, based on Svelte.**
4
4
 
5
- SvelteKit with **Pug + Civet** and the `.n` / `.c` file extensions — preconfigured. The `.c` extension is recognised as an alias for `.civet`; both compile through Civet. CoffeeScript is no longer supported.
5
+ SvelteKit with **Pug + Civet** and the `.n` / `.c` file extensions — preconfigured. The `.c` extension is recognised as an alias for `.civet`; both compile through Civet.
6
6
 
7
7
  Includes a small runtime layer: feature-folder modularity, a DI container, route/page wrappers with valibot validation, and a migrations CLI.
8
8
 
@@ -63,7 +63,7 @@ export default defineConfig({
63
63
 
64
64
  ## Auto-imports
65
65
 
66
- `nornsAutoImport()` returns an object that's both a Svelte preprocessor (for `.n` / `.svelte` files) and a Vite plugin (for standalone `.c` / `.civet` modules). Wire it in both places:
66
+ `nornsAutoImport()` returns an object that's both a Svelte preprocessor (for `.n` / `.svelte` files) and a Vite plugin (for standalone `.c` / `.civet` modules). The same instance has all four resolvers: framework helpers, project components, project utilities, and library presets. Wire it in both places — Svelte's compiler ignores the Vite hooks, Vite ignores the Svelte hooks:
67
67
 
68
68
  ```js
69
69
  // svelte.config.js
@@ -72,7 +72,13 @@ import { nornsPreprocess } from '@human-synthesis/norns/preprocess';
72
72
  import { nornsAutoImport } from '@human-synthesis/norns/auto-import';
73
73
 
74
74
  export default nornsConfig({
75
- preprocess: [...nornsPreprocess(), nornsAutoImport()]
75
+ preprocess: [
76
+ ...nornsPreprocess(),
77
+ nornsAutoImport({
78
+ componentDirs: ['src/lib/components', 'src/routes'],
79
+ exportDirs: ['src/lib', 'src/routes']
80
+ })
81
+ ]
76
82
  });
77
83
  ```
78
84
 
@@ -81,24 +87,87 @@ export default nornsConfig({
81
87
  import { nornsCivetPlugin } from '@human-synthesis/norns/vite';
82
88
  import { nornsAutoImport } from '@human-synthesis/norns/auto-import';
83
89
 
84
- export default { plugins: [nornsCivetPlugin(), nornsAutoImport(), sveltekit()] };
90
+ export default {
91
+ plugins: [
92
+ nornsCivetPlugin(),
93
+ nornsAutoImport({ exportDirs: ['src/lib', 'src/routes'] }),
94
+ sveltekit()
95
+ ]
96
+ };
85
97
  ```
86
98
 
87
- With both in place:
99
+ ### What gets auto-imported
88
100
 
89
- - **Svelte helpers** `onMount`, `tick`, `getContext`, …, plus `svelte/store` (`writable`, `readable`, `derived`, `get`).
90
- - **SvelteKit helpers** — `error`, `redirect`, `fail`, `json`, `text`, … from `@sveltejs/kit`. Plus `page`, `navigating`, `updated` from `$app/state` — gated to non-server paths so it doesn't collide with the Norns server `page` (different shape, same name).
91
- - **Norns server helpers** `boot`, `page`, `route`, `Container`, `validate`, `betterSqlite`, from `@human-synthesis/norns/server`. Gated to server paths (`*.server.{c,civet}`, `**/server/**`, `+server.{c,civet}`).
92
- - **Project components** capitalised references like `<Card>` or `<Modal>` resolve to files under `src/lib/components/**` by default. Components inside `$lib` emit `$lib/...` import paths; components outside (e.g. route-colocated under `src/routes/**`, when you add it to `componentDirs`) emit a path relative to the importer. Files without a `<script>` block get one prepended automatically.
93
- - **Runes** (`$state`, `$derived`, `$effect`, `$props`) are Svelte compiler globals no import needed; the plugin doesn't touch them.
101
+ | Layer | Resolves | Examples |
102
+ |-------|----------|----------|
103
+ | Helpers | Hardcoded module-name lists, optionally path-gated | `onMount` from `svelte`, `redirect` from `@sveltejs/kit`, `page` from `$app/state` (client) or `@human-synthesis/norns/server` (server) |
104
+ | Components (dir scan) | Capitalised basenames in `componentDirs` | `<Card>` `$lib/components/Card.svelte`; `<Game>` `./Game.n` (route-colocated, importer-relative) |
105
+ | Components (preset map) | Bare-specifier `Record<name, importPath>` from a UI library | `<Btn>` `'@human-synthesis/norns-ui/components/Btn.n'` (used verbatim) |
106
+ | Project utilities | Named exports (`export const X`, `export X := …`, `export { a, b }`) discovered in `exportDirs` | `notes` from `$lib/notes/server/public`; `scheduleAiMove` from `./ai` (sibling) |
94
107
 
95
- Configurable on `nornsAutoImport({ })`: `helpers` (each entry can carry an optional `match: RegExp` to gate by filename), `componentDirs`, `componentExtensions`, `libRoot`, `libAlias`. Pass `helpers: false` or `componentDirs: false` to disable either layer.
108
+ Resolution priority is **helpers component dir component preset exports**. A name picked up earlier shadows a later match silently first-match-wins lets you override a library preset by dropping a file under your own `componentDirs`.
109
+
110
+ Path emission:
111
+
112
+ - Files inside `$lib` emit `$lib/...` paths (portable, friendly to the dts file).
113
+ - Files outside `$lib` emit a path relative to the importer.
114
+ - Project-utility paths are stripped of their file extension to match Norns/SvelteKit convention (`'$lib/notes/server/public'`, not `…/public.c`); the configured `extensions` array does the rest.
115
+
116
+ Files without a `<script>` block get one prepended automatically when a known component is referenced from markup. Runes (`$state`, `$derived`, `$effect`, `$props`) are Svelte compiler globals — no import needed; the plugin doesn't touch them.
117
+
118
+ ### Defaults
119
+
120
+ - **Helpers**: `svelte`, `svelte/store`, `@sveltejs/kit`, `$app/state` (non-server paths), `@human-synthesis/norns/server` (server paths only).
121
+ - **Component dirs**: `['src/lib/components']`.
122
+ - **Component extensions**: `['.svelte', '.n']`.
123
+ - **Export dirs**: `false` (off) — opt in. SvelteKit route/hook files (`+*.{c,svelte,n}`, `hooks.*`) are excluded from the export scan since their named exports (`load`, `actions`, `handle`, …) are framework-consumed.
124
+ - **Export extensions**: `['.c', '.civet', '.js']`. `.ts` is excluded by default — regex-based scanning can't reliably tell value exports from type-only ones under `verbatimModuleSyntax`.
125
+
126
+ ### UI library presets
127
+
128
+ A preset is a function returning a config slice — typically a `components` map. Compose it with your own config:
129
+
130
+ ```js
131
+ // vite.config.js
132
+ import { presetUI } from '@human-synthesis/norns-ui/auto-import';
133
+
134
+ const ui = presetUI();
135
+
136
+ export default {
137
+ plugins: [
138
+ nornsCivetPlugin(),
139
+ nornsAutoImport({
140
+ exportDirs: ['src/lib', 'src/routes'],
141
+ components: ui.components // { Btn: '@human-synthesis/norns-ui/components/Btn.n', … }
142
+ }),
143
+ sveltekit()
144
+ ]
145
+ };
146
+ ```
147
+
148
+ Drop `src/lib/components/Btn.n` in your project and it shadows the preset's `Btn` silently — `componentDirs` resolves first.
149
+
150
+ > **Roadmap.** Helpers from a preset (e.g. `toast()` from a UI library) currently can't merge with the defaults — passing `helpers` to `nornsAutoImport` _replaces_ the default list. A `presets` (or `additionalHelpers`) option to extend without replacing is a planned follow-up; for now, presets only deliver components.
151
+
152
+ ### Full options reference
153
+
154
+ | Option | Default | Notes |
155
+ |--------|---------|-------|
156
+ | `helpers` | `DEFAULT_HELPERS` (5 modules) | Pass `false` to disable. Each entry: `{ from, imports[], match? }` where `match` is a regex tested against the filename. |
157
+ | `componentDirs` | `['src/lib/components']` | `false` or `[]` to disable. |
158
+ | `componentExtensions` | `['.svelte', '.n']` | |
159
+ | `components` | `null` | `Record<name, importPath>` — bare-specifier preset map. |
160
+ | `exportDirs` | `false` | Off by default. Opt in with e.g. `['src/lib', 'src/routes']`. |
161
+ | `exportExtensions` | `['.c', '.civet', '.js']` | |
162
+ | `libRoot` | `'src/lib'` | Project-relative root that `libAlias` maps to. |
163
+ | `libAlias` | `'$lib'` | Alias prefix emitted in import paths. |
164
+ | `root` | `process.cwd()` | Project root. |
96
165
 
97
166
  ## Runtime — feature folders + DI
98
167
 
99
168
  Wire your hooks once:
100
169
 
101
- ```coffee
170
+ ```civet
102
171
  # src/hooks.server.c
103
172
  import { boot } from '@human-synthesis/norns/server'
104
173
 
@@ -124,7 +193,7 @@ src/lib/notes/
124
193
 
125
194
  Routes use thin wrappers from `@human-synthesis/norns/server`:
126
195
 
127
- ```coffee
196
+ ```civet
128
197
  # src/routes/notes/+page.server.c
129
198
  import { page } from '@human-synthesis/norns/server'
130
199
  import { notes } from '$lib/notes/server/public'
@@ -160,7 +229,7 @@ v1 supports SQLite via `better-sqlite3`. For Cloudflare D1 use `wrangler d1 migr
160
229
 
161
230
  The `db` helpers wire Drizzle across multiple targets:
162
231
 
163
- ```coffee
232
+ ```civet
164
233
  # module.c — Node + better-sqlite3 in dev
165
234
  import { betterSqlite } from '@human-synthesis/norns/server'
166
235
  db := await betterSqlite 'data/app.db', { pragma: ['journal_mode = WAL'] }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@human-synthesis/norns",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Norns — SvelteKit with Civet, Pug, and the .n / .civet / .c file extensions",
5
5
  "license": "MIT",
6
6
  "author": "Daniel Teodoroiu (https://humansynthesis.ai)",
@@ -208,11 +208,20 @@ function extractExports(source) {
208
208
  return out;
209
209
  }
210
210
 
211
+ // SvelteKit route conventions (`+page.server.c`, `+layout.c`, `+server.c`,
212
+ // `+error.svelte`, …) and hooks (`hooks.server.c`, `hooks.client.c`) export
213
+ // names like `load`, `actions`, `GET`, `handle`, `prerender` that are
214
+ // CONSUMED BY THE FRAMEWORK — never meant to be imported by other code. If
215
+ // they entered the export map, a user identifier called `load` would
216
+ // auto-import a random route's load function. Excluded by basename.
217
+ const ROUTE_FILE_RE = /^(\+|hooks\.)/;
218
+
211
219
  /**
212
220
  * Walk `dirs` and build a name → absolute-file-path map of every named
213
221
  * value export found. First-match-wins on collisions (same as the component
214
222
  * scanner) — silent because warnings would noise up the dev server on
215
- * intentional re-exports.
223
+ * intentional re-exports. SvelteKit route/hook files are excluded by
224
+ * basename so framework-consumed exports don't leak into the map.
216
225
  *
217
226
  * @param {string} root
218
227
  * @param {string[]} dirs
@@ -225,6 +234,7 @@ function buildExportMap(root, dirs, exts) {
225
234
  for (const d of dirs) {
226
235
  const abs = resolve(root, d);
227
236
  for (const file of walk(abs, exts)) {
237
+ if (ROUTE_FILE_RE.test(basename(file))) continue;
228
238
  let source;
229
239
  try {
230
240
  source = readFileSync(file, 'utf8');
package/src/config.js CHANGED
@@ -14,7 +14,7 @@ import { nornsPreprocess } from '@human-synthesis/norns-core/preprocess';
14
14
  * `.ts` for hooks (it doesn't honor `moduleExtensions`), so the explicit
15
15
  * path is the non-invasive way to make `.c`/`.civet` hooks discoverable.
16
16
  * Same for the client and universal counterparts.
17
- * - `preprocess: nornsPreprocess()` — Coffee + Pug + rune fusion + auto-close
17
+ * - `preprocess: nornsPreprocess()` — Pug + Civet
18
18
  *
19
19
  * Spread your own overrides at the call site to extend or replace defaults.
20
20
  *
@@ -2,7 +2,7 @@
2
2
  * Validation glue. Norns doesn't bundle a schema library — it speaks the
3
3
  * Standard Schema interface (https://github.com/standard-schema/standard-schema)
4
4
  * supported by Valibot, Zod 3.24+, ArkType, etc. A plain function (`input -> parsed`)
5
- * also works, for ad-hoc cases or simple Coffee parsers.
5
+ * also works, for ad-hoc cases or simple hand-rolled parsers.
6
6
  */
7
7
 
8
8
  /** @typedef {{ '~standard': { validate: (input: unknown) => any } }} StandardSchema */
package/src/vite.js CHANGED
@@ -68,7 +68,6 @@ async function resolveWorkspaceFrameworkSrcs(root) {
68
68
  * Node's ESM module cache survives `server.restart()`.
69
69
  *
70
70
  * `.c` is recognised as an alias for `.civet` — both compile through Civet.
71
- * CoffeeScript is no longer supported.
72
71
  *
73
72
  * @returns {import('vite').Plugin}
74
73
  */