@teleporthq/teleport-plugin-next-workflows 0.44.6 → 0.44.7
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__/credential-columns-reply.test.ts +286 -0
- package/dist/cjs/api-route-generator.d.ts.map +1 -1
- package/dist/cjs/api-route-generator.js +3 -2
- package/dist/cjs/api-route-generator.js.map +1 -1
- package/dist/cjs/credential-columns-code.d.ts +17 -0
- package/dist/cjs/credential-columns-code.d.ts.map +1 -0
- package/dist/cjs/credential-columns-code.js +61 -0
- package/dist/cjs/credential-columns-code.js.map +1 -0
- package/dist/cjs/data-api-route-generator.d.ts +1 -0
- package/dist/cjs/data-api-route-generator.d.ts.map +1 -1
- package/dist/cjs/data-api-route-generator.js +13 -5
- 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 +12 -2
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/api-route-generator.d.ts.map +1 -1
- package/dist/esm/api-route-generator.js +3 -2
- package/dist/esm/api-route-generator.js.map +1 -1
- package/dist/esm/credential-columns-code.d.ts +17 -0
- package/dist/esm/credential-columns-code.d.ts.map +1 -0
- package/dist/esm/credential-columns-code.js +57 -0
- package/dist/esm/credential-columns-code.js.map +1 -0
- package/dist/esm/data-api-route-generator.d.ts +1 -0
- package/dist/esm/data-api-route-generator.d.ts.map +1 -1
- package/dist/esm/data-api-route-generator.js +11 -3
- 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 +12 -2
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/api-route-generator.ts +3 -2
- package/src/credential-columns-code.ts +59 -0
- package/src/data-api-route-generator.ts +11 -3
- package/src/executor-generator.ts +12 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teleporthq/teleport-plugin-next-workflows",
|
|
3
|
-
"version": "0.44.
|
|
3
|
+
"version": "0.44.7",
|
|
4
4
|
"description": "A plugin for workflow code generation in Next.js projects.",
|
|
5
5
|
"author": "teleportHQ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@babel/types": "^7.5.5",
|
|
69
|
-
"@teleporthq/teleport-shared": "^0.44.
|
|
69
|
+
"@teleporthq/teleport-shared": "^0.44.7",
|
|
70
70
|
"@teleporthq/teleport-types": "^0.44.0"
|
|
71
71
|
},
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "a279c1bd1e268a8b7302e2c4fafd45748a1d242a"
|
|
73
73
|
}
|
|
@@ -527,11 +527,12 @@ function __isStreamingAI(node, config) {
|
|
|
527
527
|
return config && config.streaming && __streamingAITypes.indexOf(node.type) >= 0;
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
-
// One node's result to the browser — never one kept on the server
|
|
530
|
+
// One node's result to the browser — never one kept on the server, and a data
|
|
531
|
+
// node's rows without the users table's credentials (see segmentReply).
|
|
531
532
|
function __streamNodeResult(res, nodeId, result) {
|
|
532
533
|
const kept = SEGMENT_CONFIG.nodes.find(function(nd) { return nd.id === nodeId; });
|
|
533
534
|
if (kept && kept.config && kept.config.keepResultOnServer === true && !utils.isBranchingNodeType(kept.type)) return;
|
|
534
|
-
res.write('data: ' + JSON.stringify({ type: 'node-result', nodeId: nodeId, result: result }) + '\\n\\n');
|
|
535
|
+
res.write('data: ' + JSON.stringify({ type: 'node-result', nodeId: nodeId, result: utils.withoutCredentialColumns(kept, result) }) + '\\n\\n');
|
|
535
536
|
}
|
|
536
537
|
|
|
537
538
|
function __collectSegBranchNodes(startId, excludeId) {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { TableAccess } from '@teleporthq/teleport-shared'
|
|
2
|
+
import { DATA_NODE_TYPES } from './data-api-route-generator'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Runtime helpers that leave the auth users table's credential columns out of
|
|
6
|
+
* the rows a server segment answers the browser with — the columns
|
|
7
|
+
* `TableAccess.AUTH_CREDENTIAL_COLUMNS` names, the ones every browser read of
|
|
8
|
+
* the data route is already served without. A data node of a server segment
|
|
9
|
+
* reads through the data route as the app's own server code, so its rows come
|
|
10
|
+
* back whole, and the segment's reply (or a streamed node result) is the
|
|
11
|
+
* browser's copy of them.
|
|
12
|
+
*
|
|
13
|
+
* Only the results of the nodes that read rows (`DATA_NODE_TYPES`) are
|
|
14
|
+
* touched: all the credentials of a row of the users table, the unambiguous
|
|
15
|
+
* ones of a raw statement's row, whose table is not known. A row is the
|
|
16
|
+
* result itself (a create or update spreads its row into it), an object it
|
|
17
|
+
* holds, or an element of an array it holds; column values are not walked.
|
|
18
|
+
*/
|
|
19
|
+
export const generateCredentialColumnsCode = (): string => `
|
|
20
|
+
var __CREDENTIAL_COLUMNS = ${JSON.stringify(TableAccess.AUTH_CREDENTIAL_COLUMNS)};
|
|
21
|
+
var __UNAMBIGUOUS_CREDENTIAL_COLUMNS = ${JSON.stringify(
|
|
22
|
+
TableAccess.UNAMBIGUOUS_CREDENTIAL_COLUMNS
|
|
23
|
+
)};
|
|
24
|
+
var __CREDENTIAL_TABLES = ${JSON.stringify(TableAccess.AUTH_CREDENTIAL_TABLES)};
|
|
25
|
+
var __ROW_NODE_TYPES = ${JSON.stringify(Array.from(DATA_NODE_TYPES))};
|
|
26
|
+
|
|
27
|
+
function credentialColumnsOf(node) {
|
|
28
|
+
if (!node || __ROW_NODE_TYPES.indexOf(node.type) === -1) return [];
|
|
29
|
+
var tableName = node.config && typeof node.config.tableName === 'string' ? node.config.tableName : '';
|
|
30
|
+
if (!tableName) return __UNAMBIGUOUS_CREDENTIAL_COLUMNS;
|
|
31
|
+
var parts = tableName.trim().toLowerCase().replace(/"/g, '').split('.');
|
|
32
|
+
return __CREDENTIAL_TABLES.indexOf(parts[parts.length - 1]) !== -1 ? __CREDENTIAL_COLUMNS : [];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function withoutColumns(row, columns) {
|
|
36
|
+
if (!row || typeof row !== 'object' || Array.isArray(row)) return row;
|
|
37
|
+
var kept = {};
|
|
38
|
+
Object.keys(row).forEach(function(key) {
|
|
39
|
+
if (columns.indexOf(String(key).toLowerCase()) === -1) kept[key] = row[key];
|
|
40
|
+
});
|
|
41
|
+
return kept;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function withoutRowsColumns(value, columns) {
|
|
45
|
+
if (Array.isArray(value)) return value.map(function(row) { return withoutColumns(row, columns); });
|
|
46
|
+
return withoutColumns(value, columns);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function withoutCredentialColumns(node, result) {
|
|
50
|
+
var columns = credentialColumnsOf(node);
|
|
51
|
+
if (columns.length === 0 || !result || typeof result !== 'object') return result;
|
|
52
|
+
if (Array.isArray(result)) return withoutRowsColumns(result, columns);
|
|
53
|
+
var kept = withoutColumns(result, columns);
|
|
54
|
+
Object.keys(kept).forEach(function(key) {
|
|
55
|
+
if (kept[key] && typeof kept[key] === 'object') kept[key] = withoutRowsColumns(kept[key], columns);
|
|
56
|
+
});
|
|
57
|
+
return kept;
|
|
58
|
+
}
|
|
59
|
+
`
|
|
@@ -15,7 +15,7 @@ import { generateSqlValidatorCode } from './sql-validator'
|
|
|
15
15
|
import { generateCommonJsSessionTokenResolverCode } from './session-cookie-resolver'
|
|
16
16
|
import { ContentTables, TableAccess } from '@teleporthq/teleport-shared'
|
|
17
17
|
|
|
18
|
-
const DATA_NODE_TYPES = new Set([
|
|
18
|
+
export const DATA_NODE_TYPES: ReadonlySet<string> = new Set([
|
|
19
19
|
'data-select',
|
|
20
20
|
'data-create-item',
|
|
21
21
|
'data-update-item',
|
|
@@ -677,6 +677,13 @@ function dropMissingOptionalColumns(tableName, entries, colTypes) {
|
|
|
677
677
|
return kept;
|
|
678
678
|
}
|
|
679
679
|
|
|
680
|
+
// The row a create or update answers with, whoever asked, without the auth
|
|
681
|
+
// users table's credentials (the columns a browser read is served without):
|
|
682
|
+
// a server-side caller hands that answer on to the browser as its result.
|
|
683
|
+
function withoutCredentialColumns(row, tableName) {
|
|
684
|
+
return row ? __taWithoutCredentials([row], tableName)[0] : row;
|
|
685
|
+
}
|
|
686
|
+
|
|
680
687
|
async function handleCreate(client, body) {
|
|
681
688
|
var tableName = body.tableName;
|
|
682
689
|
var columnMappings = body.columnMappings || {};
|
|
@@ -751,7 +758,7 @@ async function handleCreate(client, body) {
|
|
|
751
758
|
var item = result.rows && result.rows[0] ? result.rows[0] : null;
|
|
752
759
|
var idIdx = columns.indexOf('id');
|
|
753
760
|
var resolvedId = item ? (item.id || null) : (idIdx >= 0 ? values[idIdx] : null);
|
|
754
|
-
return { item: item, id: resolvedId };
|
|
761
|
+
return { item: withoutCredentialColumns(item, tableName), id: resolvedId };
|
|
755
762
|
}
|
|
756
763
|
|
|
757
764
|
async function handleUpdate(client, body) {
|
|
@@ -803,7 +810,8 @@ async function handleUpdate(client, body) {
|
|
|
803
810
|
sql += ' RETURNING *';
|
|
804
811
|
|
|
805
812
|
var result = await safeQuery(client, sql, queryParams, 'update');
|
|
806
|
-
|
|
813
|
+
var updated = result.rows[0] || null;
|
|
814
|
+
return { updatedCount: result.rowCount || 0, item: withoutCredentialColumns(updated, tableName), id: (updated && updated.id) || null };
|
|
807
815
|
}
|
|
808
816
|
|
|
809
817
|
async function handleDelete(client, body) {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
generateWorkflowLocaleHelpersCode,
|
|
5
5
|
} from './email-locale'
|
|
6
6
|
import { generateSignedInDestinationCode } from './auth-return/signed-in-destination-code'
|
|
7
|
+
import { generateCredentialColumnsCode } from './credential-columns-code'
|
|
7
8
|
|
|
8
9
|
export interface SharedRuntimeUtilsOptions {
|
|
9
10
|
/**
|
|
@@ -1414,6 +1415,10 @@ var SEGMENT_REPLY_PRIVATE_KEYS = {
|
|
|
1414
1415
|
// nodes after it in the same segment and never leaves the server (a statement's
|
|
1415
1416
|
// rows read only to build what the browser may see, a sender's recipients).
|
|
1416
1417
|
// Nothing in a later segment can read it.
|
|
1418
|
+
//
|
|
1419
|
+
// A data node's rows are replied without the auth users table's credentials
|
|
1420
|
+
// (see credential-columns-code.ts).
|
|
1421
|
+
${generateCredentialColumnsCode()}
|
|
1417
1422
|
// The nodes whose result the client branches on: never kept on the server.
|
|
1418
1423
|
function isBranchingNodeType(type) {
|
|
1419
1424
|
return type === 'general-if-statement' || type === 'general-switch';
|
|
@@ -1425,7 +1430,7 @@ function segmentReply(segmentConfig, context, snapshot) {
|
|
|
1425
1430
|
var kept = {};
|
|
1426
1431
|
var nodes = (segmentConfig && segmentConfig.nodes) || [];
|
|
1427
1432
|
for (var ni = 0; ni < nodes.length; ni++) {
|
|
1428
|
-
own[nodes[ni].id] =
|
|
1433
|
+
own[nodes[ni].id] = nodes[ni];
|
|
1429
1434
|
if (nodes[ni].config && nodes[ni].config.keepResultOnServer === true && !isBranchingNodeType(nodes[ni].type)) {
|
|
1430
1435
|
kept[nodes[ni].id] = true;
|
|
1431
1436
|
}
|
|
@@ -1436,7 +1441,11 @@ function segmentReply(segmentConfig, context, snapshot) {
|
|
|
1436
1441
|
if (SEGMENT_REPLY_PRIVATE_KEYS[key] || kept[key]) continue;
|
|
1437
1442
|
var value = context[key];
|
|
1438
1443
|
if (value === undefined) continue;
|
|
1439
|
-
if (own[key]
|
|
1444
|
+
if (own[key]) {
|
|
1445
|
+
reply[key] = withoutCredentialColumns(own[key], value);
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
if (!snapshot || !Object.prototype.hasOwnProperty.call(snapshot, key)) {
|
|
1440
1449
|
reply[key] = value;
|
|
1441
1450
|
continue;
|
|
1442
1451
|
}
|
|
@@ -1504,6 +1513,7 @@ module.exports = {
|
|
|
1504
1513
|
loopIterationContext,
|
|
1505
1514
|
snapshotIncomingContext,
|
|
1506
1515
|
segmentReply,
|
|
1516
|
+
withoutCredentialColumns,
|
|
1507
1517
|
evaluateCondition,
|
|
1508
1518
|
evaluateSingleComparison,
|
|
1509
1519
|
normalizeComparisonOperator,
|