lucid-extension-sdk 0.0.296 → 0.0.297

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Semantic Relationships serve as standardized categories of relationships which exist in multiple data sources but potentially under different names.
3
+ * For instance, regardless of the data source, relationships that pertains to parent/child structures can be categorized under the Semantic Relationship "IsParentOf" and "IsChildOf".
4
+ *
5
+ * Benefits of Semantic Relationships:
6
+ * Uniformity: Ensures that data from diverse sources is referenced consistently within Lucid.
7
+ * Integration Simplicity: Simplifies the process of integrating new data sources into Lucid by mapping to an established set of Semantic Relationships.
8
+ * Feature Compatibility: Allows for seamless use of Lucid’s intelligent features across all data, regardless of its origin.
9
+ * Data Organization: Provides a structured approach to organizing and grouping data within the Lucid ecosystem.
10
+ */
11
+ export declare enum SemanticRelationships {
12
+ RelatesTo = "RelatesTo",
13
+ Duplicates = "Duplicates",
14
+ IsDuplicatedBy = "IsDuplicatedBy",
15
+ Blocks = "Blocks",
16
+ IsBlockedBy = "IsBlockedBy",
17
+ Clones = "Clones",
18
+ IsClonedBy = "IsClonedBy",
19
+ IsParentOf = "IsParentOf",
20
+ IsChildOf = "IsChildOf"
21
+ }
22
+ export declare function getInverseSemanticRelationship(relationship: SemanticRelationships): SemanticRelationships;
23
+ export declare const isSemanticRelationship: (x: unknown) => x is SemanticRelationships;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSemanticRelationship = exports.getInverseSemanticRelationship = exports.SemanticRelationships = void 0;
4
+ const validators_1 = require("../../validators/validators");
5
+ /**
6
+ * Semantic Relationships serve as standardized categories of relationships which exist in multiple data sources but potentially under different names.
7
+ * For instance, regardless of the data source, relationships that pertains to parent/child structures can be categorized under the Semantic Relationship "IsParentOf" and "IsChildOf".
8
+ *
9
+ * Benefits of Semantic Relationships:
10
+ * Uniformity: Ensures that data from diverse sources is referenced consistently within Lucid.
11
+ * Integration Simplicity: Simplifies the process of integrating new data sources into Lucid by mapping to an established set of Semantic Relationships.
12
+ * Feature Compatibility: Allows for seamless use of Lucid’s intelligent features across all data, regardless of its origin.
13
+ * Data Organization: Provides a structured approach to organizing and grouping data within the Lucid ecosystem.
14
+ */
15
+ var SemanticRelationships;
16
+ (function (SemanticRelationships) {
17
+ SemanticRelationships["RelatesTo"] = "RelatesTo";
18
+ SemanticRelationships["Duplicates"] = "Duplicates";
19
+ SemanticRelationships["IsDuplicatedBy"] = "IsDuplicatedBy";
20
+ SemanticRelationships["Blocks"] = "Blocks";
21
+ SemanticRelationships["IsBlockedBy"] = "IsBlockedBy";
22
+ SemanticRelationships["Clones"] = "Clones";
23
+ SemanticRelationships["IsClonedBy"] = "IsClonedBy";
24
+ SemanticRelationships["IsParentOf"] = "IsParentOf";
25
+ SemanticRelationships["IsChildOf"] = "IsChildOf";
26
+ })(SemanticRelationships || (exports.SemanticRelationships = SemanticRelationships = {}));
27
+ function getInverseSemanticRelationship(relationship) {
28
+ switch (relationship) {
29
+ case SemanticRelationships.Duplicates:
30
+ return SemanticRelationships.IsDuplicatedBy;
31
+ case SemanticRelationships.IsDuplicatedBy:
32
+ return SemanticRelationships.Duplicates;
33
+ case SemanticRelationships.Blocks:
34
+ return SemanticRelationships.IsBlockedBy;
35
+ case SemanticRelationships.IsBlockedBy:
36
+ return SemanticRelationships.Blocks;
37
+ case SemanticRelationships.Clones:
38
+ return SemanticRelationships.IsClonedBy;
39
+ case SemanticRelationships.IsClonedBy:
40
+ return SemanticRelationships.Clones;
41
+ case SemanticRelationships.IsParentOf:
42
+ return SemanticRelationships.IsChildOf;
43
+ case SemanticRelationships.IsChildOf:
44
+ return SemanticRelationships.IsParentOf;
45
+ default:
46
+ return relationship;
47
+ }
48
+ }
49
+ exports.getInverseSemanticRelationship = getInverseSemanticRelationship;
50
+ exports.isSemanticRelationship = (0, validators_1.stringEnumValidator)(SemanticRelationships);
@@ -1,22 +1,6 @@
1
1
  import { isString } from '../../checks';
