@orthacms/i18n-server 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"entry-locale-extension.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/content/services/entry-locale-extension.service.ts"],"names":[],"mappings":"AAMA,OAAO,EAYH,KAAK,GAAG,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAkB,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EACH,sBAAsB,EACtB,mBAAmB,EAMnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAE1B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACxB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAuCvF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,2BAA4B,YAAW,qBAAqB;IAE/C,OAAO,CAAC,QAAQ,CAAC,EAAE;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAK3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;gBARe,EAAE,EAAE,QAAQ,EAC9B,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,sBAAsB,EAKlC,SAAS,EAAE,mBAAmB,EAC9B,GAAG,EAAE,UAAU;IAGpC,kBAAkB;IAClB,SAAS,CACL,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,GACzB,GAAG,GAAG,SAAS;IAmClB;;;;;;;;OAQG;IACG,aAAa,CACf,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAgBnC;;;;;;;OAOG;YACW,iBAAiB;IAmC/B;;;;;;;;;;;;OAYG;IACG,WAAW,CACb,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IAKhB,kBAAkB;IACZ,WAAW,CACb,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAmBrC,kBAAkB;IACZ,cAAc,CAChB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAkDxC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;;;;;;;;OAaG;YACW,mBAAmB;IAiMjC;;;;;;;;;;;;;;;;;;;;;OAqBG;YACW,yBAAyB;IAmEvC;;;;;;;;;OASG;YACW,uBAAuB;IA0CrC;;;;;;;;;;OAUG;YACW,gBAAgB;IA6C9B,kBAAkB;IAClB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,oBAAoB,GAAG,SAAS;IAcvE;;;;;;;;;;;;;;;;;;;;OAoBG;YACW,iBAAiB;IAmE/B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,aAAa;CAoBxB"}
1
+ {"version":3,"file":"entry-locale-extension.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/content/services/entry-locale-extension.service.ts"],"names":[],"mappings":"AAMA,OAAO,EAYH,KAAK,GAAG,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAkB,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EACH,sBAAsB,EACtB,mBAAmB,EAMnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAE1B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACxB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAuCvF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,2BAA4B,YAAW,qBAAqB;IAE/C,OAAO,CAAC,QAAQ,CAAC,EAAE;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAK3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;gBARe,EAAE,EAAE,QAAQ,EAC9B,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,sBAAsB,EAKlC,SAAS,EAAE,mBAAmB,EAC9B,GAAG,EAAE,UAAU;IAGpC,kBAAkB;IAClB,SAAS,CACL,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,GACzB,GAAG,GAAG,SAAS;IAuClB;;;;;;;;OAQG;IACG,aAAa,CACf,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAgBnC;;;;;;;OAOG;YACW,iBAAiB;IAmC/B;;;;;;;;;;;;OAYG;IACG,WAAW,CACb,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IAKhB,kBAAkB;IACZ,WAAW,CACb,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAmBrC,kBAAkB;IACZ,cAAc,CAChB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAkDxC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;;;;;;;;OAaG;YACW,mBAAmB;IAsMjC;;;;;;;;;;;;;;;;;;;;;OAqBG;YACW,yBAAyB;IAmEvC;;;;;;;;;OASG;YACW,uBAAuB;IA0CrC;;;;;;;;;;OAUG;YACW,gBAAgB;IA6C9B,kBAAkB;IAClB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,oBAAoB,GAAG,SAAS;IAcvE;;;;;;;;;;;;;;;;;;;;OAoBG;YACW,iBAAiB;IAmE/B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,aAAa;CAoBxB"}
@@ -103,7 +103,12 @@ let EntryLocaleExtensionService = class EntryLocaleExtensionService {
103
103
  const requestedSibling = this.db
104
104
  .select({ one: (0, drizzle_orm_1.sql) `1` })
105
105
  .from(sibling)
106
- .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(s['localeGroupId'], table['localeGroupId']), (0, drizzle_orm_1.eq)(s['workspaceId'], workspaceId), (0, drizzle_orm_1.eq)(s['locale'], requested.slug), ...(type.paranoid ? [(0, drizzle_orm_1.isNull)(s['deletedAt'])] : [])));
106
+ .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(s['localeGroupId'], table['localeGroupId']),
107
+ // The row's OWN workspace, not the caller's: a list that
108
+ // includes shared-workspace rows (ADR-0019) must find each
109
+ // group's sibling where the group lives. For an own row the
110
+ // two are the same value.
111
+ (0, drizzle_orm_1.eq)(s['workspaceId'], table['workspaceId']), (0, drizzle_orm_1.eq)(s['locale'], requested.slug), ...(type.paranoid ? [(0, drizzle_orm_1.isNull)(s['deletedAt'])] : [])));
107
112
  return (0, drizzle_orm_1.or)(strict, (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(table['locale'], fallback.slug), (0, drizzle_orm_1.notExists)(requestedSibling)));
