@kizenapps/packager 0.3.0 → 0.4.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.
- package/dist/index.cjs +785 -360
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -79
- package/dist/index.d.ts +116 -79
- package/dist/index.js +778 -360
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
API_NAME_PATTERN: () => API_NAME_PATTERN,
|
|
33
34
|
AUTOMATION_SCRIPT_FILE: () => AUTOMATION_SCRIPT_FILE,
|
|
34
35
|
AUTOMATION_STEPS_DIRECTORY_NAME: () => AUTOMATION_STEPS_DIRECTORY_NAME,
|
|
35
36
|
BLOCKS_DIRECTORY_NAME: () => BLOCKS_DIRECTORY_NAME,
|
|
@@ -40,6 +41,8 @@ __export(index_exports, {
|
|
|
40
41
|
CRYPTO_ALG: () => CRYPTO_ALG,
|
|
41
42
|
CRYPTO_VERSION: () => CRYPTO_VERSION,
|
|
42
43
|
DATA_ADORNMENTS_DIRECTORY_NAME: () => DATA_ADORNMENTS_DIRECTORY_NAME,
|
|
44
|
+
ENVIRONMENTS: () => ENVIRONMENTS,
|
|
45
|
+
ENVIRONMENT_ALIASES: () => ENVIRONMENT_ALIASES,
|
|
43
46
|
EVENT_SCRIPTS_DIRECTORY_NAME: () => EVENT_SCRIPTS_DIRECTORY_NAME,
|
|
44
47
|
FLOATING_FRAMES_DIRECTORY_NAME: () => FLOATING_FRAMES_DIRECTORY_NAME,
|
|
45
48
|
JS_ACTIONS_DIRECTORY_NAME: () => JS_ACTIONS_DIRECTORY_NAME,
|
|
@@ -48,6 +51,8 @@ __export(index_exports, {
|
|
|
48
51
|
MANIFEST_FILE_NAME: () => MANIFEST_FILE_NAME,
|
|
49
52
|
MESSAGE_SCRIPT_FILE: () => MESSAGE_SCRIPT_FILE,
|
|
50
53
|
OBJECT_SETTINGS_ITEMS_DIRECTORY_NAME: () => OBJECT_SETTINGS_ITEMS_DIRECTORY_NAME,
|
|
54
|
+
PUBLISHABLE_ENVIRONMENTS: () => PUBLISHABLE_ENVIRONMENTS,
|
|
55
|
+
PluginValidationError: () => PluginValidationError,
|
|
51
56
|
RELEASE_NOTES_EXTENSION: () => RELEASE_NOTES_EXTENSION,
|
|
52
57
|
ROUTABLE_PAGES_DIRECTORY_NAME: () => ROUTABLE_PAGES_DIRECTORY_NAME,
|
|
53
58
|
SCRIPT_EXTENSION: () => SCRIPT_EXTENSION,
|
|
@@ -59,6 +64,7 @@ __export(index_exports, {
|
|
|
59
64
|
decrypt: () => decrypt,
|
|
60
65
|
deserializeEnvelope: () => deserializeEnvelope,
|
|
61
66
|
encrypt: () => encrypt,
|
|
67
|
+
errorIssue: () => errorIssue,
|
|
62
68
|
generateKeypair: () => generateKeypair,
|
|
63
69
|
getAdornmentIcon: () => getAdornmentIcon,
|
|
64
70
|
getMinimizedConfig: () => getMinimizedConfig,
|
|
@@ -74,6 +80,7 @@ __export(index_exports, {
|
|
|
74
80
|
thumbnailImageExtensions: () => thumbnailImageExtensions,
|
|
75
81
|
transformDeployablePlugin: () => transformDeployablePlugin,
|
|
76
82
|
triggerImageExtensions: () => triggerImageExtensions,
|
|
83
|
+
validatePluginApp: () => validatePluginApp,
|
|
77
84
|
zipToUint8Array: () => zipToUint8Array
|
|
78
85
|
});
|
|
79
86
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -111,26 +118,54 @@ var minifyFiles = async (files) => {
|
|
|
111
118
|
|
|
112
119
|
// src/lib/apiNames.ts
|
|
113
120
|
var sanitizeToAPIName = (name) => {
|
|
114
|
-
return name.toLowerCase().replace(/[
|
|
121
|
+
return name.toLowerCase().replace(/[-\s]+/g, "_").replace(/[^a-z0-9_]/g, "");
|
|
115
122
|
};
|
|
123
|
+
var resolveApiName = (explicit, directoryName) => typeof explicit === "string" && explicit !== "" ? explicit : sanitizeToAPIName(directoryName);
|
|
116
124
|
var scriptRuntimeToApiName = (runtime) => {
|
|
117
125
|
const result = runtime.replace(/\s+/g, "-").replace(/\./g, "-");
|
|
118
126
|
return result;
|
|
119
127
|
};
|
|
120
128
|
|
|
121
|
-
// src/lib/
|
|
122
|
-
var
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
// src/lib/issues.ts
|
|
130
|
+
var errorIssue = (rule, message, path, pluginApiName) => ({
|
|
131
|
+
rule,
|
|
132
|
+
severity: "error",
|
|
133
|
+
message,
|
|
134
|
+
...path !== void 0 && { path },
|
|
135
|
+
...pluginApiName !== void 0 && { pluginApiName }
|
|
136
|
+
});
|
|
137
|
+
var warningIssue = (rule, message, path, pluginApiName) => ({
|
|
138
|
+
rule,
|
|
139
|
+
severity: "warning",
|
|
140
|
+
message,
|
|
141
|
+
...path !== void 0 && { path },
|
|
142
|
+
...pluginApiName !== void 0 && { pluginApiName }
|
|
143
|
+
});
|
|
144
|
+
var PluginValidationError = class extends Error {
|
|
145
|
+
issues;
|
|
146
|
+
constructor(issues) {
|
|
147
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
148
|
+
const details = errors.map((i) => `${i.path ? `${i.path}: ` : ""}${i.message}`).join("\n");
|
|
149
|
+
super(`Plugin app validation failed with ${String(errors.length)} error(s):
|
|
150
|
+
${details}`);
|
|
151
|
+
this.name = "PluginValidationError";
|
|
152
|
+
this.issues = issues;
|
|
127
153
|
}
|
|
128
|
-
return new Uint8Array(byteNumbers);
|
|
129
|
-
};
|
|
130
|
-
var zipToUint8Array = (zip) => {
|
|
131
|
-
return Uint8Array.from(zip);
|
|
132
154
|
};
|
|
133
155
|
|
|
156
|
+
// src/types/manifest.ts
|
|
157
|
+
var PUBLISHABLE_ENVIRONMENTS = [
|
|
158
|
+
"go",
|
|
159
|
+
"fmo",
|
|
160
|
+
"staging",
|
|
161
|
+
"integration",
|
|
162
|
+
"e2e-integration",
|
|
163
|
+
"e2e-staging",
|
|
164
|
+
"test1"
|
|
165
|
+
];
|
|
166
|
+
var ENVIRONMENT_ALIASES = ["prod", "dev", "testing"];
|
|
167
|
+
var ENVIRONMENTS = [...PUBLISHABLE_ENVIRONMENTS, ...ENVIRONMENT_ALIASES];
|
|
168
|
+
|
|
134
169
|
// src/lib/structure.ts
|
|
135
170
|
var thumbnailImageExtensions = ["png"];
|
|
136
171
|
var triggerImageExtensions = [...thumbnailImageExtensions, "svg"];
|
|
@@ -148,9 +183,7 @@ var USER_SETUP_ASSISTANT_DIRECTORY_NAME = "userSetupAssistant";
|
|
|
148
183
|
var CALENDAR_SOURCES_DIRECTORY_NAME = "calendarSources";
|
|
149
184
|
var VIEWS_DIRECTORY_NAME = "views";
|
|
150
185
|
var BLOCKS_DIRECTORY_NAME = "blocks";
|
|
151
|
-
var THUMBNAIL_FILE_NAMES = thumbnailImageExtensions.map(
|
|
152
|
-
(ext) => `thumbnail.${ext}`
|
|
153
|
-
);
|
|
186
|
+
var THUMBNAIL_FILE_NAMES = thumbnailImageExtensions.map((ext) => `thumbnail.${ext}`);
|
|
154
187
|
var RELEASE_NOTES_EXTENSION = "md";
|
|
155
188
|
var SCRIPT_EXTENSION = "js";
|
|
156
189
|
var MAIN_SCRIPT_FILE = `script.${SCRIPT_EXTENSION}`;
|
|
@@ -162,49 +195,70 @@ var CONFIG_FILE_NAME = "config.json";
|
|
|
162
195
|
var STYLES_FILE_NAME = "styles.css";
|
|
163
196
|
var MANIFEST_FILE_NAME = "kizen.json";
|
|
164
197
|
var KZN_FILE_NAME = "import.kzn";
|
|
165
|
-
var
|
|
198
|
+
var tryParseConfig = (content, path, pluginApiName) => {
|
|
166
199
|
if (!content) {
|
|
167
|
-
|
|
200
|
+
return {
|
|
201
|
+
issue: errorIssue(
|
|
202
|
+
"structure/config-content",
|
|
203
|
+
`No content provided for config file: ${path}`,
|
|
204
|
+
path,
|
|
205
|
+
pluginApiName
|
|
206
|
+
)
|
|
207
|
+
};
|
|
168
208
|
}
|
|
169
209
|
try {
|
|
170
|
-
return JSON.parse(content);
|
|
210
|
+
return { config: JSON.parse(content) };
|
|
171
211
|
} catch {
|
|
172
|
-
|
|
212
|
+
return {
|
|
213
|
+
issue: errorIssue(
|
|
214
|
+
"structure/config-parse",
|
|
215
|
+
`Failed to parse ${CONFIG_FILE_NAME} as JSON.`,
|
|
216
|
+
path,
|
|
217
|
+
pluginApiName
|
|
218
|
+
)
|
|
219
|
+
};
|
|
173
220
|
}
|
|
174
221
|
};
|
|
222
|
+
var maybeParseConfig = (content, path, pluginApiName) => {
|
|
223
|
+
const result = tryParseConfig(content, path, pluginApiName);
|
|
224
|
+
if ("issue" in result) throw new PluginValidationError([result.issue]);
|
|
225
|
+
return result.config;
|
|
226
|
+
};
|
|
175
227
|
var getMinimizedConfig = (config, entry, splitPath, consideredFiles) => {
|
|
176
|
-
const result = config
|
|
177
|
-
|
|
228
|
+
const result = config.minimized_config ?? {};
|
|
229
|
+
const customIconFile = result.customIconFile;
|
|
230
|
+
if (typeof customIconFile === "string" && customIconFile) {
|
|
178
231
|
let basePath = splitPath.slice(0, -1).join("/");
|
|
179
232
|
if (entry.endsWith("/")) {
|
|
180
233
|
basePath = `${entry}${basePath}`;
|
|
181
234
|
} else {
|
|
182
235
|
basePath = `${entry}/${basePath}`;
|
|
183
236
|
}
|
|
184
|
-
const filePath = `${basePath}/${
|
|
237
|
+
const filePath = `${basePath}/${customIconFile}`;
|
|
185
238
|
const file = consideredFiles.find((f) => f.path === filePath);
|
|
186
239
|
if (file?.base64Image) {
|
|
187
|
-
let extension = filePath.split(".").pop()?.toLowerCase();
|
|
240
|
+
let extension = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
188
241
|
if (extension === "svg") {
|
|
189
242
|
extension = "svg+xml";
|
|
190
243
|
}
|
|
191
|
-
result
|
|
244
|
+
result.customIcon = `data:image/${extension};base64,${file.base64Image}`;
|
|
192
245
|
}
|
|
193
246
|
}
|
|
194
247
|
return result;
|
|
195
248
|
};
|
|
196
249
|
var getAdornmentIcon = (config, entry, splitPath, consideredFiles) => {
|
|
197
|
-
|
|
250
|
+
const customIconFile = config.customIconFile;
|
|
251
|
+
if (typeof customIconFile === "string" && customIconFile) {
|
|
198
252
|
let basePath = splitPath.slice(0, -1).join("/");
|
|
199
253
|
if (entry.endsWith("/")) {
|
|
200
254
|
basePath = `${entry}${basePath}`;
|
|
201
255
|
} else {
|
|
202
256
|
basePath = `${entry}/${basePath}`;
|
|
203
257
|
}
|
|
204
|
-
const filePath = `${basePath}/${
|
|
258
|
+
const filePath = `${basePath}/${customIconFile}`;
|
|
205
259
|
const file = consideredFiles.find((f) => f.path === filePath);
|
|
206
260
|
if (file?.base64Image) {
|
|
207
|
-
let extension = filePath.split(".").pop()?.toLowerCase();
|
|
261
|
+
let extension = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
208
262
|
if (extension === "svg") {
|
|
209
263
|
extension = "svg+xml";
|
|
210
264
|
}
|
|
@@ -214,6 +268,411 @@ var getAdornmentIcon = (config, entry, splitPath, consideredFiles) => {
|
|
|
214
268
|
return "";
|
|
215
269
|
};
|
|
216
270
|
|
|
271
|
+
// src/lib/validate.ts
|
|
272
|
+
var API_NAME_PATTERN = /^[a-z_][a-z0-9_]+$/;
|
|
273
|
+
var API_NAME_HINT = "must start with a letter or underscore and contain only lowercase letters, numbers, or underscores (minimum 2 characters)";
|
|
274
|
+
var SEMVER_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
275
|
+
var PATH_PATTERN = /^[a-zA-Z][a-zA-Z0-9_\-/]*$/;
|
|
276
|
+
var SUPPORTED_ENGINES = ["1.0.0"];
|
|
277
|
+
var CONFIG_REQUIRED_DIRECTORIES = [
|
|
278
|
+
FLOATING_FRAMES_DIRECTORY_NAME,
|
|
279
|
+
BLOCKS_DIRECTORY_NAME,
|
|
280
|
+
DATA_ADORNMENTS_DIRECTORY_NAME,
|
|
281
|
+
TOOLBAR_ITEMS_DIRECTORY_NAME,
|
|
282
|
+
ROUTABLE_PAGES_DIRECTORY_NAME,
|
|
283
|
+
BROWSER_ROUTE_SCRIPTS_DIRECTORY_NAME,
|
|
284
|
+
JS_ACTIONS_DIRECTORY_NAME,
|
|
285
|
+
OBJECT_SETTINGS_ITEMS_DIRECTORY_NAME,
|
|
286
|
+
AUTOMATION_STEPS_DIRECTORY_NAME,
|
|
287
|
+
CALENDAR_SOURCES_DIRECTORY_NAME
|
|
288
|
+
];
|
|
289
|
+
var API_NAMED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
290
|
+
FLOATING_FRAMES_DIRECTORY_NAME,
|
|
291
|
+
BLOCKS_DIRECTORY_NAME,
|
|
292
|
+
TOOLBAR_ITEMS_DIRECTORY_NAME,
|
|
293
|
+
ROUTABLE_PAGES_DIRECTORY_NAME,
|
|
294
|
+
BROWSER_ROUTE_SCRIPTS_DIRECTORY_NAME,
|
|
295
|
+
JS_ACTIONS_DIRECTORY_NAME,
|
|
296
|
+
OBJECT_SETTINGS_ITEMS_DIRECTORY_NAME,
|
|
297
|
+
AUTOMATION_STEPS_DIRECTORY_NAME,
|
|
298
|
+
CALENDAR_SOURCES_DIRECTORY_NAME,
|
|
299
|
+
VIEWS_DIRECTORY_NAME
|
|
300
|
+
]);
|
|
301
|
+
var COMPONENT_DIRECTORIES = [...CONFIG_REQUIRED_DIRECTORIES, VIEWS_DIRECTORY_NAME];
|
|
302
|
+
var isNonEmptyString = (value) => typeof value === "string" && value !== "";
|
|
303
|
+
var validateManifestFields = (manifest, label, pluginApiName) => {
|
|
304
|
+
const issues = [];
|
|
305
|
+
const problem = (rule, message) => {
|
|
306
|
+
issues.push(errorIssue(rule, `${label}: ${message}`, MANIFEST_FILE_NAME, pluginApiName));
|
|
307
|
+
};
|
|
308
|
+
const warn = (rule, message) => {
|
|
309
|
+
issues.push(warningIssue(rule, `${label}: ${message}`, MANIFEST_FILE_NAME, pluginApiName));
|
|
310
|
+
};
|
|
311
|
+
const requireString = (field) => {
|
|
312
|
+
const value = manifest[field];
|
|
313
|
+
if (!isNonEmptyString(value)) {
|
|
314
|
+
problem("manifest/required-field", `${field} is required and must be a non-empty string.`);
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
return value;
|
|
318
|
+
};
|
|
319
|
+
const optionalString = (field) => {
|
|
320
|
+
const value = manifest[field];
|
|
321
|
+
if (value === void 0) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
if (!isNonEmptyString(value)) {
|
|
325
|
+
problem("manifest/required-field", `${field} must be a non-empty string when present.`);
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
return value;
|
|
329
|
+
};
|
|
330
|
+
const optionalStringArray = (field, rule) => {
|
|
331
|
+
const value = manifest[field];
|
|
332
|
+
if (value === void 0) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (!Array.isArray(value) || !value.every(isNonEmptyString)) {
|
|
336
|
+
problem(rule, `${field} must be an array of non-empty strings when present.`);
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
return value;
|
|
340
|
+
};
|
|
341
|
+
const version = requireString("version");
|
|
342
|
+
if (version !== null && !SEMVER_PATTERN.test(version)) {
|
|
343
|
+
problem(
|
|
344
|
+
"manifest/version-format",
|
|
345
|
+
`version must be a semantic version (e.g. 1.0.0), got "${version}".`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
const apiName = requireString("api_name");
|
|
349
|
+
if (apiName !== null && !API_NAME_PATTERN.test(apiName)) {
|
|
350
|
+
problem("manifest/api-name-format", `api_name "${apiName}" is invalid: ${API_NAME_HINT}.`);
|
|
351
|
+
}
|
|
352
|
+
requireString("name");
|
|
353
|
+
requireString("description");
|
|
354
|
+
const engine = requireString("engine");
|
|
355
|
+
if (engine !== null && !SUPPORTED_ENGINES.includes(engine)) {
|
|
356
|
+
problem(
|
|
357
|
+
"manifest/engine-version",
|
|
358
|
+
`engine must be one of ${SUPPORTED_ENGINES.join(", ")}, got "${engine}".`
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
const entry = requireString("entry");
|
|
362
|
+
if (entry !== null && !PATH_PATTERN.test(entry)) {
|
|
363
|
+
problem(
|
|
364
|
+
"manifest/entry-path",
|
|
365
|
+
`entry must be a directory path matching ${String(PATH_PATTERN)}, got "${entry}".`
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
const releaseNotesDirectory = optionalString("release_notes_directory");
|
|
369
|
+
if (releaseNotesDirectory !== null && !PATH_PATTERN.test(releaseNotesDirectory)) {
|
|
370
|
+
problem(
|
|
371
|
+
"manifest/release-notes-directory-path",
|
|
372
|
+
`release_notes_directory must be a directory path matching ${String(PATH_PATTERN)}, got "${releaseNotesDirectory}".`
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
optionalStringArray("release_branches", "manifest/release-branches");
|
|
376
|
+
const releaseEnvironments = optionalStringArray(
|
|
377
|
+
"release_environments",
|
|
378
|
+
"manifest/release-environments"
|
|
379
|
+
);
|
|
380
|
+
if (releaseEnvironments !== null) {
|
|
381
|
+
for (const env of releaseEnvironments) {
|
|
382
|
+
if (!ENVIRONMENTS.includes(env)) {
|
|
383
|
+
problem(
|
|
384
|
+
"manifest/release-environments",
|
|
385
|
+
`release_environments must only contain ${ENVIRONMENTS.join(", ")}. Instead, got "${env}".`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const developerBusinessId = manifest.developer_business_id;
|
|
391
|
+
if (developerBusinessId !== void 0) {
|
|
392
|
+
if (isNonEmptyString(developerBusinessId)) {
|
|
393
|
+
const distinctValidEnvs = new Set(
|
|
394
|
+
(releaseEnvironments ?? []).filter(
|
|
395
|
+
(env) => ENVIRONMENTS.includes(env)
|
|
396
|
+
)
|
|
397
|
+
);
|
|
398
|
+
if (distinctValidEnvs.size >= 2) {
|
|
399
|
+
warn(
|
|
400
|
+
"manifest/developer-business-id-environments",
|
|
401
|
+
"developer_business_id is a single id but release_environments targets multiple environments; a business id generally exists in only one environment, so publishing to the others will fail - use the per-environment object form instead."
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
} else if (typeof developerBusinessId === "object" && developerBusinessId !== null && !Array.isArray(developerBusinessId)) {
|
|
405
|
+
for (const [env, id] of Object.entries(developerBusinessId)) {
|
|
406
|
+
if (!PUBLISHABLE_ENVIRONMENTS.includes(env)) {
|
|
407
|
+
problem(
|
|
408
|
+
"manifest/developer-business-id",
|
|
409
|
+
`developer_business_id has an invalid environment key "${env}": keys must be one of ${PUBLISHABLE_ENVIRONMENTS.join(", ")}. Aliases like ${ENVIRONMENT_ALIASES.join(", ")} are not valid keys here - the publisher indexes by concrete environment, so alias keys silently resolve to nothing.`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
if (!isNonEmptyString(id)) {
|
|
413
|
+
problem(
|
|
414
|
+
"manifest/developer-business-id",
|
|
415
|
+
`developer_business_id["${env}"] must be a non-empty string.`
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
} else {
|
|
420
|
+
problem(
|
|
421
|
+
"manifest/developer-business-id",
|
|
422
|
+
"developer_business_id must be a non-empty string or an object mapping publishable environments to ids."
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return issues;
|
|
427
|
+
};
|
|
428
|
+
var collectComponents = (files, entry) => {
|
|
429
|
+
const entryPrefix = entry.endsWith("/") ? entry : `${entry}/`;
|
|
430
|
+
const components = /* @__PURE__ */ new Map();
|
|
431
|
+
for (const file of files) {
|
|
432
|
+
if (!file.path.startsWith(entryPrefix) || file.path.endsWith(".DS_Store")) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const [directory, name, child] = file.path.slice(entryPrefix.length).split("/");
|
|
436
|
+
if (!directory || !name || !COMPONENT_DIRECTORIES.includes(directory)) {
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
const key = `${directory}/${name}`;
|
|
440
|
+
const existing = components.get(key) ?? {
|
|
441
|
+
directory,
|
|
442
|
+
name,
|
|
443
|
+
configFile: void 0
|
|
444
|
+
};
|
|
445
|
+
if (child === CONFIG_FILE_NAME) {
|
|
446
|
+
existing.configFile = file;
|
|
447
|
+
}
|
|
448
|
+
components.set(key, existing);
|
|
449
|
+
}
|
|
450
|
+
return [...components.values()];
|
|
451
|
+
};
|
|
452
|
+
var PAGE_LIKE_DIRECTORIES = /* @__PURE__ */ new Set([ROUTABLE_PAGES_DIRECTORY_NAME, VIEWS_DIRECTORY_NAME]);
|
|
453
|
+
var validateComponent = (component, entry, pluginApiName) => {
|
|
454
|
+
const { directory, name, configFile } = component;
|
|
455
|
+
const entryBase = entry.endsWith("/") ? entry.slice(0, -1) : entry;
|
|
456
|
+
const componentPath = `${entryBase}/${directory}/${name}`;
|
|
457
|
+
const issues = [];
|
|
458
|
+
const apiNameIssue = (value, derived2, path) => {
|
|
459
|
+
const derivedNote = derived2 ? ` (derived from directory name "${name}")` : "";
|
|
460
|
+
const derivedFix = derived2 ? ` Set an explicit api_name in ${CONFIG_FILE_NAME}.` : "";
|
|
461
|
+
issues.push(
|
|
462
|
+
errorIssue(
|
|
463
|
+
"structure/api-name-format",
|
|
464
|
+
`api_name "${value}"${derivedNote} is invalid: ${API_NAME_HINT}.${derivedFix}`,
|
|
465
|
+
path,
|
|
466
|
+
pluginApiName
|
|
467
|
+
)
|
|
468
|
+
);
|
|
469
|
+
};
|
|
470
|
+
if (!configFile) {
|
|
471
|
+
if (CONFIG_REQUIRED_DIRECTORIES.includes(directory)) {
|
|
472
|
+
issues.push(
|
|
473
|
+
errorIssue(
|
|
474
|
+
"structure/missing-config",
|
|
475
|
+
`Missing required ${CONFIG_FILE_NAME} for ${directory}/${name}.`,
|
|
476
|
+
componentPath,
|
|
477
|
+
pluginApiName
|
|
478
|
+
)
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
if (API_NAMED_DIRECTORIES.has(directory)) {
|
|
482
|
+
const derived2 = sanitizeToAPIName(name);
|
|
483
|
+
if (!API_NAME_PATTERN.test(derived2)) {
|
|
484
|
+
apiNameIssue(derived2, true, componentPath);
|
|
485
|
+
} else {
|
|
486
|
+
return {
|
|
487
|
+
issues,
|
|
488
|
+
path: componentPath,
|
|
489
|
+
resolved: { apiName: derived2, path: componentPath }
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return { issues, path: componentPath };
|
|
494
|
+
}
|
|
495
|
+
const result = tryParseConfig(configFile.content, configFile.path, pluginApiName);
|
|
496
|
+
if ("issue" in result) {
|
|
497
|
+
return { issues: [result.issue], path: componentPath };
|
|
498
|
+
}
|
|
499
|
+
const config = result.config;
|
|
500
|
+
if (directory === FLOATING_FRAMES_DIRECTORY_NAME) {
|
|
501
|
+
const defaultPosition = config.default_position;
|
|
502
|
+
const minimizedStyle = config.minimized_style;
|
|
503
|
+
if ((defaultPosition === "bottom-left-fixed" || defaultPosition === "bottom-right-fixed") && minimizedStyle !== void 0 && minimizedStyle !== "circle") {
|
|
504
|
+
issues.push(
|
|
505
|
+
errorIssue(
|
|
506
|
+
"structure/fixed-frame-minimized-style",
|
|
507
|
+
`Floating frame "${name}" sets default_position "${defaultPosition}" with minimized_style ${JSON.stringify(minimizedStyle)}. Fixed-position frames require minimized_style "circle" (or omit it).`,
|
|
508
|
+
configFile.path,
|
|
509
|
+
pluginApiName
|
|
510
|
+
)
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (!API_NAMED_DIRECTORIES.has(directory)) {
|
|
515
|
+
return { issues, path: componentPath };
|
|
516
|
+
}
|
|
517
|
+
const explicit = config.api_name;
|
|
518
|
+
if (isNonEmptyString(explicit)) {
|
|
519
|
+
if (!API_NAME_PATTERN.test(explicit)) {
|
|
520
|
+
apiNameIssue(explicit, false, configFile.path);
|
|
521
|
+
return { issues, path: componentPath };
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
issues,
|
|
525
|
+
path: componentPath,
|
|
526
|
+
resolved: { apiName: explicit, path: configFile.path }
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
if (explicit) {
|
|
530
|
+
issues.push(
|
|
531
|
+
errorIssue(
|
|
532
|
+
"structure/api-name-format",
|
|
533
|
+
"api_name must be a non-empty string.",
|
|
534
|
+
configFile.path,
|
|
535
|
+
pluginApiName
|
|
536
|
+
)
|
|
537
|
+
);
|
|
538
|
+
return { issues, path: componentPath };
|
|
539
|
+
}
|
|
540
|
+
const derived = sanitizeToAPIName(name);
|
|
541
|
+
if (!API_NAME_PATTERN.test(derived)) {
|
|
542
|
+
apiNameIssue(derived, true, configFile.path);
|
|
543
|
+
return { issues, path: componentPath };
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
issues,
|
|
547
|
+
path: componentPath,
|
|
548
|
+
resolved: { apiName: derived, path: configFile.path }
|
|
549
|
+
};
|
|
550
|
+
};
|
|
551
|
+
var validateManifestList = (manifests, isMultiManifest, files) => {
|
|
552
|
+
const issues = [];
|
|
553
|
+
const seenApiNames = /* @__PURE__ */ new Map();
|
|
554
|
+
manifests.forEach((manifest, index) => {
|
|
555
|
+
const label = isMultiManifest ? `${MANIFEST_FILE_NAME} entry #${String(index + 1)}` : MANIFEST_FILE_NAME;
|
|
556
|
+
if (typeof manifest !== "object" || manifest === null || Array.isArray(manifest)) {
|
|
557
|
+
issues.push(errorIssue("manifest/shape", `${label}: must be a JSON object.`, MANIFEST_FILE_NAME));
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const record = manifest;
|
|
561
|
+
const rawApiName = record.api_name;
|
|
562
|
+
const pluginApiName = isNonEmptyString(rawApiName) ? rawApiName : void 0;
|
|
563
|
+
issues.push(...validateManifestFields(record, label, pluginApiName));
|
|
564
|
+
if (pluginApiName !== void 0) {
|
|
565
|
+
const firstIndex = seenApiNames.get(pluginApiName);
|
|
566
|
+
if (firstIndex !== void 0) {
|
|
567
|
+
issues.push(
|
|
568
|
+
errorIssue(
|
|
569
|
+
"manifest/duplicate-api-name",
|
|
570
|
+
`${label}: duplicate api_name "${pluginApiName}" already used by entry #${String(firstIndex + 1)}. Plugins in a multi-plugin manifest must have unique api_names.`,
|
|
571
|
+
MANIFEST_FILE_NAME,
|
|
572
|
+
pluginApiName
|
|
573
|
+
)
|
|
574
|
+
);
|
|
575
|
+
} else {
|
|
576
|
+
seenApiNames.set(pluginApiName, index);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const entry = record.entry;
|
|
580
|
+
if (isNonEmptyString(entry) && PATH_PATTERN.test(entry)) {
|
|
581
|
+
const seenResolved = /* @__PURE__ */ new Map();
|
|
582
|
+
const seenPageNames = /* @__PURE__ */ new Map();
|
|
583
|
+
for (const component of collectComponents(files, entry)) {
|
|
584
|
+
const {
|
|
585
|
+
issues: componentIssues,
|
|
586
|
+
path: componentPath,
|
|
587
|
+
resolved
|
|
588
|
+
} = validateComponent(component, entry, pluginApiName);
|
|
589
|
+
issues.push(...componentIssues);
|
|
590
|
+
if (PAGE_LIKE_DIRECTORIES.has(component.directory)) {
|
|
591
|
+
const firstPage = seenPageNames.get(component.name);
|
|
592
|
+
if (firstPage !== void 0) {
|
|
593
|
+
issues.push(
|
|
594
|
+
errorIssue(
|
|
595
|
+
"structure/duplicate-component-name",
|
|
596
|
+
`duplicate component name "${component.name}": ${component.directory}/${component.name} (${componentPath}) collides with ${firstPage.directory}/${component.name} (${firstPage.path}). pages and views share one routable-pages collection, so names must be unique across both directories.`,
|
|
597
|
+
componentPath,
|
|
598
|
+
pluginApiName
|
|
599
|
+
)
|
|
600
|
+
);
|
|
601
|
+
} else {
|
|
602
|
+
seenPageNames.set(component.name, {
|
|
603
|
+
path: componentPath,
|
|
604
|
+
directory: component.directory
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if (resolved) {
|
|
609
|
+
const key = `${component.directory}
|
|
610
|
+
${resolved.apiName}`;
|
|
611
|
+
const firstPath = seenResolved.get(key);
|
|
612
|
+
if (firstPath !== void 0) {
|
|
613
|
+
issues.push(
|
|
614
|
+
errorIssue(
|
|
615
|
+
"structure/duplicate-api-name",
|
|
616
|
+
`duplicate api_name "${resolved.apiName}" in ${component.directory}: ${resolved.path} collides with ${firstPath}. Sibling ${component.directory} components must resolve to unique api_names.`,
|
|
617
|
+
resolved.path,
|
|
618
|
+
pluginApiName
|
|
619
|
+
)
|
|
620
|
+
);
|
|
621
|
+
} else {
|
|
622
|
+
seenResolved.set(key, resolved.path);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
return issues;
|
|
629
|
+
};
|
|
630
|
+
var validatePluginApp = (files) => {
|
|
631
|
+
const manifestFile = files.find((f) => f.path === MANIFEST_FILE_NAME);
|
|
632
|
+
if (!manifestFile) {
|
|
633
|
+
return [
|
|
634
|
+
errorIssue(
|
|
635
|
+
"manifest/missing",
|
|
636
|
+
`Missing ${MANIFEST_FILE_NAME} at the root of the plugin directory.`,
|
|
637
|
+
MANIFEST_FILE_NAME
|
|
638
|
+
)
|
|
639
|
+
];
|
|
640
|
+
}
|
|
641
|
+
let parsed;
|
|
642
|
+
try {
|
|
643
|
+
parsed = JSON.parse(manifestFile.content);
|
|
644
|
+
} catch {
|
|
645
|
+
return [
|
|
646
|
+
errorIssue(
|
|
647
|
+
"manifest/parse",
|
|
648
|
+
`${MANIFEST_FILE_NAME} could not be parsed. Is it properly formatted JSON?`,
|
|
649
|
+
MANIFEST_FILE_NAME
|
|
650
|
+
)
|
|
651
|
+
];
|
|
652
|
+
}
|
|
653
|
+
const isMultiManifest = Array.isArray(parsed);
|
|
654
|
+
const manifests = isMultiManifest ? parsed : [parsed];
|
|
655
|
+
return validateManifestList(manifests, isMultiManifest, files);
|
|
656
|
+
};
|
|
657
|
+
var validatePackagedManifests = (manifests, files) => {
|
|
658
|
+
const isMultiManifest = Array.isArray(manifests);
|
|
659
|
+
const list = isMultiManifest ? manifests : [manifests];
|
|
660
|
+
return validateManifestList(list, isMultiManifest, files);
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
// src/lib/image.ts
|
|
664
|
+
var imagetoUint8Array = (base64Image) => {
|
|
665
|
+
const byteCharacters = atob(base64Image);
|
|
666
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
667
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
668
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
669
|
+
}
|
|
670
|
+
return new Uint8Array(byteNumbers);
|
|
671
|
+
};
|
|
672
|
+
var zipToUint8Array = (zip) => {
|
|
673
|
+
return Uint8Array.from(zip);
|
|
674
|
+
};
|
|
675
|
+
|
|
217
676
|
// src/lib/package.ts
|
|
218
677
|
var replacementVar = "__kizen_state";
|
|
219
678
|
var prepend = "const __kizen_utils = {};\n";
|
|
@@ -226,16 +685,13 @@ return ${inner}; })()`;
|
|
|
226
685
|
};
|
|
227
686
|
var mapFields = (fields, scriptsByKey) => {
|
|
228
687
|
return fields.map((field) => {
|
|
229
|
-
if (field
|
|
688
|
+
if (field.type === "container" && field.fields && Array.isArray(field.fields)) {
|
|
230
689
|
return {
|
|
231
690
|
...field,
|
|
232
|
-
fields: mapFields(
|
|
233
|
-
field["fields"],
|
|
234
|
-
scriptsByKey
|
|
235
|
-
)
|
|
691
|
+
fields: mapFields(field.fields, scriptsByKey)
|
|
236
692
|
};
|
|
237
693
|
}
|
|
238
|
-
const fieldKey = field
|
|
694
|
+
const fieldKey = field.key;
|
|
239
695
|
const scripts = scriptsByKey[fieldKey];
|
|
240
696
|
if (scripts) {
|
|
241
697
|
const result = { ...field };
|
|
@@ -248,12 +704,7 @@ var mapFields = (fields, scriptsByKey) => {
|
|
|
248
704
|
]) {
|
|
249
705
|
const fn = scripts[fnName];
|
|
250
706
|
if (fn) {
|
|
251
|
-
result[fnName] = convertToSelfInvokingFunction(
|
|
252
|
-
fn,
|
|
253
|
-
replacementVar,
|
|
254
|
-
{},
|
|
255
|
-
prepend
|
|
256
|
-
);
|
|
707
|
+
result[fnName] = convertToSelfInvokingFunction(fn, replacementVar, {}, prepend);
|
|
257
708
|
}
|
|
258
709
|
}
|
|
259
710
|
return result;
|
|
@@ -265,19 +716,13 @@ var processSetupAssistantFromFiles = (assistantConfig, scripts) => {
|
|
|
265
716
|
if (!assistantConfig) {
|
|
266
717
|
return void 0;
|
|
267
718
|
}
|
|
268
|
-
const scriptsByKey = scripts.reduce(
|
|
269
|
-
(acc
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
},
|
|
273
|
-
{}
|
|
274
|
-
);
|
|
719
|
+
const scriptsByKey = scripts.reduce((acc, script) => {
|
|
720
|
+
(acc[script.key] ??= {})[script.type] = script.content;
|
|
721
|
+
return acc;
|
|
722
|
+
}, {});
|
|
275
723
|
const newConfig = { ...assistantConfig };
|
|
276
|
-
if (newConfig
|
|
277
|
-
newConfig
|
|
278
|
-
newConfig["fields"],
|
|
279
|
-
scriptsByKey
|
|
280
|
-
);
|
|
724
|
+
if (newConfig.fields && Array.isArray(newConfig.fields)) {
|
|
725
|
+
newConfig.fields = mapFields(newConfig.fields, scriptsByKey);
|
|
281
726
|
}
|
|
282
727
|
return newConfig;
|
|
283
728
|
};
|
|
@@ -285,10 +730,12 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
285
730
|
const entry = manifest.entry;
|
|
286
731
|
const releaseNotesDirectory = manifest.release_notes_directory;
|
|
287
732
|
const apiName = manifest.api_name;
|
|
733
|
+
const entryPrefix = entry.endsWith("/") ? entry : `${entry}/`;
|
|
288
734
|
const consideredFiles = files.filter(
|
|
289
|
-
(f) => f.path !== MANIFEST_FILE_NAME && f.path.startsWith(
|
|
735
|
+
(f) => f.path !== MANIFEST_FILE_NAME && f.path.startsWith(entryPrefix) && !f.path.endsWith(".DS_Store")
|
|
290
736
|
);
|
|
291
|
-
const
|
|
737
|
+
const releaseNotesPrefix = releaseNotesDirectory?.endsWith("/") ? releaseNotesDirectory : `${releaseNotesDirectory ?? ""}/`;
|
|
738
|
+
const releaseNotesFiles = releaseNotesDirectory ? files.filter((f) => f.path.startsWith(releaseNotesPrefix)) : [];
|
|
292
739
|
const { version } = manifest;
|
|
293
740
|
const releaseNotes = releaseNotesFiles.find(
|
|
294
741
|
(file) => file.path.endsWith(`${version}.${RELEASE_NOTES_EXTENSION}`)
|
|
@@ -306,18 +753,16 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
306
753
|
let thumbnail = null;
|
|
307
754
|
let kznFile = null;
|
|
308
755
|
let hasBlockingCondition = false;
|
|
309
|
-
const requiredConfigFiles = {};
|
|
310
756
|
let setupAssistantJSON = null;
|
|
311
757
|
const setupAssistantFunctions = [];
|
|
312
758
|
let userSetupAssistantJSON = null;
|
|
313
759
|
const userSetupAssistantFunctions = [];
|
|
314
760
|
for (const file of consideredFiles) {
|
|
315
|
-
|
|
316
|
-
strippedPath = strippedPath.startsWith("/") ? strippedPath.substring(1) : strippedPath;
|
|
761
|
+
const strippedPath = file.path.slice(entryPrefix.length);
|
|
317
762
|
const splitPath = strippedPath.split("/");
|
|
318
763
|
if (splitPath[0] === SETUP_ASSISTANT_DIRECTORY_NAME) {
|
|
319
764
|
if (splitPath[1] === "assistant.json") {
|
|
320
|
-
setupAssistantJSON = maybeParseConfig(file.content, file.path);
|
|
765
|
+
setupAssistantJSON = maybeParseConfig(file.content, file.path, apiName);
|
|
321
766
|
} else {
|
|
322
767
|
const assistantKey = splitPath[1];
|
|
323
768
|
if (assistantKey && splitPath[2]?.endsWith(`.${SCRIPT_EXTENSION}`)) {
|
|
@@ -330,7 +775,7 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
330
775
|
}
|
|
331
776
|
} else if (splitPath[0] === USER_SETUP_ASSISTANT_DIRECTORY_NAME) {
|
|
332
777
|
if (splitPath[1] === "assistant.json") {
|
|
333
|
-
userSetupAssistantJSON = maybeParseConfig(file.content, file.path);
|
|
778
|
+
userSetupAssistantJSON = maybeParseConfig(file.content, file.path, apiName);
|
|
334
779
|
} else {
|
|
335
780
|
const assistantKey = splitPath[1];
|
|
336
781
|
if (assistantKey && splitPath[2]?.endsWith(`.${SCRIPT_EXTENSION}`)) {
|
|
@@ -346,30 +791,27 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
346
791
|
if (!floatingFrameName) {
|
|
347
792
|
continue;
|
|
348
793
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
when: ""
|
|
371
|
-
};
|
|
372
|
-
}
|
|
794
|
+
floatingFrames[floatingFrameName] ??= {
|
|
795
|
+
name: "",
|
|
796
|
+
api_name: "",
|
|
797
|
+
title: "",
|
|
798
|
+
type: "script",
|
|
799
|
+
css: "",
|
|
800
|
+
event_scripts: {},
|
|
801
|
+
default_position: "bottom-right",
|
|
802
|
+
header_color: "",
|
|
803
|
+
header_text_color: "",
|
|
804
|
+
height: 0,
|
|
805
|
+
width: 0,
|
|
806
|
+
ignore: [],
|
|
807
|
+
match: [],
|
|
808
|
+
message_handler: "",
|
|
809
|
+
minimized_style: "circle",
|
|
810
|
+
minimized_config: {},
|
|
811
|
+
script: "",
|
|
812
|
+
html: "",
|
|
813
|
+
when: ""
|
|
814
|
+
};
|
|
373
815
|
const frame = floatingFrames[floatingFrameName];
|
|
374
816
|
if (splitPath[2] === EVENT_SCRIPTS_DIRECTORY_NAME) {
|
|
375
817
|
if (splitPath[3]?.endsWith(`.${SCRIPT_EXTENSION}`)) {
|
|
@@ -377,27 +819,22 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
377
819
|
frame.event_scripts[functionName] = file.minified;
|
|
378
820
|
}
|
|
379
821
|
} else if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
frame.
|
|
383
|
-
frame.
|
|
384
|
-
frame.
|
|
385
|
-
frame.
|
|
386
|
-
frame.
|
|
387
|
-
frame.
|
|
388
|
-
frame.
|
|
389
|
-
frame.
|
|
390
|
-
frame.
|
|
391
|
-
frame.
|
|
392
|
-
|
|
393
|
-
frame.minimized_style =
|
|
394
|
-
frame.minimized_config = getMinimizedConfig(
|
|
395
|
-
|
|
396
|
-
entry,
|
|
397
|
-
splitPath,
|
|
398
|
-
consideredFiles
|
|
399
|
-
);
|
|
400
|
-
frame.when = config["when"] || "";
|
|
822
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
823
|
+
frame.name = config.name || "";
|
|
824
|
+
frame.api_name = resolveApiName(config.api_name, floatingFrameName);
|
|
825
|
+
frame.title = config.title || "";
|
|
826
|
+
frame.default_position = config.default_position || "bottom-right";
|
|
827
|
+
frame.header_color = config.header_color || "";
|
|
828
|
+
frame.header_text_color = config.header_text_color || "";
|
|
829
|
+
frame.height = config.height || 0;
|
|
830
|
+
frame.width = config.width || 0;
|
|
831
|
+
frame.ignore = Array.isArray(config.ignore) ? config.ignore : [];
|
|
832
|
+
frame.match = Array.isArray(config.match) ? config.match : [];
|
|
833
|
+
frame.html = config.html || "";
|
|
834
|
+
const minimizedStyle = config.minimized_style;
|
|
835
|
+
frame.minimized_style = minimizedStyle === "bar" || minimizedStyle === "circle" || minimizedStyle === "none" ? minimizedStyle : "circle";
|
|
836
|
+
frame.minimized_config = getMinimizedConfig(config, entry, splitPath, consideredFiles);
|
|
837
|
+
frame.when = config.when || "";
|
|
401
838
|
} else if (splitPath[2] === MESSAGE_SCRIPT_FILE) {
|
|
402
839
|
frame.message_handler = file.minified;
|
|
403
840
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
@@ -410,21 +847,18 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
410
847
|
if (!blockName) {
|
|
411
848
|
continue;
|
|
412
849
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
when: ""
|
|
426
|
-
};
|
|
427
|
-
}
|
|
850
|
+
blocks[blockName] ??= {
|
|
851
|
+
name: "",
|
|
852
|
+
api_name: "",
|
|
853
|
+
min_w: 1,
|
|
854
|
+
max_w: 12,
|
|
855
|
+
min_h: 1,
|
|
856
|
+
max_h: 12,
|
|
857
|
+
event_scripts: {},
|
|
858
|
+
script: "",
|
|
859
|
+
styles: "",
|
|
860
|
+
when: ""
|
|
861
|
+
};
|
|
428
862
|
const block = blocks[blockName];
|
|
429
863
|
if (splitPath[2] === EVENT_SCRIPTS_DIRECTORY_NAME) {
|
|
430
864
|
if (splitPath[3]?.endsWith(`.${SCRIPT_EXTENSION}`)) {
|
|
@@ -432,22 +866,21 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
432
866
|
block.event_scripts[functionName] = file.minified;
|
|
433
867
|
}
|
|
434
868
|
} else if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
block.
|
|
438
|
-
block.
|
|
439
|
-
block.
|
|
440
|
-
block.
|
|
441
|
-
block.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
block.recommended_height = config["recommended_height"];
|
|
869
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
870
|
+
block.name = config.name || "";
|
|
871
|
+
block.api_name = resolveApiName(config.api_name, blockName);
|
|
872
|
+
block.min_w = config.min_w || 1;
|
|
873
|
+
block.max_w = config.max_w || 12;
|
|
874
|
+
block.min_h = config.min_h || 1;
|
|
875
|
+
block.max_h = config.max_h || 12;
|
|
876
|
+
if (config.recommended_height != null) {
|
|
877
|
+
block.recommended_height = config.recommended_height;
|
|
445
878
|
}
|
|
446
|
-
if (config
|
|
447
|
-
block.types = config
|
|
879
|
+
if (config.types) {
|
|
880
|
+
block.types = config.types;
|
|
448
881
|
}
|
|
449
|
-
block.when = config
|
|
450
|
-
if (config
|
|
882
|
+
block.when = config.when || "";
|
|
883
|
+
if (config.when) {
|
|
451
884
|
hasBlockingCondition = true;
|
|
452
885
|
}
|
|
453
886
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
@@ -460,31 +893,23 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
460
893
|
if (!dataAdornmentName) {
|
|
461
894
|
continue;
|
|
462
895
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
when: ""
|
|
470
|
-
};
|
|
471
|
-
}
|
|
896
|
+
dataAdornments[dataAdornmentName] ??= {
|
|
897
|
+
config: { icon: "", color: "", tooltip: "" },
|
|
898
|
+
field_type: "phonenumber",
|
|
899
|
+
script: "",
|
|
900
|
+
when: ""
|
|
901
|
+
};
|
|
472
902
|
const adornment = dataAdornments[dataAdornmentName];
|
|
473
903
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
adornment.config.
|
|
477
|
-
adornment.config.
|
|
478
|
-
adornment.config.
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
consideredFiles
|
|
484
|
-
);
|
|
485
|
-
adornment.field_type = config["field_type"] || "phonenumber";
|
|
486
|
-
adornment.when = config["when"] || "";
|
|
487
|
-
if (config["when"]) hasBlockingCondition = true;
|
|
904
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
905
|
+
adornment.config.icon = config.icon || "";
|
|
906
|
+
adornment.config.color = config.color || "";
|
|
907
|
+
adornment.config.tooltip = config.tooltip || "";
|
|
908
|
+
adornment.config.customIcon = getAdornmentIcon(config, entry, splitPath, consideredFiles);
|
|
909
|
+
const fieldType = config.field_type;
|
|
910
|
+
adornment.field_type = fieldType === "phonenumber" || fieldType === "date" || fieldType === "datetime" ? fieldType : "phonenumber";
|
|
911
|
+
adornment.when = config.when || "";
|
|
912
|
+
if (config.when) hasBlockingCondition = true;
|
|
488
913
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
489
914
|
adornment.script = file.minified;
|
|
490
915
|
}
|
|
@@ -493,27 +918,23 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
493
918
|
if (!toolbarItemName) {
|
|
494
919
|
continue;
|
|
495
920
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
when: ""
|
|
505
|
-
};
|
|
506
|
-
}
|
|
921
|
+
toolbarItems[toolbarItemName] ??= {
|
|
922
|
+
api_name: "",
|
|
923
|
+
label: "",
|
|
924
|
+
icon: "",
|
|
925
|
+
color: "",
|
|
926
|
+
script: "",
|
|
927
|
+
when: ""
|
|
928
|
+
};
|
|
507
929
|
const item = toolbarItems[toolbarItemName];
|
|
508
930
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
item.
|
|
512
|
-
item.
|
|
513
|
-
item.
|
|
514
|
-
item.
|
|
515
|
-
|
|
516
|
-
if (config["when"]) hasBlockingCondition = true;
|
|
931
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
932
|
+
item.api_name = resolveApiName(config.api_name, toolbarItemName);
|
|
933
|
+
item.label = config.label || "";
|
|
934
|
+
item.icon = config.icon || "";
|
|
935
|
+
item.color = config.color || "";
|
|
936
|
+
item.when = config.when || "";
|
|
937
|
+
if (config.when) hasBlockingCondition = true;
|
|
517
938
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
518
939
|
item.script = file.minified;
|
|
519
940
|
}
|
|
@@ -522,23 +943,20 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
522
943
|
if (!pageName) {
|
|
523
944
|
continue;
|
|
524
945
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
iframe_url: ""
|
|
540
|
-
};
|
|
541
|
-
}
|
|
946
|
+
routablePages[pageName] ??= {
|
|
947
|
+
name: pageName,
|
|
948
|
+
api_name: "",
|
|
949
|
+
event_scripts: {},
|
|
950
|
+
script: "",
|
|
951
|
+
callback: "",
|
|
952
|
+
css: "",
|
|
953
|
+
is_toolbar_item: false,
|
|
954
|
+
toolbar_color: "",
|
|
955
|
+
toolbar_icon: "",
|
|
956
|
+
type: "script",
|
|
957
|
+
html: "",
|
|
958
|
+
iframe_url: ""
|
|
959
|
+
};
|
|
542
960
|
const page = routablePages[pageName];
|
|
543
961
|
if (splitPath[2] === EVENT_SCRIPTS_DIRECTORY_NAME) {
|
|
544
962
|
if (splitPath[3]?.endsWith(SCRIPT_EXTENSION)) {
|
|
@@ -546,13 +964,12 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
546
964
|
page.event_scripts[functionName] = file.minified;
|
|
547
965
|
}
|
|
548
966
|
} else if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
page.
|
|
552
|
-
page.
|
|
553
|
-
page.
|
|
554
|
-
page.
|
|
555
|
-
page.toolbar_icon = config["toolbar_icon"] || "";
|
|
967
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
968
|
+
page.api_name = resolveApiName(config.api_name, pageName);
|
|
969
|
+
page.name = config.name || pageName;
|
|
970
|
+
page.is_toolbar_item = config.is_toolbar_item || false;
|
|
971
|
+
page.toolbar_color = config.toolbar_color || "";
|
|
972
|
+
page.toolbar_icon = config.toolbar_icon || "";
|
|
556
973
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
557
974
|
page.script = file.minified;
|
|
558
975
|
} else if (splitPath[2] === CALLBACK_SCRIPT_FILE) {
|
|
@@ -565,39 +982,35 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
565
982
|
if (!stepName) {
|
|
566
983
|
continue;
|
|
567
984
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
when: ""
|
|
582
|
-
};
|
|
583
|
-
}
|
|
985
|
+
automationSteps[stepName] ??= {
|
|
986
|
+
name: "",
|
|
987
|
+
action_step_api_name: "",
|
|
988
|
+
overall_description: "",
|
|
989
|
+
action_description: "",
|
|
990
|
+
action_type: "",
|
|
991
|
+
script_runtime: scriptRuntimeToApiName("python 3.12"),
|
|
992
|
+
secrets: [],
|
|
993
|
+
inputs: [],
|
|
994
|
+
outputs: [],
|
|
995
|
+
script: "",
|
|
996
|
+
when: ""
|
|
997
|
+
};
|
|
584
998
|
const step = automationSteps[stepName];
|
|
585
999
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
step.
|
|
589
|
-
step.
|
|
590
|
-
step.
|
|
591
|
-
step.
|
|
592
|
-
step.
|
|
593
|
-
step.
|
|
594
|
-
step.
|
|
595
|
-
step.outputs = config["outputs"] || [];
|
|
1000
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
1001
|
+
step.name = config.name || stepName;
|
|
1002
|
+
step.action_step_api_name = resolveApiName(config.api_name, stepName);
|
|
1003
|
+
step.overall_description = config.plugin_description || "";
|
|
1004
|
+
step.action_description = config.action_description || "";
|
|
1005
|
+
step.action_type = config.action_type || "";
|
|
1006
|
+
step.secrets = Array.isArray(config.secrets) ? config.secrets : [];
|
|
1007
|
+
step.inputs = Array.isArray(config.inputs) ? config.inputs : [];
|
|
1008
|
+
step.outputs = Array.isArray(config.outputs) ? config.outputs : [];
|
|
596
1009
|
step.script_runtime = scriptRuntimeToApiName(
|
|
597
|
-
config
|
|
1010
|
+
config.runtime || "python 3.12"
|
|
598
1011
|
);
|
|
599
|
-
step.when = config
|
|
600
|
-
if (config
|
|
1012
|
+
step.when = config.when || "";
|
|
1013
|
+
if (config.when) hasBlockingCondition = true;
|
|
601
1014
|
} else if (splitPath[2] === AUTOMATION_SCRIPT_FILE) {
|
|
602
1015
|
step.script = file.content;
|
|
603
1016
|
}
|
|
@@ -606,24 +1019,20 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
606
1019
|
if (!routeName) {
|
|
607
1020
|
continue;
|
|
608
1021
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
name: routeName
|
|
617
|
-
};
|
|
618
|
-
}
|
|
1022
|
+
routeScripts[routeName] ??= {
|
|
1023
|
+
script: "",
|
|
1024
|
+
api_name: "",
|
|
1025
|
+
hint_object_name: "",
|
|
1026
|
+
routes: [],
|
|
1027
|
+
name: routeName
|
|
1028
|
+
};
|
|
619
1029
|
const route = routeScripts[routeName];
|
|
620
1030
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
route.
|
|
624
|
-
route.
|
|
625
|
-
route.
|
|
626
|
-
route.name = config["name"] || routeName;
|
|
1031
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
1032
|
+
route.api_name = resolveApiName(config.api_name, routeName);
|
|
1033
|
+
route.hint_object_name = config.hint_object_name || "";
|
|
1034
|
+
route.routes = Array.isArray(config.routes) ? config.routes : [];
|
|
1035
|
+
route.name = config.name || routeName;
|
|
627
1036
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
628
1037
|
route.script = file.minified;
|
|
629
1038
|
}
|
|
@@ -632,22 +1041,18 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
632
1041
|
if (!actionName) {
|
|
633
1042
|
continue;
|
|
634
1043
|
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
api_name: ""
|
|
642
|
-
};
|
|
643
|
-
}
|
|
1044
|
+
jsActions[actionName] ??= {
|
|
1045
|
+
script: "",
|
|
1046
|
+
name: "",
|
|
1047
|
+
hint_object_name: "",
|
|
1048
|
+
api_name: ""
|
|
1049
|
+
};
|
|
644
1050
|
const action = jsActions[actionName];
|
|
645
1051
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
action.
|
|
649
|
-
action.
|
|
650
|
-
action.api_name = config["api_name"] || sanitizeToAPIName(actionName);
|
|
1052
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
1053
|
+
action.name = config.name || actionName;
|
|
1054
|
+
action.hint_object_name = config.hint_object_name || "";
|
|
1055
|
+
action.api_name = resolveApiName(config.api_name, actionName);
|
|
651
1056
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
652
1057
|
action.script = file.minified;
|
|
653
1058
|
}
|
|
@@ -656,22 +1061,18 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
656
1061
|
if (!itemName) {
|
|
657
1062
|
continue;
|
|
658
1063
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
when: ""
|
|
666
|
-
};
|
|
667
|
-
}
|
|
1064
|
+
objectSettingsItems[itemName] ??= {
|
|
1065
|
+
api_name: "",
|
|
1066
|
+
label: "",
|
|
1067
|
+
script: "",
|
|
1068
|
+
when: ""
|
|
1069
|
+
};
|
|
668
1070
|
const settingsItem = objectSettingsItems[itemName];
|
|
669
1071
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
settingsItem.
|
|
673
|
-
settingsItem.
|
|
674
|
-
settingsItem.when = config["when"] || "";
|
|
1072
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
1073
|
+
settingsItem.api_name = resolveApiName(config.api_name, itemName);
|
|
1074
|
+
settingsItem.label = config.label || "";
|
|
1075
|
+
settingsItem.when = config.when || "";
|
|
675
1076
|
} else if (splitPath[2] === MAIN_SCRIPT_FILE) {
|
|
676
1077
|
settingsItem.script = file.minified;
|
|
677
1078
|
}
|
|
@@ -680,24 +1081,20 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
680
1081
|
if (!itemName) {
|
|
681
1082
|
continue;
|
|
682
1083
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
when: ""
|
|
691
|
-
};
|
|
692
|
-
}
|
|
1084
|
+
calendarSources[itemName] ??= {
|
|
1085
|
+
api_name: "",
|
|
1086
|
+
name: "",
|
|
1087
|
+
calendars_script: "",
|
|
1088
|
+
events_script: "",
|
|
1089
|
+
when: ""
|
|
1090
|
+
};
|
|
693
1091
|
const cal = calendarSources[itemName];
|
|
694
1092
|
if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
cal.
|
|
698
|
-
cal.
|
|
699
|
-
|
|
700
|
-
if (config["when"]) hasBlockingCondition = true;
|
|
1093
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
1094
|
+
cal.api_name = resolveApiName(config.api_name, itemName);
|
|
1095
|
+
cal.name = config.name || "";
|
|
1096
|
+
cal.when = config.when || "";
|
|
1097
|
+
if (config.when) hasBlockingCondition = true;
|
|
701
1098
|
} else if (splitPath[2] === "calendars.js") {
|
|
702
1099
|
cal.calendars_script = file.minified;
|
|
703
1100
|
} else if (splitPath[2] === "events.js") {
|
|
@@ -708,22 +1105,20 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
708
1105
|
if (!pageName) {
|
|
709
1106
|
continue;
|
|
710
1107
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
};
|
|
726
|
-
}
|
|
1108
|
+
routablePages[pageName] ??= {
|
|
1109
|
+
name: pageName,
|
|
1110
|
+
api_name: sanitizeToAPIName(pageName),
|
|
1111
|
+
event_scripts: {},
|
|
1112
|
+
script: "",
|
|
1113
|
+
callback: "",
|
|
1114
|
+
css: "",
|
|
1115
|
+
is_toolbar_item: false,
|
|
1116
|
+
toolbar_color: "",
|
|
1117
|
+
toolbar_icon: "",
|
|
1118
|
+
type: "html",
|
|
1119
|
+
html: "",
|
|
1120
|
+
iframe_url: ""
|
|
1121
|
+
};
|
|
727
1122
|
const page = routablePages[pageName];
|
|
728
1123
|
if (splitPath[2] === EVENT_SCRIPTS_DIRECTORY_NAME) {
|
|
729
1124
|
if (splitPath[3]?.endsWith(SCRIPT_EXTENSION)) {
|
|
@@ -731,9 +1126,9 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
731
1126
|
page.event_scripts[functionName] = file.minified;
|
|
732
1127
|
}
|
|
733
1128
|
} else if (splitPath[2] === CONFIG_FILE_NAME) {
|
|
734
|
-
const config = maybeParseConfig(file.content, file.path);
|
|
735
|
-
page.api_name = config
|
|
736
|
-
page.name = config
|
|
1129
|
+
const config = maybeParseConfig(file.content, file.path, apiName);
|
|
1130
|
+
page.api_name = resolveApiName(config.api_name, pageName);
|
|
1131
|
+
page.name = config.name || pageName;
|
|
737
1132
|
} else if (splitPath[2] === VIEW_FILE) {
|
|
738
1133
|
page.html = file.content;
|
|
739
1134
|
page.type = "html";
|
|
@@ -745,35 +1140,42 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
745
1140
|
}
|
|
746
1141
|
} else if (splitPath[0] === KZN_FILE_NAME) {
|
|
747
1142
|
if (!file.binaryData) {
|
|
748
|
-
throw new
|
|
749
|
-
|
|
750
|
-
|
|
1143
|
+
throw new PluginValidationError([
|
|
1144
|
+
errorIssue(
|
|
1145
|
+
"structure/kzn-binary",
|
|
1146
|
+
`KZN file ${file.path} does not contain binary data. Cannot proceed.`,
|
|
1147
|
+
file.path,
|
|
1148
|
+
apiName
|
|
1149
|
+
)
|
|
1150
|
+
]);
|
|
751
1151
|
}
|
|
752
1152
|
if (kznFile) {
|
|
753
|
-
throw new
|
|
754
|
-
|
|
755
|
-
|
|
1153
|
+
throw new PluginValidationError([
|
|
1154
|
+
errorIssue(
|
|
1155
|
+
"structure/duplicate-kzn",
|
|
1156
|
+
`Multiple KZN files found for plugin ${apiName}. Only one is allowed.`,
|
|
1157
|
+
file.path,
|
|
1158
|
+
apiName
|
|
1159
|
+
)
|
|
1160
|
+
]);
|
|
756
1161
|
}
|
|
757
1162
|
kznFile = zipToUint8Array(file.binaryData);
|
|
758
1163
|
} else if (THUMBNAIL_FILE_NAMES.includes(splitPath[0] ?? "")) {
|
|
759
1164
|
if (file.base64Image) {
|
|
760
1165
|
if (thumbnail) {
|
|
761
|
-
throw new
|
|
762
|
-
|
|
763
|
-
|
|
1166
|
+
throw new PluginValidationError([
|
|
1167
|
+
errorIssue(
|
|
1168
|
+
"structure/duplicate-thumbnail",
|
|
1169
|
+
`Multiple thumbnail files found for plugin ${apiName}. Only one is allowed.`,
|
|
1170
|
+
file.path,
|
|
1171
|
+
apiName
|
|
1172
|
+
)
|
|
1173
|
+
]);
|
|
764
1174
|
}
|
|
765
1175
|
thumbnail = imagetoUint8Array(file.base64Image);
|
|
766
1176
|
}
|
|
767
1177
|
}
|
|
768
1178
|
}
|
|
769
|
-
const requiredFileKeys = Object.keys(requiredConfigFiles).filter(
|
|
770
|
-
(key) => requiredConfigFiles[key] === true
|
|
771
|
-
);
|
|
772
|
-
if (requiredFileKeys.length > 0) {
|
|
773
|
-
throw new Error(
|
|
774
|
-
`The following required files are missing for plugin ${apiName}: ${requiredFileKeys.join(" config.json, ")} config.json. Please ensure these files are present in the repository.`
|
|
775
|
-
);
|
|
776
|
-
}
|
|
777
1179
|
const setupAssistantContent = processSetupAssistantFromFiles(
|
|
778
1180
|
setupAssistantJSON,
|
|
779
1181
|
setupAssistantFunctions
|
|
@@ -794,26 +1196,31 @@ var processOnePluginFromManifest = (manifest, files) => {
|
|
|
794
1196
|
if (resolvedUserSetupAssistant !== void 0) {
|
|
795
1197
|
updatedManifest.user_setup_assistant = resolvedUserSetupAssistant;
|
|
796
1198
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
automationSteps,
|
|
812
|
-
kznFile
|
|
813
|
-
}
|
|
1199
|
+
const packagedPlugin = {
|
|
1200
|
+
manifest: updatedManifest,
|
|
1201
|
+
thumbnail,
|
|
1202
|
+
floatingFrames,
|
|
1203
|
+
blocks,
|
|
1204
|
+
dataAdornments,
|
|
1205
|
+
toolbarItems,
|
|
1206
|
+
routablePages,
|
|
1207
|
+
actions: jsActions,
|
|
1208
|
+
routeScripts,
|
|
1209
|
+
objectSettingsMenuItems: objectSettingsItems,
|
|
1210
|
+
calendarSources,
|
|
1211
|
+
automationSteps,
|
|
1212
|
+
kznFile
|
|
814
1213
|
};
|
|
1214
|
+
if (releaseNotes?.content !== void 0) {
|
|
1215
|
+
packagedPlugin.releaseNotes = releaseNotes.content;
|
|
1216
|
+
}
|
|
1217
|
+
return { [apiName]: packagedPlugin };
|
|
815
1218
|
};
|
|
816
1219
|
var packagePlugin = (files, manifests) => {
|
|
1220
|
+
const errors = validatePackagedManifests(manifests, files).filter((i) => i.severity === "error");
|
|
1221
|
+
if (errors.length > 0) {
|
|
1222
|
+
throw new PluginValidationError(errors);
|
|
1223
|
+
}
|
|
817
1224
|
const manifestArray = Array.isArray(manifests) ? manifests : [manifests];
|
|
818
1225
|
return manifestArray.reduce((acc, manifest) => {
|
|
819
1226
|
return { ...acc, ...processOnePluginFromManifest(manifest, files) };
|
|
@@ -822,12 +1229,24 @@ var packagePlugin = (files, manifests) => {
|
|
|
822
1229
|
var parseManifestFromFiles = (files) => {
|
|
823
1230
|
const manifestFile = files.find((f) => f.path === MANIFEST_FILE_NAME);
|
|
824
1231
|
if (!manifestFile) {
|
|
825
|
-
throw new
|
|
1232
|
+
throw new PluginValidationError([
|
|
1233
|
+
errorIssue(
|
|
1234
|
+
"manifest/missing",
|
|
1235
|
+
`Missing ${MANIFEST_FILE_NAME} at the root of the plugin directory.`,
|
|
1236
|
+
MANIFEST_FILE_NAME
|
|
1237
|
+
)
|
|
1238
|
+
]);
|
|
826
1239
|
}
|
|
827
1240
|
try {
|
|
828
1241
|
return JSON.parse(manifestFile.content);
|
|
829
1242
|
} catch {
|
|
830
|
-
throw new
|
|
1243
|
+
throw new PluginValidationError([
|
|
1244
|
+
errorIssue(
|
|
1245
|
+
"manifest/parse",
|
|
1246
|
+
`${MANIFEST_FILE_NAME} could not be parsed. Is it properly formatted JSON?`,
|
|
1247
|
+
MANIFEST_FILE_NAME
|
|
1248
|
+
)
|
|
1249
|
+
]);
|
|
831
1250
|
}
|
|
832
1251
|
};
|
|
833
1252
|
|
|
@@ -849,9 +1268,14 @@ var formatBaseConfig = (packagedPlugin) => {
|
|
|
849
1268
|
actions: (assistantConfig.actions ?? []).map((apiName) => {
|
|
850
1269
|
const action = actionsByApiName[apiName];
|
|
851
1270
|
if (!action) {
|
|
852
|
-
throw new
|
|
853
|
-
|
|
854
|
-
|
|
1271
|
+
throw new PluginValidationError([
|
|
1272
|
+
errorIssue(
|
|
1273
|
+
"structure/setup-assistant-action-ref",
|
|
1274
|
+
`Action with API name ${apiName} not found in packaged plugin for setup assistant. Allowed actions: ${Object.keys(actionsByApiName).join(", ")}`,
|
|
1275
|
+
void 0,
|
|
1276
|
+
packagedPlugin.manifest.api_name
|
|
1277
|
+
)
|
|
1278
|
+
]);
|
|
855
1279
|
}
|
|
856
1280
|
return action;
|
|
857
1281
|
})
|
|
@@ -877,7 +1301,7 @@ var transformDeployablePlugin = (packagedPlugin) => {
|
|
|
877
1301
|
calendarSources,
|
|
878
1302
|
kznFile
|
|
879
1303
|
} = packagedPlugin;
|
|
880
|
-
|
|
1304
|
+
const deployablePlugin = {
|
|
881
1305
|
...manifest,
|
|
882
1306
|
api_name: manifest.api_name,
|
|
883
1307
|
artifacts: {
|
|
@@ -894,11 +1318,14 @@ var transformDeployablePlugin = (packagedPlugin) => {
|
|
|
894
1318
|
},
|
|
895
1319
|
thumbnail,
|
|
896
1320
|
kznFile,
|
|
897
|
-
releaseNotes,
|
|
898
1321
|
base_config: formatBaseConfig(packagedPlugin),
|
|
899
1322
|
setup_assistant: void 0,
|
|
900
1323
|
services: manifest.services ?? []
|
|
901
1324
|
};
|
|
1325
|
+
if (releaseNotes !== void 0) {
|
|
1326
|
+
deployablePlugin.releaseNotes = releaseNotes;
|
|
1327
|
+
}
|
|
1328
|
+
return deployablePlugin;
|
|
902
1329
|
};
|
|
903
1330
|
|
|
904
1331
|
// src/lib/crypto.ts
|
|
@@ -940,15 +1367,8 @@ var encrypt = (plaintext, publicKeyPem) => {
|
|
|
940
1367
|
};
|
|
941
1368
|
};
|
|
942
1369
|
var decrypt = (envelope, privateKeyPem) => {
|
|
943
|
-
const aesKey = (0, import_node_crypto.privateDecrypt)(
|
|
944
|
-
|
|
945
|
-
Buffer.from(envelope.k, "base64")
|
|
946
|
-
);
|
|
947
|
-
const decipher = (0, import_node_crypto.createDecipheriv)(
|
|
948
|
-
"aes-256-gcm",
|
|
949
|
-
aesKey,
|
|
950
|
-
Buffer.from(envelope.iv, "base64")
|
|
951
|
-
);
|
|
1370
|
+
const aesKey = (0, import_node_crypto.privateDecrypt)({ key: privateKeyPem, ...OAEP }, Buffer.from(envelope.k, "base64"));
|
|
1371
|
+
const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", aesKey, Buffer.from(envelope.iv, "base64"));
|
|
952
1372
|
decipher.setAuthTag(Buffer.from(envelope.tag, "base64"));
|
|
953
1373
|
return Buffer.concat([
|
|
954
1374
|
decipher.update(Buffer.from(envelope.ct, "base64")),
|
|
@@ -989,24 +1409,23 @@ var deserializeEnvelope = (value) => {
|
|
|
989
1409
|
const tagBytes = Buffer.from(envelope.tag, "base64");
|
|
990
1410
|
const kBytes = Buffer.from(envelope.k, "base64");
|
|
991
1411
|
if (ivBytes.length !== 12) {
|
|
992
|
-
throw new Error(
|
|
993
|
-
`Invalid encrypted value: iv must be 12 bytes (got ${ivBytes.length})`
|
|
994
|
-
);
|
|
1412
|
+
throw new Error(`Invalid encrypted value: iv must be 12 bytes (got ${String(ivBytes.length)})`);
|
|
995
1413
|
}
|
|
996
1414
|
if (tagBytes.length !== 16) {
|
|
997
1415
|
throw new Error(
|
|
998
|
-
`Invalid encrypted value: tag must be 16 bytes (got ${tagBytes.length})`
|
|
1416
|
+
`Invalid encrypted value: tag must be 16 bytes (got ${String(tagBytes.length)})`
|
|
999
1417
|
);
|
|
1000
1418
|
}
|
|
1001
1419
|
if (kBytes.length !== 384) {
|
|
1002
1420
|
throw new Error(
|
|
1003
|
-
`Invalid encrypted value: wrapped key must be 384 bytes (got ${kBytes.length})`
|
|
1421
|
+
`Invalid encrypted value: wrapped key must be 384 bytes (got ${String(kBytes.length)})`
|
|
1004
1422
|
);
|
|
1005
1423
|
}
|
|
1006
1424
|
return envelope;
|
|
1007
1425
|
};
|
|
1008
1426
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1009
1427
|
0 && (module.exports = {
|
|
1428
|
+
API_NAME_PATTERN,
|
|
1010
1429
|
AUTOMATION_SCRIPT_FILE,
|
|
1011
1430
|
AUTOMATION_STEPS_DIRECTORY_NAME,
|
|
1012
1431
|
BLOCKS_DIRECTORY_NAME,
|
|
@@ -1017,6 +1436,8 @@ var deserializeEnvelope = (value) => {
|
|
|
1017
1436
|
CRYPTO_ALG,
|
|
1018
1437
|
CRYPTO_VERSION,
|
|
1019
1438
|
DATA_ADORNMENTS_DIRECTORY_NAME,
|
|
1439
|
+
ENVIRONMENTS,
|
|
1440
|
+
ENVIRONMENT_ALIASES,
|
|
1020
1441
|
EVENT_SCRIPTS_DIRECTORY_NAME,
|
|
1021
1442
|
FLOATING_FRAMES_DIRECTORY_NAME,
|
|
1022
1443
|
JS_ACTIONS_DIRECTORY_NAME,
|
|
@@ -1025,6 +1446,8 @@ var deserializeEnvelope = (value) => {
|
|
|
1025
1446
|
MANIFEST_FILE_NAME,
|
|
1026
1447
|
MESSAGE_SCRIPT_FILE,
|
|
1027
1448
|
OBJECT_SETTINGS_ITEMS_DIRECTORY_NAME,
|
|
1449
|
+
PUBLISHABLE_ENVIRONMENTS,
|
|
1450
|
+
PluginValidationError,
|
|
1028
1451
|
RELEASE_NOTES_EXTENSION,
|
|
1029
1452
|
ROUTABLE_PAGES_DIRECTORY_NAME,
|
|
1030
1453
|
SCRIPT_EXTENSION,
|
|
@@ -1036,6 +1459,7 @@ var deserializeEnvelope = (value) => {
|
|
|
1036
1459
|
decrypt,
|
|
1037
1460
|
deserializeEnvelope,
|
|
1038
1461
|
encrypt,
|
|
1462
|
+
errorIssue,
|
|
1039
1463
|
generateKeypair,
|
|
1040
1464
|
getAdornmentIcon,
|
|
1041
1465
|
getMinimizedConfig,
|
|
@@ -1051,6 +1475,7 @@ var deserializeEnvelope = (value) => {
|
|
|
1051
1475
|
thumbnailImageExtensions,
|
|
1052
1476
|
transformDeployablePlugin,
|
|
1053
1477
|
triggerImageExtensions,
|
|
1478
|
+
validatePluginApp,
|
|
1054
1479
|
zipToUint8Array
|
|
1055
1480
|
});
|
|
1056
1481
|
//# sourceMappingURL=index.cjs.map
|