@byline/cli 2.7.0 → 3.0.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/dist/templates/byline-examples/collections/docs/admin.tsx +1 -1
- package/dist/templates/byline-examples/collections/docs/schema.ts +1 -2
- package/dist/templates/byline-examples/collections/news/admin.tsx +1 -1
- package/dist/templates/byline-examples/collections/news/schema.ts +1 -2
- package/dist/templates/byline-examples/collections/pages/admin.tsx +1 -1
- package/dist/templates/byline-examples/collections/pages/schema.ts +1 -2
- package/dist/templates/byline-examples/scripts/backfill-version-locales.ts +46 -0
- package/dist/templates/byline-examples/scripts/import-docs.ts +107 -23
- package/dist/templates/byline-examples/scripts/lib/mdast-to-lexical.test.node.ts +262 -0
- package/dist/templates/byline-examples/scripts/lib/mdast-to-lexical.ts +8 -3
- package/dist/templates/byline-examples/scripts/lib/rewrite-doc-links.ts +141 -0
- package/dist/templates/byline-examples/scripts/lib/strip-leading-h1.test.node.ts +66 -0
- package/dist/templates/byline-examples/scripts/re-anchor.ts +102 -0
- package/dist/templates/byline-examples/scripts/regenerate-media.ts +1 -1
- package/dist/templates/migrations/{0000_black_sabra.sql → 0000_yielding_northstar.sql} +22 -2
- package/dist/templates/migrations/meta/0000_snapshot.json +164 -3
- package/dist/templates/migrations/meta/_journal.json +2 -2
- package/dist/templates/routes/_byline/route.lazy.tsx +16 -6
- package/dist/templates/routes/_byline/route.tsx +34 -9
- package/package.json +1 -1
- package/dist/templates/byline-examples/fields/available-languages-field.ts +0 -99
|
@@ -272,10 +272,15 @@ const LANG_ALIASES: Record<string, string> = {
|
|
|
272
272
|
xml: 'markup',
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
// Default for unfenced / language-less code blocks. Prism crashes on
|
|
276
|
+
// null/undefined languages, and the project's docs are predominantly
|
|
277
|
+
// TypeScript, so fall back to that rather than 'plain'.
|
|
278
|
+
const DEFAULT_CODE_LANG = 'typescript'
|
|
279
|
+
|
|
280
|
+
function normalizeCodeLang(lang: string | null | undefined): string {
|
|
281
|
+
if (lang == null) return DEFAULT_CODE_LANG
|
|
277
282
|
const trimmed = lang.trim().toLowerCase()
|
|
278
|
-
if (trimmed.length === 0) return
|
|
283
|
+
if (trimmed.length === 0) return DEFAULT_CODE_LANG
|
|
279
284
|
return LANG_ALIASES[trimmed] ?? trimmed
|
|
280
285
|
}
|
|
281
286
|
|
|
@@ -0,0 +1,141 @@
|
|
|
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
|
+
* Rewrite relative markdown links so they work after import.
|
|
11
|
+
*
|
|
12
|
+
* Markdown docs commonly link to siblings via `./OTHER.md[#hash]`. Once
|
|
13
|
+
* imported into Lexical, those hrefs break — Lexical's link serializer
|
|
14
|
+
* passes them to `new URL(...)` and throws. We rewrite them in-place
|
|
15
|
+
* against a `sourcePath → importedDocPath` map built in a pre-pass.
|
|
16
|
+
*
|
|
17
|
+
* Links whose target isn't in the map (i.e. the .md file wasn't part of
|
|
18
|
+
* the same import batch) are stripped: the `link` node is replaced by
|
|
19
|
+
* its inline children, so the reader sees the link text but no broken
|
|
20
|
+
* URL. The original href is reported as a warning.
|
|
21
|
+
*
|
|
22
|
+
* Non-markdown hrefs (absolute URLs, mailto:, pure fragments, images,
|
|
23
|
+
* etc.) are left untouched.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { dirname, resolve } from 'node:path'
|
|
27
|
+
|
|
28
|
+
import type { Parent, Root, RootContent } from 'mdast'
|
|
29
|
+
|
|
30
|
+
export interface DocLinkRewriteWarning {
|
|
31
|
+
kind: 'rewritten-doc-link' | 'unresolved-doc-link' | 'stripped-empty-link'
|
|
32
|
+
href: string
|
|
33
|
+
resolvedTo?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface RewriteDocLinksOptions {
|
|
37
|
+
/** Absolute path of the markdown file currently being converted. */
|
|
38
|
+
sourceFilePath: string
|
|
39
|
+
/** Map from absolute markdown source path → imported doc path (no leading slash). */
|
|
40
|
+
pathMap: Map<string, string>
|
|
41
|
+
/** URL prefix the imported docs live under, e.g. `/docs`. */
|
|
42
|
+
urlPrefix: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const MD_EXT_RE = /\.(md|markdown)$/i
|
|
46
|
+
// A leading `scheme:` like `https:`, `mailto:`, `data:` — anything we
|
|
47
|
+
// must not touch.
|
|
48
|
+
const SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i
|
|
49
|
+
|
|
50
|
+
export function rewriteDocLinks(root: Root, opts: RewriteDocLinksOptions): DocLinkRewriteWarning[] {
|
|
51
|
+
const warnings: DocLinkRewriteWarning[] = []
|
|
52
|
+
const baseDir = dirname(opts.sourceFilePath)
|
|
53
|
+
const prefix = opts.urlPrefix.replace(/\/$/, '')
|
|
54
|
+
rewriteChildren(root as unknown as Parent, baseDir, prefix, opts.pathMap, warnings)
|
|
55
|
+
return warnings
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function rewriteChildren(
|
|
59
|
+
parent: Parent,
|
|
60
|
+
baseDir: string,
|
|
61
|
+
prefix: string,
|
|
62
|
+
pathMap: Map<string, string>,
|
|
63
|
+
warnings: DocLinkRewriteWarning[]
|
|
64
|
+
): void {
|
|
65
|
+
const next: RootContent[] = []
|
|
66
|
+
for (const child of parent.children as RootContent[]) {
|
|
67
|
+
if (child.type === 'link') {
|
|
68
|
+
const decision = classifyLink(child.url, baseDir, pathMap)
|
|
69
|
+
if (decision.kind === 'skip') {
|
|
70
|
+
// Still recurse — a link may contain other links via images, etc.
|
|
71
|
+
rewriteChildren(child as unknown as Parent, baseDir, prefix, pathMap, warnings)
|
|
72
|
+
next.push(child)
|
|
73
|
+
} else if (decision.kind === 'rewrite') {
|
|
74
|
+
const newUrl = `${prefix}/${decision.docPath}${decision.fragment}`
|
|
75
|
+
warnings.push({
|
|
76
|
+
kind: 'rewritten-doc-link',
|
|
77
|
+
href: child.url,
|
|
78
|
+
resolvedTo: newUrl,
|
|
79
|
+
})
|
|
80
|
+
child.url = newUrl
|
|
81
|
+
rewriteChildren(child as unknown as Parent, baseDir, prefix, pathMap, warnings)
|
|
82
|
+
next.push(child)
|
|
83
|
+
} else {
|
|
84
|
+
// Unresolved .md or empty/meaningless target — drop the link
|
|
85
|
+
// wrapper, keep the text so the reader still sees the prose.
|
|
86
|
+
warnings.push({
|
|
87
|
+
kind: decision.kind === 'unresolved' ? 'unresolved-doc-link' : 'stripped-empty-link',
|
|
88
|
+
href: child.url,
|
|
89
|
+
})
|
|
90
|
+
rewriteChildren(child as unknown as Parent, baseDir, prefix, pathMap, warnings)
|
|
91
|
+
for (const inner of child.children) next.push(inner as RootContent)
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
if (hasChildren(child)) {
|
|
95
|
+
rewriteChildren(child, baseDir, prefix, pathMap, warnings)
|
|
96
|
+
}
|
|
97
|
+
next.push(child)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
parent.children = next as Parent['children']
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
type Decision =
|
|
104
|
+
| { kind: 'skip' }
|
|
105
|
+
| { kind: 'rewrite'; docPath: string; fragment: string }
|
|
106
|
+
| { kind: 'unresolved' }
|
|
107
|
+
| { kind: 'empty' }
|
|
108
|
+
|
|
109
|
+
// Targets that reference "the current directory" with no real path —
|
|
110
|
+
// `.`, `..`, `./`, `../`, etc. Authors sometimes write `[text](.)` as a
|
|
111
|
+
// placeholder; in the rendered doc it has no meaning and Lexical's
|
|
112
|
+
// link serializer crashes on it.
|
|
113
|
+
const EMPTY_TARGET_RE = /^\.{1,2}\/?$/
|
|
114
|
+
|
|
115
|
+
function classifyLink(
|
|
116
|
+
url: string | undefined | null,
|
|
117
|
+
baseDir: string,
|
|
118
|
+
pathMap: Map<string, string>
|
|
119
|
+
): Decision {
|
|
120
|
+
if (url == null) return { kind: 'skip' }
|
|
121
|
+
if (url.length === 0) return { kind: 'empty' }
|
|
122
|
+
if (url.startsWith('#')) return { kind: 'skip' }
|
|
123
|
+
if (url.startsWith('//')) return { kind: 'skip' }
|
|
124
|
+
if (SCHEME_RE.test(url)) return { kind: 'skip' }
|
|
125
|
+
|
|
126
|
+
const hashIdx = url.indexOf('#')
|
|
127
|
+
const target = hashIdx >= 0 ? url.slice(0, hashIdx) : url
|
|
128
|
+
const fragment = hashIdx >= 0 ? url.slice(hashIdx) : ''
|
|
129
|
+
|
|
130
|
+
if (target.length === 0 || EMPTY_TARGET_RE.test(target)) return { kind: 'empty' }
|
|
131
|
+
if (!MD_EXT_RE.test(target)) return { kind: 'skip' }
|
|
132
|
+
|
|
133
|
+
const abs = resolve(baseDir, target)
|
|
134
|
+
const mapped = pathMap.get(abs)
|
|
135
|
+
if (mapped) return { kind: 'rewrite', docPath: mapped, fragment }
|
|
136
|
+
return { kind: 'unresolved' }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function hasChildren(node: RootContent): node is RootContent & Parent {
|
|
140
|
+
return 'children' in node && Array.isArray((node as Parent).children)
|
|
141
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
import type { Root } from 'mdast'
|
|
10
|
+
import remarkGfm from 'remark-gfm'
|
|
11
|
+
import remarkParse from 'remark-parse'
|
|
12
|
+
import { unified } from 'unified'
|
|
13
|
+
import { describe, expect, test } from 'vitest'
|
|
14
|
+
|
|
15
|
+
import { stripLeadingH1IfMatches } from './strip-leading-h1.js'
|
|
16
|
+
|
|
17
|
+
function parse(md: string): Root {
|
|
18
|
+
return unified().use(remarkParse).use(remarkGfm).parse(md) as Root
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('stripLeadingH1IfMatches', () => {
|
|
22
|
+
test('removes the leading H1 when its text matches the title', () => {
|
|
23
|
+
const root = parse('# Authentication & Authorization\n\nbody')
|
|
24
|
+
const out = stripLeadingH1IfMatches(root, 'Authentication & Authorization')
|
|
25
|
+
expect(out.children).toHaveLength(1)
|
|
26
|
+
expect(out.children[0]).toMatchObject({ type: 'paragraph' })
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('match is case-insensitive and whitespace-tolerant', () => {
|
|
30
|
+
const root = parse('# authentication & authorization \n\nbody')
|
|
31
|
+
const out = stripLeadingH1IfMatches(root, 'Authentication & Authorization')
|
|
32
|
+
expect(out.children).toHaveLength(1)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('match flattens inline formatting in the H1', () => {
|
|
36
|
+
// mdast-util-to-string drops backticks / emphasis markers from the
|
|
37
|
+
// H1's inline structure. Frontmatter titles are plain prose, so a
|
|
38
|
+
// body H1 of '# Client SDK (`@byline/client`)' compares equal to a
|
|
39
|
+
// frontmatter title of 'Client SDK (@byline/client)'.
|
|
40
|
+
const root = parse('# Client SDK (`@byline/client`)\n\nbody')
|
|
41
|
+
const out = stripLeadingH1IfMatches(root, 'Client SDK (@byline/client)')
|
|
42
|
+
expect(out.children).toHaveLength(1)
|
|
43
|
+
expect(out.children[0]).toMatchObject({ type: 'paragraph' })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('leaves the body untouched when the H1 differs', () => {
|
|
47
|
+
const root = parse('# Different Title\n\nbody')
|
|
48
|
+
const out = stripLeadingH1IfMatches(root, 'Authentication & Authorization')
|
|
49
|
+
expect(out.children).toHaveLength(2)
|
|
50
|
+
expect(out.children[0]).toMatchObject({ type: 'heading', depth: 1 })
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('leaves the body untouched when there is no leading heading', () => {
|
|
54
|
+
const root = parse('just a paragraph')
|
|
55
|
+
const out = stripLeadingH1IfMatches(root, 'Anything')
|
|
56
|
+
expect(out.children).toHaveLength(1)
|
|
57
|
+
expect(out.children[0]).toMatchObject({ type: 'paragraph' })
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('leaves the body untouched when the leading heading is H2', () => {
|
|
61
|
+
const root = parse('## A Subheading\n\nbody')
|
|
62
|
+
const out = stripLeadingH1IfMatches(root, 'A Subheading')
|
|
63
|
+
expect(out.children).toHaveLength(2)
|
|
64
|
+
expect(out.children[0]).toMatchObject({ type: 'heading', depth: 2 })
|
|
65
|
+
})
|
|
66
|
+
})
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
* Bulk re-anchor: move every fully-translated document onto a new content
|
|
11
|
+
* source locale. This is the follow-up to switching `i18n.content.defaultLocale`
|
|
12
|
+
* — Slices 1–4 make the switch *safe* (existing docs keep reading their original
|
|
13
|
+
* anchor); this command actually moves the documents that are complete in the
|
|
14
|
+
* new locale onto it (its fallback floor, path locale, and completeness
|
|
15
|
+
* yardstick). Documents not yet fully translated into the target are skipped and
|
|
16
|
+
* listed — that list is the outstanding-translation backlog. Re-run as
|
|
17
|
+
* translation progresses; it is idempotent (each doc is its own transaction).
|
|
18
|
+
*
|
|
19
|
+
* cd apps/webapp && pnpm tsx byline/scripts/re-anchor.ts --to fr
|
|
20
|
+
* cd apps/webapp && pnpm tsx byline/scripts/re-anchor.ts --to fr --collection pages
|
|
21
|
+
* cd apps/webapp && pnpm tsx byline/scripts/re-anchor.ts --to fr --dry-run
|
|
22
|
+
*
|
|
23
|
+
* See docs/I18N.md.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import '../load-env.js'
|
|
27
|
+
import '../server.config.js'
|
|
28
|
+
|
|
29
|
+
import { parseArgs } from 'node:util'
|
|
30
|
+
|
|
31
|
+
import { getBylineCore, getServerConfig } from '@byline/core'
|
|
32
|
+
import type { PgAdapter } from '@byline/db-postgres'
|
|
33
|
+
|
|
34
|
+
const USAGE =
|
|
35
|
+
'Usage: pnpm tsx byline/scripts/re-anchor.ts --to <locale> [--collection <path>] [--dry-run]'
|
|
36
|
+
|
|
37
|
+
async function run() {
|
|
38
|
+
const { values } = parseArgs({
|
|
39
|
+
options: {
|
|
40
|
+
to: { type: 'string' },
|
|
41
|
+
collection: { type: 'string' },
|
|
42
|
+
'dry-run': { type: 'boolean', default: false },
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const targetLocale = values.to
|
|
47
|
+
if (!targetLocale) {
|
|
48
|
+
console.error(`✗ missing required --to <locale>.\n${USAGE}`)
|
|
49
|
+
process.exit(1)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const config = getServerConfig()
|
|
53
|
+
|
|
54
|
+
const contentLocales = config.i18n.content.locales
|
|
55
|
+
if (!contentLocales.includes(targetLocale)) {
|
|
56
|
+
console.error(
|
|
57
|
+
`✗ --to '${targetLocale}' is not a configured content locale (${contentLocales.join(', ')})`
|
|
58
|
+
)
|
|
59
|
+
process.exit(1)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Resolve an optional collection-path filter to its id via the registered
|
|
63
|
+
// collection records (throws a clear error for an unknown path).
|
|
64
|
+
const collectionPath = values.collection
|
|
65
|
+
const collectionId = collectionPath
|
|
66
|
+
? getBylineCore().getCollectionRecord(collectionPath).collectionId
|
|
67
|
+
: undefined
|
|
68
|
+
|
|
69
|
+
const dryRun = values['dry-run'] ?? false
|
|
70
|
+
const db = config.db as PgAdapter
|
|
71
|
+
const scope = collectionPath ? `collection '${collectionPath}'` : 'all collections'
|
|
72
|
+
|
|
73
|
+
console.log(
|
|
74
|
+
`${dryRun ? '[dry-run] ' : ''}re-anchoring ${scope} → content source locale '${targetLocale}'…`
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
const report = await db.reAnchorDocuments({ targetLocale, collectionId, dryRun })
|
|
78
|
+
|
|
79
|
+
console.log(
|
|
80
|
+
`${dryRun ? '[dry-run] would re-anchor' : '✓ re-anchored'} ${report.reanchored}/${report.total} document(s) → '${targetLocale}'`
|
|
81
|
+
)
|
|
82
|
+
console.log(` • already anchored to '${targetLocale}': ${report.alreadyAnchored}`)
|
|
83
|
+
console.log(` • skipped (incomplete translation): ${report.skippedIncomplete}`)
|
|
84
|
+
|
|
85
|
+
if (report.skippedIncomplete > 0) {
|
|
86
|
+
console.log(
|
|
87
|
+
`\nDocuments needing a complete '${targetLocale}' translation before they can be re-anchored:`
|
|
88
|
+
)
|
|
89
|
+
for (const r of report.results) {
|
|
90
|
+
if (r.status === 'skipped-incomplete') {
|
|
91
|
+
console.log(` - ${r.documentId} (currently anchored to '${r.fromLocale}')`)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
run()
|
|
98
|
+
.then(() => process.exit(0))
|
|
99
|
+
.catch((error) => {
|
|
100
|
+
console.error('✗ re-anchor failed:', error)
|
|
101
|
+
process.exit(1)
|
|
102
|
+
})
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* to `'avif'` in `byline/collections/media/schema.ts`) to bring existing
|
|
19
19
|
* assets in line with the new pipeline:
|
|
20
20
|
*
|
|
21
|
-
* pnpm tsx
|
|
21
|
+
* pnpm tsx byline/scripts/regenerate-media.ts
|
|
22
22
|
*
|
|
23
23
|
* The script orchestrates the same two-step flow the admin UI uses
|
|
24
24
|
* for an existing document — upload (createDocument: false) followed by
|
|
@@ -115,6 +115,15 @@ CREATE TABLE "byline_store_datetime" (
|
|
|
115
115
|
CONSTRAINT "unique_datetime_field" UNIQUE("document_version_id","field_path","locale")
|
|
116
116
|
);
|
|
117
117
|
--> statement-breakpoint
|
|
118
|
+
CREATE TABLE "byline_document_available_locales" (
|
|
119
|
+
"document_id" uuid NOT NULL,
|
|
120
|
+
"locale" varchar(10) NOT NULL,
|
|
121
|
+
"collection_id" uuid NOT NULL,
|
|
122
|
+
"created_at" timestamp (6) with time zone DEFAULT now() NOT NULL,
|
|
123
|
+
"updated_at" timestamp (6) with time zone DEFAULT now() NOT NULL,
|
|
124
|
+
CONSTRAINT "byline_document_available_locales_document_id_locale_pk" PRIMARY KEY("document_id","locale")
|
|
125
|
+
);
|
|
126
|
+
--> statement-breakpoint
|
|
118
127
|
CREATE TABLE "byline_document_paths" (
|
|
119
128
|
"document_id" uuid NOT NULL,
|
|
120
129
|
"locale" varchar(10) NOT NULL,
|
|
@@ -133,6 +142,12 @@ CREATE TABLE "byline_document_relationships" (
|
|
|
133
142
|
CONSTRAINT "byline_document_relationships_parent_document_id_child_document_id_unique" UNIQUE("parent_document_id","child_document_id")
|
|
134
143
|
);
|
|
135
144
|
--> statement-breakpoint
|
|
145
|
+
CREATE TABLE "byline_document_version_locales" (
|
|
146
|
+
"document_version_id" uuid NOT NULL,
|
|
147
|
+
"locale" varchar(10) NOT NULL,
|
|
148
|
+
CONSTRAINT "byline_document_version_locales_document_version_id_locale_pk" PRIMARY KEY("document_version_id","locale")
|
|
149
|
+
);
|
|
150
|
+
--> statement-breakpoint
|
|
136
151
|
CREATE TABLE "byline_document_versions" (
|
|
137
152
|
"id" uuid PRIMARY KEY NOT NULL,
|
|
138
153
|
"document_id" uuid NOT NULL,
|
|
@@ -152,6 +167,7 @@ CREATE TABLE "byline_documents" (
|
|
|
152
167
|
"id" uuid PRIMARY KEY NOT NULL,
|
|
153
168
|
"collection_id" uuid NOT NULL,
|
|
154
169
|
"order_key" varchar(128) COLLATE "C",
|
|
170
|
+
"source_locale" varchar(10) NOT NULL,
|
|
155
171
|
"created_at" timestamp (6) with time zone DEFAULT now() NOT NULL,
|
|
156
172
|
"updated_at" timestamp (6) with time zone DEFAULT now() NOT NULL
|
|
157
173
|
);
|
|
@@ -270,10 +286,13 @@ ALTER TABLE "byline_store_boolean" ADD CONSTRAINT "byline_store_boolean_document
|
|
|
270
286
|
ALTER TABLE "byline_store_boolean" ADD CONSTRAINT "byline_store_boolean_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
271
287
|
ALTER TABLE "byline_store_datetime" ADD CONSTRAINT "byline_store_datetime_document_version_id_byline_document_versions_id_fk" FOREIGN KEY ("document_version_id") REFERENCES "public"."byline_document_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
272
288
|
ALTER TABLE "byline_store_datetime" ADD CONSTRAINT "byline_store_datetime_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
289
|
+
ALTER TABLE "byline_document_available_locales" ADD CONSTRAINT "byline_document_available_locales_document_id_byline_documents_id_fk" FOREIGN KEY ("document_id") REFERENCES "public"."byline_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
290
|
+
ALTER TABLE "byline_document_available_locales" ADD CONSTRAINT "byline_document_available_locales_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
273
291
|
ALTER TABLE "byline_document_paths" ADD CONSTRAINT "byline_document_paths_document_id_byline_documents_id_fk" FOREIGN KEY ("document_id") REFERENCES "public"."byline_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
274
292
|
ALTER TABLE "byline_document_paths" ADD CONSTRAINT "byline_document_paths_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
275
293
|
ALTER TABLE "byline_document_relationships" ADD CONSTRAINT "byline_document_relationships_parent_document_id_byline_documents_id_fk" FOREIGN KEY ("parent_document_id") REFERENCES "public"."byline_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
276
294
|
ALTER TABLE "byline_document_relationships" ADD CONSTRAINT "byline_document_relationships_child_document_id_byline_documents_id_fk" FOREIGN KEY ("child_document_id") REFERENCES "public"."byline_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
295
|
+
ALTER TABLE "byline_document_version_locales" ADD CONSTRAINT "byline_document_version_locales_document_version_id_byline_document_versions_id_fk" FOREIGN KEY ("document_version_id") REFERENCES "public"."byline_document_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
277
296
|
ALTER TABLE "byline_document_versions" ADD CONSTRAINT "byline_document_versions_document_id_byline_documents_id_fk" FOREIGN KEY ("document_id") REFERENCES "public"."byline_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
278
297
|
ALTER TABLE "byline_document_versions" ADD CONSTRAINT "byline_document_versions_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
279
298
|
ALTER TABLE "byline_documents" ADD CONSTRAINT "byline_documents_collection_id_byline_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."byline_collections"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
@@ -304,6 +323,7 @@ CREATE INDEX "idx_datetime_date" ON "byline_store_datetime" USING btree ("value_
|
|
|
304
323
|
CREATE INDEX "idx_datetime_timestamp_tz" ON "byline_store_datetime" USING btree ("value_timestamp_tz");--> statement-breakpoint
|
|
305
324
|
CREATE INDEX "idx_datetime_path_date" ON "byline_store_datetime" USING btree ("field_path","value_timestamp_tz");--> statement-breakpoint
|
|
306
325
|
CREATE INDEX "idx_datetime_collection_date" ON "byline_store_datetime" USING btree ("collection_id","value_timestamp_tz");--> statement-breakpoint
|
|
326
|
+
CREATE INDEX "idx_document_available_locales_document_id" ON "byline_document_available_locales" USING btree ("document_id");--> statement-breakpoint
|
|
307
327
|
CREATE INDEX "idx_document_paths_document_id" ON "byline_document_paths" USING btree ("document_id");--> statement-breakpoint
|
|
308
328
|
CREATE INDEX "idx_document_relationships_parent" ON "byline_document_relationships" USING btree ("parent_document_id");--> statement-breakpoint
|
|
309
329
|
CREATE INDEX "idx_document_relationships_child" ON "byline_document_relationships" USING btree ("child_document_id");--> statement-breakpoint
|
|
@@ -342,5 +362,5 @@ CREATE INDEX "idx_text_value" ON "byline_store_text" USING btree ("value");--> s
|
|
|
342
362
|
CREATE INDEX "idx_text_fulltext" ON "byline_store_text" USING gin (to_tsvector('english', "value"));--> statement-breakpoint
|
|
343
363
|
CREATE INDEX "idx_text_locale_value" ON "byline_store_text" USING btree ("locale","value");--> statement-breakpoint
|
|
344
364
|
CREATE INDEX "idx_text_path_value" ON "byline_store_text" USING btree ("field_path","value");--> statement-breakpoint
|
|
345
|
-
CREATE VIEW "public"."byline_current_documents" AS (with "sq" as (select "id", "document_id", "collection_id", "collection_version", "event_type", "status", "is_deleted", "created_at", "updated_at", "created_by", "change_summary", row_number() OVER (PARTITION BY "document_id" ORDER BY "id" DESC) as "rn" from "byline_document_versions" where "byline_document_versions"."is_deleted" = false) select "sq"."id", "sq"."document_id", "sq"."collection_id", "sq"."collection_version", "sq"."event_type", "sq"."status", "sq"."is_deleted", "sq"."created_at", "sq"."updated_at", "sq"."created_by", "sq"."change_summary", "byline_documents"."order_key" from "sq" inner join "byline_documents" on "byline_documents"."id" = "sq"."document_id" where "rn" = 1);--> statement-breakpoint
|
|
346
|
-
CREATE VIEW "public"."byline_current_published_documents" AS (with "sq" as (select "id", "document_id", "collection_id", "collection_version", "event_type", "status", "is_deleted", "created_at", "updated_at", "created_by", "change_summary", row_number() OVER (PARTITION BY "document_id" ORDER BY "id" DESC) as "rn" from "byline_document_versions" where "byline_document_versions"."is_deleted" = false AND "byline_document_versions"."status" = 'published') select "sq"."id", "sq"."document_id", "sq"."collection_id", "sq"."collection_version", "sq"."event_type", "sq"."status", "sq"."is_deleted", "sq"."created_at", "sq"."updated_at", "sq"."created_by", "sq"."change_summary", "byline_documents"."order_key" from "sq" inner join "byline_documents" on "byline_documents"."id" = "sq"."document_id" where "rn" = 1);
|
|
365
|
+
CREATE VIEW "public"."byline_current_documents" AS (with "sq" as (select "id", "document_id", "collection_id", "collection_version", "event_type", "status", "is_deleted", "created_at", "updated_at", "created_by", "change_summary", row_number() OVER (PARTITION BY "document_id" ORDER BY "id" DESC) as "rn" from "byline_document_versions" where "byline_document_versions"."is_deleted" = false) select "sq"."id", "sq"."document_id", "sq"."collection_id", "sq"."collection_version", "sq"."event_type", "sq"."status", "sq"."is_deleted", "sq"."created_at", "sq"."updated_at", "sq"."created_by", "sq"."change_summary", "byline_documents"."order_key", "byline_documents"."source_locale" from "sq" inner join "byline_documents" on "byline_documents"."id" = "sq"."document_id" where "rn" = 1);--> statement-breakpoint
|
|
366
|
+
CREATE VIEW "public"."byline_current_published_documents" AS (with "sq" as (select "id", "document_id", "collection_id", "collection_version", "event_type", "status", "is_deleted", "created_at", "updated_at", "created_by", "change_summary", row_number() OVER (PARTITION BY "document_id" ORDER BY "id" DESC) as "rn" from "byline_document_versions" where "byline_document_versions"."is_deleted" = false AND "byline_document_versions"."status" = 'published') select "sq"."id", "sq"."document_id", "sq"."collection_id", "sq"."collection_version", "sq"."event_type", "sq"."status", "sq"."is_deleted", "sq"."created_at", "sq"."updated_at", "sq"."created_by", "sq"."change_summary", "byline_documents"."order_key", "byline_documents"."source_locale" from "sq" inner join "byline_documents" on "byline_documents"."id" = "sq"."document_id" where "rn" = 1);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "
|
|
2
|
+
"id": "52560051-1da6-41f4-8a2c-b9a7b5421d26",
|
|
3
3
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
|
4
4
|
"version": "7",
|
|
5
5
|
"dialect": "postgresql",
|
|
@@ -1053,6 +1053,102 @@
|
|
|
1053
1053
|
"checkConstraints": {},
|
|
1054
1054
|
"isRLSEnabled": false
|
|
1055
1055
|
},
|
|
1056
|
+
"public.byline_document_available_locales": {
|
|
1057
|
+
"name": "byline_document_available_locales",
|
|
1058
|
+
"schema": "",
|
|
1059
|
+
"columns": {
|
|
1060
|
+
"document_id": {
|
|
1061
|
+
"name": "document_id",
|
|
1062
|
+
"type": "uuid",
|
|
1063
|
+
"primaryKey": false,
|
|
1064
|
+
"notNull": true
|
|
1065
|
+
},
|
|
1066
|
+
"locale": {
|
|
1067
|
+
"name": "locale",
|
|
1068
|
+
"type": "varchar(10)",
|
|
1069
|
+
"primaryKey": false,
|
|
1070
|
+
"notNull": true
|
|
1071
|
+
},
|
|
1072
|
+
"collection_id": {
|
|
1073
|
+
"name": "collection_id",
|
|
1074
|
+
"type": "uuid",
|
|
1075
|
+
"primaryKey": false,
|
|
1076
|
+
"notNull": true
|
|
1077
|
+
},
|
|
1078
|
+
"created_at": {
|
|
1079
|
+
"name": "created_at",
|
|
1080
|
+
"type": "timestamp (6) with time zone",
|
|
1081
|
+
"primaryKey": false,
|
|
1082
|
+
"notNull": true,
|
|
1083
|
+
"default": "now()"
|
|
1084
|
+
},
|
|
1085
|
+
"updated_at": {
|
|
1086
|
+
"name": "updated_at",
|
|
1087
|
+
"type": "timestamp (6) with time zone",
|
|
1088
|
+
"primaryKey": false,
|
|
1089
|
+
"notNull": true,
|
|
1090
|
+
"default": "now()"
|
|
1091
|
+
}
|
|
1092
|
+
},
|
|
1093
|
+
"indexes": {
|
|
1094
|
+
"idx_document_available_locales_document_id": {
|
|
1095
|
+
"name": "idx_document_available_locales_document_id",
|
|
1096
|
+
"columns": [
|
|
1097
|
+
{
|
|
1098
|
+
"expression": "document_id",
|
|
1099
|
+
"isExpression": false,
|
|
1100
|
+
"asc": true,
|
|
1101
|
+
"nulls": "last"
|
|
1102
|
+
}
|
|
1103
|
+
],
|
|
1104
|
+
"isUnique": false,
|
|
1105
|
+
"concurrently": false,
|
|
1106
|
+
"method": "btree",
|
|
1107
|
+
"with": {}
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
"foreignKeys": {
|
|
1111
|
+
"byline_document_available_locales_document_id_byline_documents_id_fk": {
|
|
1112
|
+
"name": "byline_document_available_locales_document_id_byline_documents_id_fk",
|
|
1113
|
+
"tableFrom": "byline_document_available_locales",
|
|
1114
|
+
"tableTo": "byline_documents",
|
|
1115
|
+
"columnsFrom": [
|
|
1116
|
+
"document_id"
|
|
1117
|
+
],
|
|
1118
|
+
"columnsTo": [
|
|
1119
|
+
"id"
|
|
1120
|
+
],
|
|
1121
|
+
"onDelete": "cascade",
|
|
1122
|
+
"onUpdate": "no action"
|
|
1123
|
+
},
|
|
1124
|
+
"byline_document_available_locales_collection_id_byline_collections_id_fk": {
|
|
1125
|
+
"name": "byline_document_available_locales_collection_id_byline_collections_id_fk",
|
|
1126
|
+
"tableFrom": "byline_document_available_locales",
|
|
1127
|
+
"tableTo": "byline_collections",
|
|
1128
|
+
"columnsFrom": [
|
|
1129
|
+
"collection_id"
|
|
1130
|
+
],
|
|
1131
|
+
"columnsTo": [
|
|
1132
|
+
"id"
|
|
1133
|
+
],
|
|
1134
|
+
"onDelete": "cascade",
|
|
1135
|
+
"onUpdate": "no action"
|
|
1136
|
+
}
|
|
1137
|
+
},
|
|
1138
|
+
"compositePrimaryKeys": {
|
|
1139
|
+
"byline_document_available_locales_document_id_locale_pk": {
|
|
1140
|
+
"name": "byline_document_available_locales_document_id_locale_pk",
|
|
1141
|
+
"columns": [
|
|
1142
|
+
"document_id",
|
|
1143
|
+
"locale"
|
|
1144
|
+
]
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
"uniqueConstraints": {},
|
|
1148
|
+
"policies": {},
|
|
1149
|
+
"checkConstraints": {},
|
|
1150
|
+
"isRLSEnabled": false
|
|
1151
|
+
},
|
|
1056
1152
|
"public.byline_document_paths": {
|
|
1057
1153
|
"name": "byline_document_paths",
|
|
1058
1154
|
"schema": "",
|
|
@@ -1264,6 +1360,53 @@
|
|
|
1264
1360
|
"checkConstraints": {},
|
|
1265
1361
|
"isRLSEnabled": false
|
|
1266
1362
|
},
|
|
1363
|
+
"public.byline_document_version_locales": {
|
|
1364
|
+
"name": "byline_document_version_locales",
|
|
1365
|
+
"schema": "",
|
|
1366
|
+
"columns": {
|
|
1367
|
+
"document_version_id": {
|
|
1368
|
+
"name": "document_version_id",
|
|
1369
|
+
"type": "uuid",
|
|
1370
|
+
"primaryKey": false,
|
|
1371
|
+
"notNull": true
|
|
1372
|
+
},
|
|
1373
|
+
"locale": {
|
|
1374
|
+
"name": "locale",
|
|
1375
|
+
"type": "varchar(10)",
|
|
1376
|
+
"primaryKey": false,
|
|
1377
|
+
"notNull": true
|
|
1378
|
+
}
|
|
1379
|
+
},
|
|
1380
|
+
"indexes": {},
|
|
1381
|
+
"foreignKeys": {
|
|
1382
|
+
"byline_document_version_locales_document_version_id_byline_document_versions_id_fk": {
|
|
1383
|
+
"name": "byline_document_version_locales_document_version_id_byline_document_versions_id_fk",
|
|
1384
|
+
"tableFrom": "byline_document_version_locales",
|
|
1385
|
+
"tableTo": "byline_document_versions",
|
|
1386
|
+
"columnsFrom": [
|
|
1387
|
+
"document_version_id"
|
|
1388
|
+
],
|
|
1389
|
+
"columnsTo": [
|
|
1390
|
+
"id"
|
|
1391
|
+
],
|
|
1392
|
+
"onDelete": "cascade",
|
|
1393
|
+
"onUpdate": "no action"
|
|
1394
|
+
}
|
|
1395
|
+
},
|
|
1396
|
+
"compositePrimaryKeys": {
|
|
1397
|
+
"byline_document_version_locales_document_version_id_locale_pk": {
|
|
1398
|
+
"name": "byline_document_version_locales_document_version_id_locale_pk",
|
|
1399
|
+
"columns": [
|
|
1400
|
+
"document_version_id",
|
|
1401
|
+
"locale"
|
|
1402
|
+
]
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1405
|
+
"uniqueConstraints": {},
|
|
1406
|
+
"policies": {},
|
|
1407
|
+
"checkConstraints": {},
|
|
1408
|
+
"isRLSEnabled": false
|
|
1409
|
+
},
|
|
1267
1410
|
"public.byline_document_versions": {
|
|
1268
1411
|
"name": "byline_document_versions",
|
|
1269
1412
|
"schema": "",
|
|
@@ -1530,6 +1673,12 @@
|
|
|
1530
1673
|
"primaryKey": false,
|
|
1531
1674
|
"notNull": false
|
|
1532
1675
|
},
|
|
1676
|
+
"source_locale": {
|
|
1677
|
+
"name": "source_locale",
|
|
1678
|
+
"type": "varchar(10)",
|
|
1679
|
+
"primaryKey": false,
|
|
1680
|
+
"notNull": true
|
|
1681
|
+
},
|
|
1533
1682
|
"created_at": {
|
|
1534
1683
|
"name": "created_at",
|
|
1535
1684
|
"type": "timestamp (6) with time zone",
|
|
@@ -2999,9 +3148,15 @@
|
|
|
2999
3148
|
"type": "varchar(128) COLLATE \"C\"",
|
|
3000
3149
|
"primaryKey": false,
|
|
3001
3150
|
"notNull": false
|
|
3151
|
+
},
|
|
3152
|
+
"source_locale": {
|
|
3153
|
+
"name": "source_locale",
|
|
3154
|
+
"type": "varchar(10)",
|
|
3155
|
+
"primaryKey": false,
|
|
3156
|
+
"notNull": true
|
|
3002
3157
|
}
|
|
3003
3158
|
},
|
|
3004
|
-
"definition": "with \"sq\" as (select \"id\", \"document_id\", \"collection_id\", \"collection_version\", \"event_type\", \"status\", \"is_deleted\", \"created_at\", \"updated_at\", \"created_by\", \"change_summary\", row_number() OVER (PARTITION BY \"document_id\" ORDER BY \"id\" DESC) as \"rn\" from \"byline_document_versions\" where \"byline_document_versions\".\"is_deleted\" = false) select \"sq\".\"id\", \"sq\".\"document_id\", \"sq\".\"collection_id\", \"sq\".\"collection_version\", \"sq\".\"event_type\", \"sq\".\"status\", \"sq\".\"is_deleted\", \"sq\".\"created_at\", \"sq\".\"updated_at\", \"sq\".\"created_by\", \"sq\".\"change_summary\", \"byline_documents\".\"order_key\" from \"sq\" inner join \"byline_documents\" on \"byline_documents\".\"id\" = \"sq\".\"document_id\" where \"rn\" = 1",
|
|
3159
|
+
"definition": "with \"sq\" as (select \"id\", \"document_id\", \"collection_id\", \"collection_version\", \"event_type\", \"status\", \"is_deleted\", \"created_at\", \"updated_at\", \"created_by\", \"change_summary\", row_number() OVER (PARTITION BY \"document_id\" ORDER BY \"id\" DESC) as \"rn\" from \"byline_document_versions\" where \"byline_document_versions\".\"is_deleted\" = false) select \"sq\".\"id\", \"sq\".\"document_id\", \"sq\".\"collection_id\", \"sq\".\"collection_version\", \"sq\".\"event_type\", \"sq\".\"status\", \"sq\".\"is_deleted\", \"sq\".\"created_at\", \"sq\".\"updated_at\", \"sq\".\"created_by\", \"sq\".\"change_summary\", \"byline_documents\".\"order_key\", \"byline_documents\".\"source_locale\" from \"sq\" inner join \"byline_documents\" on \"byline_documents\".\"id\" = \"sq\".\"document_id\" where \"rn\" = 1",
|
|
3005
3160
|
"name": "byline_current_documents",
|
|
3006
3161
|
"schema": "public",
|
|
3007
3162
|
"isExisting": false,
|
|
@@ -3085,9 +3240,15 @@
|
|
|
3085
3240
|
"type": "varchar(128) COLLATE \"C\"",
|
|
3086
3241
|
"primaryKey": false,
|
|
3087
3242
|
"notNull": false
|
|
3243
|
+
},
|
|
3244
|
+
"source_locale": {
|
|
3245
|
+
"name": "source_locale",
|
|
3246
|
+
"type": "varchar(10)",
|
|
3247
|
+
"primaryKey": false,
|
|
3248
|
+
"notNull": true
|
|
3088
3249
|
}
|
|
3089
3250
|
},
|
|
3090
|
-
"definition": "with \"sq\" as (select \"id\", \"document_id\", \"collection_id\", \"collection_version\", \"event_type\", \"status\", \"is_deleted\", \"created_at\", \"updated_at\", \"created_by\", \"change_summary\", row_number() OVER (PARTITION BY \"document_id\" ORDER BY \"id\" DESC) as \"rn\" from \"byline_document_versions\" where \"byline_document_versions\".\"is_deleted\" = false AND \"byline_document_versions\".\"status\" = 'published') select \"sq\".\"id\", \"sq\".\"document_id\", \"sq\".\"collection_id\", \"sq\".\"collection_version\", \"sq\".\"event_type\", \"sq\".\"status\", \"sq\".\"is_deleted\", \"sq\".\"created_at\", \"sq\".\"updated_at\", \"sq\".\"created_by\", \"sq\".\"change_summary\", \"byline_documents\".\"order_key\" from \"sq\" inner join \"byline_documents\" on \"byline_documents\".\"id\" = \"sq\".\"document_id\" where \"rn\" = 1",
|
|
3251
|
+
"definition": "with \"sq\" as (select \"id\", \"document_id\", \"collection_id\", \"collection_version\", \"event_type\", \"status\", \"is_deleted\", \"created_at\", \"updated_at\", \"created_by\", \"change_summary\", row_number() OVER (PARTITION BY \"document_id\" ORDER BY \"id\" DESC) as \"rn\" from \"byline_document_versions\" where \"byline_document_versions\".\"is_deleted\" = false AND \"byline_document_versions\".\"status\" = 'published') select \"sq\".\"id\", \"sq\".\"document_id\", \"sq\".\"collection_id\", \"sq\".\"collection_version\", \"sq\".\"event_type\", \"sq\".\"status\", \"sq\".\"is_deleted\", \"sq\".\"created_at\", \"sq\".\"updated_at\", \"sq\".\"created_by\", \"sq\".\"change_summary\", \"byline_documents\".\"order_key\", \"byline_documents\".\"source_locale\" from \"sq\" inner join \"byline_documents\" on \"byline_documents\".\"id\" = \"sq\".\"document_id\" where \"rn\" = 1",
|
|
3091
3252
|
"name": "byline_current_published_documents",
|
|
3092
3253
|
"schema": "public",
|
|
3093
3254
|
"isExisting": false,
|