@byline/search-postgres 3.15.0 → 3.15.1

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
@@ -42,7 +42,7 @@ defineServerConfig({
42
42
  })
43
43
  ```
44
44
 
45
- A collection opts into indexing through its role-based `search` config
45
+ A collection opts into indexing through its `search` config
46
46
  (`{ body, facets, filters, zones }`); `initBylineCore()` fails fast if a
47
47
  collection opts in but no provider is registered.
48
48
 
package/dist/migrate.d.ts CHANGED
@@ -5,6 +5,19 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
+ /**
9
+ * Migration runner — the driver owns its schema. Applies the numbered
10
+ * migrations that haven't run yet, recording each in its own
11
+ * `byline_search_migrations` bookkeeping table (separate from the host's
12
+ * migration stream). Idempotent and transactional per migration.
13
+ *
14
+ * The SQL is embedded (`./migrations-data`) so the runner is **bundle-safe** —
15
+ * a production server bundle (Nitro / rollup) inlines this package and rewrites
16
+ * `import.meta.url`, which would break reading the `.sql` files from disk at
17
+ * runtime. The numbered `.sql` files remain the source of truth and still ship
18
+ * for the by-hand path (`psql -f migrations/0001_init.sql`) in locked-down
19
+ * environments; `migrate(pool)` / `autoMigrate` are the convenience paths.
20
+ */
8
21
  import type { Pool } from 'pg';
9
22
  export interface MigrateOptions {
10
23
  /** Optional sink for progress lines (e.g. the host logger). */
package/dist/migrate.js CHANGED
@@ -5,19 +5,7 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
- /**
9
- * Migration runner — the driver owns its schema. Applies the numbered SQL
10
- * files in `../migrations` that haven't run yet, recording each in its own
11
- * `byline_search_migrations` bookkeeping table (separate from the host's
12
- * migration stream). Idempotent and transactional per file.
13
- *
14
- * The numbered `.sql` files are the source of truth: ops can apply them by
15
- * hand (`psql -f migrations/0001_init.sql`) in locked-down environments, or
16
- * call `migrate(pool)` / enable `autoMigrate` for convenience.
17
- */
18
- import { readdirSync, readFileSync } from 'node:fs';
19
- import { fileURLToPath } from 'node:url';
20
- const MIGRATIONS_DIR = fileURLToPath(new URL('../migrations', import.meta.url));
8
+ import { MIGRATIONS } from './migrations-data.js';
21
9
  /**
22
10
  * Apply any pending search-index migrations. Safe to call repeatedly (and at
23
11
  * boot via `autoMigrate`) — already-applied versions are skipped.
@@ -56,16 +44,7 @@ export async function migrate(pool, options = {}) {
56
44
  }
57
45
  return { applied };
58
46
  }
59
- /** Read + parse the numbered `.sql` files, sorted by version ascending. */
47
+ /** The embedded migrations, sorted by version ascending. */
60
48
  function loadMigrations() {
61
- return readdirSync(MIGRATIONS_DIR)
62
- .filter((f) => f.endsWith('.sql'))
63
- .map((name) => {
64
- const version = Number.parseInt(name.split('_')[0] ?? '', 10);
65
- if (!Number.isInteger(version)) {
66
- throw new Error(`[search-postgres] migration file '${name}' has no leading version number`);
67
- }
68
- return { version, name, sql: readFileSync(`${MIGRATIONS_DIR}/${name}`, 'utf8') };
69
- })
70
- .sort((a, b) => a.version - b.version);
49
+ return [...MIGRATIONS].sort((a, b) => a.version - b.version);
71
50
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ /**
9
+ * Embedded migrations — the numbered SQL in `migrations/` inlined as strings.
10
+ *
11
+ * Why inline rather than read the `.sql` files at runtime: `migrate()` must be
12
+ * callable from a production server bundle, where Nitro / rollup inline this
13
+ * package into a single file and rewrite `import.meta.url`. Any read of
14
+ * `migrations/*.sql` resolved relative to that URL then points at the bundle
15
+ * directory instead of the package, and `migrate()` ENOENTs at boot. Embedding
16
+ * the SQL into the JS makes the runner bundle-safe everywhere.
17
+ *
18
+ * The `.sql` files remain the DBA-reviewable source of truth and still ship in
19
+ * the package for the `psql -f migrations/0001_init.sql` install path —
20
+ * `migrations-data.test.node.ts` asserts the two never drift.
21
+ */
22
+ export interface EmbeddedMigration {
23
+ version: number;
24
+ name: string;
25
+ sql: string;
26
+ }
27
+ export declare const MIGRATIONS: EmbeddedMigration[];
@@ -0,0 +1,56 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ export const MIGRATIONS = [
9
+ {
10
+ version: 1,
11
+ name: '0001_init.sql',
12
+ sql: `-- @byline/search-postgres — 0001_init
13
+ --
14
+ -- The full-text search index, owned entirely by this driver. One row per
15
+ -- (collection_path, document_id, locale). The \`search_vector\` is a weighted
16
+ -- tsvector assembled from the type-enriched SearchDocument at upsert time
17
+ -- (title => A, body fields => A–D by boost, facet terms => C). Facet ids and
18
+ -- filterable scalars are kept as jsonb for aggregation / filtering.
19
+ --
20
+ -- Idempotent (IF NOT EXISTS throughout) so re-applying is safe. The driver's
21
+ -- migration runner records applied versions in byline_search_migrations.
22
+
23
+ CREATE TABLE IF NOT EXISTS byline_search_documents (
24
+ collection_path text NOT NULL,
25
+ document_id text NOT NULL,
26
+ locale text NOT NULL,
27
+ status text NOT NULL,
28
+ zones text[] NOT NULL DEFAULT '{}',
29
+ title text NOT NULL DEFAULT '',
30
+ path text,
31
+ body text NOT NULL DEFAULT '',
32
+ search_vector tsvector,
33
+ facets jsonb NOT NULL DEFAULT '{}'::jsonb,
34
+ filters jsonb NOT NULL DEFAULT '{}'::jsonb,
35
+ updated_at timestamptz NOT NULL DEFAULT now(),
36
+ PRIMARY KEY (collection_path, document_id, locale)
37
+ );
38
+
39
+ -- Ranked full-text search.
40
+ CREATE INDEX IF NOT EXISTS byline_search_documents_vector_idx
41
+ ON byline_search_documents USING gin (search_vector);
42
+
43
+ -- Zone scoping (\`zones @> ARRAY[$zone]\`).
44
+ CREATE INDEX IF NOT EXISTS byline_search_documents_zones_idx
45
+ ON byline_search_documents USING gin (zones);
46
+
47
+ -- Facet aggregation / filtering over the jsonb projection.
48
+ CREATE INDEX IF NOT EXISTS byline_search_documents_facets_idx
49
+ ON byline_search_documents USING gin (facets jsonb_path_ops);
50
+
51
+ -- Single-collection scoping + status filtering.
52
+ CREATE INDEX IF NOT EXISTS byline_search_documents_collection_idx
53
+ ON byline_search_documents (collection_path, status);
54
+ `,
55
+ },
56
+ ];
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+ import { readdirSync, readFileSync } from 'node:fs';
9
+ import { dirname, join } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { describe, expect, it } from 'vitest';
12
+ import { MIGRATIONS } from './migrations-data.js';
13
+ // Drift guard: the embedded SQL (`migrations-data.ts`, the bundle-safe source
14
+ // the runner executes) must stay byte-identical to the numbered `.sql` files
15
+ // (the DBA-reviewable source of truth that ships for the `psql -f` path). When
16
+ // adding a migration, update both — this test fails until they match.
17
+ const migrationsDir = join(dirname(fileURLToPath(import.meta.url)), '../migrations');
18
+ describe('embedded migrations vs the .sql files', () => {
19
+ const sqlFiles = readdirSync(migrationsDir)
20
+ .filter((f) => f.endsWith('.sql'))
21
+ .sort();
22
+ it('embeds exactly the .sql files that ship in the package', () => {
23
+ expect(MIGRATIONS.map((m) => m.name).sort()).toEqual(sqlFiles);
24
+ });
25
+ it.each(sqlFiles)('embedded SQL for %s matches the file on disk', (name) => {
26
+ const onDisk = readFileSync(join(migrationsDir, name), 'utf8');
27
+ const embedded = MIGRATIONS.find((m) => m.name === name);
28
+ expect(embedded, `no embedded migration named ${name}`).toBeDefined();
29
+ expect(embedded?.sql.trim()).toBe(onDisk.trim());
30
+ });
31
+ it('numbers each migration from its filename prefix', () => {
32
+ for (const m of MIGRATIONS) {
33
+ expect(m.version).toBe(Number.parseInt(m.name.split('_')[0] ?? '', 10));
34
+ }
35
+ });
36
+ });
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@byline/search-postgres",
3
3
  "private": false,
4
4
  "license": "MPL-2.0",
5
- "version": "3.15.0",
5
+ "version": "3.15.1",
6
6
  "engines": {
7
7
  "node": ">=20.9.0"
8
8
  },
@@ -42,7 +42,7 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "npm-run-all": "^4.1.5",
45
- "@byline/core": "3.15.0"
45
+ "@byline/core": "3.15.1"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "pg": "^8.21.0"