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