@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.
- package/dist/src/helpers.d.ts +15 -0
- package/dist/src/helpers.js +28 -0
- package/dist/src/index.cjs +30 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +1 -0
- package/dist/test/helpers.test.d.ts +1 -0
- package/dist/test/helpers.test.js +57 -0
- package/package.json +1 -1
- package/src/helpers.ts +37 -0
- package/src/index.ts +2 -0
- package/test/helpers.test.ts +75 -0
|
@@ -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
|
+
};
|
package/dist/src/index.cjs
CHANGED
|
@@ -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;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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
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
|
+
});
|