lucid-extension-sdk 0.0.147 → 0.0.149

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 @@
1
+ export declare const alphabet: string[];
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.alphabet = void 0;
4
+ exports.alphabet = [
5
+ 'A',
6
+ 'B',
7
+ 'C',
8
+ 'D',
9
+ 'E',
10
+ 'F',
11
+ 'G',
12
+ 'H',
13
+ 'I',
14
+ 'J',
15
+ 'K',
16
+ 'L',
17
+ 'M',
18
+ 'N',
19
+ 'O',
20
+ 'P',
21
+ 'Q',
22
+ 'R',
23
+ 'S',
24
+ 'T',
25
+ 'U',
26
+ 'V',
27
+ 'W',
28
+ 'X',
29
+ 'Y',
30
+ 'Z',
31
+ ];
@@ -0,0 +1,26 @@
1
+ import { SerializedFields } from '../serializedfield/serializedfields';
2
+ import { DataSourceType } from './datasourcetype';
3
+ import { SerializedImportedCollection } from './serializedimporteddatasource';
4
+ import { UpstreamUpdateType } from './upstreamupdatetype';
5
+ /** @ignore */
6
+ export declare function alphabetize(n: number): string;
7
+ /** @ignore */
8
+ export declare const MetadataPK = "__PK__";
9
+ /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
10
+ export declare function makeSerializedImportedCollection(id: string, name: string, rawSchema: string[], data: SerializedFields[], metadata?: {
11
+ [key: string]: SerializedFields[];
12
+ }): SerializedImportedCollection;
13
+ /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
14
+ export declare function makeSerializedImportedDataSource(id: string, name: string, collections: SerializedImportedCollection[]): {
15
+ Properties: {
16
+ Name: string;
17
+ UpstreamConfig: {
18
+ SourceType: DataSourceType;
19
+ UpdateType: UpstreamUpdateType;
20
+ SourceConfig: {
21
+ spreadsheetId: string;
22
+ };
23
+ };
24
+ };
25
+ Collections: SerializedImportedCollection[];
26
+ };
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeSerializedImportedDataSource = exports.makeSerializedImportedCollection = exports.MetadataPK = exports.alphabetize = void 0;
4
+ const scalarfieldtype_1 = require("../fieldtypedefinition/scalarfieldtype");
5
+ const alphabet_1 = require("./alphabet");
6
+ const datasourcetype_1 = require("./datasourcetype");
7
+ const upstreamupdatetype_1 = require("./upstreamupdatetype");
8
+ /** @ignore */
9
+ function _alphabetize(n) {
10
+ if (n == undefined || n < 0) {
11
+ return '';
12
+ }
13
+ else if (n < alphabet_1.alphabet.length) {
14
+ return alphabet_1.alphabet[n];
15
+ }
16
+ else {
17
+ return alphabetize(Math.floor(n / alphabet_1.alphabet.length) - 1) + alphabetize(n % alphabet_1.alphabet.length);
18
+ }
19
+ }
20
+ /** @ignore */
21
+ const memoize = new Map();
22
+ /** @ignore */
23
+ function alphabetize(n) {
24
+ const stored = memoize.get(n);
25
+ if (stored != null) {
26
+ return stored;
27
+ }
28
+ const value = _alphabetize(n);
29
+ memoize.set(n, value);
30
+ return value;
31
+ }
32
+ exports.alphabetize = alphabetize;
33
+ /** @ignore */
34
+ function normalizeName(name) {
35
+ return name.trim().toLowerCase();
36
+ }
37
+ /** @ignore */
38
+ exports.MetadataPK = '__PK__';
39
+ /** @ignore */
40
+ function makeSchema(schemaFields) {
41
+ const fields = [];
42
+ const oldToNewFields = new Map();
43
+ const usedFieldsNormalized = new Set([normalizeName(exports.MetadataPK)]);
44
+ schemaFields.forEach((field, index) => {
45
+ // don't add duplicates
46
+ if (!usedFieldsNormalized.has(normalizeName(field))) {
47
+ usedFieldsNormalized.add(normalizeName(field));
48
+ // for now we're changing all schema to the alphabet until preview data can be skipped
49
+ fields.push({ 'Name': alphabetize(index), 'Type': scalarfieldtype_1.ScalarFieldTypeEnum.ANY });
50
+ oldToNewFields.set(field, alphabetize(index));
51
+ }
52
+ });
53
+ return { sheetSchema: { 'Fields': fields, 'PrimaryKey': [] }, oldToNewFields };
54
+ }
55
+ /** @ignore */
56
+ function makeMetadataCollection(metadataType, sheetName, dataItems, sheetSchema) {
57
+ return {
58
+ 'Name': sheetName + '|' + metadataType,
59
+ 'Schema': sheetSchema,
60
+ 'Items': dataItems,
61
+ };
62
+ }
63
+ /** @ignore */
64
+ function makeItemOrderCollection(sheetLength, sheetName) {
65
+ const itemOrderItems = {};
66
+ for (let i = 1; i <= sheetLength; ++i) {
67
+ const rowIndex = i;
68
+ itemOrderItems[`${rowIndex}`] = { 'Key': `${rowIndex}`, 'Order': rowIndex };
69
+ }
70
+ const itemOrderSchema = {
71
+ 'Fields': [
72
+ { 'Name': 'Key', 'Type': scalarfieldtype_1.ScalarFieldTypeEnum.STRING },
73
+ { 'Name': 'Order', 'Type': scalarfieldtype_1.ScalarFieldTypeEnum.NUMBER },
74
+ ],
75
+ 'PrimaryKey': ['Order'],
76
+ };
77
+ return makeMetadataCollection('ItemOrder', sheetName, itemOrderItems, itemOrderSchema);
78
+ }
79
+ /** @ignore */
80
+ function makeSerializedItems(rawItems, oldToNewFields, isMetadata = false) {
81
+ const serializedItems = {};
82
+ rawItems.forEach((rawItem, rowIndex) => {
83
+ const dataItem = {};
84
+ for (const [key, field] of Object.entries(rawItem)) {
85
+ const newKey = oldToNewFields.get(key);
86
+ if (newKey) {
87
+ dataItem[newKey] = field;
88
+ }
89
+ }
90
+ const primaryKey = rowIndex + 1;
91
+ if (isMetadata && Object.keys(dataItem).length > 0) {
92
+ dataItem[exports.MetadataPK] = `${primaryKey}`;
93
+ serializedItems[`"${primaryKey}"`] = dataItem;
94
+ }
95
+ else if (!isMetadata) {
96
+ serializedItems[primaryKey] = dataItem;
97
+ }
98
+ });
99
+ return serializedItems;
100
+ }
101
+ /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
102
+ function makeSerializedImportedCollection(id, name, rawSchema, data, metadata) {
103
+ const { sheetSchema, oldToNewFields } = makeSchema(rawSchema);
104
+ const metadataCollections = {};
105
+ const itemOrderCollection = makeItemOrderCollection(data.length, name);
106
+ metadataCollections['ItemOrder'] = itemOrderCollection;
107
+ if (metadata) {
108
+ const metadataFields = [{ 'Name': exports.MetadataPK, 'Type': scalarfieldtype_1.ScalarFieldTypeEnum.STRING }];
109
+ sheetSchema['Fields'].forEach((field) => metadataFields.push({ 'Name': field['Name'], 'Type': scalarfieldtype_1.ScalarFieldTypeEnum.STRING }));
110
+ const metadataSchema = { 'Fields': metadataFields, 'PrimaryKey': [exports.MetadataPK] };
111
+ for (const [type, data] of Object.entries(metadata)) {
112
+ metadataCollections[type] = makeMetadataCollection(type, name, makeSerializedItems(data, oldToNewFields, true), metadataSchema);
113
+ }
114
+ }
115
+ return {
116
+ 'Name': name,
117
+ 'Schema': sheetSchema,
118
+ 'Items': makeSerializedItems(data, oldToNewFields),
119
+ 'UpstreamConfig': {
120
+ 'properties': {
121
+ 'UpstreamType': upstreamupdatetype_1.UpstreamUpdateType.EVENTPULL,
122
+ 'sheetId': id,
123
+ },
124
+ },
125
+ 'Metadata': metadataCollections,
126
+ };
127
+ }
128
+ exports.makeSerializedImportedCollection = makeSerializedImportedCollection;
129
+ /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
130
+ function makeSerializedImportedDataSource(id, name, collections) {
131
+ return {
132
+ 'Properties': {
133
+ 'Name': name,
134
+ 'UpstreamConfig': {
135
+ 'SourceType': datasourcetype_1.DataSourceType.DataService,
136
+ 'UpdateType': upstreamupdatetype_1.UpstreamUpdateType.EVENTPULL,
137
+ 'SourceConfig': { 'spreadsheetId': id },
138
+ },
139
+ },
140
+ 'Collections': collections,
141
+ };
142
+ }
143
+ exports.makeSerializedImportedDataSource = makeSerializedImportedDataSource;
@@ -17,7 +17,7 @@ export declare const isSerializedImportedMetadataCollection: (subject: unknown)
17
17
  /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