2
+ import { SerializedSourceForeignKey } from './serializedsourceforeignkey';
2
3
  import { SerializedUpstreamConfig } from './serializedupstreamconfig';
3
- export declare enum Direction {
4
- Inward = "inward",
5
- Outward = "outward"
6
- }
7
- export type DirectionType = Direction | null | undefined;
8
- export type SerializedSourceForeignKey = {
9
- 'Id': string;
10
- 'SourceFields': string[];
11
- 'RelationshipType': string;
12
- 'Represents'?: string | null | undefined;
13
- 'Direction'?: DirectionType;
14
- };
15
- export declare const isSerializedSourceForeignKey: (subject: unknown) => subject is import("../../guards").DestructureGuardedTypeObj<{
16
- Id: typeof isString;
17
- SourceFields: (p1: unknown) => p1 is string[];
18
- RelationshipType: typeof isString;
19
- }>;
20
4
  /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
21
5
  export interface SerializedDataSourceProperties {
22
6
  'Name': string;
@@ -1,22 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isSerializedDataSourceProperties = exports.isSerializedSourceForeignKey = exports.Direction = void 0;
3
+ exports.isSerializedDataSourceProperties = void 0;
4
4
  const checks_1 = require("../../checks");
5
5
  const validators_1 = require("../../validators/validators");
6
+ const serializedsourceforeignkey_1 = require("./serializedsourceforeignkey");
6
7
  const serializedupstreamconfig_1 = require("./serializedupstreamconfig");
7
- var Direction;
8
- (function (Direction) {
9
- Direction["Inward"] = "inward";
10
- Direction["Outward"] = "outward";
11
- })(Direction || (exports.Direction = Direction = {}));
12
- exports.isSerializedSourceForeignKey = (0, validators_1.objectValidator)({
13
- 'Id': checks_1.isString,
14
- 'SourceFields': (0, validators_1.arrayValidator)(checks_1.isString),
15
- 'RelationshipType': checks_1.isString,
16
- });
17
8
  /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
18
9
  exports.isSerializedDataSourceProperties = (0, validators_1.strictObjectValidator)({
19
10
  'Name': checks_1.isString,
20
11
  'UpstreamConfig': (0, validators_1.nullableOption)(serializedupstreamconfig_1.isSerializedUpstreamConfig),
21
- 'SourceForeignKeys': (0, validators_1.nullableOption)((0, validators_1.arrayValidator)(exports.isSerializedSourceForeignKey)),
12
+ 'SourceForeignKeys': (0, validators_1.nullableOption)((0, validators_1.arrayValidator)(serializedsourceforeignkey_1.isSerializedSourceForeignKey)),
22
13
  });
@@ -56,7 +56,6 @@ export declare const isSerializedImportedDataSource: (subject: unknown) => subje
56
56
  SourceConfig: typeof isObject;
57
57
  }> | null | undefined;
58
58
  SourceForeignKeys: (x: unknown) => x is import("../../guards").DestructureGuardedTypeObj<{
59
- /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
60
59
  Id: typeof isString;
61
60
  SourceFields: (p1: unknown) => p1 is string[];
62
61
  RelationshipType: typeof isString;
@@ -93,7 +92,6 @@ export declare const isSerializedPreviewData: (subject: unknown) => subject is i
93
92
  SourceConfig: typeof isObject;
94
93
  }> | null | undefined;