108
113
  }
109
114
  /**
@@ -403,7 +408,12 @@ let EntryLocaleExtensionService = class EntryLocaleExtensionService {
403
408
  // silently skip every sibling.
404
409
  if (type.publishable &&
405
410
  sibling['status'] === content_server_2.ENTRY_STATUS.Published) {
406
- const result = this.validation.validate(type, (0, content_server_1.toRecord)(type, updated).values);
411
+ const result = this.validation.validate(type, (0, content_server_1.toRecord)(type, updated).values,
412
+ // A required relation to a type this workspace isn't
413
+ // granted is not required here — the same waiver the
414
+ // publish gate applies, or a sync could refuse what a
415
+ // publish of that sibling would accept.
416
+ await this.validation.waivedRequired(type, workspaceId, tx));
407
417
  if (!result.valid) {
408
418
  throw new common_1.UnprocessableEntityException({
409
419
  message: `Shared fields would invalidate the published ` +
@@ -1,5 +1,5 @@
1
1
  import { type Database } from '@orthacms/database';
2
- import type { AnyContentType, EntryStatus } from '@orthacms/content-server';
2
+ import { type AnyContentType, type EntryStatus } from '@orthacms/content-server';
3
3
  import type { LocaleDir } from '../../i18n.constants';
4
4
  import { LocaleRegistryService } from '../../locales/services/locale-registry.service';
5
5
  /** One locale's slot in a translation group — the row, or null if missing. */
