veryfront 0.1.1063 → 0.1.1064
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/esm/cli/commands/pull/command-help.d.ts.map +1 -1
- package/esm/cli/commands/pull/command-help.js +7 -2
- package/esm/cli/commands/push/command-help.d.ts.map +1 -1
- package/esm/cli/commands/push/command-help.js +2 -0
- package/esm/cli/commands/push/command.d.ts.map +1 -1
- package/esm/cli/commands/push/command.js +39 -24
- package/esm/deno.js +1 -1
- package/esm/src/schedule/factory.d.ts.map +1 -1
- package/esm/src/schedule/factory.js +105 -0
- package/esm/src/schedule/index.d.ts +1 -1
- package/esm/src/schedule/index.d.ts.map +1 -1
- package/esm/src/schedule/types.d.ts +20 -1
- package/esm/src/schedule/types.d.ts.map +1 -1
- package/esm/src/schedule/types.js +65 -1
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pull/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pull/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,QAAQ,EAAE,WA4EtB,CAAC"}
|
|
@@ -66,7 +66,12 @@ export const pullHelp = {
|
|
|
66
66
|
"With --projects, each project is pulled into a subdirectory named after the slug",
|
|
67
67
|
'Projects list can also be specified in veryfront.json: { "projects": ["slug1", "slug2"] }',
|
|
68
68
|
"Priority order: --env > --release > --branch > main",
|
|
69
|
-
"--prune
|
|
70
|
-
"--prune
|
|
69
|
+
"--prune applies a full managed-source snapshot; it does not perform a Git merge",
|
|
70
|
+
"Mutating --prune requires a clean Git worktree; --yes and --force skip confirmation only",
|
|
71
|
+
"--prune --dry-run can preview anywhere and never writes or deletes local files",
|
|
72
|
+
"Only supported text files are managed; ignored, unsupported, and binary files remain unchanged",
|
|
73
|
+
"Pull preserves remote bytes exactly, including line endings and a missing final newline",
|
|
74
|
+
"Invalid, duplicate, reserved, or symlink-traversing remote paths fail before local writes",
|
|
75
|
+
"A fetch failure causes no writes or pruning; a local write or delete failure exits with an error",
|
|
71
76
|
],
|
|
72
77
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/push/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/push/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,QAAQ,EAAE,WAiDtB,CAAC"}
|
|
@@ -44,5 +44,7 @@ export const pushHelp = {
|
|
|
44
44
|
"Use --branch main to update the existing Veryfront main branch",
|
|
45
45
|
"Uploads supported text source files using their relative paths",
|
|
46
46
|
".vfignore controls which supported files are excluded",
|
|
47
|
+
"--dry-run never creates a project or branch, changes remote files, or writes a Push receipt",
|
|
48
|
+
"If an upload fails, Push does not delete remote files",
|
|
47
49
|
],
|
|
48
50
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/push/command.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/push/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAK3E,OAAO,EACL,KAAK,SAAS,EAId,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAKhC,OAAO,EAAuB,KAAK,aAAa,EAAsB,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGjE,OAAO,EAKL,KAAK,SAAS,EAIf,MAAM,uCAAuC,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;GAS7B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;GAAgC,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;GAOxB,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AASD,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AA+GD,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAgB7B;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAEzB;AAoCD,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,UAAU,EAAE,GACtB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAUrF;AAQD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,GAAG,EAAE,QAAQ,EAAE,EACf,MAAM,EAAE,OAAO,GACd,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB/C;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,OAAO,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB9C;AA+BD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,kBAAkB,EAC5B,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAgB,WAAW,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsQpE"}
|
|
@@ -305,38 +305,47 @@ export function pushCommand(options = {}) {
|
|
|
305
305
|
const client = createApiClient(config);
|
|
306
306
|
const branchName = branch || generateBranchName();
|
|
307
307
|
const isMainBranch = branchName === "main";
|
|
308
|
-
// First-push: If project doesn't exist on server yet, create it
|
|
308
|
+
// First-push: If project doesn't exist on server yet, create it unless this is a dry run.
|
|
309
309
|
let mainFiles = [];
|
|
310
|
+
let projectExists = true;
|
|
310
311
|
try {
|
|
311
312
|
mainFiles = await listAllFiles(client, config.projectSlug, { type: "main" });
|
|
312
313
|
}
|
|
313
314
|
catch (error) {
|
|
314
315
|
// Project doesn't exist yet - create it on first push
|
|
315
316
|
if (getErrorStatus(error) === 404) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
catch (reserveError) {
|
|
322
|
-
spinner.stop();
|
|
323
|
-
if (reserveError instanceof ProjectSlugConflictError) {
|
|
324
|
-
throw projectSlugConflictError(reserveError, projectReferenceSource);
|
|
317
|
+
if (dryRun) {
|
|
318
|
+
projectExists = false;
|
|
319
|
+
if (!quiet) {
|
|
320
|
+
logInfo(`Project "${config.projectSlug}" does not exist. Dry run will not create it.`);
|
|
325
321
|
}
|
|
326
|
-
throw reserveError;
|
|
327
|
-
}
|
|
328
|
-
if (reserveResult.slug !== config.projectSlug) {
|
|
329
|
-
await writeProjectSlug(projectDir, reserveResult.slug);
|
|
330
|
-
logInfo(`Project slug: ${reserveResult.slug}`);
|
|
331
322
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
323
|
+
else {
|
|
324
|
+
spinner.update("Creating project...");
|
|
325
|
+
let reserveResult;
|
|
326
|
+
try {
|
|
327
|
+
reserveResult = await reserveProjectSlug(config.projectSlug, config.apiToken, undefined, config.apiUrl, { allowAlternativeSlug: canPersistAlternativeSlug(projectReferenceSource) });
|
|
328
|
+
}
|
|
329
|
+
catch (reserveError) {
|
|
330
|
+
spinner.stop();
|
|
331
|
+
if (reserveError instanceof ProjectSlugConflictError) {
|
|
332
|
+
throw projectSlugConflictError(reserveError, projectReferenceSource);
|
|
333
|
+
}
|
|
334
|
+
throw reserveError;
|
|
335
|
+
}
|
|
336
|
+
if (reserveResult.slug !== config.projectSlug) {
|
|
337
|
+
await writeProjectSlug(projectDir, reserveResult.slug);
|
|
338
|
+
logInfo(`Project slug: ${reserveResult.slug}`);
|
|
339
|
+
}
|
|
340
|
+
config = { ...config, projectSlug: reserveResult.slug };
|
|
341
|
+
// Now try to get files again (should be empty for new project)
|
|
342
|
+
try {
|
|
343
|
+
mainFiles = await listAllFiles(client, config.projectSlug, { type: "main" });
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// Project just created, no files yet
|
|
347
|
+
mainFiles = [];
|
|
348
|
+
}
|
|
340
349
|
}
|
|
341
350
|
}
|
|
342
351
|
else {
|
|
@@ -354,7 +363,13 @@ export function pushCommand(options = {}) {
|
|
|
354
363
|
}
|
|
355
364
|
const ops = sourceSnapshot.files;
|
|
356
365
|
const localPaths = new Set(ops.map((op) => op.path));
|
|
357
|
-
const target =
|
|
366
|
+
const target = projectExists
|
|
367
|
+
? await resolvePushRemoteFiles(client, config.projectSlug, branchName, mainFiles)
|
|
368
|
+
: {
|
|
369
|
+
branchId: null,
|
|
370
|
+
remoteFiles: mainFiles,
|
|
371
|
+
source: { type: "main" },
|
|
372
|
+
};
|
|
358
373
|
const toDelete = target.remoteFiles.map((f) => f.path).filter((p) => !localPaths.has(p));
|
|
359
374
|
if (ops.length === 0 && toDelete.length === 0) {
|
|
360
375
|
try {
|
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/schedule/factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/schedule/factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,cAAc,EACd,kBAAkB,EAInB,MAAM,YAAY,CAAC;AA8LpB,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,kBAAkB,CAwCnE"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { isTriggerTarget } from "../trigger/target.js";
|
|
2
2
|
import { assertSerializable, validateTriggerId } from "../trigger/validation.js";
|
|
3
3
|
const CONCURRENCY_POLICIES = new Set(["Allow", "Forbid", "Replace"]);
|
|
4
|
+
const INTEGRATION_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
|
|
5
|
+
const REQUIREMENT_KIND_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
4
6
|
function requireString(value, label) {
|
|
5
7
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
6
8
|
throw new Error(`${label} is required.`);
|
|
@@ -14,6 +16,107 @@ function validatePositiveInteger(value, label) {
|
|
|
14
16
|
throw new Error(`${label} must be a positive integer.`);
|
|
15
17
|
}
|
|
16
18
|
}
|
|
19
|
+
function requireContractString(value, label, maxLength) {
|
|
20
|
+
const normalized = requireString(value, label).trim();
|
|
21
|
+
if (normalized.length > maxLength) {
|
|
22
|
+
throw new Error(`${label} must be at most ${maxLength} characters.`);
|
|
23
|
+
}
|
|
24
|
+
return normalized;
|
|
25
|
+
}
|
|
26
|
+
function requireIntegrationName(value, label) {
|
|
27
|
+
const normalized = requireContractString(value, label, 255);
|
|
28
|
+
if (!INTEGRATION_NAME_PATTERN.test(normalized)) {
|
|
29
|
+
throw new Error(`${label} must use a lowercase integration identifier.`);
|
|
30
|
+
}
|
|
31
|
+
return normalized;
|
|
32
|
+
}
|
|
33
|
+
function requireRequirementKind(value, label) {
|
|
34
|
+
const normalized = requireContractString(value, label, 64);
|
|
35
|
+
if (!REQUIREMENT_KIND_PATTERN.test(normalized)) {
|
|
36
|
+
throw new Error(`${label} must use a lowercase resource kind.`);
|
|
37
|
+
}
|
|
38
|
+
return normalized;
|
|
39
|
+
}
|
|
40
|
+
function assertOnlyKeys(record, allowedKeys, label) {
|
|
41
|
+
const allowed = new Set(allowedKeys);
|
|
42
|
+
const unknownKey = Object.keys(record).find((key) => !allowed.has(key));
|
|
43
|
+
if (unknownKey) {
|
|
44
|
+
throw new Error(`${label}.${unknownKey} is not supported.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function normalizeIntegrationRequirements(value) {
|
|
48
|
+
if (value === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (!Array.isArray(value)) {
|
|
51
|
+
throw new Error("Schedule integrationRequirements must be an array.");
|
|
52
|
+
}
|
|
53
|
+
if (value.length > 20) {
|
|
54
|
+
throw new Error("Schedule integrationRequirements must contain at most 20 entries.");
|
|
55
|
+
}
|
|
56
|
+
const integrations = new Set();
|
|
57
|
+
return value.map((requirement, index) => {
|
|
58
|
+
if (!requirement || typeof requirement !== "object" || Array.isArray(requirement)) {
|
|
59
|
+
throw new Error(`Schedule integrationRequirements[${index}] must be an object.`);
|
|
60
|
+
}
|
|
61
|
+
const record = requirement;
|
|
62
|
+
const label = `Schedule integrationRequirements[${index}]`;
|
|
63
|
+
assertOnlyKeys(record, ["integration", "requiredScopes", "resources"], label);
|
|
64
|
+
const integration = requireIntegrationName(record.integration, `${label}.integration`);
|
|
65
|
+
const integrationKey = integration.toLowerCase();
|
|
66
|
+
if (integrations.has(integrationKey)) {
|
|
67
|
+
throw new Error(`Schedule integrationRequirements contains duplicate integration ${integration}.`);
|
|
68
|
+
}
|
|
69
|
+
integrations.add(integrationKey);
|
|
70
|
+
const rawRequiredScopes = record.requiredScopes ?? [];
|
|
71
|
+
if (!Array.isArray(rawRequiredScopes)) {
|
|
72
|
+
throw new Error(`${label}.requiredScopes must be an array.`);
|
|
73
|
+
}
|
|
74
|
+
if (rawRequiredScopes.length > 50) {
|
|
75
|
+
throw new Error(`${label}.requiredScopes must contain at most 50 entries.`);
|
|
76
|
+
}
|
|
77
|
+
const requiredScopes = rawRequiredScopes.map((scope, scopeIndex) => requireContractString(scope, `${label}.requiredScopes[${scopeIndex}]`, 255));
|
|
78
|
+
const rawResources = record.resources ?? [];
|
|
79
|
+
if (!Array.isArray(rawResources)) {
|
|
80
|
+
throw new Error(`${label}.resources must be an array.`);
|
|
81
|
+
}
|
|
82
|
+
if (rawResources.length > 50) {
|
|
83
|
+
throw new Error(`${label}.resources must contain at most 50 entries.`);
|
|
84
|
+
}
|
|
85
|
+
const resources = rawResources.map((resource, resourceIndex) => normalizeIntegrationResource(resource, index, resourceIndex));
|
|
86
|
+
return { integration, requiredScopes, resources };
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function normalizeIntegrationResource(resource, requirementIndex, resourceIndex) {
|
|
90
|
+
if (!resource || typeof resource !== "object" || Array.isArray(resource)) {
|
|
91
|
+
throw new Error(`Schedule integrationRequirements[${requirementIndex}].resources[${resourceIndex}] must be an object.`);
|
|
92
|
+
}
|
|
93
|
+
const record = resource;
|
|
94
|
+
const label = `Schedule integrationRequirements[${requirementIndex}].resources[${resourceIndex}]`;
|
|
95
|
+
assertOnlyKeys(record, ["kind", "id", "parent"], label);
|
|
96
|
+
const kind = requireRequirementKind(record.kind, `${label}.kind`);
|
|
97
|
+
const id = requireContractString(record.id, `${label}.id`, 512);
|
|
98
|
+
const parent = record.parent;
|
|
99
|
+
const normalizedParent = normalizeIntegrationResourceParent(parent, requirementIndex, resourceIndex);
|
|
100
|
+
return {
|
|
101
|
+
kind,
|
|
102
|
+
id,
|
|
103
|
+
...(normalizedParent === undefined ? {} : { parent: normalizedParent }),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function normalizeIntegrationResourceParent(value, requirementIndex, resourceIndex) {
|
|
107
|
+
if (value === undefined)
|
|
108
|
+
return undefined;
|
|
109
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
110
|
+
throw new Error(`Schedule integrationRequirements[${requirementIndex}].resources[${resourceIndex}].parent must be an object.`);
|
|
111
|
+
}
|
|
112
|
+
const record = value;
|
|
113
|
+
const label = `Schedule integrationRequirements[${requirementIndex}].resources[${resourceIndex}].parent`;
|
|
114
|
+
assertOnlyKeys(record, ["kind", "id"], label);
|
|
115
|
+
return {
|
|
116
|
+
kind: requireRequirementKind(record.kind, `${label}.kind`),
|
|
117
|
+
id: requireContractString(record.id, `${label}.id`, 512),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
17
120
|
export function schedule(config) {
|
|
18
121
|
const id = requireString(config.id, "Schedule id");
|
|
19
122
|
validateTriggerId(id, "Schedule");
|
|
@@ -30,6 +133,7 @@ export function schedule(config) {
|
|
|
30
133
|
validatePositiveInteger(config.backoffLimit, "Schedule backoffLimit");
|
|
31
134
|
validatePositiveInteger(config.maxRuns, "Schedule maxRuns");
|
|
32
135
|
assertSerializable(config.input, "Schedule input");
|
|
136
|
+
const integrationRequirements = normalizeIntegrationRequirements(config.integrationRequirements);
|
|
33
137
|
return {
|
|
34
138
|
id,
|
|
35
139
|
...(config.name === undefined ? {} : { name: config.name }),
|
|
@@ -44,5 +148,6 @@ export function schedule(config) {
|
|
|
44
148
|
? {}
|
|
45
149
|
: { concurrencyPolicy: config.concurrencyPolicy }),
|
|
46
150
|
...(config.maxRuns === undefined ? {} : { maxRuns: config.maxRuns }),
|
|
151
|
+
...(integrationRequirements === undefined ? {} : { integrationRequirements }),
|
|
47
152
|
};
|
|
48
153
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import "../../_dnt.polyfills.js";
|
|
20
20
|
export { schedule } from "./factory.js";
|
|
21
|
-
export type { ScheduleConcurrencyPolicy, ScheduleConfig, ScheduleDefinition } from "./types.js";
|
|
21
|
+
export type { ScheduleConcurrencyPolicy, ScheduleConfig, ScheduleDefinition, ScheduleIntegrationRequirement, ScheduleIntegrationRequirementConfig, ScheduleIntegrationResource, ScheduleIntegrationResourceIdentity, } from "./types.js";
|
|
22
22
|
export { isScheduleDefinition } from "./types.js";
|
|
23
23
|
export { discoverSchedules } from "./discovery.js";
|
|
24
24
|
export type { ScheduleDiscoveryOptions, ScheduleDiscoveryResult } from "./discovery.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/schedule/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/schedule/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,YAAY,EACV,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,8BAA8B,EAC9B,oCAAoC,EACpC,2BAA2B,EAC3B,mCAAmC,GACpC,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import type { TriggerTarget } from "../trigger/target.js";
|
|
2
2
|
export type ScheduleConcurrencyPolicy = "Allow" | "Forbid" | "Replace";
|
|
3
|
+
export interface ScheduleIntegrationResourceIdentity {
|
|
4
|
+
kind: string;
|
|
5
|
+
id: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ScheduleIntegrationResource extends ScheduleIntegrationResourceIdentity {
|
|
8
|
+
parent?: ScheduleIntegrationResourceIdentity;
|
|
9
|
+
}
|
|
10
|
+
export interface ScheduleIntegrationRequirement {
|
|
11
|
+
integration: string;
|
|
12
|
+
requiredScopes: string[];
|
|
13
|
+
resources: ScheduleIntegrationResource[];
|
|
14
|
+
}
|
|
15
|
+
export interface ScheduleIntegrationRequirementConfig {
|
|
16
|
+
integration: string;
|
|
17
|
+
requiredScopes?: string[];
|
|
18
|
+
resources?: ScheduleIntegrationResource[];
|
|
19
|
+
}
|
|
3
20
|
export interface ScheduleDefinition {
|
|
4
21
|
id: string;
|
|
5
22
|
name?: string;
|
|
@@ -12,10 +29,12 @@ export interface ScheduleDefinition {
|
|
|
12
29
|
backoffLimit?: number;
|
|
13
30
|
concurrencyPolicy?: ScheduleConcurrencyPolicy;
|
|
14
31
|
maxRuns?: number;
|
|
32
|
+
integrationRequirements?: ScheduleIntegrationRequirement[];
|
|
15
33
|
}
|
|
16
|
-
export type ScheduleConfig = Omit<ScheduleDefinition, "schedule"> & {
|
|
34
|
+
export type ScheduleConfig = Omit<ScheduleDefinition, "schedule" | "integrationRequirements"> & {
|
|
17
35
|
cron?: string;
|
|
18
36
|
schedule?: string;
|
|
37
|
+
integrationRequirements?: ScheduleIntegrationRequirementConfig[];
|
|
19
38
|
};
|
|
20
39
|
export declare function isScheduleDefinition(value: unknown): value is ScheduleDefinition;
|
|
21
40
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/src/schedule/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/src/schedule/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvE,MAAM,WAAW,mCAAmC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,2BAA4B,SAAQ,mCAAmC;IACtF,MAAM,CAAC,EAAE,mCAAmC,CAAC;CAC9C;AAED,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,2BAA2B,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oCAAoC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,2BAA2B,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uBAAuB,CAAC,EAAE,8BAA8B,EAAE,CAAC;CAC5D;AAED,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,yBAAyB,CAAC,GAAG;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,oCAAoC,EAAE,CAAC;CAClE,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAUhF"}
|
|
@@ -5,5 +5,69 @@ export function isScheduleDefinition(value) {
|
|
|
5
5
|
return (typeof definition.id === "string" &&
|
|
6
6
|
typeof definition.schedule === "string" &&
|
|
7
7
|
definition.target !== null &&
|
|
8
|
-
typeof definition.target === "object"
|
|
8
|
+
typeof definition.target === "object" &&
|
|
9
|
+
isScheduleIntegrationRequirements(definition.integrationRequirements));
|
|
10
|
+
}
|
|
11
|
+
function isScheduleIntegrationRequirements(value) {
|
|
12
|
+
if (value === undefined)
|
|
13
|
+
return true;
|
|
14
|
+
if (!Array.isArray(value) || value.length > 20)
|
|
15
|
+
return false;
|
|
16
|
+
const integrations = new Set();
|
|
17
|
+
for (const requirement of value) {
|
|
18
|
+
if (!requirement || typeof requirement !== "object" || Array.isArray(requirement)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const record = requirement;
|
|
22
|
+
const integration = isIntegrationName(record.integration) ? record.integration : undefined;
|
|
23
|
+
if (integration === undefined ||
|
|
24
|
+
!hasOnlyKeys(record, ["integration", "requiredScopes", "resources"]) ||
|
|
25
|
+
integrations.has(integration.toLowerCase()) ||
|
|
26
|
+
!isStringArray(record.requiredScopes) ||
|
|
27
|
+
!isScheduleIntegrationResources(record.resources)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
integrations.add(integration.toLowerCase());
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function isScheduleIntegrationResources(value) {
|
|
35
|
+
if (!Array.isArray(value) || value.length > 50)
|
|
36
|
+
return false;
|
|
37
|
+
return value.every((resource) => {
|
|
38
|
+
if (!resource || typeof resource !== "object" || Array.isArray(resource))
|
|
39
|
+
return false;
|
|
40
|
+
const record = resource;
|
|
41
|
+
return (hasOnlyKeys(record, ["kind", "id", "parent"]) &&
|
|
42
|
+
isRequirementKind(record.kind) &&
|
|
43
|
+
isBoundedString(record.id, 512) &&
|
|
44
|
+
(record.parent === undefined || isScheduleIntegrationResourceIdentity(record.parent)));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function isScheduleIntegrationResourceIdentity(value) {
|
|
48
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
49
|
+
return false;
|
|
50
|
+
const record = value;
|
|
51
|
+
return hasOnlyKeys(record, ["kind", "id"]) &&
|
|
52
|
+
isRequirementKind(record.kind) && isBoundedString(record.id, 512);
|
|
53
|
+
}
|
|
54
|
+
function hasOnlyKeys(record, allowedKeys) {
|
|
55
|
+
const allowed = new Set(allowedKeys);
|
|
56
|
+
return Object.keys(record).every((key) => allowed.has(key));
|
|
57
|
+
}
|
|
58
|
+
function isStringArray(value) {
|
|
59
|
+
return Array.isArray(value) && value.length <= 50 &&
|
|
60
|
+
value.every((item) => isBoundedString(item, 255));
|
|
61
|
+
}
|
|
62
|
+
function isNonEmptyString(value) {
|
|
63
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
64
|
+
}
|
|
65
|
+
function isBoundedString(value, maxLength) {
|
|
66
|
+
return isNonEmptyString(value) && value.trim().length <= maxLength;
|
|
67
|
+
}
|
|
68
|
+
function isIntegrationName(value) {
|
|
69
|
+
return isBoundedString(value, 255) && /^[a-z0-9][a-z0-9_-]*$/.test(value.trim());
|
|
70
|
+
}
|
|
71
|
+
function isRequirementKind(value) {
|
|
72
|
+
return isBoundedString(value, 64) && /^[a-z][a-z0-9_-]*$/.test(value.trim());
|
|
9
73
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1064",
|
|
4
4
|
"description": "The simplest way to build AI-powered apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -328,10 +328,10 @@
|
|
|
328
328
|
"@types/react": "19.2.14",
|
|
329
329
|
"@types/react-dom": "19.2.3",
|
|
330
330
|
"ws": "8.21.0",
|
|
331
|
-
"@veryfront/ext-bundler-esbuild": "0.1.
|
|
332
|
-
"@veryfront/ext-content-mdx": "0.1.
|
|
333
|
-
"@veryfront/ext-css-tailwind": "0.1.
|
|
334
|
-
"@veryfront/ext-parser-babel": "0.1.
|
|
331
|
+
"@veryfront/ext-bundler-esbuild": "0.1.1064",
|
|
332
|
+
"@veryfront/ext-content-mdx": "0.1.1064",
|
|
333
|
+
"@veryfront/ext-css-tailwind": "0.1.1064",
|
|
334
|
+
"@veryfront/ext-parser-babel": "0.1.1064"
|
|
335
335
|
},
|
|
336
336
|
"devDependencies": {
|
|
337
337
|
"@types/node": "20.9.0"
|