@friggframework/core 2.0.0--canary.700.80ec1cc.0 → 2.0.0--canary.702.047d3c4.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/database/documentdb-utils.js +1 -6
- package/errors/index.js +0 -4
- package/generated/prisma-mongodb/edge.js +4 -52
- package/generated/prisma-mongodb/index-browser.js +1 -49
- package/generated/prisma-mongodb/index.d.ts +60 -3506
- package/generated/prisma-mongodb/index.js +4 -52
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +0 -65
- package/generated/prisma-mongodb/wasm.js +4 -52
- package/generated/prisma-postgresql/edge.js +4 -52
- package/generated/prisma-postgresql/index-browser.js +1 -49
- package/generated/prisma-postgresql/index.d.ts +94 -3824
- package/generated/prisma-postgresql/index.js +4 -52
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +0 -63
- package/generated/prisma-postgresql/wasm.js +4 -52
- package/handlers/WEBHOOKS.md +0 -29
- package/handlers/app-definition-loader.js +9 -2
- package/handlers/app-handler-helpers.js +2 -5
- package/handlers/integration-event-dispatcher.js +3 -7
- package/handlers/routers/integration-webhook-routers.js +38 -26
- package/index.js +0 -2
- package/integrations/integration-base.js +1 -162
- package/integrations/integration-router.js +1 -6
- package/integrations/repositories/integration-mapping-repository-documentdb.js +0 -50
- package/integrations/repositories/integration-mapping-repository-interface.js +0 -15
- package/integrations/repositories/integration-mapping-repository-mongo.js +0 -29
- package/integrations/repositories/integration-mapping-repository-postgres.js +0 -30
- package/integrations/repositories/integration-mapping-repository.js +0 -29
- package/integrations/repositories/integration-repository-documentdb.js +2 -6
- package/integrations/repositories/integration-repository-interface.js +0 -3
- package/integrations/repositories/integration-repository-mongo.js +5 -20
- package/integrations/repositories/integration-repository-postgres.js +1 -5
- package/integrations/repositories/process-repository-mongo.js +1 -1
- package/integrations/use-cases/create-integration.js +4 -14
- package/integrations/use-cases/delete-integration-for-user.js +4 -4
- package/integrations/use-cases/get-integration-for-user.js +2 -4
- package/integrations/use-cases/get-integration-instance.js +4 -4
- package/integrations/use-cases/get-integrations-for-user.js +4 -4
- package/integrations/use-cases/get-possible-integrations.js +2 -7
- package/integrations/use-cases/update-integration.js +4 -4
- package/package.json +6 -6
- package/prisma-mongodb/schema.prisma +0 -65
- package/prisma-postgresql/schema.prisma +0 -63
- package/queues/queuer-util.js +2 -9
- package/errors/mapping-already-exists-error.js +0 -14
- package/handlers/workers/integration-triggers.js +0 -25
- package/infrastructure/scheduler/recurrence.js +0 -204
- package/integrations/definitions/README.md +0 -278
- package/integrations/definitions/canonical.js +0 -11
- package/integrations/definitions/capabilities/AUDIT.md +0 -480
- package/integrations/definitions/capabilities/acmeerp.capabilities.json +0 -633
- package/integrations/definitions/capabilities/asana.capabilities.json +0 -279
- package/integrations/definitions/capabilities/calendly.capabilities.json +0 -385
- package/integrations/definitions/capabilities/docusign.capabilities.json +0 -314
- package/integrations/definitions/capabilities/fathom.capabilities.json +0 -238
- package/integrations/definitions/capabilities/github.capabilities.json +0 -585
- package/integrations/definitions/capabilities/hubspot.capabilities.json +0 -822
- package/integrations/definitions/capabilities/jira.capabilities.json +0 -391
- package/integrations/definitions/capabilities/klaviyo.capabilities.json +0 -503
- package/integrations/definitions/capabilities/linear.capabilities.json +0 -378
- package/integrations/definitions/capabilities/netsuite.capabilities.json +0 -535
- package/integrations/definitions/capabilities/notion.capabilities.json +0 -208
- package/integrations/definitions/capabilities/phone.capabilities.json +0 -511
- package/integrations/definitions/capabilities/pipedrive.capabilities.json +0 -430
- package/integrations/definitions/capabilities/quickbooks.capabilities.json +0 -635
- package/integrations/definitions/capabilities/salesforce.capabilities.json +0 -568
- package/integrations/definitions/capabilities/shopify.capabilities.json +0 -1128
- package/integrations/definitions/capabilities/slack.capabilities.json +0 -373
- package/integrations/definitions/capabilities/stripe.capabilities.json +0 -630
- package/integrations/definitions/capabilities/webflow.capabilities.json +0 -196
- package/integrations/definitions/capabilities/zendesk.capabilities.json +0 -422
- package/integrations/definitions/compile.js +0 -80
- package/integrations/definitions/config-form.js +0 -137
- package/integrations/definitions/examples/acme-erp-quickbooks.definition.json +0 -467
- package/integrations/definitions/examples/asana-slack.definition.json +0 -219
- package/integrations/definitions/examples/calendly-salesforce.definition.json +0 -459
- package/integrations/definitions/examples/docusign-salesforce.definition.json +0 -305
- package/integrations/definitions/examples/fathom-hubspot-notion.definition.json +0 -575
- package/integrations/definitions/examples/github-linear.definition.json +0 -322
- package/integrations/definitions/examples/hubspot-slack.definition.json +0 -427
- package/integrations/definitions/examples/klaviyo-hubspot.definition.json +0 -336
- package/integrations/definitions/examples/phone-hubspot.definition.json +0 -633
- package/integrations/definitions/examples/pipedrive-hubspot.definition.json +0 -136
- package/integrations/definitions/examples/pipedrive-phone.definition.json +0 -340
- package/integrations/definitions/examples/records/phone-hubspot.definition-version.json +0 -652
- package/integrations/definitions/examples/records/phone-hubspot.integration.json +0 -86
- package/integrations/definitions/examples/records/phone-hubspot.mappings.json +0 -39
- package/integrations/definitions/examples/records/phone-hubspot.workflow-run.json +0 -62
- package/integrations/definitions/examples/shopify-klaviyo.definition.json +0 -488
- package/integrations/definitions/examples/shopify-netsuite.definition.json +0 -622
- package/integrations/definitions/examples/stripe-quickbooks.definition.json +0 -476
- package/integrations/definitions/examples/webflow-hubspot-slack.definition.json +0 -262
- package/integrations/definitions/examples/zendesk-jira.definition.json +0 -604
- package/integrations/definitions/expressions.js +0 -229
- package/integrations/definitions/index.js +0 -45
- package/integrations/definitions/integration-runtime.js +0 -763
- package/integrations/definitions/interpreter.js +0 -104
- package/integrations/definitions/manifests.js +0 -177
- package/integrations/definitions/renderers/common.js +0 -67
- package/integrations/definitions/renderers/html.js +0 -129
- package/integrations/definitions/renderers/hubspot.js +0 -59
- package/integrations/definitions/renderers/preview.js +0 -154
- package/integrations/definitions/renderers/slack.js +0 -146
- package/integrations/definitions/repositories/definition-version-repository.js +0 -67
- package/integrations/definitions/repositories/workflow-run-repository.js +0 -80
- package/integrations/definitions/router.js +0 -170
- package/integrations/definitions/runtime.js +0 -268
- package/integrations/definitions/schema/capability-manifest.v0.1.schema.json +0 -549
- package/integrations/definitions/schema/installation.v0.1.schema.json +0 -130
- package/integrations/definitions/schema/integration-definition.v0.1.schema.json +0 -909
- package/integrations/definitions/schema/records.md +0 -105
- package/integrations/definitions/schema-check.js +0 -58
- package/integrations/definitions/scripts/check-manifests.js +0 -220
- package/integrations/definitions/scripts/validate.js +0 -66
- package/integrations/definitions/steps.js +0 -123
- package/integrations/definitions/sync-engine.js +0 -297
- package/integrations/definitions/tests/helpers-fake-crm.js +0 -49
- package/integrations/definitions/transforms.js +0 -91
- package/integrations/definitions/use-cases/definition-use-cases.js +0 -245
- package/integrations/definitions/validate.js +0 -436
- package/integrations/definitions/versioning.js +0 -176
- package/integrations/definitions/webhooks.js +0 -119
- package/integrations/integration-types.js +0 -64
- package/integrations/triggers.js +0 -244
- package/integrations/use-cases/run-trigger-tick.js +0 -155
- package/integrations/use-cases/run-trigger.js +0 -77
- package/prisma-postgresql/migrations/20261018000000_add_data_defined_integrations/migration.sql +0 -66
- package/prisma-postgresql/migrations/20261019000000_workflow_run_waits/migration.sql +0 -7
- package/prisma-postgresql/migrations/20261019120000_definition_workspace/migration.sql +0 -5
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Expressions for integrations published as definitions (v0.1).
|
|
3
|
-
*
|
|
4
|
-
* Three forms, and no others (nothing is ever passed to eval):
|
|
5
|
-
* 1. Reference "$.event.contact.id" A string that is exactly a path. Resolves to the value, keeping its type.
|
|
6
|
-
* 2. Template "Call with {{event.from}}" A string with {{path | filter}} parts. Resolves to a string, except
|
|
7
|
-
* that a string which is exactly one tag ("{{record.amount | to_cents}}") keeps the value's type, so
|
|
8
|
-
* a filter can produce a number or a list for an API argument.
|
|
9
|
-
* 3. Condition "$.steps.contact == null && $.event.duration > 30" Used by `when` and trigger filters.
|
|
10
|
-
*
|
|
11
|
-
* Paths are read from a context object: { event, steps, settings, install, vars, item, record, now }.
|
|
12
|
-
* A missing segment resolves to undefined; it never throws.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const PATH_RE = /^\$\.[A-Za-z_][\w-]*(\.[\w-]+|\[\d+\])*$/;
|
|
16
|
-
|
|
17
|
-
function getPath(ctx, path) {
|
|
18
|
-
const clean = path.replace(/^\$\./, '');
|
|
19
|
-
let cur = ctx;
|
|
20
|
-
for (const seg of clean.split(/\.|(?=\[)/)) {
|
|
21
|
-
if (cur == null) return undefined;
|
|
22
|
-
const m = /^\[(\d+)\]$/.exec(seg);
|
|
23
|
-
cur = m ? cur[Number(m[1])] : cur[seg];
|
|
24
|
-
}
|
|
25
|
-
return cur;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const num = (v) => (v == null || v === '' ? null : Number(v));
|
|
29
|
-
const arith = (f) => (v, arg) => { const a = num(v), b = num(arg); return a == null || b == null || Number.isNaN(a) || Number.isNaN(b) ? null : f(a, b); };
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Template filters. Each is a named, total function of (value, argument): no filter loops, calls out or throws on
|
|
33
|
-
* bad input (a non-number gives null, which renders as ''). Arithmetic is here, as named filters, instead of an
|
|
34
|
-
* expression language: {{item.amount | to_cents}}, {{record.created | from_unix}}.
|
|
35
|
-
*/
|
|
36
|
-
// ISO 4217 minor-unit exponents that are not 2 (Stripe's zero-decimal and three-decimal lists).
|
|
37
|
-
const MINOR_EXPONENT = { BIF: 0, CLP: 0, DJF: 0, GNF: 0, JPY: 0, KMF: 0, KRW: 0, MGA: 0, PYG: 0, RWF: 0, UGX: 0, VND: 0, VUV: 0, XAF: 0, XOF: 0, XPF: 0, BHD: 3, JOD: 3, KWD: 3, OMR: 3, TND: 3 };
|
|
38
|
-
const exponentOf = (currency) => MINOR_EXPONENT[String(currency || '').toUpperCase()] ?? 2;
|
|
39
|
-
/** a * 10^e, rounded half-up in decimal (19.995 -> 1999.5 -> 2000; 19.995 * 100 is 1999.4999... in binary). */
|
|
40
|
-
const shiftRound = (a, e) => Math.round(Number(`${a}e${e}`));
|
|
41
|
-
|
|
42
|
-
const FILTERS = {
|
|
43
|
-
upper: (v) => String(v ?? '').toUpperCase(),
|
|
44
|
-
lower: (v) => String(v ?? '').toLowerCase(),
|
|
45
|
-
minutes: (v) => (v == null ? '' : String(Math.round(Number(v) / 60000))),
|
|
46
|
-
seconds: (v) => (v == null ? '' : String(Math.round(Number(v) / 1000))),
|
|
47
|
-
date: (v) => (v ? new Date(v).toISOString().slice(0, 10) : ''),
|
|
48
|
-
json: (v) => JSON.stringify(v),
|
|
49
|
-
// Record data inside a Slack message: escaped so a name like "*x* <!channel>" neither formats nor pings.
|
|
50
|
-
mrkdwn: (v) => require('./renderers/slack').escapeMrkdwn(v),
|
|
51
|
-
default: (v, arg) => (v == null || v === '' ? arg : v),
|
|
52
|
-
truncate: (v, arg) => { const s = String(v ?? ''); const n = Number(arg) || 80; return s.length > n ? s.slice(0, n - 1) + '…' : s; },
|
|
53
|
-
// lists
|
|
54
|
-
join: (v, arg) => (Array.isArray(v) ? v.filter((x) => x != null && x !== '').join(arg ?? ', ') : v),
|
|
55
|
-
size: (v) => (Array.isArray(v) || typeof v === 'string' ? v.length : v && typeof v === 'object' ? Object.keys(v).length : 0),
|
|
56
|
-
first: (v) => (Array.isArray(v) ? v[0] : v),
|
|
57
|
-
last: (v) => (Array.isArray(v) ? v[v.length - 1] : v),
|
|
58
|
-
split: (v, arg) => (typeof v === 'string' ? v.split(arg ?? ',') : v),
|
|
59
|
-
// arithmetic
|
|
60
|
-
plus: arith((a, b) => a + b),
|
|
61
|
-
minus: arith((a, b) => a - b),
|
|
62
|
-
times: arith((a, b) => a * b),
|
|
63
|
-
divided_by: arith((a, b) => (b === 0 ? null : a / b)),
|
|
64
|
-
// Rounded in decimal-exponent form, so 1.005 | round: 2 is 1.01 (1.005 * 100 is 100.49999... in binary floating point).
|
|
65
|
-
round: (v, arg) => { const a = num(v); if (a == null || Number.isNaN(a)) return null; const d = Math.max(0, Math.min(10, Number(arg) || 0)); return Number(`${shiftRound(a, d)}e-${d}`); },
|
|
66
|
-
abs: (v) => { const a = num(v); return a == null || Number.isNaN(a) ? null : Math.abs(a); },
|
|
67
|
-
number: (v) => { const a = num(v); return a == null || Number.isNaN(a) ? null : a; },
|
|
68
|
-
// money in minor units, rounded so 19.99 -> 1999 (19.99 * 100 is 1998.9999999999998)
|
|
69
|
-
to_cents: (v) => { const a = num(v); return a == null || Number.isNaN(a) ? null : shiftRound(a, 2); },
|
|
70
|
-
from_cents: (v) => { const a = num(v); return a == null || Number.isNaN(a) ? null : Math.round(a) / 100; },
|
|
71
|
-
// the same for any currency: {{record.amount | from_minor_units: record.currency}} (JPY has no minor unit, KWD three)
|
|
72
|
-
to_minor_units: (v, cur) => { const a = num(v); if (a == null || Number.isNaN(a)) return null; return shiftRound(a, exponentOf(cur)); },
|
|
73
|
-
from_minor_units: (v, cur) => { const a = num(v); if (a == null || Number.isNaN(a)) return null; const e = exponentOf(cur); return Math.round(a) / 10 ** e; },
|
|
74
|
-
// unix seconds <-> ISO 8601
|
|
75
|
-
from_unix: (v) => { const a = num(v); return a == null || Number.isNaN(a) ? null : new Date(a * 1000).toISOString(); },
|
|
76
|
-
to_unix: (v) => { const t = v ? Date.parse(v) : NaN; return Number.isNaN(t) ? null : Math.floor(t / 1000); },
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/** A filter argument is a quoted literal ('x'), a number, or a path read from the context (steps.full.owner). */
|
|
80
|
-
function filterArg(raw, ctx) {
|
|
81
|
-
if (raw == null) return undefined;
|
|
82
|
-
const a = raw.trim();
|
|
83
|
-
if (/^'.*'$/.test(a)) return a.slice(1, -1).replace(/\\n/g, '\n').replace(/\\t/g, '\t');
|
|
84
|
-
if (/^-?\d+(\.\d+)?$/.test(a)) return a;
|
|
85
|
-
return getPath(ctx, '$.' + a.replace(/^\$\./, ''));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const TAG_RE = /\{\{\s*([^}]+?)\s*\}\}/g;
|
|
89
|
-
const SINGLE_TAG_RE = /^\{\{\s*([^}]+?)\s*\}\}$/;
|
|
90
|
-
|
|
91
|
-
/** Split one tag's expression into its path and filters: "item.amount | times: 100" -> { path, filters: [{ name, arg }] }. */
|
|
92
|
-
function parseTag(expr) {
|
|
93
|
-
const [p, ...filters] = expr.split('|').map((x) => x.trim());
|
|
94
|
-
return { path: p.replace(/^\$\./, ''), filters: filters.map((f) => { const m = /^(\w+)(?::\s*(.*))?$/.exec(f); return m ? { name: m[1], arg: m[2] } : { name: f, arg: undefined, bad: true }; }) };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function evalTag(expr, ctx) {
|
|
98
|
-
const { path, filters } = parseTag(expr);
|
|
99
|
-
let v = getPath(ctx, '$.' + path);
|
|
100
|
-
for (const f of filters) {
|
|
101
|
-
const fn = !f.bad && FILTERS[f.name];
|
|
102
|
-
if (!fn) throw new Error(`Unknown template filter "${f.name}"`);
|
|
103
|
-
v = fn(v, filterArg(f.arg, ctx));
|
|
104
|
-
}
|
|
105
|
-
return v;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function renderTemplate(str, ctx) {
|
|
109
|
-
const single = SINGLE_TAG_RE.exec(str);
|
|
110
|
-
if (single) return evalTag(single[1], ctx) ?? '';
|
|
111
|
-
return str.replace(TAG_RE, (_, expr) => {
|
|
112
|
-
const v = evalTag(expr, ctx);
|
|
113
|
-
return v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Every tag in a value (deep), for validation: [{ path, filters }]. */
|
|
118
|
-
function templateTags(value, acc = []) {
|
|
119
|
-
if (typeof value === 'string') for (const m of value.matchAll(TAG_RE)) acc.push(parseTag(m[1]));
|
|
120
|
-
else if (Array.isArray(value)) value.forEach((v) => templateTags(v, acc));
|
|
121
|
-
else if (value && typeof value === 'object') Object.values(value).forEach((v) => templateTags(v, acc));
|
|
122
|
-
return acc;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** Resolve every reference and template inside a value (deep). Non-string scalars pass through. */
|
|
126
|
-
function resolve(value, ctx) {
|
|
127
|
-
if (typeof value === 'string') {
|
|
128
|
-
if (PATH_RE.test(value)) return getPath(ctx, value);
|
|
129
|
-
if (value.includes('{{')) return renderTemplate(value, ctx);
|
|
130
|
-
return value;
|
|
131
|
-
}
|
|
132
|
-
if (Array.isArray(value)) return value.map((v) => resolve(v, ctx));
|
|
133
|
-
if (value && typeof value === 'object') {
|
|
134
|
-
const out = {};
|
|
135
|
-
for (const [k, v] of Object.entries(value)) out[k] = resolve(v, ctx);
|
|
136
|
-
return out;
|
|
137
|
-
}
|
|
138
|
-
return value;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// ---------- conditions ----------
|
|
142
|
-
const TOKEN_RE = /\s*(\$\.[A-Za-z_][\w.\-[\]]*|'(?:[^'\\]|\\.)*'|-?\d+(?:\.\d+)?|==|!=|>=|<=|&&|\|\||[()!<>]|\bin\b|\bcontains\b|\bexists\b|\btrue\b|\bfalse\b|\bnull\b)/y;
|
|
143
|
-
|
|
144
|
-
function tokenize(src) {
|
|
145
|
-
const out = [];
|
|
146
|
-
TOKEN_RE.lastIndex = 0;
|
|
147
|
-
let pos = 0;
|
|
148
|
-
while (pos < src.length) {
|
|
149
|
-
if (/^\s*$/.test(src.slice(pos))) break;
|
|
150
|
-
TOKEN_RE.lastIndex = pos;
|
|
151
|
-
const m = TOKEN_RE.exec(src);
|
|
152
|
-
if (!m) throw new Error(`Cannot parse condition near "${src.slice(pos, pos + 20)}"`);
|
|
153
|
-
out.push(m[1]);
|
|
154
|
-
pos = TOKEN_RE.lastIndex;
|
|
155
|
-
}
|
|
156
|
-
return out;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** Parse a condition into a small AST. Grammar: or := and ('||' and)* ; and := not ('&&' not)* ; not := '!' not | cmp ; cmp := atom (op atom | 'exists')? */
|
|
160
|
-
function parseCondition(src) {
|
|
161
|
-
const t = tokenize(src);
|
|
162
|
-
let i = 0;
|
|
163
|
-
const peek = () => t[i];
|
|
164
|
-
const next = () => t[i++];
|
|
165
|
-
function atom() {
|
|
166
|
-
const tok = next();
|
|
167
|
-
if (i > t.length) throw new Error(`Condition ends early: "${src}"`);
|
|
168
|
-
if (tok === '(') { const e = or(); if (next() !== ')') throw new Error(`Missing ) in "${src}"`); return e; }
|
|
169
|
-
if (tok.startsWith('$.')) return { ref: tok };
|
|
170
|
-
if (tok.startsWith("'")) return { lit: tok.slice(1, -1).replace(/\\'/g, "'") };
|
|
171
|
-
if (tok === 'true' || tok === 'false') return { lit: tok === 'true' };
|
|
172
|
-
if (tok === 'null') return { lit: null };
|
|
173
|
-
if (/^-?\d/.test(tok)) return { lit: Number(tok) };
|
|
174
|
-
throw new Error(`Unexpected "${tok}" in "${src}"`);
|
|
175
|
-
}
|
|
176
|
-
function cmp() {
|
|
177
|
-
const left = atom();
|
|
178
|
-
const op = peek();
|
|
179
|
-
if (op === 'exists') { next(); return { op: 'exists', left }; }
|
|
180
|
-
if (['==', '!=', '>', '>=', '<', '<=', 'in', 'contains'].includes(op)) { next(); return { op, left, right: atom() }; }
|
|
181
|
-
return { op: 'truthy', left };
|
|
182
|
-
}
|
|
183
|
-
function not() { if (peek() === '!') { next(); return { op: '!', left: not() }; } return cmp(); }
|
|
184
|
-
function and() { let l = not(); while (peek() === '&&') { next(); l = { op: '&&', left: l, right: not() }; } return l; }
|
|
185
|
-
function or() { let l = and(); while (peek() === '||') { next(); l = { op: '||', left: l, right: and() }; } return l; }
|
|
186
|
-
const ast = or();
|
|
187
|
-
if (i < t.length) throw new Error(`Unexpected "${t[i]}" in "${src}"`);
|
|
188
|
-
return ast;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function evalAst(n, ctx) {
|
|
192
|
-
if ('ref' in n) return getPath(ctx, n.ref);
|
|
193
|
-
if ('lit' in n) return n.lit;
|
|
194
|
-
const L = () => evalAst(n.left, ctx), R = () => evalAst(n.right, ctx);
|
|
195
|
-
switch (n.op) {
|
|
196
|
-
case 'truthy': return Boolean(L());
|
|
197
|
-
case 'exists': return L() != null;
|
|
198
|
-
case '!': return !evalAst(n.left, ctx);
|
|
199
|
-
case '&&': return Boolean(L()) && Boolean(R());
|
|
200
|
-
case '||': return Boolean(L()) || Boolean(R());
|
|
201
|
-
case '==': return L() == R(); // eslint-disable-line eqeqeq -- null == undefined is intended
|
|
202
|
-
case '!=': return L() != R(); // eslint-disable-line eqeqeq
|
|
203
|
-
case '>': return L() > R();
|
|
204
|
-
case '>=': return L() >= R();
|
|
205
|
-
case '<': return L() < R();
|
|
206
|
-
case '<=': return L() <= R();
|
|
207
|
-
case 'in': { const r = R(); return Array.isArray(r) ? r.includes(L()) : typeof r === 'string' && r.includes(String(L())); }
|
|
208
|
-
case 'contains': { const l = L(); return Array.isArray(l) ? l.includes(R()) : String(l ?? '').includes(String(R())); }
|
|
209
|
-
default: throw new Error(`Unknown operator ${n.op}`);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function evaluate(condition, ctx) {
|
|
214
|
-
if (condition == null) return true;
|
|
215
|
-
return Boolean(evalAst(parseCondition(condition), ctx));
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/** Every $.root referenced by an expression-bearing value (for validation). */
|
|
219
|
-
function referencedPaths(value, acc = []) {
|
|
220
|
-
if (typeof value === 'string') {
|
|
221
|
-
if (PATH_RE.test(value)) acc.push(value);
|
|
222
|
-
for (const m of value.matchAll(/\{\{\s*([^}|]+?)\s*(\|[^}]*)?\}\}/g)) acc.push('$.' + m[1].replace(/^\$\./, ''));
|
|
223
|
-
for (const m of value.matchAll(/\$\.[A-Za-z_][\w.\-[\]]*/g)) if (!acc.includes(m[0])) acc.push(m[0]);
|
|
224
|
-
} else if (Array.isArray(value)) value.forEach((v) => referencedPaths(v, acc));
|
|
225
|
-
else if (value && typeof value === 'object') Object.values(value).forEach((v) => referencedPaths(v, acc));
|
|
226
|
-
return acc;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
module.exports = { getPath, resolve, renderTemplate, evaluate, parseCondition, referencedPaths, templateTags, FILTERS };
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integrations published as definitions, v0.1 (ADR-063). An integration as a document: modules, syncs, workflows, queries,
|
|
3
|
-
* UI surfaces and templates, run by one runtime class on the existing Frigg infrastructure.
|
|
4
|
-
*/
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const { validate } = require('./validate');
|
|
8
|
-
const { compile, routeWebhook, eventName } = require('./compile');
|
|
9
|
-
const { execute } = require('./interpreter');
|
|
10
|
-
const { makePorts, runWorkflow, runQuery, renderSurface, resolveView, runLifecycle, resolveOptions } = require('./runtime');
|
|
11
|
-
const { diff, checkBump, planUpgrade } = require('./versioning');
|
|
12
|
-
const { defineIntegrationClass, defineSharedIntegrationClass, extendIntegrationClass, memoryDefinitions } = require('./integration-runtime');
|
|
13
|
-
const { BUILTINS } = require('./steps');
|
|
14
|
-
const { TRANSFORMS, applyMapping } = require('./transforms');
|
|
15
|
-
const { FILTERS } = require('./expressions');
|
|
16
|
-
const { validateManifest } = require('./manifests');
|
|
17
|
-
const { checkDefinition, checkManifest, checkInstallation } = require('./schema-check');
|
|
18
|
-
const { viewToSlack, escapeMrkdwn } = require('./renderers/slack');
|
|
19
|
-
const { viewToHubSpot } = require('./renderers/hubspot');
|
|
20
|
-
const { viewToHtml, slackMessageToHtml } = require('./renderers/html');
|
|
21
|
-
const { previewSurface, previewWorkflow, recordingPorts } = require('./renderers/preview');
|
|
22
|
-
const { decodeAction } = require('./renderers/common');
|
|
23
|
-
const useCases = require('./use-cases/definition-use-cases');
|
|
24
|
-
|
|
25
|
-
/** Load every capabilities/*.capabilities.json (bundled mocks; real modules ship their own). */
|
|
26
|
-
function loadManifests(dir = path.join(__dirname, 'capabilities')) {
|
|
27
|
-
const out = {};
|
|
28
|
-
for (const f of fs.readdirSync(dir)) if (f.endsWith('.capabilities.json')) { const m = JSON.parse(fs.readFileSync(path.join(dir, f), 'utf8')); out[m.module] = m; }
|
|
29
|
-
return out;
|
|
30
|
-
}
|
|
31
|
-
function loadExamples(dir = path.join(__dirname, 'examples')) {
|
|
32
|
-
return fs.readdirSync(dir).filter((f) => f.endsWith('.definition.json')).map((f) => JSON.parse(fs.readFileSync(path.join(dir, f), 'utf8')));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = {
|
|
36
|
-
SCHEMA_VERSION: '0.1',
|
|
37
|
-
validate, validateManifest, checkDefinition, checkManifest, checkInstallation, compile, routeWebhook, eventName, execute,
|
|
38
|
-
makePorts, runWorkflow, runQuery, renderSurface, resolveView, runLifecycle,
|
|
39
|
-
diff, checkBump, planUpgrade,
|
|
40
|
-
defineIntegrationClass, defineSharedIntegrationClass, extendIntegrationClass, memoryDefinitions,
|
|
41
|
-
BUILTINS, TRANSFORMS, FILTERS, applyMapping, resolveOptions,
|
|
42
|
-
loadManifests, loadExamples,
|
|
43
|
-
viewToSlack, escapeMrkdwn, viewToHubSpot, viewToHtml, slackMessageToHtml, previewSurface, previewWorkflow, recordingPorts, decodeAction,
|
|
44
|
-
...useCases,
|
|
45
|
-
};
|