@friggframework/core 2.0.0--canary.697.20e3e54.0 → 2.0.0--canary.698.b1a2d30.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/integrations/data-defined/README.md +8 -1
- package/integrations/data-defined/capabilities/AUDIT.md +451 -0
- package/integrations/data-defined/capabilities/asana.capabilities.json +22 -13
- package/integrations/data-defined/capabilities/fathom.capabilities.json +16 -6
- package/integrations/data-defined/capabilities/hubspot.capabilities.json +78 -27
- package/integrations/data-defined/capabilities/linear.capabilities.json +30 -10
- package/integrations/data-defined/capabilities/phone.capabilities.json +24 -7
- package/integrations/data-defined/capabilities/pipedrive.capabilities.json +26 -11
- package/integrations/data-defined/capabilities/salesforce.capabilities.json +64 -18
- package/integrations/data-defined/capabilities/slack.capabilities.json +12 -5
- package/integrations/data-defined/capabilities/stripe.capabilities.json +28 -10
- package/integrations/data-defined/data-defined-integration.js +2 -2
- package/integrations/data-defined/examples/asana-slack.definition.json +2 -3
- package/integrations/data-defined/examples/klaviyo-hubspot.definition.json +1 -4
- package/integrations/data-defined/examples/phone-hubspot.definition.json +1 -5
- package/integrations/data-defined/manifests.js +18 -0
- package/integrations/data-defined/runtime.js +17 -2
- package/integrations/data-defined/schema/capability-manifest.v0.1.schema.json +40 -0
- package/integrations/data-defined/scripts/check-manifests.js +220 -0
- package/integrations/data-defined/tests/helpers-fake-crm.js +11 -6
- package/integrations/data-defined/validate.js +6 -0
- package/package.json +5 -5
|
@@ -321,30 +321,44 @@
|
|
|
321
321
|
"scope": "installation",
|
|
322
322
|
"topic": "{{body.payload.ChangeEventHeader.entityName}}.{{body.payload.ChangeEventHeader.changeType}}",
|
|
323
323
|
"eventId": "{{body.id}}",
|
|
324
|
-
"verify": "verifyWebhookSignature"
|
|
324
|
+
"verify": "verifyWebhookSignature",
|
|
325
|
+
"status": "unimplemented",
|
|
326
|
+
"note": "The salesforce Api has no verifyWebhookSignature method; webhook signatures cannot be checked until the module adds one."
|
|
325
327
|
},
|
|
326
328
|
"capabilities": {
|
|
327
329
|
"lead.get": {
|
|
328
330
|
"kind": "read",
|
|
329
|
-
"method": "
|
|
331
|
+
"method": "get",
|
|
330
332
|
"input": {
|
|
331
333
|
"id": {
|
|
332
334
|
"type": "string",
|
|
333
335
|
"required": true
|
|
334
336
|
}
|
|
335
337
|
},
|
|
336
|
-
"output": "lead"
|
|
338
|
+
"output": "lead",
|
|
339
|
+
"args": [
|
|
340
|
+
{
|
|
341
|
+
"value": "Lead"
|
|
342
|
+
},
|
|
343
|
+
"id"
|
|
344
|
+
]
|
|
337
345
|
},
|
|
338
346
|
"lead.create": {
|
|
339
347
|
"kind": "write",
|
|
340
|
-
"method": "
|
|
348
|
+
"method": "create",
|
|
341
349
|
"input": {
|
|
342
350
|
"fields": {
|
|
343
351
|
"type": "object",
|
|
344
352
|
"required": true
|
|
345
353
|
}
|
|
346
354
|
},
|
|
347
|
-
"output": "lead"
|
|
355
|
+
"output": "lead",
|
|
356
|
+
"args": [
|
|
357
|
+
{
|
|
358
|
+
"value": "Lead"
|
|
359
|
+
},
|
|
360
|
+
"fields"
|
|
361
|
+
]
|
|
348
362
|
},
|
|
349
363
|
"lead.update": {
|
|
350
364
|
"kind": "write",
|
|
@@ -359,7 +373,9 @@
|
|
|
359
373
|
"required": true
|
|
360
374
|
}
|
|
361
375
|
},
|
|
362
|
-
"output": "void"
|
|
376
|
+
"output": "void",
|
|
377
|
+
"status": "unimplemented",
|
|
378
|
+
"note": "Api.update(object, data) needs the record id inside data (data.Id); the capability passes the id separately, so there is no way to call it."
|
|
363
379
|
},
|
|
364
380
|
"person.searchByEmail": {
|
|
365
381
|
"kind": "search",
|
|
@@ -371,18 +387,26 @@
|
|
|
371
387
|
"required": true
|
|
372
388
|
}
|
|
373
389
|
},
|
|
374
|
-
"output": "{ leads: lead[], contacts: contact[] }"
|
|
390
|
+
"output": "{ leads: lead[], contacts: contact[] }",
|
|
391
|
+
"status": "unimplemented",
|
|
392
|
+
"note": "Api.find(object, filter) searches one sObject at a time; searching Lead and Contact together would need two calls."
|
|
375
393
|
},
|
|
376
394
|
"event.create": {
|
|
377
395
|
"kind": "write",
|
|
378
|
-
"method": "
|
|
396
|
+
"method": "create",
|
|
379
397
|
"input": {
|
|
380
398
|
"fields": {
|
|
381
399
|
"type": "object",
|
|
382
400
|
"required": true
|
|
383
401
|
}
|
|
384
402
|
},
|
|
385
|
-
"output": "event"
|
|
403
|
+
"output": "event",
|
|
404
|
+
"args": [
|
|
405
|
+
{
|
|
406
|
+
"value": "Event"
|
|
407
|
+
},
|
|
408
|
+
"fields"
|
|
409
|
+
]
|
|
386
410
|
},
|
|
387
411
|
"event.update": {
|
|
388
412
|
"kind": "write",
|
|
@@ -397,18 +421,26 @@
|
|
|
397
421
|
"required": true
|
|
398
422
|
}
|
|
399
423
|
},
|
|
400
|
-
"output": "void"
|
|
424
|
+
"output": "void",
|
|
425
|
+
"status": "unimplemented",
|
|
426
|
+
"note": "Api.update(object, data) needs the record id inside data (data.Id); the capability passes the id separately, so there is no way to call it."
|
|
401
427
|
},
|
|
402
428
|
"opportunity.get": {
|
|
403
429
|
"kind": "read",
|
|
404
|
-
"method": "
|
|
430
|
+
"method": "get",
|
|
405
431
|
"input": {
|
|
406
432
|
"id": {
|
|
407
433
|
"type": "string",
|
|
408
434
|
"required": true
|
|
409
435
|
}
|
|
410
436
|
},
|
|
411
|
-
"output": "opportunity"
|
|
437
|
+
"output": "opportunity",
|
|
438
|
+
"args": [
|
|
439
|
+
{
|
|
440
|
+
"value": "Opportunity"
|
|
441
|
+
},
|
|
442
|
+
"id"
|
|
443
|
+
]
|
|
412
444
|
},
|
|
413
445
|
"opportunity.update": {
|
|
414
446
|
"kind": "write",
|
|
@@ -423,18 +455,26 @@
|
|
|
423
455
|
"required": true
|
|
424
456
|
}
|
|
425
457
|
},
|
|
426
|
-
"output": "void"
|
|
458
|
+
"output": "void",
|
|
459
|
+
"status": "unimplemented",
|
|
460
|
+
"note": "Api.update(object, data) needs the record id inside data (data.Id); the capability passes the id separately, so there is no way to call it."
|
|
427
461
|
},
|
|
428
462
|
"task.create": {
|
|
429
463
|
"kind": "write",
|
|
430
|
-
"method": "
|
|
464
|
+
"method": "create",
|
|
431
465
|
"input": {
|
|
432
466
|
"fields": {
|
|
433
467
|
"type": "object",
|
|
434
468
|
"required": true
|
|
435
469
|
}
|
|
436
470
|
},
|
|
437
|
-
"output": "task"
|
|
471
|
+
"output": "task",
|
|
472
|
+
"args": [
|
|
473
|
+
{
|
|
474
|
+
"value": "Task"
|
|
475
|
+
},
|
|
476
|
+
"fields"
|
|
477
|
+
]
|
|
438
478
|
},
|
|
439
479
|
"file.attach": {
|
|
440
480
|
"kind": "write",
|
|
@@ -457,7 +497,9 @@
|
|
|
457
497
|
"required": true
|
|
458
498
|
}
|
|
459
499
|
},
|
|
460
|
-
"output": "contentVersion"
|
|
500
|
+
"output": "contentVersion",
|
|
501
|
+
"status": "unimplemented",
|
|
502
|
+
"note": "Api has the generic create(object, data) only; ContentVersion field names differ from this capability's inputs."
|
|
461
503
|
},
|
|
462
504
|
"note.create": {
|
|
463
505
|
"kind": "write",
|
|
@@ -476,7 +518,9 @@
|
|
|
476
518
|
"required": true
|
|
477
519
|
}
|
|
478
520
|
},
|
|
479
|
-
"output": "contentNote"
|
|
521
|
+
"output": "contentNote",
|
|
522
|
+
"status": "unimplemented",
|
|
523
|
+
"note": "Api has the generic create(object, data) only; ContentNote field names differ from this capability's inputs."
|
|
480
524
|
},
|
|
481
525
|
"user.list": {
|
|
482
526
|
"kind": "read",
|
|
@@ -486,7 +530,9 @@
|
|
|
486
530
|
"type": "boolean"
|
|
487
531
|
}
|
|
488
532
|
},
|
|
489
|
-
"output": "user[]"
|
|
533
|
+
"output": "user[]",
|
|
534
|
+
"status": "unimplemented",
|
|
535
|
+
"note": "Api has find(object, filter) but no user listing with an activeOnly filter."
|
|
490
536
|
}
|
|
491
537
|
},
|
|
492
538
|
"options": {
|
|
@@ -206,7 +206,9 @@
|
|
|
206
206
|
"body": {
|
|
207
207
|
"challenge": "$.body.challenge"
|
|
208
208
|
}
|
|
209
|
-
}
|
|
209
|
+
},
|
|
210
|
+
"status": "unimplemented",
|
|
211
|
+
"note": "The slack Api has no verifyWebhookSignature method; webhook signatures cannot be checked until the module adds one."
|
|
210
212
|
},
|
|
211
213
|
"capabilities": {
|
|
212
214
|
"message.post": {
|
|
@@ -285,7 +287,7 @@
|
|
|
285
287
|
},
|
|
286
288
|
"message.permalink": {
|
|
287
289
|
"kind": "read",
|
|
288
|
-
"method": "
|
|
290
|
+
"method": "getMessagePermalink",
|
|
289
291
|
"label": "chat.getPermalink",
|
|
290
292
|
"input": {
|
|
291
293
|
"channel": {
|
|
@@ -301,7 +303,7 @@
|
|
|
301
303
|
},
|
|
302
304
|
"channel.list": {
|
|
303
305
|
"kind": "read",
|
|
304
|
-
"method": "
|
|
306
|
+
"method": "listChannels",
|
|
305
307
|
"label": "conversations.list",
|
|
306
308
|
"input": {
|
|
307
309
|
"types": {
|
|
@@ -325,7 +327,9 @@
|
|
|
325
327
|
"type": "number"
|
|
326
328
|
}
|
|
327
329
|
},
|
|
328
|
-
"output": "user[]"
|
|
330
|
+
"output": "user[]",
|
|
331
|
+
"status": "unimplemented",
|
|
332
|
+
"note": "Api has lookupUserByEmail, getUserById and getUserProfileById, but no user listing."
|
|
329
333
|
},
|
|
330
334
|
"user.lookupByEmail": {
|
|
331
335
|
"kind": "read",
|
|
@@ -337,7 +341,10 @@
|
|
|
337
341
|
"required": true
|
|
338
342
|
}
|
|
339
343
|
},
|
|
340
|
-
"output": "user"
|
|
344
|
+
"output": "user",
|
|
345
|
+
"args": [
|
|
346
|
+
"email"
|
|
347
|
+
]
|
|
341
348
|
}
|
|
342
349
|
},
|
|
343
350
|
"options": {
|
|
@@ -471,7 +471,9 @@
|
|
|
471
471
|
"topic": "{{body.type}}",
|
|
472
472
|
"eventId": "{{body.id}}",
|
|
473
473
|
"account": "{{body.account}}",
|
|
474
|
-
"verify": "verifyWebhookSignature"
|
|
474
|
+
"verify": "verifyWebhookSignature",
|
|
475
|
+
"status": "unimplemented",
|
|
476
|
+
"note": "The stripe Api has no verifyWebhookSignature method; webhook signatures cannot be checked until the module adds one."
|
|
475
477
|
},
|
|
476
478
|
"capabilities": {
|
|
477
479
|
"customer.get": {
|
|
@@ -483,7 +485,9 @@
|
|
|
483
485
|
"required": true
|
|
484
486
|
}
|
|
485
487
|
},
|
|
486
|
-
"output": "customer"
|
|
488
|
+
"output": "customer",
|
|
489
|
+
"status": "unimplemented",
|
|
490
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
487
491
|
},
|
|
488
492
|
"customer.list": {
|
|
489
493
|
"kind": "read",
|
|
@@ -499,7 +503,9 @@
|
|
|
499
503
|
"type": "string"
|
|
500
504
|
}
|
|
501
505
|
},
|
|
502
|
-
"output": "page<customer>"
|
|
506
|
+
"output": "page<customer>",
|
|
507
|
+
"status": "unimplemented",
|
|
508
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
503
509
|
},
|
|
504
510
|
"customer.search": {
|
|
505
511
|
"kind": "search",
|
|
@@ -510,7 +516,9 @@
|
|
|
510
516
|
"required": true
|
|
511
517
|
}
|
|
512
518
|
},
|
|
513
|
-
"output": "customer[]"
|
|
519
|
+
"output": "customer[]",
|
|
520
|
+
"status": "unimplemented",
|
|
521
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
514
522
|
},
|
|
515
523
|
"customer.create": {
|
|
516
524
|
"kind": "write",
|
|
@@ -521,7 +529,9 @@
|
|
|
521
529
|
"required": true
|
|
522
530
|
}
|
|
523
531
|
},
|
|
524
|
-
"output": "customer"
|
|
532
|
+
"output": "customer",
|
|
533
|
+
"status": "unimplemented",
|
|
534
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
525
535
|
},
|
|
526
536
|
"customer.update": {
|
|
527
537
|
"kind": "write",
|
|
@@ -536,7 +546,9 @@
|
|
|
536
546
|
"required": true
|
|
537
547
|
}
|
|
538
548
|
},
|
|
539
|
-
"output": "customer"
|
|
549
|
+
"output": "customer",
|
|
550
|
+
"status": "unimplemented",
|
|
551
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
540
552
|
},
|
|
541
553
|
"paymentIntent.get": {
|
|
542
554
|
"kind": "read",
|
|
@@ -550,7 +562,9 @@
|
|
|
550
562
|
"type": "array"
|
|
551
563
|
}
|
|
552
564
|
},
|
|
553
|
-
"output": "paymentIntent"
|
|
565
|
+
"output": "paymentIntent",
|
|
566
|
+
"status": "unimplemented",
|
|
567
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
554
568
|
},
|
|
555
569
|
"refund.get": {
|
|
556
570
|
"kind": "read",
|
|
@@ -561,7 +575,9 @@
|
|
|
561
575
|
"required": true
|
|
562
576
|
}
|
|
563
577
|
},
|
|
564
|
-
"output": "refund"
|
|
578
|
+
"output": "refund",
|
|
579
|
+
"status": "unimplemented",
|
|
580
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
565
581
|
},
|
|
566
582
|
"payout.list": {
|
|
567
583
|
"kind": "read",
|
|
@@ -580,11 +596,13 @@
|
|
|
580
596
|
"type": "number"
|
|
581
597
|
}
|
|
582
598
|
},
|
|
583
|
-
"output": "payout[]"
|
|
599
|
+
"output": "payout[]",
|
|
600
|
+
"status": "unimplemented",
|
|
601
|
+
"note": "Api wraps balance transactions, charges, accounts and webhook endpoints only; customers, payment intents, refunds and payouts are not exposed."
|
|
584
602
|
},
|
|
585
603
|
"balanceTransaction.list": {
|
|
586
604
|
"kind": "read",
|
|
587
|
-
"method": "
|
|
605
|
+
"method": "getBalanceTransactions",
|
|
588
606
|
"input": {
|
|
589
607
|
"payout": {
|
|
590
608
|
"type": "string",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
const crypto = require('crypto');
|
|
20
20
|
const { compile, routeWebhook, eventName } = require('./compile');
|
|
21
|
-
const { makePorts, runWorkflow, resumeWorkflow, runQuery, renderSurface, runLifecycle, resolveOptions, installContext } = require('./runtime');
|
|
21
|
+
const { argumentsFor, makePorts, runWorkflow, resumeWorkflow, runQuery, renderSurface, runLifecycle, resolveOptions, installContext } = require('./runtime');
|
|
22
22
|
const { createSyncEngine } = require('./sync-engine');
|
|
23
23
|
const { eventsIn, handshakeFor, modulesFor } = require('./webhooks');
|
|
24
24
|
const { buildConfigForm, missingRequired } = require('./config-form');
|
|
@@ -252,7 +252,7 @@ function makeClass({ name, defaultId, definitions, manifests, runCode, Integrati
|
|
|
252
252
|
return runCode(ref, args);
|
|
253
253
|
},
|
|
254
254
|
// The shared class registers modules by module name; a definition may name them by its own keys.
|
|
255
|
-
callApi: (moduleKey, method, args) => this.moduleFor(moduleKey).api[method](args),
|
|
255
|
+
callApi: (moduleKey, method, args, order) => this.moduleFor(moduleKey).api[method](...argumentsFor(args, order)),
|
|
256
256
|
store: this.mappingStore(),
|
|
257
257
|
});
|
|
258
258
|
}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"options": {
|
|
36
36
|
"source": "asana.project",
|
|
37
37
|
"with": {
|
|
38
|
-
"
|
|
38
|
+
"workspace": "$.settings.workspace"
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"label": "Project to announce completed tasks from",
|
|
@@ -163,8 +163,7 @@
|
|
|
163
163
|
"id": "task",
|
|
164
164
|
"use": "asana.task.get",
|
|
165
165
|
"with": {
|
|
166
|
-
"taskGid": "$.record.gid"
|
|
167
|
-
"opt_fields": "name,completed,completed_by.name,assignee.name,permalink_url"
|
|
166
|
+
"taskGid": "$.record.gid"
|
|
168
167
|
}
|
|
169
168
|
},
|
|
170
169
|
{
|
|
@@ -40,6 +40,23 @@ function validateManifest(m) {
|
|
|
40
40
|
if (!KINDS.has(c?.kind)) err(`${p}.kind`, [...KINDS].join(', '));
|
|
41
41
|
if (!/^[A-Za-z_$][\w$]*$/.test(c?.method || '')) err(`${p}.method`, 'Name of a method on the module\'s Api class');
|
|
42
42
|
for (const [arg, spec] of Object.entries(c?.input || {})) if (!spec?.type) err(`${p}.input.${arg}`, 'Input needs a type');
|
|
43
|
+
if (c?.status !== undefined && c.status !== 'unimplemented') err(`${p}.status`, 'Only "unimplemented" (the module\'s Api has no such method)');
|
|
44
|
+
if (c?.args !== undefined) {
|
|
45
|
+
if (!Array.isArray(c.args)) err(`${p}.args`, 'An ordered list: input names, "$rest", or { value }');
|
|
46
|
+
else {
|
|
47
|
+
const named = new Set();
|
|
48
|
+
c.args.forEach((a, i) => {
|
|
49
|
+
if (typeof a === 'string' && a !== '$rest') {
|
|
50
|
+
if (!(a in (c.input || {}))) err(`${p}.args[${i}]`, `"${a}" is not an input of this capability`);
|
|
51
|
+
else if (named.has(a)) err(`${p}.args[${i}]`, `"${a}" is passed twice`);
|
|
52
|
+
named.add(a);
|
|
53
|
+
} else if (a === '$rest') { if (c.args.indexOf('$rest') !== i) err(`${p}.args[${i}]`, '"$rest" appears once'); }
|
|
54
|
+
else if (!(a && typeof a === 'object' && 'value' in a)) err(`${p}.args[${i}]`, 'An input name, "$rest" or { value }');
|
|
55
|
+
});
|
|
56
|
+
// An input that is never passed would be accepted and silently dropped.
|
|
57
|
+
if (!c.args.includes('$rest')) for (const k of Object.keys(c.input || {})) if (!named.has(k)) err(`${p}.args`, `Input "${k}" is declared but never passed to ${c.method}; list it in args or use "$rest"`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
43
60
|
}
|
|
44
61
|
|
|
45
62
|
// How a sync reads and writes an object (sync-engine.js). Each operation names a capability of the right kind on
|
|
@@ -140,6 +157,7 @@ function validateManifest(m) {
|
|
|
140
157
|
if (w.account) tpl(w.account, 'webhook.account');
|
|
141
158
|
const batch = w.batch == null ? [] : Array.isArray(w.batch) ? w.batch : [w.batch];
|
|
142
159
|
if (batch.length > 2 || batch.some((b) => typeof b !== 'string')) err('webhook.batch', 'A path to the array of events, or [outer, inner] for two levels');
|
|
160
|
+
if (w.status !== undefined && w.status !== 'unimplemented') err('webhook.status', 'Only "unimplemented" (the module\'s Api has no verify method)');
|
|
143
161
|
if (w.verify != null && !/^[A-Za-z_$][\w$]*$/.test(w.verify)) err('webhook.verify', 'Name of an Api method that checks the signature');
|
|
144
162
|
if (w.handshake) {
|
|
145
163
|
try { parseCondition(w.handshake.when); } catch (e) { err('webhook.handshake.when', e.message); }
|
|
@@ -21,6 +21,21 @@ const { TRANSFORMS } = require('./transforms');
|
|
|
21
21
|
* Backed by IntegrationMapping: get = getMapping, put = upsertMapping, claim = createMapping (insert-only; false if it existed)
|
|
22
22
|
* @param {(ref:string, args:object) => Promise<any>} [p.runCode]
|
|
23
23
|
*/
|
|
24
|
+
/**
|
|
25
|
+
* The arguments an Api method is called with. A capability with no `args` takes one object holding every input; one
|
|
26
|
+
* with `args` (manifest `args`) takes them positionally: an input by name, "$rest" (an object of the inputs not
|
|
27
|
+
* named in the list) or { value } (a constant, e.g. the sObject name of Salesforce's generic create/get).
|
|
28
|
+
*/
|
|
29
|
+
function argumentsFor(input, order) {
|
|
30
|
+
if (!Array.isArray(order)) return [input];
|
|
31
|
+
const named = new Set(order.filter((a) => typeof a === 'string' && a !== '$rest'));
|
|
32
|
+
return order.map((a) => {
|
|
33
|
+
if (a === '$rest') return Object.fromEntries(Object.entries(input || {}).filter(([k]) => !named.has(k)));
|
|
34
|
+
if (a && typeof a === 'object') return a.value;
|
|
35
|
+
return input?.[a];
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
24
39
|
function makePorts({ def, manifests, callApi, store, runCode }) {
|
|
25
40
|
const manifestFor = (key) => manifests[def.modules[key]?.module];
|
|
26
41
|
const normalise = (set, key, value) => {
|
|
@@ -39,7 +54,7 @@ function makePorts({ def, manifests, callApi, store, runCode }) {
|
|
|
39
54
|
async call(moduleKey, capability, args) {
|
|
40
55
|
const c = manifestFor(moduleKey)?.capabilities?.[capability];
|
|
41
56
|
if (!c) throw new Error(`${moduleKey}.${capability} is not declared by the module manifest`);
|
|
42
|
-
return callApi(moduleKey, c.method, args);
|
|
57
|
+
return callApi(moduleKey, c.method, args, c.args);
|
|
43
58
|
},
|
|
44
59
|
links: {
|
|
45
60
|
/** By one side's id: link:<set>:<module>:<id>. By identity key: idx:<set>:<key>:<normalised value>. */
|
|
@@ -250,4 +265,4 @@ function defaultsOf(settings) {
|
|
|
250
265
|
return Object.fromEntries(Object.entries(settings || {}).filter(([, s]) => s.default !== undefined).map(([k, s]) => [k, s.default]));
|
|
251
266
|
}
|
|
252
267
|
|
|
253
|
-
module.exports = { makePorts, runWorkflow, resumeWorkflow, runQuery, renderSurface, resolveView, runLifecycle, resolveOptions, installContext, recordOf, defaultsOf };
|
|
268
|
+
module.exports = { argumentsFor, makePorts, runWorkflow, resumeWorkflow, runQuery, renderSurface, resolveView, runLifecycle, resolveOptions, installContext, recordOf, defaultsOf };
|
|
@@ -411,6 +411,15 @@
|
|
|
411
411
|
"body": {}
|
|
412
412
|
},
|
|
413
413
|
"description": "Answered at receipt, before anything is queued (Slack url_verification, Asana X-Hook-Secret)."
|
|
414
|
+
},
|
|
415
|
+
"status": {
|
|
416
|
+
"enum": [
|
|
417
|
+
"unimplemented"
|
|
418
|
+
],
|
|
419
|
+
"description": "The module's Api has no `verify` method (or none that checks a signature). Every delivery fails verification until it does, so definitions that trigger on this module's events validate with a warning."
|
|
420
|
+
},
|
|
421
|
+
"note": {
|
|
422
|
+
"type": "string"
|
|
414
423
|
}
|
|
415
424
|
}
|
|
416
425
|
},
|
|
@@ -445,6 +454,37 @@
|
|
|
445
454
|
},
|
|
446
455
|
"output": {
|
|
447
456
|
"type": "string"
|
|
457
|
+
},
|
|
458
|
+
"args": {
|
|
459
|
+
"type": "array",
|
|
460
|
+
"description": "How the Api method takes its arguments, when it is not one object holding every input. Each entry is an input name (passed positionally), \"$rest\" (an object of every input not named elsewhere in the list) or {\"value\": x} (a constant, such as the sObject name of a generic Api). Omitted: the method is called with one object of all inputs.",
|
|
461
|
+
"items": {
|
|
462
|
+
"oneOf": [
|
|
463
|
+
{
|
|
464
|
+
"type": "string"
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
"type": "object",
|
|
468
|
+
"required": [
|
|
469
|
+
"value"
|
|
470
|
+
],
|
|
471
|
+
"additionalProperties": false,
|
|
472
|
+
"properties": {
|
|
473
|
+
"value": {}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
"status": {
|
|
480
|
+
"enum": [
|
|
481
|
+
"unimplemented"
|
|
482
|
+
],
|
|
483
|
+
"description": "The module's real Api class has no method that does this (or none shaped so the call can be made). Definitions that use it validate with a warning, never an error."
|
|
484
|
+
},
|
|
485
|
+
"note": {
|
|
486
|
+
"type": "string",
|
|
487
|
+
"description": "What the real method does differently, or what is missing upstream."
|
|
448
488
|
}
|
|
449
489
|
}
|
|
450
490
|
}
|