@inwink-mcp/backoffice-extension-helpers 1.0.14 → 1.0.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inwink-mcp/backoffice-extension-helpers",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "author": "inwink",
5
5
  "license": "ISC",
6
6
  "description": "CLI pour bootstrapper, packager et vérifier les extensions backoffice inwink.",
@@ -20,6 +20,7 @@ Reference for consuming the inwink APIs from the extension. Calls always go thro
20
20
  | Past versions and deleted entities | [history.md](./history.md) |
21
21
  | Entity contracts, other endpoints | [entities.md](./entities.md) |
22
22
  | Declare a custom field (entity template) | [entity-template.md](./entity-template.md) |
23
+ | Entities defined by the organizer (custom entities) | [custom-entities.md](./custom-entities.md) |
23
24
  | `file` fields (upload / download) | [files.md](./files.md) |
24
25
  | Handle `assets` (media library) | [assets.md](./assets.md) |
25
26
 
@@ -0,0 +1,120 @@
1
+ ◂ Back to [README](./README.md)
2
+
3
+ # Custom entities
4
+
5
+ Organizers define their **own entities** (custom entities, "objets personnalisés" in the back office):
6
+ job offers, vehicles, parking spots, sponsorship deals… Each one has a key, labels, fields and relations,
7
+ and holds **records**. Users name them in their own words ("my job offers"), never as "custom entities".
8
+
9
+ They exist on events (`eventapi`), communities (`communityapi`), customers and audiences (`customerapi`).
10
+ On the public website (front API), only **event** custom entities are served.
11
+
12
+ ## Names
13
+
14
+ | Where | Name | Example |
15
+ |---|---|---|
16
+ | Record routes | `customentity/{key}` | `{eventId}/customentity/joboffer/query` |
17
+ | Relation target, CMS entity kind | `customentity.{key}` | `"target": "customentity.joboffer"` |
18
+ | Definition | `key` | `joboffer` (`^[a-z][a-z0-9_]{1,31}$`, cannot change after creation) |
19
+
20
+ An unknown key answers `404`. Keys are unique per event / community / customer, not across them.
21
+
22
+ ## Definitions
23
+
24
+ `{shard}/customentitydefinition` (on an audience: `{customerId}/audience/{tenantId}/authtenantcustomentitydefinition`) — generic routes: `query`, `count`, create (`POST` with `{ "entity": {…} }`),
25
+ update (`POST {id}`), `delete`.
26
+
27
+ | Field | Role |
28
+ |---|---|
29
+ | `key` | Technical name, fixed after creation |
30
+ | `labels`, `pluralLabels` | Display names per language, e.g. `{ "fr": "Offre d'emploi", "en": "Job offer" }` |
31
+ | `description` | What the entity holds |
32
+ | `icon` | Back-office icon |
33
+ | `status` | `Active` or `Disabled` (hidden from the back-office menu; records stay readable) |
34
+ | `displayLabelPattern` | How a record is named, with merge tags: `{{title}} – {{company}}` |
35
+ | `accessClaimType` | Optional right that replaces the generic custom entity right |
36
+ | `frontAccess` | Website access: `read` (`None` = not on the site, `Anonymous`, `Authenticated`), `write` (owner kinds allowed to write: `Person`, `Exhibitor`…), `publication` (records are published one by one), `visibleToOwnersOf` (relation keys whose target owner can read the records) |
37
+
38
+ The fields are **not** in the definition: they live in the template of the records (below).
39
+ A definition cannot be deleted while it has records, or while another definition has a relation to it.
40
+
41
+ ## Fields (template)
42
+
43
+ The fields of a custom entity are a regular entity template, read and written on the record routes:
44
+
45
+ | Verb | Route | Role |
46
+ |---|---|---|
47
+ | `GET` | `{shard}/customentity/{key}/worktemplate` | Fields, relations and scopes |
48
+ | `PATCH` | `{shard}/customentity/{key}/template` | Partial edit — see [entity-template.md](./entity-template.md) |
49
+ | `POST` | `{shard}/customentity/{key}/updateentitytemplate` | Full replacement |
50
+
51
+ All field types work, files and images included. **Relation** fields (type `Relation`, 51) link a record to
52
+ another entity:
53
+
54
+ ```json
55
+ {
56
+ "key": "company",
57
+ "type": "Relation",
58
+ "labels": { "fr": "Exposant", "en": "Exhibitor" },
59
+ "relation": {
60
+ "target": "Exhibitor",
61
+ "cardinality": "ManyToOne",
62
+ "inverseKey": "jobOffers",
63
+ "inverseLabels": { "fr": "Offres d'emploi", "en": "Job offers" },
64
+ "isOwner": true
65
+ }
66
+ }
67
+ ```
68
+
69
+ - `target`: a native entity of the same container (`Person`, `Exhibitor`, `Session`, `Room`, `Member`…) or
70
+ `customentity.{key}`.
71
+ - `cardinality`: `ManyToOne`, `OneToOne`, `OneToMany` or `ManyToMany`.
72
+ - `inverseKey`: the field added on the target side (`exhibitor.jobOffers`). It is computed, returned only when
73
+ selected, and writing it relinks the records.
74
+ - `isOwner`: the target owns the record (at most one per entity, towards `Person`, `Member`, `Exhibitor`,
75
+ `Company` or an audience contact). The owner edits its records on the website when `frontAccess.write` allows it.
76
+
77
+ Field **scopes**: `public` (shown on the website), `own` (the owner sees it), `related`, `private` (back office only).
78
+
79
+ ## Records
80
+
81
+ `{shard}/customentity/{key}` — the generic entity routes: `query`, `count`, `aggregate`, create, `GET/POST {id}`,
82
+ `delete`, `massupdate`, `massdelete`, `export`, `history/query`, `history/removed/query|count`, `file`.
83
+
84
+ Technical fields: `id`, `externalId` (≤ 200 characters, unique per entity), `status` (`0` draft, `1` published —
85
+ meaningful when `frontAccess.publication` is on), `creationDate`, `validFrom`.
86
+
87
+ Relations are returned as `{ "id": "…" }` and loaded only when selected:
88
+
89
+ ```json
90
+ { "selects": { "$all": true, "company": { "$all": true } } }
91
+ ```
92
+
93
+ Filter on a to-one relation directly (`{ "owner": { "id": "…" } }`), on a to-many relation with `$any` / `$all` (see [query-language.md](./query-language.md)). Write a relation with `{ "id": "…" }`
94
+ (single) or `[{ "id": "…" }]` (many).
95
+
96
+ **Upsert by external id** — create or update in one call:
97
+
98
+ ```
99
+ POST {shard}/customentity/{key}/upsert
100
+ { "externalId": "OFFER-042", "entity": { "title": "Data engineer", "company": { "id": "…" } } }
101
+ ```
102
+
103
+ ## Website (front API, events only)
104
+
105
+ | Route | Role |
106
+ |---|---|
107
+ | `GET {eventId}/customentitydefinition` | Active definitions |
108
+ | `POST {eventId}/customentity/{key}/query`, `count`, `GET {id}` | Public fields; published records only when publication is on |
109
+ | `GET {eventId}/customentity/{key}/worktemplate` | Public template |
110
+ | `{eventId}/customentity/{key}/me/…` | The connected person's own records (`query`, create, update, delete, `worktemplate`) |
111
+ | `{eventId}/customentity/{key}/related/{relationKey}/…` | Records received through a relation (read only) |
112
+ | `GET …/me/{id}/file/{field}`, `GET …/related/{relationKey}/{id}/file/{field}` | Temporary link to a private file (own or received records only) |
113
+
114
+ `read: None` answers `404`; `Authenticated` answers `401` to visitors.
115
+
116
+ ---
117
+
118
+ *See also: [entities.md](./entities.md), [entity-template.md](./entity-template.md), [query.md](./query.md), [query-language.md](./query-language.md).*
119
+
120
+ The key and the fields of a custom entity are discovered with `inwink_mcp_get_entity_description` and the shardId (`customEntities.matches`).
@@ -11,6 +11,7 @@
11
11
  - **Customer Entity** — scoped to CustomerAPI. Always has a `customerId` property. The URL uses `{customerId}` as shardId.