18
18
  export interface SerializedImportedCollection {
19
19
  'Name': string;
20
- 'Id': string;
20
+ 'Id'?: string;
21
21
  'Schema': SerializedSchema;
22
22
  'Items': SerializedDataItems;
23
23
  'UpstreamConfig': {
@@ -30,7 +30,6 @@ export interface SerializedImportedCollection {
30
30
  /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
31
31
  export declare const isSerializedImportedCollection: (subject: unknown) => subject is import("../../guards").DestructureGuardedTypeObj<{
32
32
  Name: typeof isString;
33
- Id: typeof isString;
34
33
  Schema: typeof isSerializedSchema;
35
34
  Items: typeof isSerializedDataItems;
36
35
  UpstreamConfig: typeof isObject;
@@ -58,7 +57,6 @@ export declare const isSerializedImportedDataSource: (subject: unknown) => subje
58
57
  }>;
59
58
  Collections: (val: unknown) => val is import("../../guards").DestructureGuardedTypeObj<{
60
59
  Name: typeof isString;
61
- Id: typeof isString;
62
60
  Schema: typeof isSerializedSchema;
63
61
  Items: typeof isSerializedDataItems;
64
62
  UpstreamConfig: typeof isObject;
@@ -15,7 +15,6 @@ exports.isSerializedImportedMetadataCollection = (0, validators_1.strictObjectVa
15
15
  /** @ignore until spreadsheet integration is ready for launch (CHART-51946) */
16
16
  exports.isSerializedImportedCollection = (0, validators_1.strictObjectValidator)({
17
17
  'Name': checks_1.isString,
18
- 'Id': checks_1.isString,
19
18
  'Schema': serializedschema_1.isSerializedSchema,
20
19
  'Items': serializeddataitems_1.isSerializedDataItems,
21
20
  'UpstreamConfig': checks_1.isObject,
@@ -0,0 +1,11 @@
1
+ export declare interface BufferSingleton {
2
+ from(str: string, encoding?: string): unknown;
3
+ }
4
+ export declare interface CryptoModule {
5
+ createPublicKey(key: string): unknown;
6
+ verify(algorithm: string, data: unknown, publicKey: unknown, signature: unknown): boolean;
7
+ }
8
+ export declare type CryptoDependencies = {
9
+ Buffer: BufferSingleton;
10
+ crypto: CryptoModule;
11
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,6 @@
1
1
  import { JsonObject } from '../core/jsonserializable';
2
2
  import { DataConnectorAction } from './actions/action';
3
+ import { CryptoDependencies } from './cryptodependencies';
3
4
  import { DataSourceClient, MockDataSourceClient } from './datasourceclient';
4
5
  import { SignatureValidator } from './signaturevalidator';
5
6
  /** @ignore */
@@ -13,13 +14,14 @@ export declare type WebhookValidationSecret = {
13
14
  * Client for requests to and from Lucid
14
15
  */
15
16
  export declare class DataConnectorClient {
17
+ private readonly cryptoDependencies;
16
18
  urls: {
17
19
  main: string;
18
20
  api: string;
19
21
  };
20
22
  private fetchMethod;
21
23
  private cachedPublicKey;
22
- constructor(urls?: {
24
+ constructor(cryptoDependencies: CryptoDependencies, urls?: {
23
25
  main: string;
24
26
  api: string;
25
27
  }, fetchMethod?: import("./defaultfetchfunction").GlobalFetchType);
@@ -43,6 +45,7 @@ export declare class DataConnectorClient {
43
45
  export declare class MockDataConnectorClient extends DataConnectorClient {
44
46
  /** set properties on this to modify how data source updates are mocked */
45
47
  readonly dataSourceClient: MockDataSourceClient;
48
+ constructor();
46
49
  /** @ignore */
47
50
  getDataSourceClient(updateToken: string): DataSourceClient;
48
51
  /** Mocked version just always returns successful */
@@ -12,7 +12,8 @@ const LUCID_URLS = { main: 'https://lucid.app/', api: 'https://api.lucid.co/' };
12
12
  * Client for requests to and from Lucid
13
13
  */
14
14
  class DataConnectorClient {
15
- constructor(urls = LUCID_URLS, fetchMethod = defaultfetchfunction_1.globalFetch) {
15
+ constructor(cryptoDependencies, urls = LUCID_URLS, fetchMethod = defaultfetchfunction_1.globalFetch) {
16
+ this.cryptoDependencies = cryptoDependencies;
16
17
  this.urls = urls;
17
18
  this.fetchMethod = fetchMethod;
18
19
  this.cachedPublicKey = undefined;
@@ -23,7 +24,7 @@ class DataConnectorClient {
23
24
  }
24
25
  /** Get a validator to prove a given request came from Lucid */
25
26
  async getSignatureValidator() {
26
- return new signaturevalidator_1.SignatureValidator(await this.getPublicKey());
27
+ return new signaturevalidator_1.SignatureValidator(this.cryptoDependencies, await this.getPublicKey());
27
28
  }
28
29
  /** Get Lucid's public key to verify requests came from Lucid if you don't want to use the SignatureValidator. Maybe
29
30
  * you're not running in a NodeJS environment */
@@ -92,7 +93,7 @@ exports.DataConnectorClient = DataConnectorClient;
92
93
  /** Use this for writing automated tests for your data connector */
93
94
  class MockDataConnectorClient extends DataConnectorClient {
94
95
  constructor() {
95
- super(...arguments);
96
+ super(undefined);
96
97
  /** set properties on this to modify how data source updates are mocked */
97
98
  this.dataSourceClient = new datasourceclient_1.MockDataSourceClient();
98
99
  }
@@ -10,6 +10,17 @@ function routeDebugServer(dataConnector, options) {
10
10
  // We can't use Express's JSON parsing because we need to send the string of the request body
11
11
  // directly for the route style flows. Some extensions compute a HMAC of from this data
12
12
  app.use(express.raw({ type: () => true }));
13
+ // CORS
14
+ app.use((req, res, next) => {
15
+ var _a, _b;
16
+ if ((_b = (_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin) === null || _b === void 0 ? void 0 : _b.match(/.lucid(dev|staging|preprod|).app$/)) {
17
+ res.header('Access-Control-Allow-Origin', req.headers.origin);
18
+ res.header('Vary', 'Origin');
19
+ res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
20
+ res.header('Access-Control-Allow-Headers', '*');
21
+ }
22
+ next();
23
+ });
13
24
  const prefix = (_b = options.prefix) !== null && _b !== void 0 ? _b : '/';
14
25
  console.log(`Routing ${prefix}?kind=action (${Object.keys(dataConnector.actions).join(', ')})`);
15
26
  if (dataConnector.routes) {
@@ -1,16 +1,13 @@
1
- /** @ignore */
2
- export declare const signatureValidatorImportedNode: {
3
- Buffer: any;
4
- crypto: any;
5
- };
1
+ import { CryptoDependencies } from './cryptodependencies';
6
2
  /**
7
3
  * Allows validation that requests originated from Lucid. This class can only be instanciated in a NodeJS environment.
8
4
  * Technically any environment that provides NodeJS compatible implementations of `globalThis.Buffer` and
9
5
  * `globalThis.require('crypto')` will work.
10
6
  */
11
7
  export declare class SignatureValidator {
8
+ private readonly dependencies;
12
9
  private readonly publicKey;
13
- constructor(publicKey: string);
10
+ constructor(dependencies: CryptoDependencies, publicKey: string);
14
11
  /**
15
12
  * Validate a given request came from Lucid.
16
13
  * @param body The body of the request as a plain JavaScript object. This should be JSON.parse called on exactly the
@@ -1,35 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MockSignatureValidator = exports.SignatureValidator = exports.signatureValidatorImportedNode = void 0;
4
- // Don't import these normally, so they're resolved at runtime.
5
- // This is so the lucid-extension-sdk can be used from a browser.
6
- // This class only is implemented for NodeJS environments, so
7
- // it will fail at runtime if you try to instanciate it in a browser.
8
- // It's also exported and mutable because while this compiles and
9
- // works in the lambda environment, for some reason it doesn't work
10
- // in the debug server environment, so from there we import it and
11
- // patch it up with imports that do work.
12
- /** @ignore */
13
- exports.signatureValidatorImportedNode = (() => {
14
- const Buffer = globalThis['Buffer'];
15
- const require = globalThis['require'];
16
- const crypto = require && require('crypto');
17
- return { 'Buffer': Buffer, 'crypto': crypto };
18
- })();
3
+ exports.MockSignatureValidator = exports.SignatureValidator = void 0;
19
4
  /**
20
5
  * Allows validation that requests originated from Lucid. This class can only be instanciated in a NodeJS environment.
21
6
  * Technically any environment that provides NodeJS compatible implementations of `globalThis.Buffer` and
22
7
  * `globalThis.require('crypto')` will work.
23
8
  */
24
9
  class SignatureValidator {
25
- constructor(publicKey) {
26
- if (!exports.signatureValidatorImportedNode['Buffer']) {
27
- throw new Error('Expect `Buffer` class to be defined');
28
- }
29
- if (!exports.signatureValidatorImportedNode['crypto']) {
30
- throw new Error("Expect `require('crypto')` to be defined");
31
- }
32
- this.publicKey = exports.signatureValidatorImportedNode['crypto']['createPublicKey'](publicKey);
10
+ constructor(dependencies, publicKey) {
11
+ this.dependencies = dependencies;
12
+ this.publicKey = dependencies.crypto.createPublicKey(publicKey);
33
13
  }
34
14
  /**
35
15
  * Validate a given request came from Lucid.
@@ -44,9 +24,9 @@ class SignatureValidator {
44
24
  const parts = url.split('?');
45
25
  const params = parts.length > 0 ? parts[1] : '';
46
26
  const nonce = headers['x-lucid-rsa-nonce'];
47
- const signature = exports.signatureValidatorImportedNode['Buffer']['from'](headers['x-lucid-signature'], 'base64');
48
- const data = exports.signatureValidatorImportedNode['Buffer']['from'](JSON.stringify(body) + nonce + params);
49
- const verified = exports.signatureValidatorImportedNode['crypto']['verify']('SHA384', data, this.publicKey, signature);
27
+ const signature = this.dependencies.Buffer.from(headers['x-lucid-signature'], 'base64');
28
+ const data = this.dependencies.Buffer.from(JSON.stringify(body) + nonce + params);
29
+ const verified = this.dependencies.crypto.verify('SHA384', data, this.publicKey, signature);
50
30
  return verified;
51
31
  }
52
32
  }
package/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './core/cardintegration/lucidcardintegration';
7
7
  export * from './core/cardintegration/lucidcardintegrationregistry';
8
8
  export * from './core/checks';
9
9
  export * from './core/data/datasource/datasourcetype';
10
+ export * from './core/data/datasource/datasourceutils';
10
11
  export * from './core/data/datasource/metadatatypes';
11
12
  export * from './core/data/datasource/serializeddatasourceproperties';
12
13
  export * from './core/data/datasource/serializedimporteddatasource';
package/index.js CHANGED
@@ -23,6 +23,7 @@ __exportStar(require("./core/cardintegration/lucidcardintegration"), exports);
23
23
  __exportStar(require("./core/cardintegration/lucidcardintegrationregistry"), exports);
24
24
  __exportStar(require("./core/checks"), exports);
25
25
  __exportStar(require("./core/data/datasource/datasourcetype"), exports);
26
+ __exportStar(require("./core/data/datasource/datasourceutils"), exports);
26
27
  __exportStar(require("./core/data/datasource/metadatatypes"), exports);
27
28
  __exportStar(require("./core/data/datasource/serializeddatasourceproperties"), exports);
28
29
  __exportStar(require("./core/data/datasource/serializedimporteddatasource"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucid-extension-sdk",
3
- "version": "0.0.147",
3
+ "version": "0.0.149",
4
4
  "description": "Utility classes for writing Lucid Software editor extensions",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",