@human-synthesis/norns 0.0.10 → 0.0.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@human-synthesis/norns",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
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)",
@@ -653,12 +653,6 @@ function renderImports(entries) {
653
653
  * and excluded from auto-import — forcing an explicit import to disambiguate.
654
654
  *
655
655
  * Default `[]` (off; explicit imports for service-layer code).
656
- * @param {string[] | false} [options.exportDirs]
657
- * DEPRECATED. Equivalent to `exportGlobs: dirs.map(d => '${d}/**\/*.{c,civet,js}')`,
658
- * which scans every file under those dirs. Path-scoping is still applied,
659
- * so server exports won't leak into client files — but the broad scan
660
- * surfaces every internal export as a potential auto-import. Migrate to
661
- * `exportGlobs: ['src/lib/**\/public.c']` for an intentional API surface.
662
656
  * @param {string[]} [options.exportExtensions]
663
657
  * File extensions accepted for exports (defence-in-depth on top of the
664
658
  * glob). Default `['.c', '.civet', '.js']` — `.ts` excluded because
@@ -667,8 +661,8 @@ function renderImports(entries) {
667
661
  * @param {string} [options.libAlias] Default `'$lib'`.
668
662
  * @param {string} [options.root] Default `process.cwd()`.
669
663
  * @param {(msg: string) => void} [options.log]
670
- * Channel for conflict / deprecation warnings. Default `console.warn`.
671
- * Tests pass a stub to assert behavior without polluting output.
664
+ * Channel for conflict warnings. Default `console.warn`. Tests pass a
665
+ * stub to assert behavior without polluting output.
672
666
  */
673
667
  export function nornsAutoImport(options = {}) {
674
668
  const root = options.root ?? process.cwd();
@@ -682,23 +676,8 @@ export function nornsAutoImport(options = {}) {
682
676
  const componentSpecs = options.components ?? null;
683
677
  const log = options.log ?? console.warn;
684
678
 
685
- // Build the effective glob list. `exportGlobs` is the new API;
686
- // `exportDirs` is shimmed in for backward compatibility with a one-time
687
- // deprecation notice per init.
688
- const explicitGlobs =
679
+ const effectiveGlobs =
689
680
  options.exportGlobs === false || options.exportGlobs == null ? [] : options.exportGlobs;
690
- const legacyDirs =
691
- options.exportDirs === false || options.exportDirs == null ? [] : options.exportDirs;
692
- let effectiveGlobs = [...explicitGlobs];
693
- if (legacyDirs.length > 0) {
694
- log(
695
- '[norns-auto-import] `exportDirs` is deprecated. Migrate to `exportGlobs`, e.g. ' +
696
- "`exportGlobs: ['src/lib/**/public.c']` — barrel-file scope is the safe default."
697
- );
698
- effectiveGlobs = effectiveGlobs.concat(
699
- legacyDirs.map((d) => `${d.replace(/\\/g, '/').replace(/\/+$/, '')}/**/*.{c,civet,js}`)
700
- );
701
- }
702
681
 
703
682
  const components =
704
683
  componentDirs.length === 0
package/src/migrate.js CHANGED
@@ -10,9 +10,11 @@
10
10
  * tooling (this CLI, wrangler for D1) reads. Keeping them out of `src/lib`
11
11
  * also keeps SvelteKit's bundler from ever trying to ship them.
12
12
  *
13
- * v1 supports SQLite via `better-sqlite3`. Postgres/libSQL come later;
14
- * Cloudflare D1 is intentionally out of scope here use
15
- * `wrangler d1 migrations apply <db>` for D1 deploys.
13
+ * v1 supports SQLite only. Backend selection is runtime-detected:
14
+ * - Under Bun: built-in `bun:sqlite` (no native build, works on Alpine).
15
+ * - Under Node: `better-sqlite3` (must be installed in the consumer app).
16
+ * Postgres/libSQL come later; Cloudflare D1 is intentionally out of scope
17
+ * here — use `wrangler d1 migrations apply <db>` for D1 deploys.
16
18
  */
17
19
 
18
20
  import { existsSync, readdirSync, statSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
@@ -115,11 +117,21 @@ export function resolveDatabaseUrl(cwd) {
115
117
  }
116
118
 
117
119
  /**
118
- * Open a better-sqlite3 db at `path` and ensure the migration tracking table
119
- * exists.
120
+ * Open a SQLite db at `path` and ensure the migration tracking table exists.
121
+ *
122
+ * Backend is runtime-selected: `bun:sqlite` under Bun (no native build,
123
+ * works on Alpine where `better-sqlite3`'s N-API binding fails to load
124
+ * against Bun's V8 compat layer), `better-sqlite3` under Node.
125
+ *
126
+ * The returned object exposes the better-sqlite3 surface used by the
127
+ * migration code (`pragma`, `exec`, `prepare(...).all/get/run`,
128
+ * `transaction`, `close`). Under Bun a minimal `pragma()` shim is grafted
129
+ * on — bun:sqlite has no built-in `pragma` method, but `exec('PRAGMA …')`
130
+ * is equivalent for the writes the migrate code performs.
120
131
  *
121
132
  * @param {string} cwd directory whose `package.json` is used to resolve
122
133
  * better-sqlite3 from the consumer's node_modules
134
+ * (only relevant under Node)
123
135
  * @param {string} path SQLite file path
124
136
  * @param {{ requireFrom?: string | URL }} [opts] override the require base
125
137
  * (used by tests)
@@ -127,6 +139,32 @@ export function resolveDatabaseUrl(cwd) {
127
139
  */
128
140
  export function openSqliteDb(cwd, path, opts = {}) {
129
141
  mkdirSync(dirname(path), { recursive: true });
142
+ const db = openRawSqlite(cwd, path, opts);
143
+ db.pragma('journal_mode = WAL');
144
+ db.exec(`CREATE TABLE IF NOT EXISTS ${MIGRATION_TABLE} (
145
+ id TEXT PRIMARY KEY,
146
+ applied_at INTEGER NOT NULL
147
+ )`);
148
+ return db;
149
+ }
150
+
151
+ /**
152
+ * @param {string} cwd
153
+ * @param {string} path
154
+ * @param {{ requireFrom?: string | URL }} opts
155
+ * @returns {any}
156
+ */
157
+ function openRawSqlite(cwd, path, opts) {
158
+ if (typeof Bun !== 'undefined') {
159
+ const r = createRequire(import.meta.url);
160
+ const { Database } = r('bun:sqlite');
161
+ const db = new Database(path);
162
+ // bun:sqlite has no `pragma()` method. Norns calls it only with
163
+ // write-style statements (`'journal_mode = WAL'`, `'foreign_keys = ON'`),
164
+ // for which `exec('PRAGMA …')` is the documented equivalent.
165
+ db.pragma = (stmt) => db.exec('PRAGMA ' + stmt);
166
+ return db;
167
+ }
130
168
  const require = createRequire(opts.requireFrom ?? join(cwd, 'package.json'));
131
169
  let Database;
132
170
  try {
@@ -136,13 +174,7 @@ export function openSqliteDb(cwd, path, opts = {}) {
136
174
  'norns migrate: `better-sqlite3` is not installed in this app. Run: bun add better-sqlite3'
137
175
  );
138
176
  }
139
- const db = new Database(path);
140
- db.pragma('journal_mode = WAL');
141
- db.exec(`CREATE TABLE IF NOT EXISTS ${MIGRATION_TABLE} (
142
- id TEXT PRIMARY KEY,
143
- applied_at INTEGER NOT NULL
144
- )`);
145
- return db;
177
+ return new Database(path);
146
178
  }
147
179
 
148
180
  /**
package/src/server/db.js CHANGED
@@ -56,13 +56,31 @@ function importDynamic(mod) {
56
56
  */
57
57
 
58
58
  /**
59
- * Open a Drizzle instance backed by `better-sqlite3`.
59
+ * Open a Drizzle instance backed by SQLite.
60
+ *
61
+ * Backend is runtime-selected: `bun:sqlite` + `drizzle-orm/bun-sqlite` under
62
+ * Bun (built-in, no native build, works on Alpine), `better-sqlite3` +
63
+ * `drizzle-orm/better-sqlite3` under Node. The function name keeps the
64
+ * `betterSqlite` alias for backward compatibility — what actually gets
65
+ * loaded depends on the runtime.
60
66
  *
61
67
  * @param {string} path SQLite file path (e.g. `data/notes.db`)
62
68
  * @param {BetterSqliteOptions} [opts]
63
69
  * @returns {Promise<any>}
64
70
  */
65
71
  export async function betterSqlite(path, opts = {}) {
72
+ if (typeof Bun !== 'undefined') {
73
+ const [{ Database }, { drizzle }] = await Promise.all([
74
+ importDynamic('bun:sqlite'),
75
+ importDynamic('drizzle-orm/bun-sqlite')
76
+ ]);
77
+ const sqlite = new Database(path, opts.connection);
78
+ if (opts.pragma) {
79
+ // bun:sqlite has no `pragma()` method — use `exec('PRAGMA …')`.
80
+ for (const p of opts.pragma) sqlite.exec('PRAGMA ' + p);
81
+ }
82
+ return drizzle(sqlite, opts.drizzle);
83
+ }
66
84
  const [{ default: Database }, { drizzle }] = await Promise.all([
67
85
  importDynamic('better-sqlite3'),
68
86
  importDynamic('drizzle-orm/better-sqlite3')