@unito/integration-sdk 1.0.4 → 1.0.5

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,15 @@
1
+ import { FieldSchema } from '@unito/integration-api';
2
+ import { Filter } from './index.js';
3
+ /**
4
+ * Use this helper function to retrieve the applicable filters from the context object. While using filters
5
+ * directly from context might work, it doesn't offer any guarantees about the shape of the filters nor the
6
+ * validity of the fields against which the filters are applied. On the other hand, this function ensures that
7
+ * all filters are valid and that the fields against which the filters are applied are present in the schema.
8
+ *
9
+ * @param context The object containing the raw filters
10
+ * @param fields The schema of the item against which the filters are applied
11
+ * @returns The validated filters
12
+ */
13
+ export declare const getApplicableFilters: (context: {
14
+ filters: Filter[];
15
+ }, fields: FieldSchema[]) => Filter[];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Use this helper function to retrieve the applicable filters from the context object. While using filters
3
+ * directly from context might work, it doesn't offer any guarantees about the shape of the filters nor the
4
+ * validity of the fields against which the filters are applied. On the other hand, this function ensures that
5
+ * all filters are valid and that the fields against which the filters are applied are present in the schema.
6
+ *
7
+ * @param context The object containing the raw filters
8
+ * @param fields The schema of the item against which the filters are applied
9
+ * @returns The validated filters
10
+ */
11
+ export const getApplicableFilters = (context, fields) => {
12
+ const applicableFilters = [];
13
+ for (const filter of context.filters) {
14
+ let field = undefined;
15
+ const filterFieldParts = filter.field.split(':', 2);
16
+ switch (filterFieldParts[0]) {
17
+ case 'semantic':
18
+ field = fields.find(f => f.semantic === filterFieldParts[1]);
19
+ break;
20
+ default:
21
+ field = fields.find(f => f.name === filterFieldParts[0]);
22
+ }
23
+ if (field) {
24
+ applicableFilters.push({ ...filter, field: field.name });
25
+ }
26
+ }
27
+ return applicableFilters;
28
+ };
@@ -1115,9 +1115,39 @@ class Provider {
1115
1115
  }
1116
1116
  }
1117
1117
 
1118
+ /**
1119
+ * Use this helper function to retrieve the applicable filters from the context object. While using filters
1120
+ * directly from context might work, it doesn't offer any guarantees about the shape of the filters nor the
1121
+ * validity of the fields against which the filters are applied. On the other hand, this function ensures that
1122
+ * all filters are valid and that the fields against which the filters are applied are present in the schema.
1123
+ *
1124
+ * @param context The object containing the raw filters
1125
+ * @param fields The schema of the item against which the filters are applied
1126
+ * @returns The validated filters
1127
+ */
1128
+ const getApplicableFilters = (context, fields) => {
1129
+ const applicableFilters = [];
1130
+ for (const filter of context.filters) {
1131
+ let field = undefined;
1132
+ const filterFieldParts = filter.field.split(':', 2);
1133
+ switch (filterFieldParts[0]) {
1134
+ case 'semantic':
1135
+ field = fields.find(f => f.semantic === filterFieldParts[1]);
1136
+ break;
1137
+ default:
1138
+ field = fields.find(f => f.name === filterFieldParts[0]);
1139
+ }
1140
+ if (field) {
1141
+ applicableFilters.push({ ...filter, field: field.name });
1142
+ }
1143
+ }
1144
+ return applicableFilters;
1145
+ };
1146
+
1118
1147
  exports.Api = integrationApi__namespace;
1119
1148
  exports.Cache = Cache;
1120
1149
  exports.Handler = Handler;
1121
1150
  exports.HttpErrors = httpErrors;
1122
1151
  exports.Integration = Integration;
1123
1152
  exports.Provider = Provider;
1153
+ exports.getApplicableFilters = getApplicableFilters;
@@ -5,6 +5,8 @@ export * from './handler.js';
5
5
  export { Provider, type Response as ProviderResponse, type RequestOptions as ProviderRequestOptions, type RateLimiter, } from './resources/provider.js';