@@ -19,6 +19,14 @@ export interface EntryLocaleItem {
19
19
  /** The group's row in this locale, or null when not yet translated. */
20
20
  entry: {
21
21
  id: string;
22
+ /**
23
+ * The row's display title in its own language — the same field the
24
+ * relation picker labels a record with. Absent when the row has none
25
+ * yet (a draft saved before its title), rather than the id standing in:
26
+ * the locale menu lists these side by side, and a uuid there reads as
27
+ * content.
28
+ */
29
+ title?: string;
22
30
  /** Publish state — publishable types only. */
23
31
  status?: EntryStatus;
24
32
  /**
@@ -68,6 +76,8 @@ export declare class LocaleGroupService {
68
76
  * missing (or soft-deleted) in this workspace.
69
77
  */
70
78
  entryLocales(type: AnyContentType, id: string, workspaceId: string): Promise<EntryLocalesView>;
79
+ /** `{ title }` when the row has a real one, else nothing. */
80
+ private titleOf;
71
81
  /**
72
82
  * Batched group summary for the records table's Locales column: for each
73
83
  * requested group id, its live members **in a configured locale**, with
@@ -1 +1 @@
1
- {"version":3,"file":"locale-group.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/content/services/locale-group.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAKvF,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC5B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,EAAE,SAAS,CAAC;IACf,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,KAAK,EAAE;QACH,EAAE,EAAE,MAAM,CAAC;QACX,8CAA8C;QAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB;;;;;WAKG;QACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,kCAAkC;QAClC,SAAS,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI,CAAC;CACZ;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC7B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,KAAK,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAC9B,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,qBACa,kBAAkB;IAEL,OAAO,CAAC,QAAQ,CAAC,EAAE;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADW,EAAE,EAAE,QAAQ,EAC9B,OAAO,EAAE,qBAAqB;IAGnD;;;;OAIG;IACG,YAAY,CACd,IAAI,EAAE,cAAc,EACpB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC;IAyD5B;;;;;;;;;OASG;IACG,SAAS,CACX,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC;IAoD7B,gFAAgF;IAChF,OAAO,CAAC,WAAW;IAKnB,4EAA4E;IAC5E,OAAO,CAAC,SAAS;CAYpB"}
1
+ {"version":3,"file":"locale-group.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/content/services/locale-group.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAEH,KAAK,cAAc,EACnB,KAAK,WAAW,EACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAKvF,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC5B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,EAAE,SAAS,CAAC;IACf,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,KAAK,EAAE;QACH,EAAE,EAAE,MAAM,CAAC;QACX;;;;;;WAMG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,8CAA8C;QAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB;;;;;WAKG;QACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,kCAAkC;QAClC,SAAS,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI,CAAC;CACZ;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC7B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,KAAK,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAC9B,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,qBACa,kBAAkB;IAEL,OAAO,CAAC,QAAQ,CAAC,EAAE;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADW,EAAE,EAAE,QAAQ,EAC9B,OAAO,EAAE,qBAAqB;IAGnD;;;;OAIG;IACG,YAAY,CACd,IAAI,EAAE,cAAc,EACpB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC;IA0D5B,6DAA6D;IAC7D,OAAO,CAAC,OAAO;IASf;;;;;;;;;OASG;IACG,SAAS,CACX,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC;IAoD7B,gFAAgF;IAChF,OAAO,CAAC,WAAW;IAKnB,4EAA4E;IAC5E,OAAO,CAAC,SAAS;CAYpB"}
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const common_1 = require("@nestjs/common");
6
6
  const drizzle_orm_1 = require("drizzle-orm");
7
7
  const database_1 = require("@orthacms/database");
8
+ const content_server_1 = require("@orthacms/content-server");
8
9
  const locale_registry_service_1 = require("../../locales/services/locale-registry.service");
9
10
  /**
10
11
  * Reads over translation groups: the per-entry locale panel (which locales
@@ -52,6 +53,7 @@ let LocaleGroupService = class LocaleGroupService {
52
53
  entry: sibling
53
54
  ? {
54
55
  id: sibling['id'],
56
+ ...this.titleOf(type, sibling),
55
57
  ...(type.publishable
56
58
  ? {
57
59
  status: sibling['status'],
@@ -65,6 +67,12 @@ let LocaleGroupService = class LocaleGroupService {
65
67
  })
66
68
  };
67
69
  }
70
+ /** `{ title }` when the row has a real one, else nothing. */
71
+ titleOf(type, row) {
72
+ const title = (0, content_server_1.entryTitle)(type, row);
73
+ // `entryTitle` falls back to the id; that is not a title.
74
+ return title === row['id'] ? {} : { title };
75
+ }
68
76
  /**
69
77
  * Batched group summary for the records table's Locales column: for each
70
78
  * requested group id, its live members **in a configured locale**, with
@@ -1 +1 @@
1
- {"version":3,"file":"i18n-tool.provider.d.ts","sourceRoot":"","sources":["../../../src/lib/copilot/i18n-tool.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAEH,oBAAoB,EACpB,KAAK,mBAAmB,EAC3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,uBAAwB,YAAW,YAAY,EAAE,YAAY;IAElE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACX,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBALzB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,kBAAkB,EAE1B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,oBAAoB,EAChB,YAAY,CAAC,EAAE,YAAY,YAAA;IAG5D;;;;;OAKG;IACH,YAAY,IAAI,IAAI;IAIpB,8DAA8D;IAC9D,KAAK,IAAI,SAAS,cAAc,EAAE;IAIlC,iEAAiE;IACjE,OAAO,CAAC,WAAW;IAiCnB,kEAAkE;IAClE,OAAO,CAAC,eAAe;CA8D1B"}
1
+ {"version":3,"file":"i18n-tool.provider.d.ts","sourceRoot":"","sources":["../../../src/lib/copilot/i18n-tool.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAEH,oBAAoB,EACpB,KAAK,mBAAmB,EAC3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,uBAAwB,YAAW,YAAY,EAAE,YAAY;IAElE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACX,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBALzB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,kBAAkB,EAE1B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,oBAAoB,EAChB,YAAY,CAAC,EAAE,YAAY,YAAA;IAG5D;;;;;OAKG;IACH,YAAY,IAAI,IAAI;IAIpB,8DAA8D;IAC9D,KAAK,IAAI,SAAS,cAAc,EAAE;IAIlC,iEAAiE;IACjE,OAAO,CAAC,WAAW;IAiCnB,kEAAkE;IAClE,OAAO,CAAC,eAAe;CAiE1B"}
@@ -128,7 +128,8 @@ let I18nCopilotToolProvider = class I18nCopilotToolProvider {
128
128
  // does not check grants — its callers are already behind a
129
129
  // workspace-scoped controller reached from the admin's own UI.
130
130
  const type = this.registry.get(args.typeName);
131
- const granted = await this.grants.grantedSlugs(ctx.workspaceId);
131
+ // A read: reachable, own or shared (ADR-0019).
132
+ const granted = await this.grants.reachableSlugs(ctx.workspaceId);
132
133
  if (!type || !granted.has(type.name)) {
133
134
  throw new Error(`Unknown content type "${args.typeName}" in this workspace.`);
134
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"translation-proposal.applier.d.ts","sourceRoot":"","sources":["../../../src/lib/copilot/translation-proposal.applier.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EACH,kBAAkB,EAElB,oBAAoB,EAIpB,KAAK,mBAAmB,EAC3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EACR,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,cAAc,EACjB,MAAM,0BAA0B,CAAC;AAMlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBACa,0BAA2B,YAAW,eAAe;IAK1D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACL,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPzC,QAAQ,CAAC,IAAI,yBAAyC;gBAIjC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,oBAAoB,EACV,EAAE,EAAE,QAAQ;IAG7C,KAAK,CACP,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EACjE,KAAK,EAAE,aAAa,GACrB,OAAO,CAAC,mBAAmB,CAAC;CAkDlC;AA0DD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,8BAA+B,YAAW,eAAe;IAK9D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACL,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPzC,QAAQ,CAAC,IAAI,8BAAuC;gBAI/B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,oBAAoB,EACV,EAAE,EAAE,QAAQ;IAG7C,KAAK,CACP,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EACjE,KAAK,EAAE,aAAa,GACrB,OAAO,CAAC,mBAAmB,CAAC;CA8FlC"}
1
+ {"version":3,"file":"translation-proposal.applier.d.ts","sourceRoot":"","sources":["../../../src/lib/copilot/translation-proposal.applier.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EACH,kBAAkB,EAElB,oBAAoB,EAIpB,KAAK,mBAAmB,EAG3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EACR,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,cAAc,EACjB,MAAM,0BAA0B,CAAC;AAMlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBACa,0BAA2B,YAAW,eAAe;IAK1D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACL,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPzC,QAAQ,CAAC,IAAI,yBAAyC;gBAIjC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,oBAAoB,EACV,EAAE,EAAE,QAAQ;IAG7C,KAAK,CACP,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EACjE,KAAK,EAAE,aAAa,GACrB,OAAO,CAAC,mBAAmB,CAAC;CAyDlC;AA0DD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,8BAA+B,YAAW,eAAe;IAK9D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACL,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPzC,QAAQ,CAAC,IAAI,8BAAuC;gBAI/B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,oBAAoB,EACV,EAAE,EAAE,QAAQ;IAG7C,KAAK,CACP,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EACjE,KAAK,EAAE,aAAa,GACrB,OAAO,CAAC,mBAAmB,CAAC;CAqGlC"}
@@ -75,10 +75,15 @@ let TranslationProposalApplier = class TranslationProposalApplier {
75
75
  // between proposing and applying, and a stored type name is an
76
76
  // argument like any other.
77
77
  const type = this.registry.get(typeName);
78
- const granted = await this.grants.grantedSlugs(actor.workspaceId);
79
- if (!type || !granted.has(type.name)) {
78
+ // A write: it needs the own grant. A type read only from shared
79
+ // workspaces is visible to the model, so it is told why (ADR-0019).
80
+ const access = (await this.grants.access(actor.workspaceId)).get(typeName);
81
+ if (!type || !(0, content_server_1.isReachable)(access)) {
80
82
  throw new Error(`Unknown content type "${typeName}" in this workspace.`);
81
83
  }
84
+ if (!access?.own) {
85
+ throw new content_server_1.SharedOnlyContentTypeException(type);
86
+ }
82
87
  const translated = (input.patch['values'] ?? {});
83
88
  const inherited = await sharedValues(this.db, type, sourceId, actor.workspaceId);
84
89
  const entry = await this.writer.create(type, { ...inherited, ...translated }, actor.workspaceId, undefined, locale, localeGroupId, (0, copilot_server_1.proposalEventActor)(actor));
@@ -181,10 +186,15 @@ let BulkTranslationProposalApplier = class BulkTranslationProposalApplier {
181
186
  // between proposing and applying, and a stored type name is an
182
187
  // argument like any other.
183
188
  const type = this.registry.get(typeName);
184
- const granted = await this.grants.grantedSlugs(actor.workspaceId);
185
- if (!type || !granted.has(type.name)) {
189
+ // A write: it needs the own grant. A type read only from shared
190
+ // workspaces is visible to the model, so it is told why (ADR-0019).
191
+ const access = (await this.grants.access(actor.workspaceId)).get(typeName);
192
+ if (!type || !(0, content_server_1.isReachable)(access)) {
186
193
  throw new Error(`Unknown content type "${typeName}" in this workspace.`);
187
194
  }
195
+ if (!access?.own) {
196
+ throw new content_server_1.SharedOnlyContentTypeException(type);
197
+ }
188
198
  const items = input.patch['items'];
189
199
  if (!Array.isArray(items) || items.length === 0) {
190
200
  throw new Error('This change names no translations.');
@@ -1 +1 @@
1
- {"version":3,"file":"translation-proposal.provider.d.ts","sourceRoot":"","sources":["../../../src/lib/copilot/translation-proposal.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAGH,oBAAoB,EACpB,KAAK,mBAAmB,EAE3B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EACH,kBAAkB,EAErB,MAAM,0CAA0C,CAAC;AAElD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB;IAC5B,0DAA0D;;IAE1D;;;;;;;;;OASG;;CAEG,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,+BACT,YAAW,YAAY,EAAE,YAAY;IAIjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACX,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAJzB,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,oBAAoB,EAChB,YAAY,CAAC,EAAE,YAAY,YAAA;IAG5D;;;;;OAKG;IACH,YAAY,IAAI,IAAI;IAIpB,iEAAiE;IACjE,KAAK,IAAI,SAAS,cAAc,EAAE;IAIlC;;;;;;;;;OASG;YACW,oBAAoB;IAgBlC;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IASvB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAoB1B,2EAA2E;IAC3E,OAAO,CAAC,OAAO;IAKf,8DAA8D;IAC9D,OAAO,CAAC,kBAAkB;IA8H1B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,sBAAsB;CA2MjC"}
1
+ {"version":3,"file":"translation-proposal.provider.d.ts","sourceRoot":"","sources":["../../../src/lib/copilot/translation-proposal.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAGH,oBAAoB,EACpB,KAAK,mBAAmB,EAI3B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EACH,kBAAkB,EAErB,MAAM,0CAA0C,CAAC;AAElD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB;IAC5B,0DAA0D;;IAE1D;;;;;;;;;OASG;;CAEG,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,+BACT,YAAW,YAAY,EAAE,YAAY;IAIjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACX,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAJzB,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,oBAAoB,EAChB,YAAY,CAAC,EAAE,YAAY,YAAA;IAG5D;;;;;OAKG;IACH,YAAY,IAAI,IAAI;IAIpB,iEAAiE;IACjE,KAAK,IAAI,SAAS,cAAc,EAAE;IAIlC;;;;;;;;;OASG;YACW,oBAAoB;IAqBlC;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IASvB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAoB1B,2EAA2E;IAC3E,OAAO,CAAC,OAAO;IAKf,8DAA8D;IAC9D,OAAO,CAAC,kBAAkB;IA8H1B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,sBAAsB;CA2MjC"}
@@ -79,10 +79,15 @@ let TranslationProposalToolProvider = class TranslationProposalToolProvider {
79
79
  */
80
80
  async resolveLocalizedType(typeName, workspaceId) {
81
81
  const type = this.registry.get(typeName);
82
- const granted = await this.grants.grantedSlugs(workspaceId);
83
- if (!type || !granted.has(type.name)) {
82
+ // A write: it needs the own grant. A type read only from shared
83
+ // workspaces is visible to the model, so it is told why (ADR-0019).
84
+ const access = (await this.grants.access(workspaceId)).get(typeName);
85
+ if (!type || !(0, content_server_1.isReachable)(access)) {
84
86
  throw new Error(`Unknown content type "${typeName}" in this workspace.`);
85
87
  }
88
+ if (!access?.own) {
89
+ throw new content_server_1.SharedOnlyContentTypeException(type);
90
+ }
86
91
  if (!type.i18n) {
87
92
  throw new Error(`Content type "${type.name}" is not localized, so it cannot be translated.`);
88
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"i18n-schemas.d.ts","sourceRoot":"","sources":["../../../src/lib/docs/i18n-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,qEAAqE;AACrE,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,6EAA6E;AAC7E,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAE/C;AAqED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,GAC/B,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAoG/B"}
1
+ {"version":3,"file":"i18n-schemas.d.ts","sourceRoot":"","sources":["../../../src/lib/docs/i18n-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,qEAAqE;AACrE,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,6EAA6E;AAC7E,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAE/C;AA0ED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,GAC/B,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAoG/B"}
@@ -63,13 +63,17 @@ const PUBLISHED_AT_SCHEMA = {
63
63
  const ENTRY_ROW_SCHEMA = {
64
64
  type: 'object',
65
65
  nullable: true,
66
- description: 'The group’s row in this locale, or `null` when it has not been translated yet. Enough to route to the row and render its state — not its values.',
66
+ description: 'The group’s row in this locale, or `null` when it has not been translated yet. Enough to route to the row, name it and render its state — not its values.',
67
67
  properties: {
68
68
  id: {
69
69
  type: 'string',
70
70
  format: 'uuid',
71
71
  description: 'The entry id of this locale’s row.'
72
72
  },
73
+ title: {
74
+ type: 'string',
75
+ description: 'The row’s display title in its own language. Absent when it has none yet.'
76
+ },
73
77
  status: STATUS_SCHEMA,
74
78
  publishedAt: PUBLISHED_AT_SCHEMA,
75
79
  updatedAt: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orthacms/i18n-server",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "description": "@orthacms/i18n-server — part of Ortha CMS.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orthacms.com",
@@ -27,15 +27,15 @@
27
27
  "dependencies": {
28
28
  "@nestjs/common": "^11.0.0",
29
29
  "@nestjs/swagger": "^11.4.6",
30
- "@orthacms/bootstrap-server": "^0.5.2",
31
- "@orthacms/content-server": "^0.5.2",
32
- "@orthacms/copilot-domain": "^0.5.2",
33
- "@orthacms/copilot-server": "^0.5.2",
34
- "@orthacms/database": "^0.5.2",
35
- "@orthacms/identity-server": "^0.5.2",
36
- "@orthacms/tools-server": "^0.5.2",
37
- "@orthacms/utils-server": "^0.5.2",
38
- "@orthacms/workspaces-server": "^0.5.2",
30
+ "@orthacms/bootstrap-server": "^0.7.0",
31
+ "@orthacms/content-server": "^0.7.0",
32
+ "@orthacms/copilot-domain": "^0.7.0",
33
+ "@orthacms/copilot-server": "^0.7.0",
34
+ "@orthacms/database": "^0.7.0",
35
+ "@orthacms/identity-server": "^0.7.0",
36
+ "@orthacms/tools-server": "^0.7.0",
37
+ "@orthacms/utils-server": "^0.7.0",
38
+ "@orthacms/workspaces-server": "^0.7.0",
39
39
  "class-transformer": "^0.5.1",
40
40
  "class-validator": "^0.15.1",
41
41
  "drizzle-orm": "^0.45.0",