@dropsh/plugin-canvas 0.0.2 → 0.1.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.
|
@@ -35,22 +35,27 @@ function slotSchema(knownSlots) {
|
|
|
35
35
|
: "No SDC slots were reported by jsonapi_sdc. Use null for root components.",
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
-
function componentItemVariant(component, knownSlots) {
|
|
38
|
+
function componentItemVariant(component, knownSlots, version) {
|
|
39
39
|
return {
|
|
40
40
|
type: "object",
|
|
41
41
|
additionalProperties: false,
|
|
42
42
|
properties: {
|
|
43
43
|
uuid: { type: "string", format: "uuid" },
|
|
44
44
|
component_id: { type: "string", const: toSdcComponentId(component.id) },
|
|
45
|
+
component_version: {
|
|
46
|
+
type: "string",
|
|
47
|
+
const: version,
|
|
48
|
+
description: "Active version hash of the Canvas component config entity.",
|
|
49
|
+
},
|
|
45
50
|
parent_uuid: { type: ["string", "null"], format: "uuid" },
|
|
46
51
|
slot: slotSchema(knownSlots),
|
|
47
52
|
inputs: inputSchema(component),
|
|
48
53
|
label: { type: ["string", "null"] },
|
|
49
54
|
},
|
|
50
|
-
required: ["uuid", "component_id", "inputs"],
|
|
55
|
+
required: ["uuid", "component_id", "component_version", "inputs"],
|
|
51
56
|
};
|
|
52
57
|
}
|
|
53
|
-
function componentMetadata(component) {
|
|
58
|
+
function componentMetadata(component, version) {
|
|
54
59
|
return {
|
|
55
60
|
id: toSdcComponentId(component.id),
|
|
56
61
|
source_id: component.id,
|
|
@@ -58,12 +63,13 @@ function componentMetadata(component) {
|
|
|
58
63
|
description: component.description,
|
|
59
64
|
provider: component.provider,
|
|
60
65
|
status: component.status,
|
|
66
|
+
version,
|
|
61
67
|
props: cloneValue(component.props),
|
|
62
68
|
slots: cloneValue(component.slots),
|
|
63
69
|
variants: cloneValue(component.variants),
|
|
64
70
|
};
|
|
65
71
|
}
|
|
66
|
-
export function extendCanvasSchema(baseSchema, operation, components) {
|
|
72
|
+
export function extendCanvasSchema(baseSchema, operation, components, versions) {
|
|
67
73
|
const schema = cloneSchema(baseSchema);
|
|
68
74
|
const data = ensureObjectProperty(schema, "data");
|
|
69
75
|
if (operation === "update") {
|
|
@@ -71,9 +77,13 @@ export function extendCanvasSchema(baseSchema, operation, components) {
|
|
|
71
77
|
}
|
|
72
78
|
const attributes = ensureObjectProperty(data, "attributes");
|
|
73
79
|
const knownSlots = slotNames(components);
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
const sortedComponents = [...components].sort((a, b) => toSdcComponentId(a.id).localeCompare(toSdcComponentId(b.id)));
|
|
81
|
+
// Only components with a Canvas `Component` config entity can be placed:
|
|
82
|
+
// the server validates component_id against that config and requires its
|
|
83
|
+
// active version hash on every tree item.
|
|
84
|
+
const componentItemVariants = sortedComponents
|
|
85
|
+
.filter((component) => versions.has(toSdcComponentId(component.id)))
|
|
86
|
+
.map((component) => componentItemVariant(component, knownSlots, versions.get(toSdcComponentId(component.id))));
|
|
77
87
|
attributes.properties.components = {
|
|
78
88
|
type: "array",
|
|
79
89
|
description: "Canvas component tree. Root components use parent_uuid=null and slot=null. Child components set parent_uuid to another component uuid and slot to one of the parent's slot names.",
|
|
@@ -82,6 +92,6 @@ export function extendCanvasSchema(baseSchema, operation, components) {
|
|
|
82
92
|
},
|
|
83
93
|
};
|
|
84
94
|
schema["x-dropsh-builder"] = "canvas";
|
|
85
|
-
schema["x-dropsh-components"] = components.map(componentMetadata);
|
|
95
|
+
schema["x-dropsh-components"] = components.map((component) => componentMetadata(component, versions.get(toSdcComponentId(component.id)) ?? null));
|
|
86
96
|
return schema;
|
|
87
97
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { HttpError } from "dropsh/plugin";
|
|
2
|
+
/**
|
|
3
|
+
* Fetches the Canvas `Component` config entities and returns a map of
|
|
4
|
+
* component config id (e.g. "sdc.olivero.teaser") to its active version
|
|
5
|
+
* hash. The server validates `component_version` on every component tree
|
|
6
|
+
* item against this hash, so payloads cannot be built without it.
|
|
7
|
+
*/
|
|
8
|
+
export async function fetchComponentVersions(ctx) {
|
|
9
|
+
const versions = new Map();
|
|
10
|
+
let url = `${ctx.baseUrl.replace(/\/+$/, "")}/jsonapi/component/component`;
|
|
11
|
+
while (url) {
|
|
12
|
+
const request = await ctx.auth.apply({
|
|
13
|
+
method: "GET",
|
|
14
|
+
url,
|
|
15
|
+
headers: { Accept: "application/vnd.api+json" },
|
|
16
|
+
});
|
|
17
|
+
let response;
|
|
18
|
+
try {
|
|
19
|
+
response = await ctx.http.send(request);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (error instanceof HttpError && error.status === 404) {
|
|
23
|
+
throw new HttpError(error.status, "Drupal module canvas is required to fetch component versions.", error.body);
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
let body;
|
|
28
|
+
try {
|
|
29
|
+
body = JSON.parse(response.body);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new HttpError(502, "Invalid JSON:API response from component endpoint.", response.body);
|
|
33
|
+
}
|
|
34
|
+
for (const resource of body.data ?? []) {
|
|
35
|
+
const id = resource.attributes?.drupal_internal__id;
|
|
36
|
+
const version = resource.attributes?.active_version;
|
|
37
|
+
if (typeof id === "string" && typeof version === "string" && version.length > 0) {
|
|
38
|
+
versions.set(id, version);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
url = body.links?.next?.href ?? null;
|
|
42
|
+
}
|
|
43
|
+
return versions;
|
|
44
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { fetchSdcComponents } from "@dropsh/sdc-client";
|
|
2
2
|
import { HttpError } from "dropsh/plugin";
|
|
3
3
|
import { extendCanvasSchema } from "./canvas-schema.js";
|
|
4
|
+
import { fetchComponentVersions } from "./component-versions.js";
|
|
4
5
|
export function canvasPlugin() {
|
|
5
6
|
return {
|
|
6
7
|
id: "canvas",
|
|
@@ -13,16 +14,20 @@ export function canvasPlugin() {
|
|
|
13
14
|
return schema;
|
|
14
15
|
}
|
|
15
16
|
let components;
|
|
17
|
+
let versions;
|
|
16
18
|
try {
|
|
17
|
-
components = await
|
|
19
|
+
[components, versions] = await Promise.all([
|
|
20
|
+
fetchSdcComponents(ctx),
|
|
21
|
+
fetchComponentVersions(ctx),
|
|
22
|
+
]);
|
|
18
23
|
}
|
|
19
24
|
catch (err) {
|
|
20
25
|
if (err instanceof HttpError && err.status === 404) {
|
|
21
|
-
throw new HttpError(404, "Canvas plugin requires Drupal
|
|
26
|
+
throw new HttpError(404, "Canvas plugin requires Drupal modules canvas and jsonapi_sdc to build component schemas.", err.body);
|
|
22
27
|
}
|
|
23
28
|
throw err;
|
|
24
29
|
}
|
|
25
|
-
return extendCanvasSchema(schema, operation, components);
|
|
30
|
+
return extendCanvasSchema(schema, operation, components, versions);
|
|
26
31
|
},
|
|
27
32
|
};
|
|
28
33
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dropsh/plugin-canvas",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/plugins/canvas/src/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"dropsh": "*"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@dropsh/sdc-client": "0.0
|
|
20
|
+
"@dropsh/sdc-client": "0.1.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"typescript": "^5.6.0",
|
|
24
24
|
"vitest": "^4.1.8",
|
|
25
|
-
"dropsh": "0.0
|
|
25
|
+
"dropsh": "0.1.0"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsc",
|