12
12
  - **Auth Tenant Entity** — scoped to an **audience** (tenant) of a customer, on CustomerAPI. Its name starts with `authtenant` (`authtenantcommunity`, `authtenantcontact`, `authtenantcompany`, `authtenantmailtemplate`…). The URL takes two segments: `{customerId}/audience/{tenantId}` — see [README.md](./README.md#audience-scoped-entities-customerapi).
13
13
  - **Dynamic Entity** — can have custom properties added through the backoffice or the template API. Custom properties declared on the entity's own template (the one `inwink_mcp_get_entity_description` returns) behave exactly like native properties on every endpoint. Some fields are declared by a parent record instead: they resolve only on the routes scoped to that parent record, and fail elsewhere with `400 … property resolution error`, like an unknown name. To declare a custom property from the extension, see [entity-template.md](./entity-template.md).
14
+ - **Custom Entity** — an entity defined by the organizer (job offers, vehicles…), on events, communities, customers and audiences. Its records use the name `customentity/{key}` in the routes (`{shardId}/customentity/joboffer/query`) and its fields are in its own template. Users name it in their own words. See [custom-entities.md](./custom-entities.md).
14
15
  - **With Publication Status** — has a `status` property (string, case-insensitive): `Draft`, `Preview`, `Published`, `Canceled`, `Rejected`.
15
16
  - **With History** — modifications are tracked in a history table (see [history.md](./history.md)). Read-only properties: `validFrom` (start of validity of the current version = last modification date, UTC), `validTo` (end of validity; on the current table, an "infinity" sentinel value), `modifiedById` (UUID), `modifiedByDisplayName` (string).
16
17
 
@@ -28,6 +29,7 @@
28
29
  | Removed | `POST {api}/{shardId}/{entity}/history/removed/query` | Deleted entities (+ `/history/removed/count`) — see [history.md](./history.md) |
29
30
  | Massupdate | `POST {api}/{shardId}/{entity}/massupdate` | Bulk EDIT, like `UPDATE … WHERE` in SQL — see [update.md](./update.md) |
30
31
  | Massdelete | `POST {api}/{shardId}/{entity}/massdelete` | Bulk DELETE, like `DELETE … WHERE` in SQL — see [delete.md](./delete.md) |
32
+ | Upsert (custom entity) | `POST {api}/{shardId}/customentity/{key}/upsert` | Create or update a record by its `externalId` — see [custom-entities.md](./custom-entities.md) |
31
33
  | Export | | Returns entities as an Excel file |
32
34
  | File | | File upload — see [files.md](./files.md) |
33
35