lucid-extension-sdk 0.0.260 → 0.0.262
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/core/data/fieldspecification.d.ts +1 -0
- package/core/data/fieldspecification.js +4 -1
- package/core/rules/conditions.d.ts +5 -1
- package/core/rules/conditions.js +6 -1
- package/core/rules/conditiontype.d.ts +2 -1
- package/core/rules/conditiontype.js +1 -0
- package/dataconnector/actions/patchresponsebody.d.ts +2 -7
- package/dataconnector/dataconnector.d.ts +6 -1
- package/dataconnector/dataconnector.js +11 -3
- package/dataconnector/datasourceupdatetypes.d.ts +2 -0
- package/dataconnector/datasourceupdatetypes.js +2 -0
- package/dataconnector/itemrekeyer.d.ts +15 -0
- package/dataconnector/itemrekeyer.js +79 -0
- package/document/documentelement/documentelementtype.d.ts +2 -1
- package/document/documentelement/documentelementtype.js +1 -0
- package/package.json +1 -1
|
@@ -71,6 +71,7 @@ export declare class FormattedPrimaryKey<Fields extends FieldsStructure, Primary
|
|
|
71
71
|
* ```
|
|
72
72
|
*/
|
|
73
73
|
forItem(item: PartialItemType<Fields, PrimaryKey>): string;
|
|
74
|
+
static serializeList(items: unknown[]): string;
|
|
74
75
|
}
|
|
75
76
|
/**
|
|
76
77
|
* Root type for something that looks like the field list we use to sync with the data-sync service.
|
|
@@ -68,7 +68,10 @@ class FormattedPrimaryKey {
|
|
|
68
68
|
* ```
|
|
69
69
|
*/
|
|
70
70
|
forItem(item) {
|
|
71
|
-
|
|
71
|
+
return FormattedPrimaryKey.serializeList(this.elements.map((field) => item[field]));
|
|
72
|
+
}
|
|
73
|
+
static serializeList(items) {
|
|
74
|
+
let pk = JSON.stringify(items);
|
|
72
75
|
pk = pk.substring(1, pk.length - 1);
|
|
73
76
|
return pk;
|
|
74
77
|
}
|
|
@@ -48,4 +48,8 @@ export declare enum ConnectedShapesCondition {
|
|
|
48
48
|
Between = 14,
|
|
49
49
|
NotBetween = 15
|
|
50
50
|
}
|
|
51
|
-
export
|
|
51
|
+
export declare enum ContainmentConditions {
|
|
52
|
+
TextContains = 2,
|
|
53
|
+
TextDoesNotContain = 3
|
|
54
|
+
}
|
|
55
|
+
export type Conditions = TextConditions | ShapeDataConditions | ShapeTypeConditions | ConnectedShapesCondition | ContainmentConditions;
|
package/core/rules/conditions.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ConnectedShapesCondition = exports.ShapeTypeConditions = exports.ShapeDataConditions = exports.TextConditions = exports.ConditionCombination = void 0;
|
|
3
|
+
exports.ContainmentConditions = exports.ConnectedShapesCondition = exports.ShapeTypeConditions = exports.ShapeDataConditions = exports.TextConditions = exports.ConditionCombination = void 0;
|
|
4
4
|
var ConditionCombination;
|
|
5
5
|
(function (ConditionCombination) {
|
|
6
6
|
ConditionCombination["AND"] = "AND";
|
|
@@ -56,3 +56,8 @@ var ConnectedShapesCondition;
|
|
|
56
56
|
ConnectedShapesCondition[ConnectedShapesCondition["Between"] = 14] = "Between";
|
|
57
57
|
ConnectedShapesCondition[ConnectedShapesCondition["NotBetween"] = 15] = "NotBetween";
|
|
58
58
|
})(ConnectedShapesCondition || (exports.ConnectedShapesCondition = ConnectedShapesCondition = {}));
|
|
59
|
+
var ContainmentConditions;
|
|
60
|
+
(function (ContainmentConditions) {
|
|
61
|
+
ContainmentConditions[ContainmentConditions["TextContains"] = 2] = "TextContains";
|
|
62
|
+
ContainmentConditions[ContainmentConditions["TextDoesNotContain"] = 3] = "TextDoesNotContain";
|
|
63
|
+
})(ContainmentConditions || (exports.ContainmentConditions = ContainmentConditions = {}));
|
|
@@ -8,4 +8,5 @@ var ConditionType;
|
|
|
8
8
|
ConditionType[ConditionType["Formula"] = 2] = "Formula";
|
|
9
9
|
ConditionType[ConditionType["ShapeType"] = 3] = "ShapeType";
|
|
10
10
|
ConditionType[ConditionType["ConnectedShapes"] = 4] = "ConnectedShapes";
|
|
11
|
+
ConditionType[ConditionType["Containment"] = 5] = "Containment";
|
|
11
12
|
})(ConditionType || (exports.ConditionType = ConditionType = {}));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ItemsPatch } from '../datasourceupdatetypes';
|
|
1
|
+
import { ItemsPatch, SerializedItemsPatch } from '../datasourceupdatetypes';
|
|
2
2
|
export type PatchChangeCollection = {
|
|
3
3
|
collectionId: string;
|
|
4
4
|
itemsPatch: ItemsPatch;
|
|
@@ -26,12 +26,7 @@ export type SerializedPatchChange = {
|
|
|
26
26
|
'syncId': string;
|
|
27
27
|
'collections': {
|
|
28
28
|
'collectionId': string;
|
|
29
|
-
'itemsPatch':
|
|
30
|
-
'items': Record<string, object>;
|
|
31
|
-
'itemsDeleted': string[];
|
|
32
|
-
} | {
|
|
33
|
-
'exhaustiveItems': Record<string, object>;
|
|
34
|
-
};
|
|
29
|
+
'itemsPatch': SerializedItemsPatch;
|
|
35
30
|
}[];
|
|
36
31
|
};
|
|
37
32
|
/** Wire format for "Patch" Action responses */
|
|
@@ -3,8 +3,9 @@ import { DataConnectorActionKeys } from './actions/dataconnectoractionkeys';
|
|
|
3
3
|
import { PatchChange } from './actions/patchresponsebody';
|
|
4
4
|
import { DataConnectorClient } from './dataconnectorclient';
|
|
5
5
|
import { ExpressAppLike, RunDebugServerOptions } from './debugserver';
|
|
6
|
+
import { ItemRekeyer } from './itemrekeyer';
|
|
6
7
|
/** Type to define an action request handler. That is a function that can fulfil an incoming action */
|
|
7
|
-
type ActionRequest<ArgType, BodyType = unknown> = (args: ArgType) => Promise<BodyType>;
|
|
8
|
+
type ActionRequest<ArgType, BodyType = unknown> = (args: ArgType, dataConnectorRequestState: DataConnectorRequestState) => Promise<BodyType>;
|
|
8
9
|
/** Type to define an arbitrary non-action request to this server. Useful for handling webhook responses in the same
|
|
9
10
|
* lambda that handles data actions */
|
|
10
11
|
export type DataConnectorRoute = (args: {
|
|
@@ -32,6 +33,10 @@ export declare class DataConnectorRequestError extends Error {
|
|
|
32
33
|
constructor(status: number, message: string, response: string, statusText?: string | undefined);
|
|
33
34
|
toString(): string;
|
|
34
35
|
}
|
|
36
|
+
export declare class DataConnectorRequestState {
|
|
37
|
+
itemRekeyer: ItemRekeyer;
|
|
38
|
+
constructor(itemRekeyer: ItemRekeyer);
|
|
39
|
+
}
|
|
35
40
|
/** Thrown by any APIs the client didn't recognize when parsing */
|
|
36
41
|
export declare class DataConnectorResponseError extends Error {
|
|
37
42
|
response: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DataConnector = exports.DataConnectorResponseError = exports.DataConnectorRequestError = exports.DataConnectorRunError = void 0;
|
|
3
|
+
exports.DataConnector = exports.DataConnectorResponseError = exports.DataConnectorRequestState = exports.DataConnectorRequestError = exports.DataConnectorRunError = void 0;
|
|
4
4
|
const checks_1 = require("../core/checks");
|
|
5
5
|
const validators_1 = require("../core/validators/validators");
|
|
6
6
|
const action_1 = require("./actions/action");
|
|
@@ -8,6 +8,7 @@ const dataconnectoractionkeys_1 = require("./actions/dataconnectoractionkeys");
|
|
|
8
8
|
const managewebhookresponsebody_1 = require("./actions/managewebhookresponsebody");
|
|
9
9
|
const patchresponsebody_1 = require("./actions/patchresponsebody");
|
|
10
10
|
const debugserver_1 = require("./debugserver");
|
|
11
|
+
const itemrekeyer_1 = require("./itemrekeyer");
|
|
11
12
|
/** Throw this from an action request handler to produce a non-200 response code and not have to return the expected
|
|
12
13
|
* result type */
|
|
13
14
|
class DataConnectorRunError extends Error {
|
|
@@ -34,6 +35,12 @@ class DataConnectorRequestError extends Error {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
exports.DataConnectorRequestError = DataConnectorRequestError;
|
|
38
|
+
class DataConnectorRequestState {
|
|
39
|
+
constructor(itemRekeyer) {
|
|
40
|
+
this.itemRekeyer = itemRekeyer;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.DataConnectorRequestState = DataConnectorRequestState;
|
|
37
44
|
/** Thrown by any APIs the client didn't recognize when parsing */
|
|
38
45
|
class DataConnectorResponseError extends Error {
|
|
39
46
|
constructor(message, response) {
|
|
@@ -65,6 +72,7 @@ class DataConnector {
|
|
|
65
72
|
}
|
|
66
73
|
/** Call a defined action handler and gather its serialized response */
|
|
67
74
|
async runAction(url, headers, body) {
|
|
75
|
+
const state = new DataConnectorRequestState(new itemrekeyer_1.ItemRekeyer());
|
|
68
76
|
const actions = await this.client.parseActions(url, headers, body);
|
|
69
77
|
if (!actions) {
|
|
70
78
|
console.warn('Received bad request', url, headers, body);
|
|
@@ -83,10 +91,10 @@ class DataConnector {
|
|
|
83
91
|
if (!(action instanceof action_1.DataConnectorAsynchronousAction)) {
|
|
84
92
|
throw DataConnectorRunError.withMessage(400, `Passing uncredentialed action to ${action.name} which is defined to be asynchronous`);
|
|
85
93
|
}
|
|
86
|
-
return actionResponder(action);
|
|
94
|
+
return actionResponder(action, state);
|
|
87
95
|
}
|
|
88
96
|
else {
|
|
89
|
-
return actionResponder(action);
|
|
97
|
+
return actionResponder(action, state);
|
|
90
98
|
}
|
|
91
99
|
})();
|
|
92
100
|
responses.push(await response);
|
|
@@ -59,6 +59,7 @@ export declare class ItemsPatchInexhaustive {
|
|
|
59
59
|
/** Items to remove from the collection, based on the same primary key algorithm. */
|
|
60
60
|
itemsDeleted?: string[] | undefined;
|
|
61
61
|
errors?: Map<string, SerializedLucidDictionary> | undefined;
|
|
62
|
+
private readonly _brand;
|
|
62
63
|
constructor(
|
|
63
64
|
/**
|
|
64
65
|
* Items to be added or changed in the collection. Mapping from item serialized primary key to
|
|
@@ -72,6 +73,7 @@ export declare class ItemsPatchExhaustive {
|
|
|
72
73
|
items: Map<string, SerializedFields>;
|
|
73
74
|
rekeyingMap?: Map<string, string | null> | undefined;
|
|
74
75
|
errors?: Map<string, SerializedLucidDictionary> | undefined;
|
|
76
|
+
private readonly _brand;
|
|
75
77
|
constructor(items: Map<string, SerializedFields>, rekeyingMap?: Map<string, string | null> | undefined, errors?: Map<string, SerializedLucidDictionary> | undefined);
|
|
76
78
|
}
|
|
77
79
|
export type ItemsPatch = {
|
|
@@ -17,6 +17,7 @@ class ItemsPatchInexhaustive {
|
|
|
17
17
|
this.items = items;
|
|
18
18
|
this.itemsDeleted = itemsDeleted;
|
|
19
19
|
this.errors = errors;
|
|
20
|
+
this._brand = ItemsPatchInexhaustive;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
exports.ItemsPatchInexhaustive = ItemsPatchInexhaustive;
|
|
@@ -25,6 +26,7 @@ class ItemsPatchExhaustive {
|
|
|
25
26
|
this.items = items;
|
|
26
27
|
this.rekeyingMap = rekeyingMap;
|
|
27
28
|
this.errors = errors;
|
|
29
|
+
this._brand = ItemsPatchExhaustive;
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
exports.ItemsPatchExhaustive = ItemsPatchExhaustive;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FormattedPrimaryKey } from '../core/data/fieldspecification';
|
|
2
|
+
import { Patch, PatchItems } from './actions/action';
|
|
3
|
+
import { ItemsPatch } from './datasourceupdatetypes';
|
|
4
|
+
export declare class RekeyingMap {
|
|
5
|
+
map: Map<string, string | null>;
|
|
6
|
+
constructor(map: Map<string, string | null>);
|
|
7
|
+
getNewKey(key: string): string;
|
|
8
|
+
getRecordWithNewKeys(items: PatchItems): PatchItems;
|
|
9
|
+
getRekeyedPatch(patch: Patch): Patch;
|
|
10
|
+
}
|
|
11
|
+
export declare class ItemRekeyer {
|
|
12
|
+
private rekeyingMaps;
|
|
13
|
+
addRekeyingsFor(collectionId: string, itemsPatch: ItemsPatch, primaryKey?: FormattedPrimaryKey<any, string>): void;
|
|
14
|
+
getRekeyingMap(patch: Patch): RekeyingMap | undefined;
|
|
15
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ItemRekeyer = exports.RekeyingMap = void 0;
|
|
4
|
+
const fieldspecification_1 = require("../core/data/fieldspecification");
|
|
5
|
+
const object_1 = require("../core/object");
|
|
6
|
+
const action_1 = require("./actions/action");
|
|
7
|
+
const datasourceupdatetypes_1 = require("./datasourceupdatetypes");
|
|
8
|
+
function calculateRekeyingMap(itemsPatch, primaryKey) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
if (itemsPatch instanceof datasourceupdatetypes_1.ItemsPatchExhaustive) {
|
|
11
|
+
return itemsPatch.rekeyingMap;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
if (!primaryKey) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const constPrimaryKey = primaryKey;
|
|
18
|
+
function primaryKeyIfChanged(oldPrimaryKey, item) {
|
|
19
|
+
const changedParts = constPrimaryKey.elements.map((field) => item[field]);
|
|
20
|
+
if (changedParts.find((x) => x !== undefined) === undefined) {
|
|
21
|
+
// this patch didn't touch the primary key
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
// we might need parts of the old primary key if only some of the primary key fields changed.
|
|
25
|
+
// As an optimization we could only compute this if at least one of the changedParts is
|
|
26
|
+
// undefined.
|
|
27
|
+
const oldParts = JSON.parse(`[${oldPrimaryKey}]`);
|
|
28
|
+
const newParts = changedParts.map((part, index) => (part !== undefined ? part : oldParts[index]));
|
|
29
|
+
const newPrimaryKey = fieldspecification_1.FormattedPrimaryKey.serializeList(newParts);
|
|
30
|
+
if (newPrimaryKey !== oldPrimaryKey) {
|
|
31
|
+
return newPrimaryKey;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const itemsMap = [...itemsPatch.items.entries()]
|
|
38
|
+
.map(([key, value]) => [key, primaryKeyIfChanged(key, value)])
|
|
39
|
+
.filter((x) => x[1] !== undefined);
|
|
40
|
+
const deletedMap = (_b = (_a = itemsPatch.itemsDeleted) === null || _a === void 0 ? void 0 : _a.map((key) => [key, null])) !== null && _b !== void 0 ? _b : [];
|
|
41
|
+
const theMap = new Map([...itemsMap, ...deletedMap]);
|
|
42
|
+
return theMap.size > 0 ? theMap : undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
class RekeyingMap {
|
|
46
|
+
constructor(map) {
|
|
47
|
+
this.map = map;
|
|
48
|
+
}
|
|
49
|
+
getNewKey(key) {
|
|
50
|
+
var _a;
|
|
51
|
+
return (_a = this.map.get(key)) !== null && _a !== void 0 ? _a : key;
|
|
52
|
+
}
|
|
53
|
+
getRecordWithNewKeys(items) {
|
|
54
|
+
return (0, object_1.fromEntries)(Object.entries(items).map(([key, value]) => [this.getNewKey(key), value]));
|
|
55
|
+
}
|
|
56
|
+
getRekeyedPatch(patch) {
|
|
57
|
+
var _a;
|
|
58
|
+
return new action_1.Patch(patch.id, this.getRecordWithNewKeys(patch.itemsAdded), this.getRecordWithNewKeys(patch.itemsChanged), patch.itemsDeleted.map((key) => this.getNewKey(key)), (_a = patch.itemOrderChanged) === null || _a === void 0 ? void 0 : _a.map(([a, b]) => [this.getNewKey(a), b && this.getNewKey(b)]), patch.syncSourceId, patch.syncCollectionId);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.RekeyingMap = RekeyingMap;
|
|
62
|
+
class ItemRekeyer {
|
|
63
|
+
constructor() {
|
|
64
|
+
this.rekeyingMaps = new Map();
|
|
65
|
+
}
|
|
66
|
+
addRekeyingsFor(collectionId, itemsPatch, primaryKey) {
|
|
67
|
+
var _a;
|
|
68
|
+
const rekeyingMap = calculateRekeyingMap(itemsPatch, primaryKey);
|
|
69
|
+
if (rekeyingMap) {
|
|
70
|
+
const existingMap = this.rekeyingMaps.get(collectionId);
|
|
71
|
+
const rekeyedExisting = [...((_a = existingMap === null || existingMap === void 0 ? void 0 : existingMap.map.entries()) !== null && _a !== void 0 ? _a : [])].map(([key, value]) => { var _a; return [key, value && ((_a = rekeyingMap.get(value)) !== null && _a !== void 0 ? _a : value)]; });
|
|
72
|
+
this.rekeyingMaps.set(collectionId, new RekeyingMap(new Map([...rekeyingMap.entries(), ...rekeyedExisting])));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
getRekeyingMap(patch) {
|
|
76
|
+
return this.rekeyingMaps.get(patch.syncCollectionId);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.ItemRekeyer = ItemRekeyer;
|
|
@@ -13,5 +13,6 @@ export declare enum DocumentElementType {
|
|
|
13
13
|
TaskCardFieldsConfig = "TaskCardFieldsConfig",
|
|
14
14
|
GeneratorView = "GeneratorView",
|
|
15
15
|
ShapeStylePreset = "ShapeStylePreset",
|
|
16
|
-
ShapeSpecificDefaultProperties = "ShapeSpecificDefaultProperties"
|
|
16
|
+
ShapeSpecificDefaultProperties = "ShapeSpecificDefaultProperties",
|
|
17
|
+
TrackedFormulaLocation = "TrackedFormulaLocation"
|
|
17
18
|
}
|
|
@@ -18,4 +18,5 @@ var DocumentElementType;
|
|
|
18
18
|
DocumentElementType["GeneratorView"] = "GeneratorView";
|
|
19
19
|
DocumentElementType["ShapeStylePreset"] = "ShapeStylePreset";
|
|
20
20
|
DocumentElementType["ShapeSpecificDefaultProperties"] = "ShapeSpecificDefaultProperties";
|
|
21
|
+
DocumentElementType["TrackedFormulaLocation"] = "TrackedFormulaLocation";
|
|
21
22
|
})(DocumentElementType || (exports.DocumentElementType = DocumentElementType = {}));
|