@pramen/cms 0.0.50 → 0.0.51
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 +22 -0
- package/dist/index.d.ts +43 -4
- package/dist/index.js +13 -2
- package/package.json +2 -2
- package/src/index.ts +27 -4
package/README.md
CHANGED
|
@@ -467,6 +467,28 @@ index is what turns a concurrent duplicate into a visible failure instead of a s
|
|
|
467
467
|
ambiguous history. For the same reason the delete-and-purge pair is atomic on the DO but not
|
|
468
468
|
on D1.
|
|
469
469
|
|
|
470
|
+
### Locales
|
|
471
|
+
|
|
472
|
+
A deployment declares the locales it publishes in, and the editor renders its i18n surface
|
|
473
|
+
off that — the Translations panel, the Locale field, the per-row locale column:
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
const handlers = { ...createCmsHandlers({ locales: ["cs", "en"] }), ... };
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
One locale (or none declared) means monolingual: no i18n chrome anywhere, and the editor
|
|
480
|
+
stops sending `locale` on a page save at all, so nothing can blind-overwrite a field it no
|
|
481
|
+
longer shows. The FIRST entry is the locale a page is stamped with when created without
|
|
482
|
+
one — derived, not a second `defaultLocale` option, because two settings that can disagree
|
|
483
|
+
about the same fact is how a Czech-only site ends up publishing `en`.
|
|
484
|
+
|
|
485
|
+
Declared, not inferred from the data: the only way to create a second locale is
|
|
486
|
+
`createTranslation`, which the editor exposes from inside the Translations panel — so a rule
|
|
487
|
+
like "show i18n once a second locale exists" would mean a monolingual site could never
|
|
488
|
+
become multilingual. `listCmsCapabilities` is what the editor reads; `listLocales` remains a
|
|
489
|
+
DATA query (which locales are actually authored), and the two differ while a locale is
|
|
490
|
+
declared but not yet used.
|
|
491
|
+
|
|
470
492
|
## Limitations
|
|
471
493
|
|
|
472
494
|
- **Block `fields` are opaque JSON**, so pramen's row/cell-level ACL and relational queries
|
package/dist/index.d.ts
CHANGED
|
@@ -791,8 +791,19 @@ export interface CmsHandlerOpts {
|
|
|
791
791
|
editorRoles?: readonly string[];
|
|
792
792
|
/** Max accepted media upload size in bytes (enforced at the Worker). Default 25 MB. */
|
|
793
793
|
mediaMaxSize?: number;
|
|
794
|
-
/**
|
|
795
|
-
|
|
794
|
+
/** The locales this deployment publishes in, most-preferred first. Default `["en"]`.
|
|
795
|
+
*
|
|
796
|
+
* DECLARED, not inferred. The editor renders its i18n surface — the Translations panel,
|
|
797
|
+
* the Locale field, the per-row locale column — only when there is more than one, and
|
|
798
|
+
* `listCmsCapabilities` is how it finds out. Inferring "is this site multilingual?" from
|
|
799
|
+
* the locales PRESENT IN DATA cannot work: the only way to create a second locale is
|
|
800
|
+
* `createTranslation`, which the editor exposes from inside the very panel that would
|
|
801
|
+
* stay hidden, so a monolingual site could never become multilingual.
|
|
802
|
+
*
|
|
803
|
+
* The first entry is the default stamped on a page created without one, which is why
|
|
804
|
+
* `defaultLocale` is derived from this rather than configured beside it — two options
|
|
805
|
+
* that can disagree about the same fact is how a Czech-only site ends up stamping "en". */
|
|
806
|
+
locales?: readonly string[];
|
|
796
807
|
/** Roles permitted to approve/reject a page in review and publish (the editorial gate).
|
|
797
808
|
* Default `["reviewer", "admin"]`. */
|
|
798
809
|
reviewerRoles?: readonly string[];
|
|
@@ -960,7 +971,21 @@ export declare function createCmsHandlers(opts?: CmsHandlerOpts): {
|
|
|
960
971
|
title: string;
|
|
961
972
|
status: string;
|
|
962
973
|
}[]>;
|
|
963
|
-
/**
|
|
974
|
+
/** What this deployment supports, for an editor to render against — the pages-side
|
|
975
|
+
* counterpart to `listCollections`' `supports: [...]`.
|
|
976
|
+
*
|
|
977
|
+
* The editor asks the SERVER what exists rather than being told by its own /config.js:
|
|
978
|
+
* a client flag can hide a control but cannot make the data right, and the two drift
|
|
979
|
+
* the moment someone adds a locale. `multilingual` is the derived answer to the only
|
|
980
|
+
* question the UI actually asks, so each surface doesn't re-derive it from the list. */
|
|
981
|
+
listCmsCapabilities: import("@pramen/server").Handler<unknown, {
|
|
982
|
+
locales: string[];
|
|
983
|
+
defaultLocale: string;
|
|
984
|
+
multilingual: boolean;
|
|
985
|
+
}>;
|
|
986
|
+
/** Distinct locales present across all pages. NOTE: a DATA query — what is in the
|
|
987
|
+
* store — not configuration. `listCmsCapabilities().locales` is what the deployment
|
|
988
|
+
* declares; these two differ while a locale is declared but not yet authored. */
|
|
964
989
|
listLocales: import("@pramen/server").Handler<unknown, string[]>;
|
|
965
990
|
/** Create a block instance and place it into a page region in one call (the common
|
|
966
991
|
* editor action). Validates the fields against the block type's schema and the region
|
|
@@ -1300,7 +1325,21 @@ export declare const cmsHandlers: {
|
|
|
1300
1325
|
title: string;
|
|
1301
1326
|
status: string;
|
|
1302
1327
|
}[]>;
|
|
1303
|
-
/**
|
|
1328
|
+
/** What this deployment supports, for an editor to render against — the pages-side
|
|
1329
|
+
* counterpart to `listCollections`' `supports: [...]`.
|
|
1330
|
+
*
|
|
1331
|
+
* The editor asks the SERVER what exists rather than being told by its own /config.js:
|
|
1332
|
+
* a client flag can hide a control but cannot make the data right, and the two drift
|
|
1333
|
+
* the moment someone adds a locale. `multilingual` is the derived answer to the only
|
|
1334
|
+
* question the UI actually asks, so each surface doesn't re-derive it from the list. */
|
|
1335
|
+
listCmsCapabilities: import("@pramen/server").Handler<unknown, {
|
|
1336
|
+
locales: string[];
|
|
1337
|
+
defaultLocale: string;
|
|
1338
|
+
multilingual: boolean;
|
|
1339
|
+
}>;
|
|
1340
|
+
/** Distinct locales present across all pages. NOTE: a DATA query — what is in the
|
|
1341
|
+
* store — not configuration. `listCmsCapabilities().locales` is what the deployment
|
|
1342
|
+
* declares; these two differ while a locale is declared but not yet authored. */
|
|
1304
1343
|
listLocales: import("@pramen/server").Handler<unknown, string[]>;
|
|
1305
1344
|
/** Create a block instance and place it into a page region in one call (the common
|
|
1306
1345
|
* editor action). Validates the fields against the block type's schema and the region
|
package/dist/index.js
CHANGED
|
@@ -959,7 +959,8 @@ export function createCmsHandlers(opts = {}) {
|
|
|
959
959
|
const editorRoles = opts.editorRoles ?? ["editor", "admin"];
|
|
960
960
|
const editor = { auth: editorRoles };
|
|
961
961
|
const mediaMaxSize = opts.mediaMaxSize ?? 25_000_000;
|
|
962
|
-
const
|
|
962
|
+
const locales = opts.locales && opts.locales.length > 0 ? [...opts.locales] : ["en"];
|
|
963
|
+
const defaultLocale = locales[0];
|
|
963
964
|
const reviewerRoles = opts.reviewerRoles ?? ["reviewer", "admin"];
|
|
964
965
|
const reviewer = { auth: reviewerRoles };
|
|
965
966
|
const previewTtl = opts.previewTtlSeconds ?? DEFAULT_PREVIEW_TTL_SECONDS;
|
|
@@ -1499,7 +1500,17 @@ export function createCmsHandlers(opts = {}) {
|
|
|
1499
1500
|
return o;
|
|
1500
1501
|
},
|
|
1501
1502
|
}),
|
|
1502
|
-
/**
|
|
1503
|
+
/** What this deployment supports, for an editor to render against — the pages-side
|
|
1504
|
+
* counterpart to `listCollections`' `supports: [...]`.
|
|
1505
|
+
*
|
|
1506
|
+
* The editor asks the SERVER what exists rather than being told by its own /config.js:
|
|
1507
|
+
* a client flag can hide a control but cannot make the data right, and the two drift
|
|
1508
|
+
* the moment someone adds a locale. `multilingual` is the derived answer to the only
|
|
1509
|
+
* question the UI actually asks, so each surface doesn't re-derive it from the list. */
|
|
1510
|
+
listCmsCapabilities: query(() => ({ locales, defaultLocale, multilingual: locales.length > 1 }), viewer),
|
|
1511
|
+
/** Distinct locales present across all pages. NOTE: a DATA query — what is in the
|
|
1512
|
+
* store — not configuration. `listCmsCapabilities().locales` is what the deployment
|
|
1513
|
+
* declares; these two differ while a locale is declared but not yet authored. */
|
|
1503
1514
|
listLocales: query(async (ctx) => {
|
|
1504
1515
|
// Raw exec bypasses the ACL, so the trash filter has to be written out by hand —
|
|
1505
1516
|
// otherwise the editor's locale switcher offers a locale with zero live pages.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pramen/cms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
4
4
|
"description": "Optional block/page builder for pramen — Drupal-Paragraphs-style typed blocks in named regions, reusable blocks, scheduled publishing, built entirely from pramen primitives.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@pramen/server": "0.0.
|
|
44
|
+
"@pramen/server": "0.0.51"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"react": ">=18"
|
package/src/index.ts
CHANGED
|
@@ -1379,8 +1379,19 @@ export interface CmsHandlerOpts {
|
|
|
1379
1379
|
editorRoles?: readonly string[];
|
|
1380
1380
|
/** Max accepted media upload size in bytes (enforced at the Worker). Default 25 MB. */
|
|
1381
1381
|
mediaMaxSize?: number;
|
|
1382
|
-
/**
|
|
1383
|
-
|
|
1382
|
+
/** The locales this deployment publishes in, most-preferred first. Default `["en"]`.
|
|
1383
|
+
*
|
|
1384
|
+
* DECLARED, not inferred. The editor renders its i18n surface — the Translations panel,
|
|
1385
|
+
* the Locale field, the per-row locale column — only when there is more than one, and
|
|
1386
|
+
* `listCmsCapabilities` is how it finds out. Inferring "is this site multilingual?" from
|
|
1387
|
+
* the locales PRESENT IN DATA cannot work: the only way to create a second locale is
|
|
1388
|
+
* `createTranslation`, which the editor exposes from inside the very panel that would
|
|
1389
|
+
* stay hidden, so a monolingual site could never become multilingual.
|
|
1390
|
+
*
|
|
1391
|
+
* The first entry is the default stamped on a page created without one, which is why
|
|
1392
|
+
* `defaultLocale` is derived from this rather than configured beside it — two options
|
|
1393
|
+
* that can disagree about the same fact is how a Czech-only site ends up stamping "en". */
|
|
1394
|
+
locales?: readonly string[];
|
|
1384
1395
|
/** Roles permitted to approve/reject a page in review and publish (the editorial gate).
|
|
1385
1396
|
* Default `["reviewer", "admin"]`. */
|
|
1386
1397
|
reviewerRoles?: readonly string[];
|
|
@@ -1398,7 +1409,8 @@ export function createCmsHandlers(opts: CmsHandlerOpts = {}) {
|
|
|
1398
1409
|
const editorRoles = opts.editorRoles ?? ["editor", "admin"];
|
|
1399
1410
|
const editor = { auth: editorRoles };
|
|
1400
1411
|
const mediaMaxSize = opts.mediaMaxSize ?? 25_000_000;
|
|
1401
|
-
const
|
|
1412
|
+
const locales = opts.locales && opts.locales.length > 0 ? [...opts.locales] : ["en"];
|
|
1413
|
+
const defaultLocale = locales[0]!;
|
|
1402
1414
|
const reviewerRoles = opts.reviewerRoles ?? ["reviewer", "admin"];
|
|
1403
1415
|
const reviewer = { auth: reviewerRoles };
|
|
1404
1416
|
const previewTtl = opts.previewTtlSeconds ?? DEFAULT_PREVIEW_TTL_SECONDS;
|
|
@@ -1932,7 +1944,18 @@ export function createCmsHandlers(opts: CmsHandlerOpts = {}) {
|
|
|
1932
1944
|
},
|
|
1933
1945
|
}),
|
|
1934
1946
|
|
|
1935
|
-
/**
|
|
1947
|
+
/** What this deployment supports, for an editor to render against — the pages-side
|
|
1948
|
+
* counterpart to `listCollections`' `supports: [...]`.
|
|
1949
|
+
*
|
|
1950
|
+
* The editor asks the SERVER what exists rather than being told by its own /config.js:
|
|
1951
|
+
* a client flag can hide a control but cannot make the data right, and the two drift
|
|
1952
|
+
* the moment someone adds a locale. `multilingual` is the derived answer to the only
|
|
1953
|
+
* question the UI actually asks, so each surface doesn't re-derive it from the list. */
|
|
1954
|
+
listCmsCapabilities: query(() => ({ locales, defaultLocale, multilingual: locales.length > 1 }), viewer),
|
|
1955
|
+
|
|
1956
|
+
/** Distinct locales present across all pages. NOTE: a DATA query — what is in the
|
|
1957
|
+
* store — not configuration. `listCmsCapabilities().locales` is what the deployment
|
|
1958
|
+
* declares; these two differ while a locale is declared but not yet authored. */
|
|
1936
1959
|
listLocales: query(async (ctx) => {
|
|
1937
1960
|
// Raw exec bypasses the ACL, so the trash filter has to be written out by hand —
|
|
1938
1961
|
// otherwise the editor's locale switcher offers a locale with zero live pages.
|