95
94
  SourceForeignKeys: (x: unknown) => x is import("../../guards").DestructureGuardedTypeObj<{
96
- /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
97
95
  Id: typeof isString;
98
96
  SourceFields: (p1: unknown) => p1 is string[];
99
97
  RelationshipType: typeof isString;
@@ -0,0 +1,19 @@
1
+ import { isString } from '../../checks';
2
+ import { SemanticRelationships } from './semanticrelationships';
3
+ export declare enum Direction {
4
+ Inward = "inward",
5
+ Outward = "outward"
6
+ }
7
+ export type DirectionType = Direction | null | undefined;
8
+ export type SerializedSourceForeignKey = {
9
+ 'Id': string;
10
+ 'SourceFields': string[];
11
+ 'RelationshipType': SemanticRelationships | string;
12
+ 'Represents'?: string | null | undefined;
13
+ 'Direction'?: DirectionType;
14
+ };
15
+ export declare const isSerializedSourceForeignKey: (subject: unknown) => subject is import("../../guards").DestructureGuardedTypeObj<{
16
+ Id: typeof isString;
17
+ SourceFields: (p1: unknown) => p1 is string[];
18
+ RelationshipType: typeof isString;
19
+ }>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSerializedSourceForeignKey = exports.Direction = void 0;
4
+ const checks_1 = require("../../checks");
5
+ const validators_1 = require("../../validators/validators");
6
+ var Direction;
7
+ (function (Direction) {
8
+ Direction["Inward"] = "inward";
9
+ Direction["Outward"] = "outward";
10
+ })(Direction || (exports.Direction = Direction = {}));
11
+ exports.isSerializedSourceForeignKey = (0, validators_1.objectValidator)({
12
+ 'Id': checks_1.isString,
13
+ 'SourceFields': (0, validators_1.arrayValidator)(checks_1.isString),
14
+ 'RelationshipType': checks_1.isString,
15
+ });
@@ -0,0 +1,11 @@
1
+ import { SemanticRelationships } from './semanticrelationships';
2
+ import { DirectionType, SerializedSourceForeignKey } from './serializedsourceforeignkey';
3
+ export type SourceForeignKey = {
4
+ 'id': string;
5
+ 'sourceFields': string[];
6
+ 'relationshipType': SemanticRelationships | string;
7
+ 'represents'?: string | undefined;
8
+ 'direction'?: DirectionType;
9
+ };
10
+ export declare function serializeSourceForeignKey(foreignKey: SourceForeignKey): SerializedSourceForeignKey;
11
+ export declare function deserializeSourceForeignKey(foreignKey: SerializedSourceForeignKey): SourceForeignKey;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deserializeSourceForeignKey = exports.serializeSourceForeignKey = void 0;
4
+ function serializeSourceForeignKey(foreignKey) {
5
+ return {
6
+ 'Id': foreignKey.id,
7
+ 'SourceFields': foreignKey.sourceFields,
8
+ 'RelationshipType': foreignKey.relationshipType,
9
+ 'Represents': foreignKey.represents,
10
+ 'Direction': foreignKey.direction,
11
+ };
12
+ }
13
+ exports.serializeSourceForeignKey = serializeSourceForeignKey;
14
+ function deserializeSourceForeignKey(foreignKey) {
15
+ return {
16
+ 'id': foreignKey['Id'],
17
+ 'sourceFields': foreignKey['SourceFields'],
18
+ 'relationshipType': foreignKey['RelationshipType'],
19
+ 'represents': foreignKey['Represents'] === null ? undefined : foreignKey['Represents'],
20
+ 'direction': foreignKey['Direction'],
21
+ };
22
+ }
23
+ exports.deserializeSourceForeignKey = deserializeSourceForeignKey;
@@ -1,7 +1,9 @@
1
- import { ItemsPatch, SerializedItemsPatch } from '../datasourceupdatetypes';
1
+ import { SchemaDefinition } from '../../data/schemadefinition';
2
+ import { ItemsPatch, SerializedItemsPatch, SerializedSchemaForApi } from '../datasourceupdatetypes';
2
3
  export type PatchChangeCollection = {
3
4
  collectionId: string;
4
5
  itemsPatch: ItemsPatch;
6
+ schema?: SchemaDefinition;
5
7
  };
6
8
  /**
7
9
  * Reports a completed change back to Lucid
@@ -27,6 +29,7 @@ export type SerializedPatchChange = {
27
29
  'collections': {
28
30
  'collectionId': string;
29
31
  'itemsPatch': SerializedItemsPatch;
32
+ 'schema'?: SerializedSchemaForApi;
30
33
  }[];
31
34
  };
32
35
  /** Wire format for "Patch" Action responses */
@@ -34,10 +34,7 @@ function serializePatchResponse(patchChange) {
34
34
  return {
35
35
  'syncId': patchChange.syncId,
36
36
  'collections': patchChange.collections.map((c) => {
37
- return {
38
- 'collectionId': c.collectionId,
39
- 'itemsPatch': (0, datasourceupdatetypes_1.serializeItemsPatch)(c.itemsPatch),
40
- };
37
+ return Object.assign({ 'collectionId': c.collectionId, 'itemsPatch': (0, datasourceupdatetypes_1.serializeItemsPatch)(c.itemsPatch) }, (c.schema != null ? { 'schema': (0, datasourceupdatetypes_1.serializeSchemaForApi)(c.schema) } : undefined));
41
38
  }),
42
39
  };
43
40
  }
@@ -4,7 +4,7 @@ import { ItemPatch, Patch, PatchParser } from './actions/patch';
4
4
  import { PatchChange } from './actions/patchresponsebody';
5
5
  import { DataConnectorClient } from './dataconnectorclient';
6
6
  import { ExpressAppLike, RunDebugServerOptions } from './debugserver';
7
- import { ItemRekeyer } from './itemrekeyer';
7
+ import { ItemRekeyerAndRelabeler } from './itemrekeyerandrelabeler';
8
8
  /** Type to define an action request handler. That is a function that can fulfil an incoming action */
9
9
  type ActionRequest<ArgType, BodyType = unknown> = (args: ArgType, dataConnectorRequestState: DataConnectorRequestState) => Promise<BodyType>;
10
10
  /** Type to define an arbitrary non-action request to this server. Useful for handling webhook responses in the same
@@ -35,8 +35,8 @@ export declare class DataConnectorRequestError extends Error {
35
35
  toString(): string;
36
36
  }
37
37
  export declare class DataConnectorRequestState {
38
- itemRekeyer: ItemRekeyer;
39
- constructor(itemRekeyer: ItemRekeyer);
38
+ itemRekeyer: ItemRekeyerAndRelabeler;
39
+ constructor(itemRekeyer: ItemRekeyerAndRelabeler);
40
40
  }
41
41
  /** Thrown by any APIs the client didn't recognize when parsing */
42
42
  export declare class DataConnectorResponseError extends Error {
@@ -9,7 +9,7 @@ const managewebhookresponsebody_1 = require("./actions/managewebhookresponsebody
9
9
  const patch_1 = require("./actions/patch");
10
10
  const patchresponsebody_1 = require("./actions/patchresponsebody");
11
11
  const debugserver_1 = require("./debugserver");
12
- const itemrekeyer_1 = require("./itemrekeyer");
12
+ const itemrekeyerandrelabeler_1 = require("./itemrekeyerandrelabeler");
13
13
  /** Throw this from an action request handler to produce a non-200 response code and not have to return the expected
14
14
  * result type */
15
15
  class DataConnectorRunError extends Error {
@@ -74,7 +74,7 @@ class DataConnector {
74
74
  }
75
75
  /** Call a defined action handler and gather its serialized response */
76
76
  async runAction(url, headers, body) {
77
- const state = new DataConnectorRequestState(new itemrekeyer_1.ItemRekeyer());
77
+ const state = new DataConnectorRequestState(new itemrekeyerandrelabeler_1.ItemRekeyerAndRelabeler());
78
78
  const actions = await this.client.parseActions(url, headers, body, this.patchParser);
79
79
  if (!actions) {
80
80
  console.warn('Received bad request', url, headers, body);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MockDataSourceClient = exports.DataSourceClient = void 0;
4
4
  const checks_1 = require("../core/checks");
5
5
  const datasourcetype_1 = require("../core/data/datasource/datasourcetype");
6
+ const sourceforeignkeys_1 = require("../core/data/datasource/sourceforeignkeys");
6
7
  const upstreamconfig_1 = require("../core/data/datasource/upstreamconfig");
7
8
  const upstreamupdatetype_1 = require("../core/data/datasource/upstreamupdatetype");
8
9
  const result_1 = require("../core/result");
@@ -24,7 +25,7 @@ class DataSourceClient {
24
25
  const dataSyncUrl = urls.dataSync;
25
26
  this.metadataUrl = (0, checks_1.isString)(dataSyncUrl) ? `${dataSyncUrl}dataSource/metadata` : undefined;
26
27
  }
27
- formatBody({ dataSourceName, collections, updateFilterType, dataSourceConfiguration }) {
28
+ formatBody({ dataSourceName, collections, updateFilterType, dataSourceConfiguration, sourceForeignKeys, }) {
28
29
  const updateData = {};
29
30
  for (const collectionId in collections) {
30
31
  updateData[collectionId] = (0, datasourceupdatetypes_1.serializeCollectionPatch)(collections[collectionId]);
@@ -36,10 +37,12 @@ class DataSourceClient {
36
37
  patchType: dataSourceConfiguration === null || dataSourceConfiguration === void 0 ? void 0 : dataSourceConfiguration.patchType,
37
38
  sourceConfig: Object.assign({}, updateFilterTypeObj),
38
39
  };
40
+ const foreignKeys = sourceForeignKeys ? sourceForeignKeys.map(sourceforeignkeys_1.serializeSourceForeignKey) : [];
39
41
  return {
40
42
  'updateData': updateData,
41
43
  'name': dataSourceName,
42
44
  'upstreamConfig': (0, upstreamconfig_1.serializeUpstreamConfig)(upstreamConfig),
45
+ 'sourceForeignKeys': foreignKeys,
43
46
  };
44
47
  }
45
48
  /** Create or update a datasource. If you create a new collection it must be fully specified in terms of schema and
@@ -1,4 +1,5 @@
1
1
  import { SemanticCollection } from '../core/data/datasource/semanticcollection';
2
+ import { SourceForeignKey } from '../core/data/datasource/sourceforeignkeys';
2
3
  import { UpstreamPatchType } from '../core/data/datasource/upstreampatchtype';
3
4
  import { SerializedFieldTypeDefinition } from '../core/data/fieldtypedefinition/fieldtypedefinition';
4
5
  import { SemanticFields } from '../core/data/fieldtypedefinition/semanticfields';
@@ -24,6 +25,8 @@ export type DataSourceRequest = {
24
25
  /** Configures how changes made to the data are pushed to the external source */
25
26
  patchType: UpstreamPatchType;
26
27
  };
28
+ /** Configuration for relationships between collections in the data source */
29
+ sourceForeignKeys?: SourceForeignKey[];
27
30
  };
28
31
  type SerializedFieldConstraintForApi = {
29
32
  'type': FieldConstraintType;
@@ -36,7 +39,7 @@ type SerializedFieldDefinitionForApi = {
36
39
  'syncSchema'?: string;
37
40
  'mapping'?: readonly SemanticKind[] | readonly SemanticFields[];
38
41
  };
39
- type SerializedSchemaForApi = {
42
+ export type SerializedSchemaForApi = {
40
43
  'fields': SerializedFieldDefinitionForApi[];
41
44
  'primaryKey': string[];
42
45
  'fieldLabelOverrides'?: SerializedLabelOverrides | undefined;
@@ -124,6 +127,7 @@ export interface CollectionPatch {
124
127
  }
125
128
  /** @ignore */
126
129
  export declare function serializeFieldDefinitionForApi(field: FieldDefinition): SerializedFieldDefinitionForApi;
130
+ export declare function serializeSchemaForApi(schema: SchemaDefinition): SerializedSchemaForApi;
127
131
  export declare function serializeCollectionPatch(patch: CollectionPatch): SerializedCollectionPatch;
128
132
  /**
129
133
  * For the moment, when the upstream Google Sheet is changed in such a way that the schema has changed, we simply
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.schemaOKStatus = exports.schemaOutOfSyncStatus = exports.serializeCollectionPatch = exports.serializeFieldDefinitionForApi = exports.serializeItemsPatch = exports.ItemsPatchExhaustive = exports.ItemsPatchInexhaustive = void 0;
3
+ exports.schemaOKStatus = exports.schemaOutOfSyncStatus = exports.serializeCollectionPatch = exports.serializeSchemaForApi = exports.serializeFieldDefinitionForApi = exports.serializeItemsPatch = exports.ItemsPatchExhaustive = exports.ItemsPatchInexhaustive = void 0;
4
4
  const checks_1 = require("../core/checks");
5
5
  const fieldtypedefinition_1 = require("../core/data/fieldtypedefinition/fieldtypedefinition");
6
6
  const object_1 = require("../core/object");
@@ -74,6 +74,7 @@ function serializeSchemaForApi(schema) {
74
74
  'fieldLabelOverrides': schema.fieldLabels,
75
75
  };
76
76
  }
77
+ exports.serializeSchemaForApi = serializeSchemaForApi;
77
78
  function serializeRepresentsAsPropertyForApi(represents) {
78
79
  return {
79
80
  'Represents': represents, // key needs to match 'Represents' key in cake/app/webroot/ts/property/collection/collectionproperties.ts
@@ -0,0 +1,20 @@
1
+ import { FormattedPrimaryKey } from '../core/data/fieldspecification';
2
+ import { Patch } from './actions/patch';
3
+ import { ItemsPatch } from './datasourceupdatetypes';
4
+ export declare class RekeyingRelabelingMap {
5
+ readonly keyMap: Map<string, string | null>;
6
+ readonly labelMap: Map<string, string | null>;
7
+ constructor(keyMap: Map<string, string | null>, labelMap: Map<string, string | null>);
8
+ private getNewKey;
9
+ private getNewLabel;
10
+ private getRelabeledItem;
11
+ private getRecordWithNewKeysAndLabels;
12
+ private getRelabeledThirdPartyColumn;
13
+ private getRelabeledThirdPartyColumnPatches;
14
+ getRekeyedRelabeledPatch(patch: Patch): Patch;
15
+ }
16
+ export declare class ItemRekeyerAndRelabeler {
17
+ private rekeyingRelabelingMaps;
18
+ addRekeyingsRelabelingsFor(collectionId: string, itemsPatch: ItemsPatch, primaryKey?: FormattedPrimaryKey<any, string>): void;
19
+ getRekeyingRelabelingMap(patch: Patch): RekeyingRelabelingMap | undefined;
20
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ItemRekeyerAndRelabeler = exports.RekeyingRelabelingMap = void 0;
4
+ const fieldspecification_1 = require("../core/data/fieldspecification");
5
+ const object_1 = require("../core/object");
6
+ const patch_1 = require("./actions/patch");
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
+ function calculateRelabelingMap(itemsPatch) {
46
+ if (itemsPatch instanceof datasourceupdatetypes_1.ItemsPatchExhaustive) {
47
+ return itemsPatch.fieldNamesChanged;
48
+ }
49
+ else {
50
+ return undefined;
51
+ }
52
+ }
53
+ class RekeyingRelabelingMap {
54
+ constructor(keyMap, labelMap) {
55
+ this.keyMap = keyMap;
56
+ this.labelMap = labelMap;
57
+ }
58
+ getNewKey(key) {
59
+ var _a;
60
+ return (_a = this.keyMap.get(key)) !== null && _a !== void 0 ? _a : key;
61
+ }
62
+ getNewLabel(label) {
63
+ var _a;
64
+ return (_a = this.labelMap.get(label)) !== null && _a !== void 0 ? _a : label;
65
+ }
66
+ getRelabeledItem(item) {
67
+ const newItem = {};
68
+ for (const key in item) {
69
+ newItem[this.getNewLabel(key)] = item[key];
70
+ }
71
+ return newItem;
72
+ }
73
+ getRecordWithNewKeysAndLabels(items) {
74
+ return (0, object_1.fromEntries)(Object.entries(items).map(([key, value]) => [this.getNewKey(key), this.getRelabeledItem(value)]));
75
+ }
76
+ getRelabeledThirdPartyColumn(thirdPartyColumn) {
77
+ return new patch_1.ThirdPartyColumn(this.getNewLabel(thirdPartyColumn.name), thirdPartyColumn.fieldType);
78
+ }
79
+ getRelabeledThirdPartyColumnPatches(thirdPartyColumnPatch) {
80
+ const newRecord = {};
81
+ for (const label in thirdPartyColumnPatch) {
82
+ newRecord[this.getNewLabel(label)] = thirdPartyColumnPatch[label];
83
+ }
84
+ return newRecord;
85
+ }
86
+ getRekeyedRelabeledPatch(patch) {
87
+ var _a, _b;
88
+ if (patch instanceof patch_1.ItemPatch) {
89
+ return new patch_1.ItemPatch(patch.id, this.getRecordWithNewKeysAndLabels(patch.itemsAdded), this.getRecordWithNewKeysAndLabels(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);
90
+ }
91
+ if (patch instanceof patch_1.SchemaPatch) {
92
+ return new patch_1.SchemaPatch(patch.id, patch.columnsAdded.map((column) => this.getRelabeledThirdPartyColumn(column)), this.getRelabeledThirdPartyColumnPatches(patch.columnsChanged), patch.columnsDeleted.map((columnName) => this.getNewLabel(columnName)), (_b = patch.columnOrdering) === null || _b === void 0 ? void 0 : _b.map(([movedColumn, anchorColumn]) => [
93
+ this.getNewLabel(movedColumn),
94
+ anchorColumn != null ? this.getNewLabel(anchorColumn) : anchorColumn,
95
+ ]), patch.syncSourceId, patch.syncCollectionId);
96
+ }
97
+ return patch.clone();
98
+ }
99
+ }
100
+ exports.RekeyingRelabelingMap = RekeyingRelabelingMap;
101
+ class ItemRekeyerAndRelabeler {
102
+ constructor() {
103
+ this.rekeyingRelabelingMaps = new Map();
104
+ }
105
+ addRekeyingsRelabelingsFor(collectionId, itemsPatch, primaryKey) {
106
+ var _a, _b, _c, _d;
107
+ const rekeyingMap = calculateRekeyingMap(itemsPatch, primaryKey);
108
+ const relabelingMap = calculateRelabelingMap(itemsPatch);
109
+ const existingKeyAndLabelMap = this.rekeyingRelabelingMaps.get(collectionId);
110
+ const rekeyedExisting = rekeyingMap &&
111
+ [...((_a = existingKeyAndLabelMap === null || existingKeyAndLabelMap === void 0 ? void 0 : existingKeyAndLabelMap.keyMap.entries()) !== null && _a !== void 0 ? _a : [])].map(([key, value]) => {
112
+ var _a;
113
+ return [
114
+ key,
115
+ value && ((_a = rekeyingMap.get(value)) !== null && _a !== void 0 ? _a : value),
116
+ ];
117
+ });
118
+ const relabeledExisting = relabelingMap &&
119
+ [...((_b = existingKeyAndLabelMap === null || existingKeyAndLabelMap === void 0 ? void 0 : existingKeyAndLabelMap.labelMap.entries()) !== null && _b !== void 0 ? _b : [])].map(([key, value]) => {
120
+ var _a;
121
+ return [
122
+ key,
123
+ value && ((_a = relabelingMap.get(value)) !== null && _a !== void 0 ? _a : value),
124
+ ];
125
+ });
126
+ this.rekeyingRelabelingMaps.set(collectionId, new RekeyingRelabelingMap(new Map([...((_c = rekeyingMap === null || rekeyingMap === void 0 ? void 0 : rekeyingMap.entries()) !== null && _c !== void 0 ? _c : []), ...(rekeyedExisting !== null && rekeyedExisting !== void 0 ? rekeyedExisting : [])]), new Map([...((_d = relabelingMap === null || relabelingMap === void 0 ? void 0 : relabelingMap.entries()) !== null && _d !== void 0 ? _d : []), ...(relabeledExisting !== null && relabeledExisting !== void 0 ? relabeledExisting : [])])));
127
+ }
128
+ getRekeyingRelabelingMap(patch) {
129
+ return this.rekeyingRelabelingMaps.get(patch.syncCollectionId);
130
+ }
131
+ }
132
+ exports.ItemRekeyerAndRelabeler = ItemRekeyerAndRelabeler;
package/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export * from './core/data/datasource/datasourceutils';
11
11
  export * from './core/data/datasource/metadatatypes';
12
12
  export * from './core/data/datasource/serializeddatasourceproperties';
13
13
  export * from './core/data/datasource/serializedimporteddatasource';
14
+ export * from './core/data/datasource/serializedsourceforeignkey';
14
15
  export * from './core/data/datasource/serializedupstreamconfig';
15
16
  export * from './core/data/datasource/upstreamconfig';
16
17
  export * from './core/data/datasource/upstreampatchtype';
package/index.js CHANGED
@@ -27,6 +27,7 @@ __exportStar(require("./core/data/datasource/datasourceutils"), exports);
27
27
  __exportStar(require("./core/data/datasource/metadatatypes"), exports);
28
28
  __exportStar(require("./core/data/datasource/serializeddatasourceproperties"), exports);
29
29
  __exportStar(require("./core/data/datasource/serializedimporteddatasource"), exports);
30
+ __exportStar(require("./core/data/datasource/serializedsourceforeignkey"), exports);
30
31
  __exportStar(require("./core/data/datasource/serializedupstreamconfig"), exports);
31
32
  __exportStar(require("./core/data/datasource/upstreamconfig"), exports);
32
33
  __exportStar(require("./core/data/datasource/upstreampatchtype"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucid-extension-sdk",
3
- "version": "0.0.296",
3
+ "version": "0.0.297",
4
4
  "description": "Utility classes for writing Lucid Software editor extensions",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -1,16 +0,0 @@
1
- import { FormattedPrimaryKey } from '../core/data/fieldspecification';
2
- import { PatchItems } from './actions/action';
3
- import { Patch } from './actions/patch';
4
- import { ItemsPatch } from './datasourceupdatetypes';
5
- export declare class RekeyingMap {
6
- map: Map<string, string | null>;
7
- constructor(map: Map<string, string | null>);
8
- getNewKey(key: string): string;
9
- getRecordWithNewKeys(items: PatchItems): PatchItems;
10
- getRekeyedPatch(patch: Patch): Patch;
11
- }
12
- export declare class ItemRekeyer {
13
- private rekeyingMaps;
14
- addRekeyingsFor(collectionId: string, itemsPatch: ItemsPatch, primaryKey?: FormattedPrimaryKey<any, string>): void;
15
- getRekeyingMap(patch: Patch): RekeyingMap | undefined;
16
- }
@@ -1,82 +0,0 @@
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 patch_1 = require("./actions/patch");
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
- if (patch instanceof patch_1.ItemPatch) {
59
- return new patch_1.ItemPatch(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);
60
- }
61
- return patch.clone();
62
- }
63
- }
64
- exports.RekeyingMap = RekeyingMap;
65
- class ItemRekeyer {
66
- constructor() {
67
- this.rekeyingMaps = new Map();
68
- }
69
- addRekeyingsFor(collectionId, itemsPatch, primaryKey) {
70
- var _a;
71
- const rekeyingMap = calculateRekeyingMap(itemsPatch, primaryKey);
72
- if (rekeyingMap) {
73
- const existingMap = this.rekeyingMaps.get(collectionId);
74
- 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)]; });
75
- this.rekeyingMaps.set(collectionId, new RekeyingMap(new Map([...rekeyingMap.entries(), ...rekeyedExisting])));
76
- }
77
- }
78
- getRekeyingMap(patch) {
79
- return this.rekeyingMaps.get(patch.syncCollectionId);
80
- }
81
- }
82
- exports.ItemRekeyer = ItemRekeyer;