@byline/cli 0.1.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/LICENSE +373 -0
- package/README.md +23 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +72 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +36 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +76 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/context.d.ts +38 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +37 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/pg-url.d.ts +11 -0
- package/dist/lib/pg-url.d.ts.map +1 -0
- package/dist/lib/pg-url.js +22 -0
- package/dist/lib/pg-url.js.map +1 -0
- package/dist/manifest/deps.d.ts +29 -0
- package/dist/manifest/deps.d.ts.map +1 -0
- package/dist/manifest/deps.js +97 -0
- package/dist/manifest/deps.js.map +1 -0
- package/dist/manifest/env.d.ts +18 -0
- package/dist/manifest/env.d.ts.map +1 -0
- package/dist/manifest/env.js +38 -0
- package/dist/manifest/env.js.map +1 -0
- package/dist/phases/db-init.d.ts +3 -0
- package/dist/phases/db-init.d.ts.map +1 -0
- package/dist/phases/db-init.js +163 -0
- package/dist/phases/db-init.js.map +1 -0
- package/dist/phases/db.d.ts +11 -0
- package/dist/phases/db.d.ts.map +1 -0
- package/dist/phases/db.js +93 -0
- package/dist/phases/db.js.map +1 -0
- package/dist/phases/deps.d.ts +3 -0
- package/dist/phases/deps.d.ts.map +1 -0
- package/dist/phases/deps.js +115 -0
- package/dist/phases/deps.js.map +1 -0
- package/dist/phases/env.d.ts +3 -0
- package/dist/phases/env.d.ts.map +1 -0
- package/dist/phases/env.js +172 -0
- package/dist/phases/env.js.map +1 -0
- package/dist/phases/host.d.ts +3 -0
- package/dist/phases/host.d.ts.map +1 -0
- package/dist/phases/host.js +99 -0
- package/dist/phases/host.js.map +1 -0
- package/dist/phases/index.d.ts +7 -0
- package/dist/phases/index.d.ts.map +1 -0
- package/dist/phases/index.js +40 -0
- package/dist/phases/index.js.map +1 -0
- package/dist/phases/preflight.d.ts +4 -0
- package/dist/phases/preflight.d.ts.map +1 -0
- package/dist/phases/preflight.js +81 -0
- package/dist/phases/preflight.js.map +1 -0
- package/dist/phases/routes.d.ts +3 -0
- package/dist/phases/routes.d.ts.map +1 -0
- package/dist/phases/routes.js +145 -0
- package/dist/phases/routes.js.map +1 -0
- package/dist/phases/scaffold.d.ts +3 -0
- package/dist/phases/scaffold.d.ts.map +1 -0
- package/dist/phases/scaffold.js +113 -0
- package/dist/phases/scaffold.js.map +1 -0
- package/dist/phases/stub.d.ts +3 -0
- package/dist/phases/stub.d.ts.map +1 -0
- package/dist/phases/stub.js +25 -0
- package/dist/phases/stub.js.map +1 -0
- package/dist/phases/ui.d.ts +3 -0
- package/dist/phases/ui.d.ts.map +1 -0
- package/dist/phases/ui.js +93 -0
- package/dist/phases/ui.js.map +1 -0
- package/dist/phases/wire/index.d.ts +3 -0
- package/dist/phases/wire/index.d.ts.map +1 -0
- package/dist/phases/wire/index.js +67 -0
- package/dist/phases/wire/index.js.map +1 -0
- package/dist/phases/wire/root-tsx.d.ts +3 -0
- package/dist/phases/wire/root-tsx.d.ts.map +1 -0
- package/dist/phases/wire/root-tsx.js +57 -0
- package/dist/phases/wire/root-tsx.js.map +1 -0
- package/dist/phases/wire/server-ts.d.ts +3 -0
- package/dist/phases/wire/server-ts.d.ts.map +1 -0
- package/dist/phases/wire/server-ts.js +54 -0
- package/dist/phases/wire/server-ts.js.map +1 -0
- package/dist/phases/wire/shared.d.ts +34 -0
- package/dist/phases/wire/shared.d.ts.map +1 -0
- package/dist/phases/wire/shared.js +2 -0
- package/dist/phases/wire/shared.js.map +1 -0
- package/dist/phases/wire/start-ts.d.ts +3 -0
- package/dist/phases/wire/start-ts.d.ts.map +1 -0
- package/dist/phases/wire/start-ts.js +149 -0
- package/dist/phases/wire/start-ts.js.map +1 -0
- package/dist/phases/wire/tsconfig.d.ts +3 -0
- package/dist/phases/wire/tsconfig.d.ts.map +1 -0
- package/dist/phases/wire/tsconfig.js +105 -0
- package/dist/phases/wire/tsconfig.js.map +1 -0
- package/dist/phases/wire/vite-config.d.ts +3 -0
- package/dist/phases/wire/vite-config.d.ts.map +1 -0
- package/dist/phases/wire/vite-config.js +46 -0
- package/dist/phases/wire/vite-config.js.map +1 -0
- package/dist/prompts.d.ts +34 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +49 -0
- package/dist/prompts.js.map +1 -0
- package/dist/runner.d.ts +5 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +91 -0
- package/dist/runner.js.map +1 -0
- package/dist/state.d.ts +18 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +68 -0
- package/dist/state.js.map +1 -0
- package/dist/templates/byline/admin.config.ts +41 -0
- package/dist/templates/byline/i18n.ts +47 -0
- package/dist/templates/byline/routes.ts +28 -0
- package/dist/templates/byline/seed.ts +19 -0
- package/dist/templates/byline/seeds/admin.ts +62 -0
- package/dist/templates/byline/server.config.ts +92 -0
- package/dist/templates/byline-examples/admin.config.ts +74 -0
- package/dist/templates/byline-examples/blocks/photo-block.ts +59 -0
- package/dist/templates/byline-examples/blocks/richtext-block.ts +35 -0
- package/dist/templates/byline-examples/collections/doc-example-flat-locale-all.ts +373 -0
- package/dist/templates/byline-examples/collections/doc-example-flat-locale-en.ts +283 -0
- package/dist/templates/byline-examples/collections/doc-example-tree-locale-all.ts +278 -0
- package/dist/templates/byline-examples/collections/doc-example-tree-locale-en.ts +205 -0
- package/dist/templates/byline-examples/collections/docs/admin.tsx +204 -0
- package/dist/templates/byline-examples/collections/docs/components/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/docs/components/feature-formatter.tsx +10 -0
- package/dist/templates/byline-examples/collections/docs/hooks/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/docs/index.ts +10 -0
- package/dist/templates/byline-examples/collections/docs/schema.ts +209 -0
- package/dist/templates/byline-examples/collections/docs-categories/admin.tsx +78 -0
- package/dist/templates/byline-examples/collections/docs-categories/components/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/docs-categories/hooks/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/docs-categories/index.ts +10 -0
- package/dist/templates/byline-examples/collections/docs-categories/schema.ts +33 -0
- package/dist/templates/byline-examples/collections/media/admin.tsx +188 -0
- package/dist/templates/byline-examples/collections/media/components/media-list-view.tsx +330 -0
- package/dist/templates/byline-examples/collections/media/components/media-thumbnail.tsx +63 -0
- package/dist/templates/byline-examples/collections/media/hooks/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/media/index.ts +10 -0
- package/dist/templates/byline-examples/collections/media/schema.ts +157 -0
- package/dist/templates/byline-examples/collections/news/admin.tsx +192 -0
- package/dist/templates/byline-examples/collections/news/components/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/news/hooks/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/news/index.ts +10 -0
- package/dist/templates/byline-examples/collections/news/schema.ts +91 -0
- package/dist/templates/byline-examples/collections/news-categories/admin.tsx +78 -0
- package/dist/templates/byline-examples/collections/news-categories/components/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/news-categories/hooks/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/news-categories/index.ts +10 -0
- package/dist/templates/byline-examples/collections/news-categories/schema.ts +33 -0
- package/dist/templates/byline-examples/collections/pages/admin.tsx +183 -0
- package/dist/templates/byline-examples/collections/pages/components/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/pages/hooks/.gitkeep +0 -0
- package/dist/templates/byline-examples/collections/pages/index.ts +10 -0
- package/dist/templates/byline-examples/collections/pages/schema.ts +96 -0
- package/dist/templates/byline-examples/components/length-indicator.tsx +138 -0
- package/dist/templates/byline-examples/components/pill.tsx +38 -0
- package/dist/templates/byline-examples/components/summary-length.tsx +39 -0
- package/dist/templates/byline-examples/fields/available-languages-field.ts +90 -0
- package/dist/templates/byline-examples/fields/lexical-richtext-compact.ts +88 -0
- package/dist/templates/byline-examples/i18n.ts +47 -0
- package/dist/templates/byline-examples/routes.ts +28 -0
- package/dist/templates/byline-examples/scripts/regenerate-media.ts +275 -0
- package/dist/templates/byline-examples/seed.ts +25 -0
- package/dist/templates/byline-examples/seeds/admin.ts +62 -0
- package/dist/templates/byline-examples/seeds/doc-categories.ts +71 -0
- package/dist/templates/byline-examples/seeds/docs.ts +293 -0
- package/dist/templates/byline-examples/seeds/news-categories.ts +71 -0
- package/dist/templates/byline-examples/server.config.ts +179 -0
- package/dist/templates/host/vite.config.ts +41 -0
- package/dist/templates/migrations/0000_condemned_kronos.sql +324 -0
- package/dist/templates/migrations/0001_sudden_phantom_reporter.sql +1 -0
- package/dist/templates/migrations/meta/0000_snapshot.json +2793 -0
- package/dist/templates/migrations/meta/0001_snapshot.json +2799 -0
- package/dist/templates/migrations/meta/_journal.json +20 -0
- package/dist/templates/routes/(byline)/admin/account/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/collections/$collection/$id/api.tsx +16 -0
- package/dist/templates/routes/(byline)/admin/collections/$collection/$id/history.tsx +19 -0
- package/dist/templates/routes/(byline)/admin/collections/$collection/$id/index.tsx +16 -0
- package/dist/templates/routes/(byline)/admin/collections/$collection/create.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/collections/$collection/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/permissions/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/roles/$id/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/roles/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/route.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/users/$id/index.tsx +11 -0
- package/dist/templates/routes/(byline)/admin/users/index.tsx +11 -0
- package/dist/templates/routes/(byline)/sign-in.tsx +11 -0
- package/dist/templates/ui-byline/blocks/photo-block/index.tsx +80 -0
- package/dist/templates/ui-byline/blocks/richtext-block/index.tsx +46 -0
- package/dist/templates/ui-byline/components/admonition/index.tsx +40 -0
- package/dist/templates/ui-byline/components/code/code-serializer.tsx +20 -0
- package/dist/templates/ui-byline/components/code/code.tsx +50 -0
- package/dist/templates/ui-byline/components/code/index.module.scss +137 -0
- package/dist/templates/ui-byline/components/code/index.ts +2 -0
- package/dist/templates/ui-byline/components/code/types.ts +5 -0
- package/dist/templates/ui-byline/components/code/utils.ts +20 -0
- package/dist/templates/ui-byline/components/heading-anchor/heading-anchor.tsx +69 -0
- package/dist/templates/ui-byline/components/heading-anchor/index.ts +1 -0
- package/dist/templates/ui-byline/components/heading-anchor/utils.ts +15 -0
- package/dist/templates/ui-byline/components/inline-image/index.tsx +109 -0
- package/dist/templates/ui-byline/components/layout/index.tsx +63 -0
- package/dist/templates/ui-byline/components/link/lang-link.tsx +70 -0
- package/dist/templates/ui-byline/components/link/link-field.tsx +298 -0
- package/dist/templates/ui-byline/components/link/link-lexical.tsx +191 -0
- package/dist/templates/ui-byline/components/list/index.ts +2 -0
- package/dist/templates/ui-byline/components/list/list-item.tsx +32 -0
- package/dist/templates/ui-byline/components/list/list.tsx +17 -0
- package/dist/templates/ui-byline/components/responsive-image/index.tsx +205 -0
- package/dist/templates/ui-byline/components/richtext-lexical/index.tsx +31 -0
- package/dist/templates/ui-byline/components/richtext-lexical/serialize/index.tsx +249 -0
- package/dist/templates/ui-byline/components/richtext-lexical/serialize/richtext-node-formats.ts +66 -0
- package/dist/templates/ui-byline/components/richtext-lexical/serialize/types.ts +48 -0
- package/dist/templates/ui-byline/components/richtext-lexical/serialize/utils.ts +15 -0
- package/dist/templates/ui-byline/components/table-cell/index.tsx +36 -0
- package/dist/templates/ui-byline/components/vimeo/index.tsx +21 -0
- package/dist/templates/ui-byline/components/youtube/index.tsx +22 -0
- package/dist/templates/ui-byline/render-blocks.tsx +71 -0
- package/dist/templates/ui-byline/types/i18n.ts +14 -0
- package/dist/templates/ui-byline/utils/image-sources.ts +102 -0
- package/dist/templates/ui-byline/utils/to-kebab-case.ts +5 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/diff.d.ts +4 -0
- package/dist/ui/diff.d.ts.map +1 -0
- package/dist/ui/diff.js +23 -0
- package/dist/ui/diff.js.map +1 -0
- package/dist/ui/grid.d.ts +7 -0
- package/dist/ui/grid.d.ts.map +1 -0
- package/dist/ui/grid.js +24 -0
- package/dist/ui/grid.js.map +1 -0
- package/dist/ui/logger.d.ts +14 -0
- package/dist/ui/logger.d.ts.map +1 -0
- package/dist/ui/logger.js +30 -0
- package/dist/ui/logger.js.map +1 -0
- package/dist/ui/snippet.d.ts +2 -0
- package/dist/ui/snippet.d.ts.map +1 -0
- package/dist/ui/snippet.js +7 -0
- package/dist/ui/snippet.js.map +1 -0
- package/package.json +69 -0
package/dist/runner.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { execa } from 'execa';
|
|
4
|
+
import { renderDiff } from './ui/diff.js';
|
|
5
|
+
export async function runPhase(phase, ctx) {
|
|
6
|
+
const detected = await phase.detect(ctx);
|
|
7
|
+
if (detected === 'done' && !ctx.cliFlags.force) {
|
|
8
|
+
ctx.logger.success(`${phase.id} — already complete`);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (detected === 'blocked') {
|
|
12
|
+
ctx.logger.error(`${phase.id} — blocked; cannot proceed`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
ctx.logger.step(`${phase.id} — planning`);
|
|
16
|
+
const plan = await phase.plan(ctx);
|
|
17
|
+
if (plan.writes.length === 0 && plan.commands.length === 0 && plan.notes.length === 0) {
|
|
18
|
+
ctx.logger.info(`${phase.id} — nothing to do`);
|
|
19
|
+
ctx.state.markPhaseComplete(phase.id);
|
|
20
|
+
ctx.state.flush();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
previewPlan(phase, plan, ctx);
|
|
24
|
+
if (ctx.dryRun) {
|
|
25
|
+
ctx.logger.info(`${phase.id} — dry-run; skipping apply`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const shouldApply = await decideApply(phase, ctx);
|
|
29
|
+
if (!shouldApply) {
|
|
30
|
+
ctx.logger.warn(`${phase.id} — skipped by user`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const result = await phase.apply(plan, ctx);
|
|
34
|
+
if (result.notes)
|
|
35
|
+
for (const n of result.notes)
|
|
36
|
+
ctx.logger.info(n);
|
|
37
|
+
if (result.state === 'done') {
|
|
38
|
+
ctx.state.markPhaseComplete(phase.id);
|
|
39
|
+
ctx.logger.success(`${phase.id} — done`);
|
|
40
|
+
}
|
|
41
|
+
else if (result.state === 'partial') {
|
|
42
|
+
ctx.logger.warn(`${phase.id} — partial; re-run to finish`);
|
|
43
|
+
}
|
|
44
|
+
else if (result.state === 'blocked') {
|
|
45
|
+
ctx.logger.error(`${phase.id} — blocked`);
|
|
46
|
+
}
|
|
47
|
+
ctx.state.flush();
|
|
48
|
+
}
|
|
49
|
+
function previewPlan(phase, plan, ctx) {
|
|
50
|
+
ctx.logger.raw('');
|
|
51
|
+
ctx.logger.raw(` ${phase.title}`);
|
|
52
|
+
for (const note of plan.notes)
|
|
53
|
+
ctx.logger.raw(` • ${note}`);
|
|
54
|
+
for (const w of plan.writes) {
|
|
55
|
+
const before = w.before ?? readIfExists(w.path);
|
|
56
|
+
const label = before ? 'modify' : 'create';
|
|
57
|
+
ctx.logger.raw(` ${label} ${w.path}`);
|
|
58
|
+
if (before !== w.contents) {
|
|
59
|
+
ctx.logger.raw(renderDiff(w.path, before, w.contents));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const c of plan.commands) {
|
|
63
|
+
ctx.logger.raw(` run ${c.command} ${c.args.join(' ')}`);
|
|
64
|
+
}
|
|
65
|
+
ctx.logger.raw('');
|
|
66
|
+
}
|
|
67
|
+
async function decideApply(phase, ctx) {
|
|
68
|
+
if (ctx.apply && phase.defaultMode === 'confirm')
|
|
69
|
+
return true;
|
|
70
|
+
if (phase.defaultMode === 'auto' && ctx.apply !== false)
|
|
71
|
+
return true;
|
|
72
|
+
if (ctx.yes)
|
|
73
|
+
return true;
|
|
74
|
+
return ctx.prompter.confirm({
|
|
75
|
+
message: `Apply ${phase.id} changes?`,
|
|
76
|
+
defaultValue: phase.defaultMode === 'auto',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function readIfExists(path) {
|
|
80
|
+
return existsSync(path) ? readFileSync(path, 'utf8') : '';
|
|
81
|
+
}
|
|
82
|
+
export async function executePlan(plan, ctx) {
|
|
83
|
+
for (const w of plan.writes) {
|
|
84
|
+
mkdirSync(dirname(w.path), { recursive: true });
|
|
85
|
+
writeFileSync(w.path, w.contents, 'utf8');
|
|
86
|
+
}
|
|
87
|
+
for (const c of plan.commands) {
|
|
88
|
+
await execa(c.command, c.args, { cwd: c.cwd ?? ctx.cwd, stdio: 'inherit' });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { InstallState, PhaseId } from './types.js';
|
|
2
|
+
export declare class StateStore {
|
|
3
|
+
private state;
|
|
4
|
+
private readonly path;
|
|
5
|
+
private dirty;
|
|
6
|
+
constructor(cwd: string);
|
|
7
|
+
private fresh;
|
|
8
|
+
private load;
|
|
9
|
+
get(): Readonly<InstallState>;
|
|
10
|
+
patch(partial: Partial<InstallState>): void;
|
|
11
|
+
patchAnswers(partial: InstallState['answers']): void;
|
|
12
|
+
markPhaseComplete(id: PhaseId): void;
|
|
13
|
+
isComplete(id: PhaseId): boolean;
|
|
14
|
+
setWireSubEdit(key: string, status: 'pending' | 'done' | 'manual' | 'skipped'): void;
|
|
15
|
+
flush(): void;
|
|
16
|
+
filePath(): string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAIvD,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,KAAK,CAAQ;gBAET,GAAG,EAAE,MAAM;IAKvB,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,IAAI;IAWZ,GAAG,IAAI,QAAQ,CAAC,YAAY,CAAC;IAI7B,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAK3C,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI;IAKpD,iBAAiB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI;IAOpC,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO;IAIhC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,IAAI;IAKpF,KAAK,IAAI,IAAI;IAMb,QAAQ,IAAI,MAAM;CAGnB"}
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
const STATE_FILE = '.byline-install.json';
|
|
4
|
+
export class StateStore {
|
|
5
|
+
state;
|
|
6
|
+
path;
|
|
7
|
+
dirty = false;
|
|
8
|
+
constructor(cwd) {
|
|
9
|
+
this.path = resolve(cwd, STATE_FILE);
|
|
10
|
+
this.state = this.load() ?? this.fresh();
|
|
11
|
+
}
|
|
12
|
+
fresh() {
|
|
13
|
+
return {
|
|
14
|
+
version: 1,
|
|
15
|
+
startedAt: new Date().toISOString(),
|
|
16
|
+
completedPhases: [],
|
|
17
|
+
answers: {},
|
|
18
|
+
wireSubEdits: {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
load() {
|
|
22
|
+
if (!existsSync(this.path))
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const raw = JSON.parse(readFileSync(this.path, 'utf8'));
|
|
26
|
+
if (raw.version !== 1)
|
|
27
|
+
return null;
|
|
28
|
+
return raw;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
get() {
|
|
35
|
+
return this.state;
|
|
36
|
+
}
|
|
37
|
+
patch(partial) {
|
|
38
|
+
this.state = { ...this.state, ...partial };
|
|
39
|
+
this.dirty = true;
|
|
40
|
+
}
|
|
41
|
+
patchAnswers(partial) {
|
|
42
|
+
this.state.answers = { ...this.state.answers, ...partial };
|
|
43
|
+
this.dirty = true;
|
|
44
|
+
}
|
|
45
|
+
markPhaseComplete(id) {
|
|
46
|
+
if (!this.state.completedPhases.includes(id)) {
|
|
47
|
+
this.state.completedPhases.push(id);
|
|
48
|
+
this.dirty = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
isComplete(id) {
|
|
52
|
+
return this.state.completedPhases.includes(id);
|
|
53
|
+
}
|
|
54
|
+
setWireSubEdit(key, status) {
|
|
55
|
+
this.state.wireSubEdits[key] = status;
|
|
56
|
+
this.dirty = true;
|
|
57
|
+
}
|
|
58
|
+
flush() {
|
|
59
|
+
if (!this.dirty)
|
|
60
|
+
return;
|
|
61
|
+
writeFileSync(this.path, `${JSON.stringify(this.state, null, 2)}\n`, 'utf8');
|
|
62
|
+
this.dirty = false;
|
|
63
|
+
}
|
|
64
|
+
filePath() {
|
|
65
|
+
return this.path;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,MAAM,UAAU,GAAG,sBAAsB,CAAA;AAEzC,MAAM,OAAO,UAAU;IACb,KAAK,CAAc;IACV,IAAI,CAAQ;IACrB,KAAK,GAAG,KAAK,CAAA;IAErB,YAAY,GAAW;QACrB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;QACpC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAA;IAC1C,CAAC;IAEO,KAAK;QACX,OAAO;YACL,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,eAAe,EAAE,EAAE;YACnB,OAAO,EAAE,EAAE;YACX,YAAY,EAAE,EAAE;SACjB,CAAA;IACH,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QACvC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAiB,CAAA;YACvE,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAA;YAClC,OAAO,GAAG,CAAA;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,KAAK,CAAC,OAA8B;QAClC,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,OAAO,EAAE,CAAA;QAC1C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACnB,CAAC;IAED,YAAY,CAAC,OAAgC;QAC3C,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,CAAA;QAC1D,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACnB,CAAC;IAED,iBAAiB,CAAC,EAAW;QAC3B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QACnB,CAAC;IACH,CAAC;IAED,UAAU,CAAC,EAAW;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAChD,CAAC;IAED,cAAc,CAAC,GAAW,EAAE,MAAiD;QAC3E,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,MAAM,CAAA;QACrC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACnB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QACvB,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC5E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
* Registers Byline's client-side config (collection admin UI configs,
|
|
11
|
+
* field editors, i18n, routes) in the current module graph. Imported as
|
|
12
|
+
* a side-effect from `src/routes/__root.tsx` — that module runs in both
|
|
13
|
+
* the SSR render and client module graphs, so a single import there
|
|
14
|
+
* covers both contexts.
|
|
15
|
+
*
|
|
16
|
+
* This is the minimal scaffold: no example collections registered. Add
|
|
17
|
+
* collection schemas + admin configs to the `collections` and `admin`
|
|
18
|
+
* arrays as you create them.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type { ClientConfig } from '@byline/core'
|
|
22
|
+
import { defineClientConfig } from '@byline/core'
|
|
23
|
+
import { RichTextField as LexicalRichTextField } from '@byline/richtext-lexical'
|
|
24
|
+
|
|
25
|
+
import { i18n } from './i18n.js'
|
|
26
|
+
import { DEFAULT_SERVER_URL, routes } from './routes.js'
|
|
27
|
+
|
|
28
|
+
const serverURL = import.meta.env.VITE_SERVER_URL || DEFAULT_SERVER_URL
|
|
29
|
+
|
|
30
|
+
export const config: ClientConfig = {
|
|
31
|
+
serverURL,
|
|
32
|
+
i18n,
|
|
33
|
+
routes,
|
|
34
|
+
collections: [],
|
|
35
|
+
admin: [],
|
|
36
|
+
fields: {
|
|
37
|
+
richText: { editor: LexicalRichTextField },
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
defineClientConfig(config)
|
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
* Shared i18n locale configuration — no upstream dependencies, safe to import
|
|
11
|
+
* from both config entry-points and collection schema files without circular
|
|
12
|
+
* references.
|
|
13
|
+
*
|
|
14
|
+
* `interface` locales govern the CMS admin UI language.
|
|
15
|
+
* `content` locales govern the languages a document can be published in.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface LocaleDefinition {
|
|
19
|
+
code: string
|
|
20
|
+
label: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Locales available in the CMS admin interface. */
|
|
24
|
+
export const interfaceLocales: LocaleDefinition[] = [
|
|
25
|
+
{ code: 'en', label: 'English' },
|
|
26
|
+
{ code: 'fr', label: 'Français' },
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
/** Locales a document can be published in. */
|
|
30
|
+
export const contentLocales = [
|
|
31
|
+
{ code: 'en', label: 'English' },
|
|
32
|
+
{ code: 'fr', label: 'Français' },
|
|
33
|
+
{ code: 'es', label: 'Español' },
|
|
34
|
+
{ code: 'de', label: 'Deutsch' },
|
|
35
|
+
] as const
|
|
36
|
+
|
|
37
|
+
/** Derived config object — passed directly to defineServerConfig / defineClientConfig. */
|
|
38
|
+
export const i18n = {
|
|
39
|
+
interface: {
|
|
40
|
+
defaultLocale: 'en',
|
|
41
|
+
locales: interfaceLocales.map((l) => l.code),
|
|
42
|
+
},
|
|
43
|
+
content: {
|
|
44
|
+
defaultLocale: 'en',
|
|
45
|
+
locales: contentLocales.map((l) => l.code),
|
|
46
|
+
},
|
|
47
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
* URL segments for admin and (future) public API routes. Defaults of
|
|
11
|
+
* `/admin` and `/api` are applied automatically by `resolveRoutes()` —
|
|
12
|
+
* keys only need to be set here when overriding either default.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { RoutesConfig } from '@byline/core'
|
|
16
|
+
|
|
17
|
+
export const routes: Partial<RoutesConfig> = {
|
|
18
|
+
admin: '/admin',
|
|
19
|
+
api: '/api',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Fallback used by both server and admin entry points when no
|
|
24
|
+
* `VITE_SERVER_URL` env var is set. Each entry resolves the env var
|
|
25
|
+
* itself (Vite's `import.meta.env` on the client, Node's `process.env`
|
|
26
|
+
* on the server) and falls back to this literal.
|
|
27
|
+
*/
|
|
28
|
+
export const DEFAULT_SERVER_URL = 'http://localhost:5173/'
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
// Initialize Byline config by importing the server config
|
|
10
|
+
import 'dotenv/config'
|
|
11
|
+
import './server.config.js'
|
|
12
|
+
|
|
13
|
+
import { seedAdmin } from './seeds/admin.js'
|
|
14
|
+
|
|
15
|
+
async function run() {
|
|
16
|
+
await seedAdmin()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
run()
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
* Super-admin bootstrap seed.
|
|
11
|
+
*
|
|
12
|
+
* Idempotent. Reads credentials from env (`BYLINE_SUPERADMIN_EMAIL`,
|
|
13
|
+
* `BYLINE_SUPERADMIN_PASSWORD`) and calls the built-in
|
|
14
|
+
* `seedSuperAdmin` helper from `@byline/admin/admin-users` against an
|
|
15
|
+
* `AdminStore` built on the application's single connection pool.
|
|
16
|
+
*
|
|
17
|
+
* The admin account it produces:
|
|
18
|
+
* - `is_super_admin: true` — bypasses every ability check
|
|
19
|
+
* - `is_enabled: true` — ready to sign in immediately
|
|
20
|
+
* - `is_email_verified: true` — skip the verification gate for bootstrap
|
|
21
|
+
*
|
|
22
|
+
* In any non-dev deployment: change the credentials in env, run the seed
|
|
23
|
+
* once, then immediately change the password from inside the admin UI.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type { AdminStore } from '@byline/admin'
|
|
27
|
+
import { seedSuperAdmin } from '@byline/admin/admin-users'
|
|
28
|
+
import { getBylineCore } from '@byline/core'
|
|
29
|
+
|
|
30
|
+
export async function seedAdmin() {
|
|
31
|
+
const email = process.env.BYLINE_SUPERADMIN_EMAIL
|
|
32
|
+
const password = process.env.BYLINE_SUPERADMIN_PASSWORD
|
|
33
|
+
|
|
34
|
+
if (!email || !password) {
|
|
35
|
+
console.warn(
|
|
36
|
+
'Skipping admin seed: BYLINE_SUPERADMIN_EMAIL and BYLINE_SUPERADMIN_PASSWORD ' +
|
|
37
|
+
'must both be set (see .env.example).'
|
|
38
|
+
)
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const bylineCore = getBylineCore<AdminStore>()
|
|
43
|
+
|
|
44
|
+
if (!bylineCore.adminStore) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'seedAdmin: bylineCore.adminStore is not configured. ' +
|
|
47
|
+
'Pass adminStore to initBylineCore() in byline/server.config.ts.'
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = await seedSuperAdmin(bylineCore.adminStore, { email, password })
|
|
52
|
+
|
|
53
|
+
const parts: string[] = []
|
|
54
|
+
if (result.created.role) parts.push('role')
|
|
55
|
+
if (result.created.user) parts.push('user')
|
|
56
|
+
if (result.created.assignment) parts.push('assignment')
|
|
57
|
+
if (parts.length === 0) {
|
|
58
|
+
console.log(`Super-admin already present (${email}) — no changes.`)
|
|
59
|
+
} else {
|
|
60
|
+
console.log(`Super-admin seed: created ${parts.join(', ')} for ${email}.`)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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 any seed / migration script that needs the
|
|
12
|
+
* configured runtime). Resolves the composed `BylineCore` and registers
|
|
13
|
+
* it on the process global via `initBylineCore()` — server-side callers
|
|
14
|
+
* read it back with `getBylineCore<AdminStore>()`.
|
|
15
|
+
*
|
|
16
|
+
* This is the minimal scaffold: no example collections registered. Add
|
|
17
|
+
* collection schemas to the `collections` array as you create them under
|
|
18
|
+
* `byline/collections/<name>/schema.ts`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { type AdminStore, registerAdminAbilities } from '@byline/admin'
|
|
22
|
+
import { JwtSessionProvider } from '@byline/admin/auth'
|
|
23
|
+
import { type BylineCore, initBylineCore } from '@byline/core'
|
|
24
|
+
import { pgAdapter } from '@byline/db-postgres'
|
|
25
|
+
import { createAdminStore } from '@byline/db-postgres/admin'
|
|
26
|
+
import { getAdminBylineClient } from '@byline/host-tanstack-start/integrations/byline-client'
|
|
27
|
+
import { lexicalEditorServer } from '@byline/richtext-lexical/server'
|
|
28
|
+
import { localStorageProvider } from '@byline/storage-local'
|
|
29
|
+
|
|
30
|
+
import { i18n } from './i18n.js'
|
|
31
|
+
import { DEFAULT_SERVER_URL, routes } from './routes.js'
|
|
32
|
+
|
|
33
|
+
const serverURL = process.env.VITE_SERVER_URL || DEFAULT_SERVER_URL
|
|
34
|
+
|
|
35
|
+
const collections: Parameters<typeof pgAdapter>[0]['collections'] = []
|
|
36
|
+
|
|
37
|
+
// HMR-safe singleton. Vite's program reload re-evaluates this module
|
|
38
|
+
// without disposing the previous module's resources — every reload
|
|
39
|
+
// would otherwise allocate a fresh pg `Pool` (max: 20) inside
|
|
40
|
+
// `pgAdapter`, the previous pool would orphan but stay alive, and
|
|
41
|
+
// after a handful of HMR cycles Postgres' `max_connections` is
|
|
42
|
+
// exhausted. Stashing the resolving `Promise` lets module reloads
|
|
43
|
+
// reuse the same pool. Production has no HMR so this guard is a no-op.
|
|
44
|
+
declare global {
|
|
45
|
+
// biome-ignore lint: globalThis augmentation requires `var` rather than `let`
|
|
46
|
+
var __bylineCoreSingleton__: Promise<BylineCore<AdminStore>> | undefined
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function buildBylineCore(): Promise<BylineCore<AdminStore>> {
|
|
50
|
+
const db = pgAdapter({
|
|
51
|
+
connectionString: process.env.DB_CONNECTION_STRING || '',
|
|
52
|
+
collections,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const adminStore = createAdminStore(db.drizzle)
|
|
56
|
+
|
|
57
|
+
const signingSecret = process.env.BYLINE_JWT_SECRET
|
|
58
|
+
if (!signingSecret || signingSecret.length < 32) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
'BYLINE_JWT_SECRET must be set and carry at least 32 bytes of entropy. ' +
|
|
61
|
+
'Generate one with `openssl rand -base64 48` and add it to your .env.'
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const sessionProvider = new JwtSessionProvider({
|
|
66
|
+
store: adminStore,
|
|
67
|
+
signingSecret,
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const core = await initBylineCore<AdminStore>({
|
|
71
|
+
serverURL,
|
|
72
|
+
i18n,
|
|
73
|
+
routes,
|
|
74
|
+
collections,
|
|
75
|
+
db,
|
|
76
|
+
adminStore,
|
|
77
|
+
storage: localStorageProvider({
|
|
78
|
+
uploadDir: './public/uploads',
|
|
79
|
+
baseUrl: '/uploads',
|
|
80
|
+
}),
|
|
81
|
+
sessionProvider,
|
|
82
|
+
fields: {
|
|
83
|
+
richText: { populate: lexicalEditorServer({ getClient: getAdminBylineClient }) },
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
registerAdminAbilities(core.abilities)
|
|
88
|
+
return core
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
globalThis.__bylineCoreSingleton__ ??= buildBylineCore()
|
|
92
|
+
await globalThis.__bylineCoreSingleton__
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
* Registers Byline's client-side config (collection admin UI configs,
|
|
11
|
+
* field editors, i18n, routes) in the current module graph. Imported as
|
|
12
|
+
* a side-effect from `src/routes/__root.tsx` — that module runs in both
|
|
13
|
+
* the SSR render and client module graphs, so a single import there
|
|
14
|
+
* covers both contexts.
|
|
15
|
+
*
|
|
16
|
+
* In TanStack Start with Vite 6 the server entry (`src/server.ts`) and
|
|
17
|
+
* the SSR rendering context run in separate Vite environments, so
|
|
18
|
+
* importing this file from `src/server.ts` would NOT propagate the
|
|
19
|
+
* registration into the SSR render module graph.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { ClientConfig } from '@byline/core'
|
|
23
|
+
import { defineClientConfig } from '@byline/core'
|
|
24
|
+
import { RichTextField as LexicalRichTextField } from '@byline/richtext-lexical'
|
|
25
|
+
|
|
26
|
+
// Import `lexicalEditor` instead of (or alongside) `RichTextField` if you
|
|
27
|
+
// want to register the editor with site-wide custom settings. See the
|
|
28
|
+
// commented `richText` block below for the exact shape.
|
|
29
|
+
// import { lexicalEditor } from '@byline/richtext-lexical'
|
|
30
|
+
|
|
31
|
+
import { Docs, DocsAdmin } from './collections/docs/index.js'
|
|
32
|
+
import { DocsCategories, DocsCategoriesAdmin } from './collections/docs-categories/index.js'
|
|
33
|
+
import { Media, MediaAdmin } from './collections/media/index.js'
|
|
34
|
+
import { News, NewsAdmin } from './collections/news/index.js'
|
|
35
|
+
import { NewsCategories, NewsCategoriesAdmin } from './collections/news-categories/index.js'
|
|
36
|
+
import { Pages, PagesAdmin } from './collections/pages/index.js'
|
|
37
|
+
import { i18n } from './i18n.js'
|
|
38
|
+
import { DEFAULT_SERVER_URL, routes } from './routes.js'
|
|
39
|
+
|
|
40
|
+
const serverURL = import.meta.env.VITE_SERVER_URL || DEFAULT_SERVER_URL
|
|
41
|
+
|
|
42
|
+
export const config: ClientConfig = {
|
|
43
|
+
serverURL,
|
|
44
|
+
i18n,
|
|
45
|
+
routes,
|
|
46
|
+
collections: [Docs, News, Pages, Media, DocsCategories, NewsCategories],
|
|
47
|
+
admin: [DocsAdmin, NewsAdmin, PagesAdmin, MediaAdmin, DocsCategoriesAdmin, NewsCategoriesAdmin],
|
|
48
|
+
fields: {
|
|
49
|
+
// Default registration — every `type: 'richText'` field gets the full
|
|
50
|
+
// Lexical feature set unless overridden per-field via
|
|
51
|
+
// `RichTextField.editorConfig` (see `byline/fields/lexical-richtext-compact.ts`
|
|
52
|
+
// for the per-field pattern).
|
|
53
|
+
richText: { editor: LexicalRichTextField },
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------
|
|
56
|
+
// Alternatively — register the editor with site-wide custom settings.
|
|
57
|
+
// The `configure` callback receives a deep clone of `defaultEditorConfig`,
|
|
58
|
+
// so mutating it is safe. Per-field `editorConfig` continues to take
|
|
59
|
+
// precedence over whatever is baked in here.
|
|
60
|
+
//
|
|
61
|
+
// richText: {
|
|
62
|
+
// editor: lexicalEditor((c) => {
|
|
63
|
+
// c.settings.options.tablePlugin = false
|
|
64
|
+
// c.settings.options.codeHighlightPlugin = false
|
|
65
|
+
// c.settings.options.admonitionPlugin = false
|
|
66
|
+
// c.settings.placeholderText = 'Start writing...'
|
|
67
|
+
// return c
|
|
68
|
+
// }),
|
|
69
|
+
// },
|
|
70
|
+
// ---------------------------------------------------------------------
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
defineClientConfig(config)
|
|
@@ -0,0 +1,59 @@
|
|
|
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 BlockData, type BlockFieldData, defineBlock } from '@byline/core'
|
|
10
|
+
|
|
11
|
+
export const PhotoBlock = defineBlock({
|
|
12
|
+
blockType: 'photoBlock',
|
|
13
|
+
label: 'Photo Block',
|
|
14
|
+
helpText: 'A block for displaying a photo with optional caption and alt text.',
|
|
15
|
+
fields: [
|
|
16
|
+
{
|
|
17
|
+
name: 'display',
|
|
18
|
+
label: 'Display',
|
|
19
|
+
type: 'select',
|
|
20
|
+
optional: true,
|
|
21
|
+
defaultValue: 'default',
|
|
22
|
+
helpText: 'Select a display option for the photo.',
|
|
23
|
+
options: [
|
|
24
|
+
{ label: 'Default', value: 'default' },
|
|
25
|
+
{ label: 'Wide', value: 'wide' },
|
|
26
|
+
{ label: 'Full Width', value: 'full_width' },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'photo',
|
|
31
|
+
label: 'Photo',
|
|
32
|
+
type: 'relation',
|
|
33
|
+
targetCollection: 'media',
|
|
34
|
+
displayField: 'title',
|
|
35
|
+
optional: true,
|
|
36
|
+
},
|
|
37
|
+
{ name: 'alt', label: 'Alt', type: 'text', localized: false },
|
|
38
|
+
{
|
|
39
|
+
name: 'caption',
|
|
40
|
+
label: 'Caption',
|
|
41
|
+
type: 'richText',
|
|
42
|
+
optional: true,
|
|
43
|
+
localized: true,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Field-only data shape for the photo block — useful for forms or
|
|
50
|
+
* block-internal helpers.
|
|
51
|
+
*/
|
|
52
|
+
export type PhotoBlockFields = BlockFieldData<typeof PhotoBlock>
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Full block instance shape (`_id`, `_type` + fields) as it appears
|
|
56
|
+
* inside a document tree. Use this as the prop type for the photo
|
|
57
|
+
* block renderer.
|
|
58
|
+
*/
|
|
59
|
+
export type PhotoBlockData = BlockData<typeof PhotoBlock>
|
|
@@ -0,0 +1,35 @@
|
|
|
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 BlockData, type BlockFieldData, defineBlock } from '@byline/core'
|
|
10
|
+
|
|
11
|
+
export const RichTextBlock = defineBlock({
|
|
12
|
+
blockType: 'richTextBlock',
|
|
13
|
+
label: 'Richtext Block',
|
|
14
|
+
helpText: 'A block for displaying a richtext editor.',
|
|
15
|
+
fields: [
|
|
16
|
+
{
|
|
17
|
+
name: 'richText',
|
|
18
|
+
label: 'Richtext',
|
|
19
|
+
type: 'richText',
|
|
20
|
+
localized: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'constrainedWidth',
|
|
24
|
+
label: 'Constrained Width',
|
|
25
|
+
type: 'checkbox',
|
|
26
|
+
optional: true,
|
|
27
|
+
defaultValue: true,
|
|
28
|
+
helpText:
|
|
29
|
+
'If enabled, the richtext content will be constrained to a maximum width for better readability.',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export type RichTextBlockFields = BlockFieldData<typeof RichTextBlock>
|
|
35
|
+
export type RichTextBlockData = BlockData<typeof RichTextBlock>
|