@teleporthq/teleport-plugin-next-workflows 0.43.26 → 0.43.30
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/__tests__/_helpers/load-handler.ts +11 -1
- package/__tests__/file-storage-upload-picked-files.test.ts +135 -0
- package/__tests__/runtime-operator-aliases.test.ts +180 -0
- package/__tests__/runtime-template-token-resolution.test.ts +225 -0
- package/__tests__/salesforce-opportunity-id.test.ts +122 -0
- package/__tests__/state-update-array-type-guard.test.ts +172 -0
- package/dist/cjs/data-api-route-generator.d.ts.map +1 -1
- package/dist/cjs/data-api-route-generator.js +10 -0
- package/dist/cjs/data-api-route-generator.js.map +1 -1
- package/dist/cjs/executor-generator.d.ts.map +1 -1
- package/dist/cjs/executor-generator.js +134 -5
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/nodes/data/data-count.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-count.js +16 -0
- package/dist/cjs/nodes/data/data-count.js.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.js +20 -0
- package/dist/cjs/nodes/data/data-create-item.js.map +1 -1
- package/dist/cjs/nodes/data/data-delete-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-delete-item.js +26 -1
- package/dist/cjs/nodes/data/data-delete-item.js.map +1 -1
- package/dist/cjs/nodes/data/data-select.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-select.js +18 -0
- package/dist/cjs/nodes/data/data-select.js.map +1 -1
- package/dist/cjs/nodes/data/data-update-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-update-item.js +43 -1
- package/dist/cjs/nodes/data/data-update-item.js.map +1 -1
- package/dist/cjs/nodes/integrations/integration-salesforce.d.ts.map +1 -1
- package/dist/cjs/nodes/integrations/integration-salesforce.js +3 -3
- package/dist/cjs/nodes/integrations/integration-salesforce.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/workflow-component-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-component-plugin.js +56 -9
- package/dist/cjs/workflow-component-plugin.js.map +1 -1
- package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-project-plugin.js +34 -9
- package/dist/cjs/workflow-project-plugin.js.map +1 -1
- package/dist/esm/data-api-route-generator.d.ts.map +1 -1
- package/dist/esm/data-api-route-generator.js +10 -0
- package/dist/esm/data-api-route-generator.js.map +1 -1
- package/dist/esm/executor-generator.d.ts.map +1 -1
- package/dist/esm/executor-generator.js +134 -5
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/nodes/data/data-count.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-count.js +16 -0
- package/dist/esm/nodes/data/data-count.js.map +1 -1
- package/dist/esm/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-create-item.js +20 -0
- package/dist/esm/nodes/data/data-create-item.js.map +1 -1
- package/dist/esm/nodes/data/data-delete-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-delete-item.js +26 -1
- package/dist/esm/nodes/data/data-delete-item.js.map +1 -1
- package/dist/esm/nodes/data/data-select.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-select.js +18 -0
- package/dist/esm/nodes/data/data-select.js.map +1 -1
- package/dist/esm/nodes/data/data-update-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-update-item.js +43 -1
- package/dist/esm/nodes/data/data-update-item.js.map +1 -1
- package/dist/esm/nodes/integrations/integration-salesforce.d.ts.map +1 -1
- package/dist/esm/nodes/integrations/integration-salesforce.js +3 -3
- package/dist/esm/nodes/integrations/integration-salesforce.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/workflow-component-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-component-plugin.js +56 -9
- package/dist/esm/workflow-component-plugin.js.map +1 -1
- package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-project-plugin.js +34 -9
- package/dist/esm/workflow-project-plugin.js.map +1 -1
- package/package.json +2 -2
- package/src/data-api-route-generator.ts +10 -0
- package/src/executor-generator.ts +134 -5
- package/src/nodes/data/data-count.ts +20 -0
- package/src/nodes/data/data-create-item.ts +19 -0
- package/src/nodes/data/data-delete-item.ts +30 -1
- package/src/nodes/data/data-select.ts +22 -0
- package/src/nodes/data/data-update-item.ts +45 -1
- package/src/nodes/integrations/integration-salesforce.ts +22 -13
- package/src/workflow-component-plugin.ts +61 -3
- package/src/workflow-project-plugin.ts +29 -4
|
@@ -246,11 +246,14 @@ async function integration_salesforce(config: any, context: Record<string, unkno
|
|
|
246
246
|
}
|
|
247
247
|
case 'update-opportunity': {
|
|
248
248
|
const body = config.fields || {}
|
|
249
|
-
const response = await fetch(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
249
|
+
const response = await fetch(
|
|
250
|
+
baseUrl + 'sobjects/Opportunity/' + (config.opportunityId || config.oppId),
|
|
251
|
+
{
|
|
252
|
+
method: 'PATCH',
|
|
253
|
+
headers,
|
|
254
|
+
body: JSON.stringify(body),
|
|
255
|
+
}
|
|
256
|
+
)
|
|
254
257
|
if (!response.ok) {
|
|
255
258
|
const data = await __readJson(response)
|
|
256
259
|
return {
|
|
@@ -261,10 +264,13 @@ async function integration_salesforce(config: any, context: Record<string, unkno
|
|
|
261
264
|
return { success: true }
|
|
262
265
|
}
|
|
263
266
|
case 'get-opportunity': {
|
|
264
|
-
const response = await fetch(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
267
|
+
const response = await fetch(
|
|
268
|
+
baseUrl + 'sobjects/Opportunity/' + (config.opportunityId || config.oppId),
|
|
269
|
+
{
|
|
270
|
+
method: 'GET',
|
|
271
|
+
headers,
|
|
272
|
+
}
|
|
273
|
+
)
|
|
268
274
|
const data = await __readJson(response)
|
|
269
275
|
if (!response.ok) {
|
|
270
276
|
return {
|
|
@@ -275,10 +281,13 @@ async function integration_salesforce(config: any, context: Record<string, unkno
|
|
|
275
281
|
return { success: true, opportunity: data }
|
|
276
282
|
}
|
|
277
283
|
case 'delete-opportunity': {
|
|
278
|
-
const response = await fetch(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
284
|
+
const response = await fetch(
|
|
285
|
+
baseUrl + 'sobjects/Opportunity/' + (config.opportunityId || config.oppId),
|
|
286
|
+
{
|
|
287
|
+
method: 'DELETE',
|
|
288
|
+
headers,
|
|
289
|
+
}
|
|
290
|
+
)
|
|
282
291
|
if (!response.ok) {
|
|
283
292
|
const data = await __readJson(response)
|
|
284
293
|
return {
|
|
@@ -327,7 +327,14 @@ export const createNextWorkflowPlugin: ComponentPluginFactory<WorkflowPluginConf
|
|
|
327
327
|
const hasCurrentUserGlobalRefs = activeWorkflows.some((wf) =>
|
|
328
328
|
hasGlobalContextStateRefTransitively(wf.nodes, workflows.customNodes, new Set<string>())
|
|
329
329
|
)
|
|
330
|
-
|
|
330
|
+
// Node configs may also reference the logged-in user via a literal
|
|
331
|
+
// {{Current User.id}} template token (resolved at runtime from the
|
|
332
|
+
// __stateValues.currentUser bridge) — those pages need the same
|
|
333
|
+
// GlobalContext plumbing even without a state-get/update node.
|
|
334
|
+
const hasCurrentUserToken = activeWorkflows.some((wf) =>
|
|
335
|
+
wf.nodes.some((n) => JSON.stringify(n.config || {}).includes('{{Current User.'))
|
|
336
|
+
)
|
|
337
|
+
const needsGlobalContextBridge = hasAuthNodes || hasCurrentUserGlobalRefs || hasCurrentUserToken
|
|
331
338
|
|
|
332
339
|
const hasAudioNodes = activeWorkflows.some((wf) =>
|
|
333
340
|
wf.nodes.some((n) => n.type === 'audio-play' || n.type === 'audio-stop')
|
|
@@ -399,6 +406,15 @@ export const createNextWorkflowPlugin: ComponentPluginFactory<WorkflowPluginConf
|
|
|
399
406
|
(!pageProtection.allowedRoles || pageProtection.allowedRoles.length === 0)
|
|
400
407
|
)
|
|
401
408
|
|
|
409
|
+
const dynamicRouteAttributeRaw = (uidl as any).outputOptions?.dynamicRouteAttribute as
|
|
410
|
+
| string
|
|
411
|
+
| undefined
|
|
412
|
+
const dynamicRouteAttribute =
|
|
413
|
+
typeof dynamicRouteAttributeRaw === 'string' &&
|
|
414
|
+
/^[A-Za-z_][A-Za-z0-9_-]*$/.test(dynamicRouteAttributeRaw)
|
|
415
|
+
? dynamicRouteAttributeRaw
|
|
416
|
+
: undefined
|
|
417
|
+
|
|
402
418
|
const moduleCode = generateModuleLevelCode(
|
|
403
419
|
activeWorkflows,
|
|
404
420
|
matchedElementTriggers,
|
|
@@ -408,7 +424,8 @@ export const createNextWorkflowPlugin: ComponentPluginFactory<WorkflowPluginConf
|
|
|
408
424
|
globalStateChangeWorkflows,
|
|
409
425
|
hasAudioNodes,
|
|
410
426
|
needsAdminFormHydration,
|
|
411
|
-
isRowOwnedSelfGuardedPage
|
|
427
|
+
isRowOwnedSelfGuardedPage,
|
|
428
|
+
dynamicRouteAttribute
|
|
412
429
|
)
|
|
413
430
|
|
|
414
431
|
if (moduleCode) {
|
|
@@ -558,6 +575,14 @@ export const createNextWorkflowPlugin: ComponentPluginFactory<WorkflowPluginConf
|
|
|
558
575
|
path: `${pathPrefix}utils/workflows/runtime`,
|
|
559
576
|
}
|
|
560
577
|
|
|
578
|
+
// Router singleton for {{urlDifferentiator}}-style token resolution in
|
|
579
|
+
// __execWf (route params are only reachable client-side at call time).
|
|
580
|
+
dependencies.Router = {
|
|
581
|
+
type: 'library',
|
|
582
|
+
path: 'next/router',
|
|
583
|
+
version: '12.1.0',
|
|
584
|
+
}
|
|
585
|
+
|
|
561
586
|
dependencies.workflowClientHandlers = {
|
|
562
587
|
type: 'local',
|
|
563
588
|
path: `${pathPrefix}utils/workflows/node-handlers-client`,
|
|
@@ -1160,7 +1185,8 @@ const generateModuleLevelCode = (
|
|
|
1160
1185
|
globalStateChangeWorkflows: UIDLWorkflow[],
|
|
1161
1186
|
hasAudioNodes?: boolean,
|
|
1162
1187
|
includeAdminFormHydrationHelper?: boolean,
|
|
1163
|
-
isRowOwnedSelfGuardedPage?: boolean
|
|
1188
|
+
isRowOwnedSelfGuardedPage?: boolean,
|
|
1189
|
+
dynamicRouteAttribute?: string
|
|
1164
1190
|
): string => {
|
|
1165
1191
|
if (allWorkflows.length === 0) {
|
|
1166
1192
|
return ''
|
|
@@ -1451,6 +1477,26 @@ function __createWorkflowHandlers(stateSetters, stateTypes, stateValuesRef) {
|
|
|
1451
1477
|
) {
|
|
1452
1478
|
value = value.value;
|
|
1453
1479
|
}
|
|
1480
|
+
// Array-typed states must never receive a non-array payload — one
|
|
1481
|
+
// poisoned write (e.g. a ref resolving to a custom-js node's whole
|
|
1482
|
+
// { result: [...] } return object instead of its array property)
|
|
1483
|
+
// bricks every downstream consumer: the mapper renders nothing and
|
|
1484
|
+
// the next add-row spread throws "is not iterable". Mirrors the
|
|
1485
|
+
// GUI-side guard: unwrap an object with a single array-valued
|
|
1486
|
+
// property, otherwise fall back to an empty array.
|
|
1487
|
+
if (type === 'array' && !Array.isArray(value)) {
|
|
1488
|
+
console.warn(
|
|
1489
|
+
'[workflow] non-array value written to array state "' + property + '"; coercing',
|
|
1490
|
+
value
|
|
1491
|
+
);
|
|
1492
|
+
if (value && typeof value === 'object') {
|
|
1493
|
+
var arrayKeys = Object.keys(value);
|
|
1494
|
+
if (arrayKeys.length === 1 && Array.isArray(value[arrayKeys[0]])) {
|
|
1495
|
+
return value[arrayKeys[0]];
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
return [];
|
|
1499
|
+
}
|
|
1454
1500
|
if (type === 'boolean') return value === 'true' || value === true;
|
|
1455
1501
|
if (type === 'number' && typeof value === 'string') {
|
|
1456
1502
|
const parsed = Number(value);
|
|
@@ -1552,6 +1598,18 @@ function __createWorkflowHandlers(stateSetters, stateTypes, stateValuesRef) {
|
|
|
1552
1598
|
|
|
1553
1599
|
function __execWf(config, triggerContext, serverUrls) {
|
|
1554
1600
|
triggerContext.__stateValues = Object.assign({}, stateValuesRef.current);
|
|
1601
|
+
// Route context for {{urlDifferentiator}} / {{Current Page Entity.id}}
|
|
1602
|
+
// template tokens in node configs — resolved by the shared runtime's
|
|
1603
|
+
// resolveTemplateTokenString. Read at call time (not render time) so the
|
|
1604
|
+
// handlers survive client-side navigation between dynamic routes.
|
|
1605
|
+
if (typeof window !== 'undefined' && Router && Router.router && Router.router.query) {
|
|
1606
|
+
triggerContext.__routeParams = Object.assign({}, Router.router.query);
|
|
1607
|
+
}
|
|
1608
|
+
${
|
|
1609
|
+
dynamicRouteAttribute
|
|
1610
|
+
? ` triggerContext.__dynamicRouteParam = '${dynamicRouteAttribute}';\n`
|
|
1611
|
+
: ''
|
|
1612
|
+
}
|
|
1555
1613
|
var fullConfig = typeof workflowCustomNodes !== 'undefined'
|
|
1556
1614
|
? Object.assign({}, config, { customNodes: workflowCustomNodes })
|
|
1557
1615
|
: config;
|
|
@@ -413,10 +413,35 @@ export class NextWorkflowProjectPlugin implements ProjectPlugin {
|
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
if (needsDataAPIRoute(usedNodeTypes)) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
416
|
+
// Resolve the actual IDENTITY (users) table, not just the first auth-table
|
|
417
|
+
// key. Getting this wrong is a security hole: the /api/data guard only
|
|
418
|
+
// protects AUTH_USERS_TABLE, so if it points at an auxiliary table like
|
|
419
|
+
// `password_reset_tokens`, the real `users` table is left mutable
|
|
420
|
+
// unauthenticated. The identity table is the one storing credentials
|
|
421
|
+
// (an email/login column AND a password column).
|
|
422
|
+
const authUsersTableName = ((): string | undefined => {
|
|
423
|
+
if (!uidl.authentication?.enabled || !uidl.authentication?.tables) {
|
|
424
|
+
return undefined
|
|
425
|
+
}
|
|
426
|
+
const tables = uidl.authentication.tables
|
|
427
|
+
const names = Object.keys(tables)
|
|
428
|
+
if (names.length === 0) return 'users'
|
|
429
|
+
const cols = (n: string) => (tables[n] || []).map((c) => (c.name || '').toLowerCase())
|
|
430
|
+
const has = (n: string, re: RegExp) => cols(n).some((c) => re.test(c))
|
|
431
|
+
const identity = names.find(
|
|
432
|
+
(n) =>
|
|
433
|
+
has(n, /^(email|e_mail|username|user_name|login|user_email)$/) &&
|
|
434
|
+
has(n, /pass(word)?|pwd|password_hash|hashed_password/)
|
|
435
|
+
)
|
|
436
|
+
if (identity) return identity
|
|
437
|
+
const named = names.find((n) =>
|
|
438
|
+
/^(app_)?users?$|^members?$|^customers?$|^accounts?$/i.test(n)
|
|
439
|
+
)
|
|
440
|
+
if (named) return named
|
|
441
|
+
const AUX = /token|session|verification|reset|oauth|provider|magic|otp|account_link/i
|
|
442
|
+
const nonAux = names.find((n) => !AUX.test(n))
|
|
443
|
+
return nonAux || names[0]
|
|
444
|
+
})()
|
|
420
445
|
// Low-stock auto-fire: the data-api wakes up the
|
|
421
446
|
// /api/ecommerce/low-stock-alert endpoint on the place-order
|
|
422
447
|
// workflow's stock-check SELECT. Both flags are sourced from
|