@50arms/plugin-sdk 0.2.56 → 0.2.59
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/dist/card-kit.d.ts +186 -132
- package/dist/cli.js +183 -44
- package/dist/publish.js +168 -41
- package/dist/vite.js +186 -58
- package/dist/widgets.js +5 -1
- package/package.json +2 -2
package/dist/vite.js
CHANGED
|
@@ -12,11 +12,18 @@ var PLUGIN_RUNTIME_SPECIFIERS = [
|
|
|
12
12
|
{ specifier: "react/jsx-runtime", library: "react" },
|
|
13
13
|
{ specifier: "react-dom", library: "react-dom" },
|
|
14
14
|
{ specifier: "@50arms/ui", library: "@50arms/ui" },
|
|
15
|
-
{
|
|
15
|
+
{
|
|
16
|
+
specifier: `${CARD_KIT_LIBRARY}@${CARD_KIT_MAJOR}`,
|
|
17
|
+
library: CARD_KIT_LIBRARY
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
var PLUGIN_RUNTIME_LEGACY_ALIASES = [
|
|
21
|
+
{ specifier: "@danxbot/ui", library: "@50arms/ui", major: 33 }
|
|
16
22
|
];
|
|
17
|
-
var PLUGIN_RUNTIME_LEGACY_ALIASES = [{ specifier: "@danxbot/ui", library: "@50arms/ui", major: 33 }];
|
|
18
23
|
var PLUGIN_NEVER_BUNDLED_PACKAGES = [
|
|
19
|
-
...PLUGIN_RUNTIME_LIBRARIES.map((library) => library.name).filter(
|
|
24
|
+
...PLUGIN_RUNTIME_LIBRARIES.map((library) => library.name).filter(
|
|
25
|
+
(name) => name !== CARD_KIT_LIBRARY
|
|
26
|
+
),
|
|
20
27
|
// A source still importing the old name, built with the current SDK, would bundle a second copy of the design system; the build refuses it.
|
|
21
28
|
...PLUGIN_RUNTIME_LEGACY_ALIASES.map((alias) => alias.specifier),
|
|
22
29
|
"scheduler",
|
|
@@ -25,7 +32,9 @@ var PLUGIN_NEVER_BUNDLED_PACKAGES = [
|
|
|
25
32
|
function pluginRuntimeContract() {
|
|
26
33
|
return {
|
|
27
34
|
specifiers: PLUGIN_RUNTIME_SPECIFIERS.map((entry) => entry.specifier),
|
|
28
|
-
majors: Object.fromEntries(
|
|
35
|
+
majors: Object.fromEntries(
|
|
36
|
+
PLUGIN_RUNTIME_LIBRARIES.map((library) => [library.name, library.major])
|
|
37
|
+
)
|
|
29
38
|
};
|
|
30
39
|
}
|
|
31
40
|
|
|
@@ -39,11 +48,16 @@ var PLUGIN_KEY_PATTERN = "^[a-z0-9][a-z0-9_-]{0,63}$";
|
|
|
39
48
|
var PLUGIN_MANIFEST_FILE = "danx-plugin.json";
|
|
40
49
|
var CARD_VIEW_EXPORT = "CardView";
|
|
41
50
|
var CARD_LIST_VIEW_EXPORT = "CardListView";
|
|
42
|
-
var PLUGIN_VIEW_EXPORTS = [
|
|
51
|
+
var PLUGIN_VIEW_EXPORTS = [
|
|
52
|
+
CARD_VIEW_EXPORT,
|
|
53
|
+
CARD_LIST_VIEW_EXPORT
|
|
54
|
+
];
|
|
43
55
|
|
|
44
56
|
// src/manifest.ts
|
|
45
57
|
function filesUnder(root, dir = root) {
|
|
46
|
-
return readdirSync(dir, { withFileTypes: true }).flatMap(
|
|
58
|
+
return readdirSync(dir, { withFileTypes: true }).flatMap(
|
|
59
|
+
(entry) => entry.isDirectory() ? filesUnder(root, join(dir, entry.name)) : [join(dir, entry.name)]
|
|
60
|
+
).sort();
|
|
47
61
|
}
|
|
48
62
|
function describeFile(root, file) {
|
|
49
63
|
const bytes = readFileSync(file);
|
|
@@ -55,7 +69,10 @@ function describeFile(root, file) {
|
|
|
55
69
|
}
|
|
56
70
|
function buildManifest(outDir, entry, exports, cardTypes, widgets) {
|
|
57
71
|
const files = filesUnder(outDir).map((file) => describeFile(outDir, file)).filter((file) => file.path !== PLUGIN_MANIFEST_FILE);
|
|
58
|
-
if (!files.some((file) => file.path === entry))
|
|
72
|
+
if (!files.some((file) => file.path === entry))
|
|
73
|
+
throw new Error(
|
|
74
|
+
`danx-plugin: the build produced no entry module ${entry} in ${outDir}`
|
|
75
|
+
);
|
|
59
76
|
return {
|
|
60
77
|
entry,
|
|
61
78
|
styles: files.filter((file) => file.path.endsWith(".css")).map((file) => file.path),
|
|
@@ -69,36 +86,53 @@ function buildManifest(outDir, entry, exports, cardTypes, widgets) {
|
|
|
69
86
|
}
|
|
70
87
|
function writeManifest(outDir, entry, exports, cardTypes, widgets) {
|
|
71
88
|
const manifest = buildManifest(outDir, entry, exports, cardTypes, widgets);
|
|
72
|
-
writeFileSync(
|
|
73
|
-
|
|
89
|
+
writeFileSync(
|
|
90
|
+
join(outDir, PLUGIN_MANIFEST_FILE),
|
|
91
|
+
`${JSON.stringify(manifest, null, 2)}
|
|
92
|
+
`
|
|
93
|
+
);
|
|
74
94
|
return manifest;
|
|
75
95
|
}
|
|
76
96
|
|
|
77
97
|
// ../../src/widget-surfaces/model.ts
|
|
78
98
|
var GRID_COLUMNS = 24;
|
|
79
|
-
var DATE_RANGE_MS = {
|
|
80
|
-
|
|
99
|
+
var DATE_RANGE_MS = {
|
|
100
|
+
"24h": 864e5,
|
|
101
|
+
"7d": 7 * 864e5,
|
|
102
|
+
"30d": 30 * 864e5
|
|
103
|
+
};
|
|
104
|
+
var SURFACE_WIDE_SETTING_KEYS = [
|
|
105
|
+
"date_range",
|
|
106
|
+
"keyword"
|
|
107
|
+
];
|
|
81
108
|
|
|
82
109
|
// ../../src/widget-surfaces/value-schema.ts
|
|
83
110
|
function fieldIssue(field, schema, value) {
|
|
84
111
|
switch (schema.type) {
|
|
85
112
|
case "string":
|
|
86
113
|
if (typeof value !== "string") return { field, rule: "notText" };
|
|
87
|
-
if (schema.maxLength !== void 0 && value.length > schema.maxLength)
|
|
88
|
-
|
|
114
|
+
if (schema.maxLength !== void 0 && value.length > schema.maxLength)
|
|
115
|
+
return { field, rule: "tooLong", limit: schema.maxLength };
|
|
116
|
+
if (schema.enum !== void 0 && !schema.enum.includes(value))
|
|
117
|
+
return { field, rule: "notOneOf", options: schema.enum };
|
|
89
118
|
return null;
|
|
90
119
|
case "number":
|
|
91
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
92
|
-
|
|
93
|
-
if (schema.
|
|
94
|
-
|
|
120
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
121
|
+
return { field, rule: "notNumber" };
|
|
122
|
+
if (schema.integer === true && !Number.isInteger(value))
|
|
123
|
+
return { field, rule: "notWhole" };
|
|
124
|
+
if (schema.min !== void 0 && value < schema.min)
|
|
125
|
+
return { field, rule: "tooSmall", limit: schema.min };
|
|
126
|
+
if (schema.max !== void 0 && value > schema.max)
|
|
127
|
+
return { field, rule: "tooLarge", limit: schema.max };
|
|
95
128
|
return null;
|
|
96
129
|
case "boolean":
|
|
97
130
|
return typeof value === "boolean" ? null : { field, rule: "notBoolean" };
|
|
98
131
|
}
|
|
99
132
|
}
|
|
100
133
|
function valueIssues(schema, values) {
|
|
101
|
-
if (typeof values !== "object" || values === null || Array.isArray(values))
|
|
134
|
+
if (typeof values !== "object" || values === null || Array.isArray(values))
|
|
135
|
+
return [{ field: "", rule: "notObject" }];
|
|
102
136
|
const issues = [];
|
|
103
137
|
for (const [name, value] of Object.entries(values)) {
|
|
104
138
|
const field = schema[name];
|
|
@@ -118,16 +152,30 @@ function labelIssues(schema) {
|
|
|
118
152
|
if (field.type !== "string") continue;
|
|
119
153
|
const options = field.enum ?? [];
|
|
120
154
|
const labelled = Object.keys(field.optionLabels ?? {});
|
|
121
|
-
if (field.enum !== void 0 && field.optionLabels === void 0)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
for (const
|
|
155
|
+
if (field.enum !== void 0 && field.optionLabels === void 0)
|
|
156
|
+
issues.push(`field "${name}" offers options and labels none of them`);
|
|
157
|
+
if (field.enum === void 0 && field.optionLabels !== void 0)
|
|
158
|
+
issues.push(`field "${name}" labels options it does not offer`);
|
|
159
|
+
for (const option of options)
|
|
160
|
+
if (!labelled.includes(option))
|
|
161
|
+
issues.push(`field "${name}" has no label for option "${option}"`);
|
|
162
|
+
for (const option of labelled)
|
|
163
|
+
if (!options.includes(option) && field.enum !== void 0)
|
|
164
|
+
issues.push(
|
|
165
|
+
`field "${name}" labels "${option}", which is not one of its options`
|
|
166
|
+
);
|
|
167
|
+
for (const [option, text] of Object.entries(field.optionLabels ?? {}))
|
|
168
|
+
if (blank(text))
|
|
169
|
+
issues.push(
|
|
170
|
+
`field "${name}" has an empty label for option "${option}"`
|
|
171
|
+
);
|
|
126
172
|
}
|
|
127
173
|
return issues;
|
|
128
174
|
}
|
|
129
175
|
function defaultsOf(schema) {
|
|
130
|
-
return Object.fromEntries(
|
|
176
|
+
return Object.fromEntries(
|
|
177
|
+
Object.entries(schema).map(([name, field]) => [name, field.default])
|
|
178
|
+
);
|
|
131
179
|
}
|
|
132
180
|
|
|
133
181
|
// ../../src/widget-surfaces/declaration.ts
|
|
@@ -141,19 +189,32 @@ function pluginWidgetKey(pluginKey, widgetKey) {
|
|
|
141
189
|
function declarationBodyIssues(def) {
|
|
142
190
|
const issues = [];
|
|
143
191
|
const { min, max, default: initial } = def.size;
|
|
144
|
-
for (const [label, size] of [
|
|
145
|
-
|
|
146
|
-
|
|
192
|
+
for (const [label, size] of [
|
|
193
|
+
["min", min],
|
|
194
|
+
["default", initial],
|
|
195
|
+
["max", max]
|
|
196
|
+
]) {
|
|
197
|
+
if (!Number.isInteger(size.w) || !Number.isInteger(size.h) || size.w < 1 || size.h < 1)
|
|
198
|
+
issues.push(`${label} size ${size.w}x${size.h} is not whole cells`);
|
|
199
|
+
if (size.w > GRID_COLUMNS)
|
|
200
|
+
issues.push(
|
|
201
|
+
`${label} width ${size.w} is wider than the ${GRID_COLUMNS}-column grid`
|
|
202
|
+
);
|
|
147
203
|
}
|
|
148
|
-
if (initial.w < min.w || initial.h < min.h || initial.w > max.w || initial.h > max.h)
|
|
204
|
+
if (initial.w < min.w || initial.h < min.h || initial.w > max.w || initial.h > max.h)
|
|
205
|
+
issues.push("the default size is outside the min and max sizes");
|
|
149
206
|
for (const scope of ["config", "settings"]) {
|
|
150
|
-
for (const issue of valueIssues(def[scope], defaultsOf(def[scope])))
|
|
151
|
-
|
|
207
|
+
for (const issue of valueIssues(def[scope], defaultsOf(def[scope])))
|
|
208
|
+
issues.push(`${scope} default: ${JSON.stringify(issue)}`);
|
|
209
|
+
for (const issue of labelIssues(def[scope]))
|
|
210
|
+
issues.push(`${scope}: ${issue}`);
|
|
152
211
|
}
|
|
153
212
|
for (const key of def.readsSurfaceSettings) {
|
|
154
|
-
if (!SURFACE_WIDE_SETTING_KEYS.includes(key))
|
|
213
|
+
if (!SURFACE_WIDE_SETTING_KEYS.includes(key))
|
|
214
|
+
issues.push(`"${key}" is not a surface-wide setting`);
|
|
155
215
|
}
|
|
156
|
-
if (new Set(def.readsSurfaceSettings).size !== def.readsSurfaceSettings.length)
|
|
216
|
+
if (new Set(def.readsSurfaceSettings).size !== def.readsSurfaceSettings.length)
|
|
217
|
+
issues.push("readsSurfaceSettings names a setting twice");
|
|
157
218
|
return issues;
|
|
158
219
|
}
|
|
159
220
|
|
|
@@ -163,7 +224,9 @@ var MAX_WIDGET_TITLE_LENGTH = 80;
|
|
|
163
224
|
var MAX_WIDGET_DESCRIPTION_LENGTH = 300;
|
|
164
225
|
var MAX_PLUGIN_WIDGETS = 32;
|
|
165
226
|
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
166
|
-
var keysAre = (value, required, optional = []) => required.every((key) => key in value) && Object.keys(value).every(
|
|
227
|
+
var keysAre = (value, required, optional = []) => required.every((key) => key in value) && Object.keys(value).every(
|
|
228
|
+
(key) => required.includes(key) || optional.includes(key)
|
|
229
|
+
);
|
|
167
230
|
var isStringArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
168
231
|
var isFieldText = (value) => isObject(value) && (keysAre(value, ["messageId"]) && typeof value.messageId === "string" || keysAre(value, ["text"]) && typeof value.text === "string");
|
|
169
232
|
var isSize = (value) => isObject(value) && keysAre(value, ["w", "h"]) && typeof value.w === "number" && typeof value.h === "number";
|
|
@@ -172,9 +235,17 @@ function fieldShapeIsValid(field) {
|
|
|
172
235
|
if (!isObject(field) || !isFieldText(field.label)) return false;
|
|
173
236
|
switch (field.type) {
|
|
174
237
|
case "string":
|
|
175
|
-
return keysAre(
|
|
238
|
+
return keysAre(
|
|
239
|
+
field,
|
|
240
|
+
["type", "label", "default"],
|
|
241
|
+
["maxLength", "enum", "optionLabels"]
|
|
242
|
+
) && typeof field.default === "string" && isOptionalNumber(field.maxLength) && (field.enum === void 0 || isStringArray(field.enum)) && (field.optionLabels === void 0 || isObject(field.optionLabels) && Object.values(field.optionLabels).every(isFieldText));
|
|
176
243
|
case "number":
|
|
177
|
-
return keysAre(
|
|
244
|
+
return keysAre(
|
|
245
|
+
field,
|
|
246
|
+
["type", "label", "default"],
|
|
247
|
+
["min", "max", "integer"]
|
|
248
|
+
) && typeof field.default === "number" && isOptionalNumber(field.min) && isOptionalNumber(field.max) && (field.integer === void 0 || typeof field.integer === "boolean");
|
|
178
249
|
case "boolean":
|
|
179
250
|
return keysAre(field, ["type", "label", "default"]) && typeof field.default === "boolean";
|
|
180
251
|
default:
|
|
@@ -182,41 +253,67 @@ function fieldShapeIsValid(field) {
|
|
|
182
253
|
}
|
|
183
254
|
}
|
|
184
255
|
function declarationShapeIssues(value) {
|
|
185
|
-
if (!isObject(value) || !keysAre(value, [
|
|
186
|
-
|
|
256
|
+
if (!isObject(value) || !keysAre(value, [
|
|
257
|
+
"key",
|
|
258
|
+
"size",
|
|
259
|
+
"config",
|
|
260
|
+
"settings",
|
|
261
|
+
"readsSurfaceSettings",
|
|
262
|
+
"needsHostContext"
|
|
263
|
+
])) {
|
|
264
|
+
return [
|
|
265
|
+
"the declaration must hold exactly key, size, config, settings, readsSurfaceSettings and needsHostContext"
|
|
266
|
+
];
|
|
187
267
|
}
|
|
188
268
|
const issues = [];
|
|
189
269
|
if (typeof value.key !== "string") issues.push("the key must be text");
|
|
190
|
-
if (!isObject(value.size) || !keysAre(value.size, ["default", "min", "max"]) || ![value.size.default, value.size.min, value.size.max].every(isSize))
|
|
270
|
+
if (!isObject(value.size) || !keysAre(value.size, ["default", "min", "max"]) || ![value.size.default, value.size.min, value.size.max].every(isSize))
|
|
271
|
+
issues.push("size must hold default, min and max, each {w, h} in cells");
|
|
191
272
|
for (const scope of ["config", "settings"]) {
|
|
192
273
|
const schema = value[scope];
|
|
193
274
|
if (!isObject(schema)) issues.push(`${scope} must be an object of fields`);
|
|
194
|
-
else
|
|
275
|
+
else
|
|
276
|
+
for (const [name, field] of Object.entries(schema))
|
|
277
|
+
if (!fieldShapeIsValid(field))
|
|
278
|
+
issues.push(
|
|
279
|
+
`${scope} field "${name}" is not a string, number or boolean field with a label and a default`
|
|
280
|
+
);
|
|
195
281
|
}
|
|
196
|
-
if (!isStringArray(value.readsSurfaceSettings))
|
|
197
|
-
|
|
282
|
+
if (!isStringArray(value.readsSurfaceSettings))
|
|
283
|
+
issues.push("readsSurfaceSettings must be a list of setting names");
|
|
284
|
+
if (!isStringArray(value.needsHostContext))
|
|
285
|
+
issues.push("needsHostContext must be a list of host context keys");
|
|
198
286
|
return issues;
|
|
199
287
|
}
|
|
200
288
|
function manifestWidgetIssues(widgets, pluginKey) {
|
|
201
289
|
if (!Array.isArray(widgets)) return ["widgets must be a list"];
|
|
202
|
-
if (widgets.length > MAX_PLUGIN_WIDGETS)
|
|
290
|
+
if (widgets.length > MAX_PLUGIN_WIDGETS)
|
|
291
|
+
return [`a plugin declares at most ${MAX_PLUGIN_WIDGETS} Widgets`];
|
|
203
292
|
const issues = [];
|
|
204
293
|
const exports = /* @__PURE__ */ new Set();
|
|
205
294
|
const keys = /* @__PURE__ */ new Set();
|
|
206
295
|
widgets.forEach((widget, index) => {
|
|
207
296
|
if (!isObject(widget) || !keysAre(widget, ["export", "title", "description", "declaration"])) {
|
|
208
|
-
issues.push(
|
|
297
|
+
issues.push(
|
|
298
|
+
`widget ${index + 1}: must hold exactly export, title, description and declaration`
|
|
299
|
+
);
|
|
209
300
|
return;
|
|
210
301
|
}
|
|
211
302
|
const name = typeof widget.export === "string" ? widget.export : `widget ${index + 1}`;
|
|
212
303
|
const say = (issue) => issues.push(`${name}: ${issue}`);
|
|
213
304
|
if (typeof widget.export !== "string" || !EXPORT_SHAPE.test(widget.export) || PLUGIN_VIEW_EXPORTS.includes(widget.export)) {
|
|
214
|
-
say(
|
|
305
|
+
say(
|
|
306
|
+
`the export must be a component name (a capital letter, then letters and digits), and not ${PLUGIN_VIEW_EXPORTS.join(" or ")}`
|
|
307
|
+
);
|
|
215
308
|
} else if (exports.has(widget.export)) say("two Widgets name this export");
|
|
216
309
|
else exports.add(widget.export);
|
|
217
|
-
for (const [field, max] of [
|
|
310
|
+
for (const [field, max] of [
|
|
311
|
+
["title", MAX_WIDGET_TITLE_LENGTH],
|
|
312
|
+
["description", MAX_WIDGET_DESCRIPTION_LENGTH]
|
|
313
|
+
]) {
|
|
218
314
|
const text = widget[field];
|
|
219
|
-
if (typeof text !== "string" || text.trim() === "" || text.length > max)
|
|
315
|
+
if (typeof text !== "string" || text.trim() === "" || text.length > max)
|
|
316
|
+
say(`the ${field} must be text of 1 to ${max} characters`);
|
|
220
317
|
}
|
|
221
318
|
const shape = declarationShapeIssues(widget.declaration);
|
|
222
319
|
if (shape.length > 0) {
|
|
@@ -224,10 +321,15 @@ function manifestWidgetIssues(widgets, pluginKey) {
|
|
|
224
321
|
return;
|
|
225
322
|
}
|
|
226
323
|
const declaration = widget.declaration;
|
|
227
|
-
if (!WIDGET_KEY_SHAPE.test(declaration.key))
|
|
228
|
-
|
|
324
|
+
if (!WIDGET_KEY_SHAPE.test(declaration.key))
|
|
325
|
+
say(`the key "${declaration.key}" is not lowercase words joined by "-"`);
|
|
326
|
+
else if (keys.has(declaration.key))
|
|
327
|
+
say(`two Widgets have the key "${declaration.key}"`);
|
|
229
328
|
else keys.add(declaration.key);
|
|
230
|
-
if (pluginKey !== null && pluginWidgetKey(pluginKey, declaration.key).length > WIDGET_KEY_MAX_LENGTH)
|
|
329
|
+
if (pluginKey !== null && pluginWidgetKey(pluginKey, declaration.key).length > WIDGET_KEY_MAX_LENGTH)
|
|
330
|
+
say(
|
|
331
|
+
`its stored key ${pluginWidgetKey(pluginKey, declaration.key)} is longer than ${WIDGET_KEY_MAX_LENGTH} characters`
|
|
332
|
+
);
|
|
231
333
|
for (const issue of declarationBodyIssues(declaration)) say(issue);
|
|
232
334
|
});
|
|
233
335
|
return issues;
|
|
@@ -238,7 +340,9 @@ var PLUGIN_ENTRY_FILE = "index.js";
|
|
|
238
340
|
var STYLESHEET_FILE = "index.css";
|
|
239
341
|
function bundledNeverPackage(moduleId) {
|
|
240
342
|
const normalised = moduleId.replaceAll("\\", "/");
|
|
241
|
-
return PLUGIN_NEVER_BUNDLED_PACKAGES.find(
|
|
343
|
+
return PLUGIN_NEVER_BUNDLED_PACKAGES.find(
|
|
344
|
+
(name) => normalised.includes(`/node_modules/${name}/`)
|
|
345
|
+
);
|
|
242
346
|
}
|
|
243
347
|
function danxPlugin(options = {}) {
|
|
244
348
|
const entry = options.entry ?? "src/index.tsx";
|
|
@@ -258,7 +362,9 @@ function danxPlugin(options = {}) {
|
|
|
258
362
|
cssCodeSplit: false,
|
|
259
363
|
lib: { entry, formats: ["es"], fileName: () => PLUGIN_ENTRY_FILE },
|
|
260
364
|
rollupOptions: {
|
|
261
|
-
external: PLUGIN_RUNTIME_SPECIFIERS.map(
|
|
365
|
+
external: PLUGIN_RUNTIME_SPECIFIERS.map(
|
|
366
|
+
(shared) => shared.specifier
|
|
367
|
+
),
|
|
262
368
|
output: {
|
|
263
369
|
chunkFileNames: "chunks/[name]-[hash].js",
|
|
264
370
|
assetFileNames: (asset) => asset.names.some((name) => name.endsWith(".css")) ? STYLESHEET_FILE : "assets/[name]-[hash][extname]"
|
|
@@ -268,18 +374,31 @@ function danxPlugin(options = {}) {
|
|
|
268
374
|
};
|
|
269
375
|
},
|
|
270
376
|
generateBundle(_options, bundle) {
|
|
271
|
-
const entryChunk = Object.values(bundle).find(
|
|
272
|
-
|
|
273
|
-
|
|
377
|
+
const entryChunk = Object.values(bundle).find(
|
|
378
|
+
(output) => output.type === "chunk" && output.isEntry
|
|
379
|
+
);
|
|
380
|
+
if (entryChunk?.type !== "chunk")
|
|
381
|
+
throw new Error(
|
|
382
|
+
`danx-plugin: the build produced no entry chunk for ${entry}`
|
|
383
|
+
);
|
|
384
|
+
viewExports = PLUGIN_VIEW_EXPORTS.filter(
|
|
385
|
+
(name) => entryChunk.exports.includes(name)
|
|
386
|
+
);
|
|
274
387
|
if (viewExports.length === 0 && widgets.length === 0) {
|
|
275
388
|
throw new Error(
|
|
276
389
|
`danx-plugin: ${entry} must export ${PLUGIN_VIEW_EXPORTS.join(" and/or ")}, or the plugin must declare Widgets, but it exports ${entryChunk.exports.length === 0 ? "nothing" : entryChunk.exports.join(", ")}.`
|
|
277
390
|
);
|
|
278
391
|
}
|
|
279
392
|
const issues = manifestWidgetIssues(widgets, null);
|
|
280
|
-
if (issues.length > 0)
|
|
393
|
+
if (issues.length > 0)
|
|
394
|
+
throw new Error(
|
|
395
|
+
`danx-plugin: the plugin's Widgets cannot be used: ${issues.join("; ")}`
|
|
396
|
+
);
|
|
281
397
|
const missing = widgets.filter((widget) => !entryChunk.exports.includes(widget.export)).map((widget) => widget.export);
|
|
282
|
-
if (missing.length > 0)
|
|
398
|
+
if (missing.length > 0)
|
|
399
|
+
throw new Error(
|
|
400
|
+
`danx-plugin: ${entry} does not export ${missing.join(", ")}, which the plugin's Widgets name as their components.`
|
|
401
|
+
);
|
|
283
402
|
for (const output of Object.values(bundle)) {
|
|
284
403
|
if (output.type !== "chunk") continue;
|
|
285
404
|
for (const id of output.moduleIds) {
|
|
@@ -292,8 +411,17 @@ function danxPlugin(options = {}) {
|
|
|
292
411
|
}
|
|
293
412
|
},
|
|
294
413
|
writeBundle(output) {
|
|
295
|
-
if (output.dir === void 0)
|
|
296
|
-
|
|
414
|
+
if (output.dir === void 0)
|
|
415
|
+
throw new Error(
|
|
416
|
+
"danx-plugin: the build has no output directory to write the manifest into"
|
|
417
|
+
);
|
|
418
|
+
writeManifest(
|
|
419
|
+
output.dir,
|
|
420
|
+
PLUGIN_ENTRY_FILE,
|
|
421
|
+
viewExports,
|
|
422
|
+
options.cardTypes ?? [],
|
|
423
|
+
widgets
|
|
424
|
+
);
|
|
297
425
|
}
|
|
298
426
|
};
|
|
299
427
|
}
|
package/dist/widgets.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// ../../src/widget-surfaces/model.ts
|
|
2
|
-
var DATE_RANGE_MS = {
|
|
2
|
+
var DATE_RANGE_MS = {
|
|
3
|
+
"24h": 864e5,
|
|
4
|
+
"7d": 7 * 864e5,
|
|
5
|
+
"30d": 30 * 864e5
|
|
6
|
+
};
|
|
3
7
|
|
|
4
8
|
// ../../src/plugins/plugin-manifest.ts
|
|
5
9
|
var PLUGIN_KEY_PATTERN = "^[a-z0-9][a-z0-9_-]{0,63}$";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@50arms/plugin-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.59",
|
|
4
4
|
"description": "SDK for building 50 Arms plugins (DX-5170): the card kit's type declarations, the Widget declaration kit, a Vite preset that builds a plugin against the app's shared runtime and writes its manifest, and the danx-plugin CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"test": "vitest run"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@50arms/ui": "36.
|
|
53
|
+
"@50arms/ui": "36.4.2",
|
|
54
54
|
"@types/node": "^22.0.0",
|
|
55
55
|
"@types/react": "^19.2.2",
|
|
56
56
|
"esbuild": "^0.25.0",
|