6
6
  export type { Secrets } from './middlewares/secrets.js';
7
7
  export type { Credentials } from './middlewares/credentials.js';
8
+ export type { Filter } from './middlewares/filters.js';
8
9
  export * as HttpErrors from './httpErrors.js';
10
+ export { getApplicableFilters } from './helpers.js';
9
11
  export * from './resources/context.js';
10
12
  export { type default as Logger } from './resources/logger.js';
package/dist/src/index.js CHANGED
@@ -5,5 +5,6 @@ export { default as Integration } from './integration.js';
5
5
  export * from './handler.js';
6
6
  export { Provider, } from './resources/provider.js';
7
7
  export * as HttpErrors from './httpErrors.js';
8
+ export { getApplicableFilters } from './helpers.js';
8
9
  export * from './resources/context.js';
9
10
  /* c8 ignore stop */
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import { FieldValueType, OperatorType, Semantic } from '@unito/integration-api';
2
+ import assert from 'node:assert/strict';
3
+ import { describe, it } from 'node:test';
4
+ import { getApplicableFilters } from '../src/helpers.js';
5
+ describe('Helpers', () => {
6
+ describe('getApplicableFilters', () => {
7
+ it('returns only filters for defined fields', () => {
8
+ const actual = getApplicableFilters({
9
+ filters: [
10
+ { field: 'status', operator: OperatorType.EQUAL, values: ['active', 'pending'] },
11
+ { field: 'email', operator: OperatorType.IS_NOT_NULL, values: [] },
12
+ ],
13
+ }, [
14
+ {
15
+ name: 'status',
16
+ label: 'Status',
17
+ type: FieldValueType.STRING,
18
+ },
19
+ ]);
20
+ const expected = [{ field: 'status', operator: OperatorType.EQUAL, values: ['active', 'pending'] }];
21
+ assert.deepEqual(actual, expected);
22
+ });
23
+ it('translates semantics into field names', () => {
24
+ const actual = getApplicableFilters({
25
+ filters: [
26
+ { field: 'semantic:displayName', operator: OperatorType.START_WITH, values: ['Bob'] },
27
+ { field: 'semantic:createdAt', operator: OperatorType.EQUAL, values: ['2021-01-01'] },
28
+ ],
29
+ }, [
30
+ {
31
+ name: 'name',
32
+ label: 'Name',
33
+ type: FieldValueType.STRING,
34
+ semantic: Semantic.DISPLAY_NAME,
35
+ },
36
+ ]);
37
+ const expected = [{ field: 'name', operator: OperatorType.START_WITH, values: ['Bob'] }];
38
+ assert.deepEqual(actual, expected);
39
+ });
40
+ it('gracefully handle garbage', () => {
41
+ const actual = getApplicableFilters({
42
+ filters: [
43
+ { field: '...', operator: OperatorType.EQUAL, values: [] },
44
+ { field: ':', operator: OperatorType.EQUAL, values: [] },
45
+ { field: '', operator: OperatorType.EQUAL, values: [] },
46
+ ],
47
+ }, [
48
+ {
49
+ name: 'status',
50
+ label: 'Status',
51
+ type: FieldValueType.STRING,
52
+ },
53
+ ]);
54
+ assert.deepEqual(actual, []);
55
+ });
56
+ });
57
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unito/integration-sdk",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Integration SDK",
5
5
  "type": "module",
6
6
  "types": "dist/src/index.d.ts",
package/src/helpers.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { FieldSchema } from '@unito/integration-api';
2
+
3
+ import { Filter } from './index.js';
4
+
5
+ /**
6
+ * Use this helper function to retrieve the applicable filters from the context object. While using filters
7
+ * directly from context might work, it doesn't offer any guarantees about the shape of the filters nor the
8
+ * validity of the fields against which the filters are applied. On the other hand, this function ensures that
9
+ * all filters are valid and that the fields against which the filters are applied are present in the schema.
10
+ *
11
+ * @param context The object containing the raw filters
12
+ * @param fields The schema of the item against which the filters are applied
13
+ * @returns The validated filters
14
+ */
15
+ export const getApplicableFilters = (context: { filters: Filter[] }, fields: FieldSchema[]): Filter[] => {
16
+ const applicableFilters: Filter[] = [];
17
+
18
+ for (const filter of context.filters) {
19
+ let field: FieldSchema | undefined = undefined;
20
+
21
+ const filterFieldParts = filter.field.split(':', 2);
22
+
23
+ switch (filterFieldParts[0]) {
24
+ case 'semantic':
25
+ field = fields.find(f => f.semantic === filterFieldParts[1]);
26
+ break;
27
+ default:
28
+ field = fields.find(f => f.name === filterFieldParts[0]);
29
+ }
30
+
31
+ if (field) {
32
+ applicableFilters.push({ ...filter, field: field.name });
33
+ }
34
+ }
35
+
36
+ return applicableFilters;
37
+ };
package/src/index.ts CHANGED
@@ -11,7 +11,9 @@ export {
11
11
  } from './resources/provider.js';
12
12
  export type { Secrets } from './middlewares/secrets.js';
13
13
  export type { Credentials } from './middlewares/credentials.js';
14
+ export type { Filter } from './middlewares/filters.js';
14
15
  export * as HttpErrors from './httpErrors.js';
16
+ export { getApplicableFilters } from './helpers.js';
15
17
  export * from './resources/context.js';
16
18
  export { type default as Logger } from './resources/logger.js';
17
19
  /* c8 ignore stop */
@@ -0,0 +1,75 @@
1
+ import { FieldValueType, OperatorType, Semantic } from '@unito/integration-api';
2
+
3
+ import assert from 'node:assert/strict';
4
+ import { describe, it } from 'node:test';
5
+ import { getApplicableFilters } from '../src/helpers.js';
6
+
7
+ describe('Helpers', () => {
8
+ describe('getApplicableFilters', () => {
9
+ it('returns only filters for defined fields', () => {
10
+ const actual = getApplicableFilters(
11
+ {
12
+ filters: [
13
+ { field: 'status', operator: OperatorType.EQUAL, values: ['active', 'pending'] },
14
+ { field: 'email', operator: OperatorType.IS_NOT_NULL, values: [] },
15
+ ],
16
+ },
17
+ [
18
+ {
19
+ name: 'status',
20
+ label: 'Status',
21
+ type: FieldValueType.STRING,
22
+ },
23
+ ],
24
+ );
25
+
26
+ const expected = [{ field: 'status', operator: OperatorType.EQUAL, values: ['active', 'pending'] }];
27
+
28
+ assert.deepEqual(actual, expected);
29
+ });
30
+
31
+ it('translates semantics into field names', () => {
32
+ const actual = getApplicableFilters(
33
+ {
34
+ filters: [
35
+ { field: 'semantic:displayName', operator: OperatorType.START_WITH, values: ['Bob'] },
36
+ { field: 'semantic:createdAt', operator: OperatorType.EQUAL, values: ['2021-01-01'] },
37
+ ],
38
+ },
39
+ [
40
+ {
41
+ name: 'name',
42
+ label: 'Name',
43
+ type: FieldValueType.STRING,
44
+ semantic: Semantic.DISPLAY_NAME,
45
+ },
46
+ ],
47
+ );
48
+
49
+ const expected = [{ field: 'name', operator: OperatorType.START_WITH, values: ['Bob'] }];
50
+
51
+ assert.deepEqual(actual, expected);
52
+ });
53
+
54
+ it('gracefully handle garbage', () => {
55
+ const actual = getApplicableFilters(
56
+ {
57
+ filters: [
58
+ { field: '...', operator: OperatorType.EQUAL, values: [] },
59
+ { field: ':', operator: OperatorType.EQUAL, values: [] },
60
+ { field: '', operator: OperatorType.EQUAL, values: [] },
61
+ ],
62
+ },
63
+ [
64
+ {
65
+ name: 'status',
66
+ label: 'Status',
67
+ type: FieldValueType.STRING,
68
+ },
69
+ ],
70
+ );
71
+
72
+ assert.deepEqual(actual, []);
73
+ });
74
+ });
75
+ });