@byline/cli 4.8.0 → 4.10.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/README.md +56 -15
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +8 -5
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +2 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/setup-checks.d.ts +2 -0
- package/dist/commands/setup-checks.d.ts.map +1 -1
- package/dist/commands/setup-checks.js +14 -6
- package/dist/commands/setup-checks.js.map +1 -1
- package/dist/commands/setup-flow.test.d.ts +2 -0
- package/dist/commands/setup-flow.test.d.ts.map +1 -0
- package/dist/commands/setup-flow.test.js +230 -0
- package/dist/commands/setup-flow.test.js.map +1 -0
- package/dist/commands/setup.d.ts +30 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +71 -35
- package/dist/commands/setup.js.map +1 -1
- package/dist/context.d.ts +4 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +3 -0
- package/dist/context.js.map +1 -1
- package/dist/lib/baseline-drift.test.d.ts +2 -0
- package/dist/lib/baseline-drift.test.d.ts.map +1 -0
- package/dist/lib/baseline-drift.test.js +97 -0
- package/dist/lib/baseline-drift.test.js.map +1 -0
- package/dist/lib/baseline.d.ts +10 -0
- package/dist/lib/baseline.d.ts.map +1 -0
- package/dist/lib/baseline.js +12 -0
- package/dist/lib/baseline.js.map +1 -0
- package/dist/lib/database/adapters.d.ts +54 -0
- package/dist/lib/database/adapters.d.ts.map +1 -0
- package/dist/lib/database/adapters.js +83 -0
- package/dist/lib/database/adapters.js.map +1 -0
- package/dist/lib/database/adapters.test.d.ts +2 -0
- package/dist/lib/database/adapters.test.d.ts.map +1 -0
- package/dist/lib/database/adapters.test.js +36 -0
- package/dist/lib/database/adapters.test.js.map +1 -0
- package/dist/lib/database/dialect.d.ts +12 -0
- package/dist/lib/database/dialect.d.ts.map +1 -0
- package/dist/lib/database/dialect.js +53 -0
- package/dist/lib/database/dialect.js.map +1 -0
- package/dist/lib/database/dialect.test.d.ts +2 -0
- package/dist/lib/database/dialect.test.d.ts.map +1 -0
- package/dist/lib/database/dialect.test.js +58 -0
- package/dist/lib/database/dialect.test.js.map +1 -0
- package/dist/lib/database/mysql.d.ts +21 -0
- package/dist/lib/database/mysql.d.ts.map +1 -0
- package/dist/lib/database/mysql.js +152 -0
- package/dist/lib/database/mysql.js.map +1 -0
- package/dist/lib/database/mysql.test.d.ts +2 -0
- package/dist/lib/database/mysql.test.d.ts.map +1 -0
- package/dist/lib/database/mysql.test.js +45 -0
- package/dist/lib/database/mysql.test.js.map +1 -0
- package/dist/lib/database/postgres.d.ts +8 -0
- package/dist/lib/database/postgres.d.ts.map +1 -0
- package/dist/lib/database/postgres.js +142 -0
- package/dist/lib/database/postgres.js.map +1 -0
- package/dist/lib/database/postgres.test.d.ts +2 -0
- package/dist/lib/database/postgres.test.d.ts.map +1 -0
- package/dist/lib/database/postgres.test.js +14 -0
- package/dist/lib/database/postgres.test.js.map +1 -0
- package/dist/lib/database/provisioner.d.ts +35 -0
- package/dist/lib/database/provisioner.d.ts.map +1 -0
- package/dist/lib/database/provisioner.js +20 -0
- package/dist/lib/database/provisioner.js.map +1 -0
- package/dist/lib/database/provisioner.test.d.ts +2 -0
- package/dist/lib/database/provisioner.test.d.ts.map +1 -0
- package/dist/lib/database/provisioner.test.js +32 -0
- package/dist/lib/database/provisioner.test.js.map +1 -0
- package/dist/lib/database/selection.d.ts +11 -0
- package/dist/lib/database/selection.d.ts.map +1 -0
- package/dist/lib/database/selection.js +52 -0
- package/dist/lib/database/selection.js.map +1 -0
- package/dist/lib/database/selection.test.d.ts +2 -0
- package/dist/lib/database/selection.test.d.ts.map +1 -0
- package/dist/lib/database/selection.test.js +58 -0
- package/dist/lib/database/selection.test.js.map +1 -0
- package/dist/lib/database/state.d.ts +4 -0
- package/dist/lib/database/state.d.ts.map +1 -0
- package/dist/lib/database/state.js +10 -0
- package/dist/lib/database/state.js.map +1 -0
- package/dist/lib/database/state.test.d.ts +2 -0
- package/dist/lib/database/state.test.d.ts.map +1 -0
- package/dist/lib/database/state.test.js +17 -0
- package/dist/lib/database/state.test.js.map +1 -0
- package/dist/lib/database/urls.d.ts +19 -0
- package/dist/lib/database/urls.d.ts.map +1 -0
- package/dist/lib/database/urls.js +14 -0
- package/dist/lib/database/urls.js.map +1 -0
- package/dist/lib/database/urls.test.d.ts +2 -0
- package/dist/lib/database/urls.test.d.ts.map +1 -0
- package/dist/lib/database/urls.test.js +31 -0
- package/dist/lib/database/urls.test.js.map +1 -0
- package/dist/lib/dependency-version.d.ts.map +1 -1
- package/dist/lib/dependency-version.js +5 -4
- package/dist/lib/dependency-version.js.map +1 -1
- package/dist/lib/template-hook-boundary.test.node.js +9 -4
- package/dist/lib/template-hook-boundary.test.node.js.map +1 -1
- package/dist/manifest/deps.d.ts +8 -1
- package/dist/manifest/deps.d.ts.map +1 -1
- package/dist/manifest/deps.js +40 -13
- package/dist/manifest/deps.js.map +1 -1
- package/dist/manifest/env.d.ts +4 -1
- package/dist/manifest/env.d.ts.map +1 -1
- package/dist/manifest/env.js +12 -6
- package/dist/manifest/env.js.map +1 -1
- package/dist/phases/db-init.d.ts +2 -1
- package/dist/phases/db-init.d.ts.map +1 -1
- package/dist/phases/db-init.js +141 -124
- package/dist/phases/db-init.js.map +1 -1
- package/dist/phases/db-init.test.d.ts +2 -0
- package/dist/phases/db-init.test.d.ts.map +1 -0
- package/dist/phases/db-init.test.js +144 -0
- package/dist/phases/db-init.test.js.map +1 -0
- package/dist/phases/db.d.ts +0 -8
- package/dist/phases/db.d.ts.map +1 -1
- package/dist/phases/db.js +69 -49
- package/dist/phases/db.js.map +1 -1
- package/dist/phases/db.test.d.ts +2 -0
- package/dist/phases/db.test.d.ts.map +1 -0
- package/dist/phases/db.test.js +69 -0
- package/dist/phases/db.test.js.map +1 -0
- package/dist/phases/deps.d.ts.map +1 -1
- package/dist/phases/deps.js +7 -4
- package/dist/phases/deps.js.map +1 -1
- package/dist/phases/deps.test.js +67 -5
- package/dist/phases/deps.test.js.map +1 -1
- package/dist/phases/env.d.ts.map +1 -1
- package/dist/phases/env.js +30 -21
- package/dist/phases/env.js.map +1 -1
- package/dist/phases/env.test.d.ts +2 -0
- package/dist/phases/env.test.d.ts.map +1 -0
- package/dist/phases/env.test.js +79 -0
- package/dist/phases/env.test.js.map +1 -0
- package/dist/phases/scaffold-smoke.test.js +44 -10
- package/dist/phases/scaffold-smoke.test.js.map +1 -1
- package/dist/phases/scaffold.d.ts.map +1 -1
- package/dist/phases/scaffold.js +32 -23
- package/dist/phases/scaffold.js.map +1 -1
- package/dist/phases/scaffold.test.js +22 -0
- package/dist/phases/scaffold.test.js.map +1 -1
- package/dist/phases/wire/vite-config.d.ts.map +1 -1
- package/dist/phases/wire/vite-config.js +2 -0
- package/dist/phases/wire/vite-config.js.map +1 -1
- package/dist/phases/wire/vite-config.test.js +25 -2
- package/dist/phases/wire/vite-config.test.js.map +1 -1
- package/dist/state.d.ts +6 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +40 -4
- package/dist/state.js.map +1 -1
- package/dist/state.test.d.ts +2 -0
- package/dist/state.test.d.ts.map +1 -0
- package/dist/state.test.js +77 -0
- package/dist/state.test.js.map +1 -0
- package/dist/templates/byline-examples/collections/docs/admin.tsx +1 -1
- package/dist/templates/byline-examples/collections/docs/hooks.ts +1 -1
- package/dist/templates/byline-examples/collections/docs/schema.ts +8 -8
- package/dist/templates/byline-examples/collections/media/schema.ts +7 -7
- package/dist/templates/byline-examples/collections/news/schema.ts +7 -7
- package/dist/templates/byline-examples/collections/news-categories/schema.ts +7 -7
- package/dist/templates/byline-examples/collections/pages/schema.ts +7 -7
- package/dist/templates/byline-examples/scripts/import-docs.ts +1 -1
- package/dist/templates/dialects/mysql/byline/server.config.ts +105 -0
- package/dist/templates/dialects/mysql/byline-examples/server.config.ts +115 -0
- package/dist/templates/{byline-examples → dialects/postgres/byline-examples}/scripts/backfill-version-locales.ts +1 -1
- package/dist/templates/{byline-examples → dialects/postgres/byline-examples}/scripts/re-anchor.ts +1 -1
- package/dist/templates/{byline-examples → dialects/postgres/byline-examples}/server.config.ts +2 -2
- package/dist/templates/host/vite.config.ts +4 -3
- package/dist/templates/migrations/mysql/0000_unknown_kulan_gath.sql +412 -0
- package/dist/templates/migrations/mysql/meta/_journal.json +13 -0
- package/dist/test-helpers.d.ts +14 -2
- package/dist/test-helpers.d.ts.map +1 -1
- package/dist/test-helpers.js +12 -9
- package/dist/test-helpers.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -2
- package/dist/templates/migrations/meta/0000_snapshot.json +0 -3471
- /package/dist/templates/{byline → dialects/postgres/byline}/server.config.ts +0 -0
- /package/dist/templates/migrations/{0000_mushy_luckman.sql → postgres/0000_mushy_luckman.sql} +0 -0
- /package/dist/templates/migrations/{meta → postgres/meta}/_journal.json +0 -0
|
@@ -96,7 +96,7 @@ export const DocsAdmin: CollectionAdminConfig = defineAdmin(Docs, {
|
|
|
96
96
|
* rebuilds this collection's search index; it self-gates on the
|
|
97
97
|
* `collections.docs.reindex` ability, so it only appears for actors who
|
|
98
98
|
* hold it. Drop this (and the `search` config in schema.ts) if you don't
|
|
99
|
-
* want search on this collection. See docs/
|
|
99
|
+
* want search on this collection. See docs/06-search/index.md.
|
|
100
100
|
*/
|
|
101
101
|
listActions: [ReindexButton],
|
|
102
102
|
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* Indexing is background maintenance that runs from out-of-band write paths
|
|
47
47
|
* too (the import-docs script, seeds, migrations), where there is no HTTP
|
|
48
48
|
* request to read a session cookie from. See
|
|
49
|
-
* docs/
|
|
49
|
+
* docs/06-search/index.md.
|
|
50
50
|
*/
|
|
51
51
|
|
|
52
52
|
import { defineHooks } from '@byline/core'
|
|
@@ -42,19 +42,19 @@ export const Docs = defineCollection({
|
|
|
42
42
|
// byline/scripts/import-docs.ts --tree).
|
|
43
43
|
tree: true,
|
|
44
44
|
// Admin list-view quick-search. The collection list route's search box
|
|
45
|
-
// matches these top-level text-store fields with substring
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
45
|
+
// matches these top-level text-store fields with adapter-native substring
|
|
46
|
+
// queries against `store_text` — a lightweight "find the row I mean"
|
|
47
|
+
// affordance that needs no indexing and no lifecycle hooks. Falls back to
|
|
48
|
+
// `useAsTitle` when omitted; declared explicitly here for guidance.
|
|
49
49
|
listSearch: ['title'],
|
|
50
|
-
// Search-*provider* config (docs/
|
|
50
|
+
// Search-*provider* config (docs/06-search/index.md) —
|
|
51
51
|
// distinct from `listSearch` above. Each key names the part a field plays in
|
|
52
52
|
// the index: `body` fields feed the full-text search vector (`title` is
|
|
53
53
|
// display-only unless listed here, so we include it and boost it into the
|
|
54
54
|
// heaviest weight class); `facets`, `filters`, and `zones` round out the
|
|
55
|
-
// surface. This drives the
|
|
56
|
-
//
|
|
57
|
-
//
|
|
55
|
+
// surface. This drives the configured full-text SearchProvider and requires
|
|
56
|
+
// a `search` provider registered in byline/server.config.ts. Unlike
|
|
57
|
+
// `listSearch`, `search` is inert on its own
|
|
58
58
|
// — opting in here is what makes the index / reindex / deindex lifecycle
|
|
59
59
|
// hooks in ./hooks.ts keep this collection's provider index in sync.
|
|
60
60
|
// `content` is a container (blocks) field: naming it walks every text-bearing
|
|
@@ -51,14 +51,14 @@ export const Media = defineCollection({
|
|
|
51
51
|
}),
|
|
52
52
|
showStats: true,
|
|
53
53
|
// Admin list-view quick-search. The collection list route's search box
|
|
54
|
-
// matches these top-level text-store fields with substring
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
54
|
+
// matches these top-level text-store fields with adapter-native substring
|
|
55
|
+
// queries against `store_text` — a lightweight "find the row I mean"
|
|
56
|
+
// affordance that needs no indexing and no lifecycle hooks. Falls back to
|
|
57
|
+
// `useAsTitle` when omitted; declared explicitly here for guidance.
|
|
58
58
|
listSearch: ['title'],
|
|
59
|
-
// Search-*provider* config (docs/
|
|
60
|
-
// distinct from `listSearch` above. This drives the
|
|
61
|
-
//
|
|
59
|
+
// Search-*provider* config (docs/06-search/index.md) —
|
|
60
|
+
// distinct from `listSearch` above. This drives the configured full-text
|
|
61
|
+
// SearchProvider and offers richer options:
|
|
62
62
|
// per-field weighting/`boost`, `facets`, `filters`, and `zones`. Unlike
|
|
63
63
|
// `listSearch`, `search` is inert on its own — it MUST be paired with index /
|
|
64
64
|
// reindex / deindex document-lifecycle hooks that keep the provider index in
|
|
@@ -31,14 +31,14 @@ export const News = defineCollection({
|
|
|
31
31
|
}),
|
|
32
32
|
showStats: true,
|
|
33
33
|
// Admin list-view quick-search. The collection list route's search box
|
|
34
|
-
// matches these top-level text-store fields with substring
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
34
|
+
// matches these top-level text-store fields with adapter-native substring
|
|
35
|
+
// queries against `store_text` — a lightweight "find the row I mean"
|
|
36
|
+
// affordance that needs no indexing and no lifecycle hooks. Falls back to
|
|
37
|
+
// `useAsTitle` when omitted; declared explicitly here for guidance.
|
|
38
38
|
listSearch: ['title'],
|
|
39
|
-
// Search-*provider* config (docs/
|
|
40
|
-
// distinct from `listSearch` above. This drives the
|
|
41
|
-
//
|
|
39
|
+
// Search-*provider* config (docs/06-search/index.md) —
|
|
40
|
+
// distinct from `listSearch` above. This drives the configured full-text
|
|
41
|
+
// SearchProvider and offers richer options:
|
|
42
42
|
// per-field weighting/`boost`, `facets`, `filters`, and `zones`. Unlike
|
|
43
43
|
// `listSearch`, `search` is inert on its own — it MUST be paired with index /
|
|
44
44
|
// reindex / deindex document-lifecycle hooks that keep the provider index in
|
|
@@ -22,14 +22,14 @@ export const NewsCategories = defineCollection({
|
|
|
22
22
|
workflow: SINGLE_STATUS_WORKFLOW,
|
|
23
23
|
showStats: true,
|
|
24
24
|
// Admin list-view quick-search. The collection list route's search box
|
|
25
|
-
// matches these top-level text-store fields with substring
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
25
|
+
// matches these top-level text-store fields with adapter-native substring
|
|
26
|
+
// queries against `store_text` — a lightweight "find the row I mean"
|
|
27
|
+
// affordance that needs no indexing and no lifecycle hooks. Falls back to
|
|
28
|
+
// `useAsTitle` when omitted; declared explicitly here for guidance.
|
|
29
29
|
listSearch: ['name'],
|
|
30
|
-
// Search-*provider* config (docs/
|
|
31
|
-
// distinct from `listSearch` above. This drives the
|
|
32
|
-
//
|
|
30
|
+
// Search-*provider* config (docs/06-search/index.md) —
|
|
31
|
+
// distinct from `listSearch` above. This drives the configured full-text
|
|
32
|
+
// SearchProvider and offers richer options:
|
|
33
33
|
// per-field weighting/`boost`, `facets`, `filters`, and `zones`. Unlike
|
|
34
34
|
// `listSearch`, `search` is inert on its own — it MUST be paired with index /
|
|
35
35
|
// reindex / deindex document-lifecycle hooks that keep the provider index in
|
|
@@ -33,14 +33,14 @@ export const Pages = defineCollection({
|
|
|
33
33
|
}),
|
|
34
34
|
showStats: true,
|
|
35
35
|
// Admin list-view quick-search. The collection list route's search box
|
|
36
|
-
// matches these top-level text-store fields with substring
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
36
|
+
// matches these top-level text-store fields with adapter-native substring
|
|
37
|
+
// queries against `store_text` — a lightweight "find the row I mean"
|
|
38
|
+
// affordance that needs no indexing and no lifecycle hooks. Falls back to
|
|
39
|
+
// `useAsTitle` when omitted; declared explicitly here for guidance.
|
|
40
40
|
listSearch: ['title'],
|
|
41
|
-
// Search-*provider* config (docs/
|
|
42
|
-
// distinct from `listSearch` above. This drives the
|
|
43
|
-
//
|
|
41
|
+
// Search-*provider* config (docs/06-search/index.md) —
|
|
42
|
+
// distinct from `listSearch` above. This drives the configured full-text
|
|
43
|
+
// SearchProvider and offers richer options:
|
|
44
44
|
// per-field weighting/`boost`, `facets`, `filters`, and `zones`. Unlike
|
|
45
45
|
// `listSearch`, `search` is inert on its own — it MUST be paired with index /
|
|
46
46
|
// reindex / deindex document-lifecycle hooks that keep the provider index in
|
|
@@ -317,7 +317,7 @@ async function processFile(
|
|
|
317
317
|
// Advertise the imported locale (editorial available-locales set), merged
|
|
318
318
|
// with whatever is already advertised so a later-locale re-import doesn't
|
|
319
319
|
// clobber an earlier one. The public set is still gated by the version
|
|
320
|
-
// completeness ledger (intersection). See docs/
|
|
320
|
+
// completeness ledger (intersection). See docs/08-internationalization/index.md.
|
|
321
321
|
availableLocales: [...new Set([...(existing.availableLocales ?? []), locale])],
|
|
322
322
|
})
|
|
323
323
|
await walkToStatus(handle, result.documentId, workflowStatuses, defaultStatus, desiredStatus)
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
/**
|
|
10
|
+
* Server-side Byline bootstrap. Imported as a side-effect from
|
|
11
|
+
* `src/server.ts` and from scripts that need the configured runtime.
|
|
12
|
+
*
|
|
13
|
+
* This is the minimal scaffold: no example collections or search provider.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { type AdminStore, registerAdminAbilities } from '@byline/admin'
|
|
17
|
+
import { JwtSessionProvider } from '@byline/admin/auth'
|
|
18
|
+
import { getAdminBylineClient } from '@byline/client/server'
|
|
19
|
+
import { type BylineCore, initBylineCore } from '@byline/core'
|
|
20
|
+
import { mysqlAdapter } from '@byline/db-mysql'
|
|
21
|
+
import { createAdminStore } from '@byline/db-mysql/admin'
|
|
22
|
+
import { registerTanstackStartHostBridge } from '@byline/host-tanstack-start/integrations/host-bridge'
|
|
23
|
+
import {
|
|
24
|
+
lexicalEditorEmbedServer,
|
|
25
|
+
lexicalEditorPopulateServer,
|
|
26
|
+
lexicalEditorToMarkdownServer,
|
|
27
|
+
} from '@byline/richtext-lexical/server'
|
|
28
|
+
import { localStorageProvider } from '@byline/storage-local'
|
|
29
|
+
|
|
30
|
+
import { collections } from './collections/index.js'
|
|
31
|
+
import { serverHooks } from './collections/server-hooks.js'
|
|
32
|
+
import { i18n } from './i18n.js'
|
|
33
|
+
import { DEFAULT_SERVER_URL, routes } from './routes.js'
|
|
34
|
+
|
|
35
|
+
const serverURL = process.env.VITE_SERVER_URL || DEFAULT_SERVER_URL
|
|
36
|
+
|
|
37
|
+
// HMR-safe singleton. Reusing the resolving Promise prevents development
|
|
38
|
+
// reloads from orphaning MySQL pools and exhausting server connections.
|
|
39
|
+
declare global {
|
|
40
|
+
// biome-ignore lint: globalThis augmentation requires `var` rather than `let`
|
|
41
|
+
var __bylineCoreSingleton__: Promise<BylineCore<AdminStore>> | undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
|
|
45
|
+
const db = mysqlAdapter({
|
|
46
|
+
connectionString: process.env.BYLINE_DB_MYSQL_CONNECTION_STRING || '',
|
|
47
|
+
collections,
|
|
48
|
+
defaultContentLocale: i18n.content.defaultLocale,
|
|
49
|
+
// Optional pool tuning. Omit these values to use the adapter defaults:
|
|
50
|
+
// 20 connections, 2s idle timeout, and 30s connection timeout.
|
|
51
|
+
connectionLimit: process.env.BYLINE_DB_MYSQL_CONNECTION_LIMIT
|
|
52
|
+
? Number(process.env.BYLINE_DB_MYSQL_CONNECTION_LIMIT)
|
|
53
|
+
: undefined,
|
|
54
|
+
idleTimeout: process.env.BYLINE_DB_MYSQL_IDLE_TIMEOUT_MILLIS
|
|
55
|
+
? Number(process.env.BYLINE_DB_MYSQL_IDLE_TIMEOUT_MILLIS)
|
|
56
|
+
: undefined,
|
|
57
|
+
connectTimeout: process.env.BYLINE_DB_MYSQL_CONNECTION_TIMEOUT_MILLIS
|
|
58
|
+
? Number(process.env.BYLINE_DB_MYSQL_CONNECTION_TIMEOUT_MILLIS)
|
|
59
|
+
: undefined,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const adminStore = createAdminStore(db.drizzle)
|
|
63
|
+
const signingSecret = process.env.BYLINE_JWT_SECRET
|
|
64
|
+
if (!signingSecret || signingSecret.length < 32) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
'BYLINE_JWT_SECRET must be set and carry at least 32 bytes of entropy. ' +
|
|
67
|
+
'Generate one with `openssl rand -base64 48` and add it to your .env.local.'
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const sessionProvider = new JwtSessionProvider({
|
|
72
|
+
store: adminStore,
|
|
73
|
+
signingSecret,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
registerTanstackStartHostBridge()
|
|
77
|
+
|
|
78
|
+
const core = await initBylineCore<AdminStore>({
|
|
79
|
+
serverURL,
|
|
80
|
+
i18n,
|
|
81
|
+
routes,
|
|
82
|
+
collections,
|
|
83
|
+
hooks: serverHooks,
|
|
84
|
+
db,
|
|
85
|
+
adminStore,
|
|
86
|
+
storage: localStorageProvider({
|
|
87
|
+
uploadDir: './uploads',
|
|
88
|
+
baseUrl: '/uploads',
|
|
89
|
+
}),
|
|
90
|
+
sessionProvider,
|
|
91
|
+
fields: {
|
|
92
|
+
richText: {
|
|
93
|
+
embed: lexicalEditorEmbedServer({ getClient: getAdminBylineClient }),
|
|
94
|
+
populate: lexicalEditorPopulateServer({ getClient: getAdminBylineClient }),
|
|
95
|
+
toMarkdown: lexicalEditorToMarkdownServer(),
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
registerAdminAbilities(core.abilities)
|
|
101
|
+
return core
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
globalThis.__bylineCoreSingleton__ ??= buildBylineCore()
|
|
105
|
+
await globalThis.__bylineCoreSingleton__
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
/**
|
|
10
|
+
* Server-side Byline bootstrap for the MySQL example scaffold.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { type AdminStore, registerAdminAbilities } from '@byline/admin'
|
|
14
|
+
import { JwtSessionProvider } from '@byline/admin/auth'
|
|
15
|
+
import { getAdminBylineClient } from '@byline/client/server'
|
|
16
|
+
import { type BylineCore, initBylineCore } from '@byline/core'
|
|
17
|
+
import { mysqlAdapter } from '@byline/db-mysql'
|
|
18
|
+
import { createAdminStore } from '@byline/db-mysql/admin'
|
|
19
|
+
import { registerTanstackStartHostBridge } from '@byline/host-tanstack-start/integrations/host-bridge'
|
|
20
|
+
import {
|
|
21
|
+
lexicalEditorEmbedServer,
|
|
22
|
+
lexicalEditorPopulateServer,
|
|
23
|
+
lexicalEditorToMarkdownServer,
|
|
24
|
+
lexicalEditorToTextServer,
|
|
25
|
+
} from '@byline/richtext-lexical/server'
|
|
26
|
+
import { migrate, mysqlSearch } from '@byline/search-mysql'
|
|
27
|
+
import { localStorageProvider } from '@byline/storage-local'
|
|
28
|
+
|
|
29
|
+
import { collections } from './collections/index.js'
|
|
30
|
+
import { serverHooks } from './collections/server-hooks.js'
|
|
31
|
+
import { i18n } from './i18n.js'
|
|
32
|
+
import { DEFAULT_SERVER_URL, routes } from './routes.js'
|
|
33
|
+
|
|
34
|
+
const serverURL = process.env.VITE_SERVER_URL || DEFAULT_SERVER_URL
|
|
35
|
+
|
|
36
|
+
// HMR-safe singleton. Reusing the resolving Promise prevents development
|
|
37
|
+
// reloads from orphaning MySQL pools and exhausting server connections.
|
|
38
|
+
declare global {
|
|
39
|
+
// biome-ignore lint: globalThis augmentation requires `var` rather than `let`
|
|
40
|
+
var __bylineCoreSingleton__: Promise<BylineCore<AdminStore>> | undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
|
|
44
|
+
const db = mysqlAdapter({
|
|
45
|
+
connectionString: process.env.BYLINE_DB_MYSQL_CONNECTION_STRING || '',
|
|
46
|
+
collections,
|
|
47
|
+
defaultContentLocale: i18n.content.defaultLocale,
|
|
48
|
+
// Optional pool tuning. Omit these values to use the adapter defaults:
|
|
49
|
+
// 20 connections, 2s idle timeout, and 30s connection timeout.
|
|
50
|
+
connectionLimit: process.env.BYLINE_DB_MYSQL_CONNECTION_LIMIT
|
|
51
|
+
? Number(process.env.BYLINE_DB_MYSQL_CONNECTION_LIMIT)
|
|
52
|
+
: undefined,
|
|
53
|
+
idleTimeout: process.env.BYLINE_DB_MYSQL_IDLE_TIMEOUT_MILLIS
|
|
54
|
+
? Number(process.env.BYLINE_DB_MYSQL_IDLE_TIMEOUT_MILLIS)
|
|
55
|
+
: undefined,
|
|
56
|
+
connectTimeout: process.env.BYLINE_DB_MYSQL_CONNECTION_TIMEOUT_MILLIS
|
|
57
|
+
? Number(process.env.BYLINE_DB_MYSQL_CONNECTION_TIMEOUT_MILLIS)
|
|
58
|
+
: undefined,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// Search owns its disposable projection and numbered migration stream.
|
|
62
|
+
// Apply it explicitly at startup with the adapter's existing pool. A
|
|
63
|
+
// migration failure degrades search without taking down the application.
|
|
64
|
+
try {
|
|
65
|
+
await migrate(db.pool, { log: (message) => console.log(message) })
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('[search-mysql] migrate failed — search may be unavailable:', error)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const adminStore = createAdminStore(db.drizzle)
|
|
71
|
+
const signingSecret = process.env.BYLINE_JWT_SECRET
|
|
72
|
+
if (!signingSecret || signingSecret.length < 32) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
'BYLINE_JWT_SECRET must be set and carry at least 32 bytes of entropy. ' +
|
|
75
|
+
'Generate one with `openssl rand -base64 48` and add it to your .env.local.'
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const sessionProvider = new JwtSessionProvider({
|
|
80
|
+
store: adminStore,
|
|
81
|
+
signingSecret,
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
registerTanstackStartHostBridge()
|
|
85
|
+
|
|
86
|
+
const core = await initBylineCore<AdminStore>({
|
|
87
|
+
serverURL,
|
|
88
|
+
i18n,
|
|
89
|
+
routes,
|
|
90
|
+
collections,
|
|
91
|
+
hooks: serverHooks,
|
|
92
|
+
db,
|
|
93
|
+
adminStore,
|
|
94
|
+
storage: localStorageProvider({
|
|
95
|
+
uploadDir: './uploads',
|
|
96
|
+
baseUrl: '/uploads',
|
|
97
|
+
}),
|
|
98
|
+
sessionProvider,
|
|
99
|
+
fields: {
|
|
100
|
+
richText: {
|
|
101
|
+
embed: lexicalEditorEmbedServer({ getClient: getAdminBylineClient }),
|
|
102
|
+
populate: lexicalEditorPopulateServer({ getClient: getAdminBylineClient }),
|
|
103
|
+
toMarkdown: lexicalEditorToMarkdownServer(),
|
|
104
|
+
toText: lexicalEditorToTextServer(),
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
search: mysqlSearch({ pool: db.pool, defaultLocale: i18n.content.defaultLocale }),
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
registerAdminAbilities(core.abilities)
|
|
111
|
+
return core
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
globalThis.__bylineCoreSingleton__ ??= buildBylineCore()
|
|
115
|
+
await globalThis.__bylineCoreSingleton__
|
package/dist/templates/{byline-examples → dialects/postgres/byline-examples}/scripts/re-anchor.ts
RENAMED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* pnpm tsx byline/scripts/re-anchor.ts --to fr --collection pages
|
|
21
21
|
* pnpm tsx byline/scripts/re-anchor.ts --to fr --dry-run
|
|
22
22
|
*
|
|
23
|
-
* See docs/
|
|
23
|
+
* See docs/08-internationalization/index.md.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import '../load-env.js'
|
package/dist/templates/{byline-examples → dialects/postgres/byline-examples}/server.config.ts
RENAMED
|
@@ -103,7 +103,7 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
|
|
|
103
103
|
// host's Drizzle migration stream. We run it deliberately here, rather
|
|
104
104
|
// than relying on the driver's `autoMigrate` option, so startup DDL is an
|
|
105
105
|
// explicit, awaited step. Reuses the adapter's pool — no second
|
|
106
|
-
// connection. See docs/
|
|
106
|
+
// connection. See docs/06-search/index.md.
|
|
107
107
|
//
|
|
108
108
|
// Wrapped defensively: a migration failure degrades search but must not
|
|
109
109
|
// take down the whole app at boot. We log loudly and continue. (For
|
|
@@ -233,7 +233,7 @@ async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
|
|
|
233
233
|
// `body` fields to indexable text for `buildSearchDocument`. Pure
|
|
234
234
|
// JSON walk, no client. Required by any collection that lists a
|
|
235
235
|
// richText field in its `search.body`. See
|
|
236
|
-
// docs/
|
|
236
|
+
// docs/06-search/index.md.
|
|
237
237
|
toText: lexicalEditorToTextServer(),
|
|
238
238
|
},
|
|
239
239
|
},
|
|
@@ -44,7 +44,7 @@ const bylineSsrNoExternal = [/^@byline\//]
|
|
|
44
44
|
// kept external so Node resolves them at runtime instead.
|
|
45
45
|
// - sharp + @byline/storage-local — image processing (libvips)
|
|
46
46
|
// - @byline/storage-s3 — bundles the AWS SDK; keep external for Node resolution
|
|
47
|
-
// - @byline/db-postgres
|
|
47
|
+
// - @byline/db-postgres + @byline/db-mysql — database drivers
|
|
48
48
|
// - pino — CJS entrypoints don't execute under Vite's module runner
|
|
49
49
|
//
|
|
50
50
|
// `@byline/admin` is intentionally NOT externalised: it now hosts
|
|
@@ -53,7 +53,7 @@ const bylineSsrNoExternal = [/^@byline\//]
|
|
|
53
53
|
// `import './foo_module.css'`. Node's ESM loader can't handle `.css`,
|
|
54
54
|
// so admin must flow through Vite's SSR pipeline where the CSS plugin
|
|
55
55
|
// resolves the side-effect imports. Server-only admin subpaths reach
|
|
56
|
-
//
|
|
56
|
+
// database / storage adapters through composition at runtime, not
|
|
57
57
|
// through `@byline/admin`'s own import graph, so this is safe.
|
|
58
58
|
const ssrExternal = [
|
|
59
59
|
'sharp',
|
|
@@ -61,6 +61,7 @@ const ssrExternal = [
|
|
|
61
61
|
'@byline/storage-local',
|
|
62
62
|
'@byline/storage-s3',
|
|
63
63
|
'@byline/db-postgres',
|
|
64
|
+
'@byline/db-mysql',
|
|
64
65
|
]
|
|
65
66
|
|
|
66
67
|
const config = defineConfig({
|
|
@@ -198,7 +199,7 @@ const config = defineConfig({
|
|
|
198
199
|
'react-dom',
|
|
199
200
|
'pino',
|
|
200
201
|
'sharp',
|
|
201
|
-
/^@byline\/(db-postgres|storage-local|storage-s3)/,
|
|
202
|
+
/^@byline\/(db-postgres|db-mysql|storage-local|storage-s3)/,
|
|
202
203
|
],
|
|
203
204
|
},
|
|
204
205
|
}),
|