@forestadmin/agent 1.0.0-alpha.1

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.
Files changed (119) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +0 -0
  3. package/dist/agent.d.ts +76 -0
  4. package/dist/agent.js +133 -0
  5. package/dist/framework-mounter.d.ts +43 -0
  6. package/dist/framework-mounter.js +157 -0
  7. package/dist/index.d.ts +8 -0
  8. package/dist/index.js +15 -0
  9. package/dist/routes/access/api-chart.d.ts +16 -0
  10. package/dist/routes/access/api-chart.js +47 -0
  11. package/dist/routes/access/chart.d.ts +18 -0
  12. package/dist/routes/access/chart.js +162 -0
  13. package/dist/routes/access/count-related.d.ts +9 -0
  14. package/dist/routes/access/count-related.js +31 -0
  15. package/dist/routes/access/count.d.ts +9 -0
  16. package/dist/routes/access/count.js +31 -0
  17. package/dist/routes/access/csv-related.d.ts +9 -0
  18. package/dist/routes/access/csv-related.js +33 -0
  19. package/dist/routes/access/csv.d.ts +9 -0
  20. package/dist/routes/access/csv.js +31 -0
  21. package/dist/routes/access/get.d.ts +9 -0
  22. package/dist/routes/access/get.js +29 -0
  23. package/dist/routes/access/list-related.d.ts +9 -0
  24. package/dist/routes/access/list-related.js +25 -0
  25. package/dist/routes/access/list.d.ts +9 -0
  26. package/dist/routes/access/list.js +22 -0
  27. package/dist/routes/base-route.d.ts +13 -0
  28. package/dist/routes/base-route.js +13 -0
  29. package/dist/routes/collection-route.d.ts +12 -0
  30. package/dist/routes/collection-route.js +20 -0
  31. package/dist/routes/index.d.ts +30 -0
  32. package/dist/routes/index.js +108 -0
  33. package/dist/routes/modification/action.d.ts +16 -0
  34. package/dist/routes/modification/action.js +104 -0
  35. package/dist/routes/modification/associate-related.d.ts +12 -0
  36. package/dist/routes/modification/associate-related.js +51 -0
  37. package/dist/routes/modification/create.d.ts +14 -0
  38. package/dist/routes/modification/create.js +83 -0
  39. package/dist/routes/modification/delete.d.ts +11 -0
  40. package/dist/routes/modification/delete.js +41 -0
  41. package/dist/routes/modification/dissociate-delete-related.d.ts +20 -0
  42. package/dist/routes/modification/dissociate-delete-related.js +89 -0
  43. package/dist/routes/modification/update-field.d.ts +9 -0
  44. package/dist/routes/modification/update-field.js +39 -0
  45. package/dist/routes/modification/update-relation.d.ts +11 -0
  46. package/dist/routes/modification/update-relation.js +59 -0
  47. package/dist/routes/modification/update.d.ts +9 -0
  48. package/dist/routes/modification/update.js +31 -0
  49. package/dist/routes/relation-route.d.ts +10 -0
  50. package/dist/routes/relation-route.js +18 -0
  51. package/dist/routes/security/authentication.d.ts +15 -0
  52. package/dist/routes/security/authentication.js +74 -0
  53. package/dist/routes/security/ip-whitelist.d.ts +14 -0
  54. package/dist/routes/security/ip-whitelist.js +35 -0
  55. package/dist/routes/security/scope-invalidation.d.ts +11 -0
  56. package/dist/routes/security/scope-invalidation.js +28 -0
  57. package/dist/routes/system/error-handling.d.ts +13 -0
  58. package/dist/routes/system/error-handling.js +75 -0
  59. package/dist/routes/system/healthcheck.d.ts +11 -0
  60. package/dist/routes/system/healthcheck.js +22 -0
  61. package/dist/routes/system/logger.d.ts +10 -0
  62. package/dist/routes/system/logger.js +35 -0
  63. package/dist/services/authorization/authorization.d.ts +15 -0
  64. package/dist/services/authorization/authorization.js +45 -0
  65. package/dist/services/authorization/index.d.ts +5 -0
  66. package/dist/services/authorization/index.js +16 -0
  67. package/dist/services/authorization/internal/action-permission.d.ts +16 -0
  68. package/dist/services/authorization/internal/action-permission.js +68 -0
  69. package/dist/services/authorization/internal/generate-action-identifier.d.ts +4 -0
  70. package/dist/services/authorization/internal/generate-action-identifier.js +12 -0
  71. package/dist/services/authorization/internal/generate-actions-from-permissions.d.ts +8 -0
  72. package/dist/services/authorization/internal/generate-actions-from-permissions.js +87 -0
  73. package/dist/services/authorization/internal/types.d.ts +61 -0
  74. package/dist/services/authorization/internal/types.js +26 -0
  75. package/dist/services/index.d.ts +12 -0
  76. package/dist/services/index.js +16 -0
  77. package/dist/services/permissions.d.ts +19 -0
  78. package/dist/services/permissions.js +85 -0
  79. package/dist/services/serializer.d.ts +12 -0
  80. package/dist/services/serializer.js +120 -0
  81. package/dist/types.d.ts +41 -0
  82. package/dist/types.js +23 -0
  83. package/dist/utils/body-parser.d.ts +7 -0
  84. package/dist/utils/body-parser.js +18 -0
  85. package/dist/utils/condition-tree-parser.d.ts +11 -0
  86. package/dist/utils/condition-tree-parser.js +53 -0
  87. package/dist/utils/context-filter-factory.d.ts +7 -0
  88. package/dist/utils/context-filter-factory.js +28 -0
  89. package/dist/utils/csv-generator.d.ts +12 -0
  90. package/dist/utils/csv-generator.js +39 -0
  91. package/dist/utils/csv-route-context.d.ts +5 -0
  92. package/dist/utils/csv-route-context.js +14 -0
  93. package/dist/utils/forest-http-api.d.ts +68 -0
  94. package/dist/utils/forest-http-api.js +202 -0
  95. package/dist/utils/forest-schema/action-values.d.ts +34 -0
  96. package/dist/utils/forest-schema/action-values.js +144 -0
  97. package/dist/utils/forest-schema/emitter.d.ts +20 -0
  98. package/dist/utils/forest-schema/emitter.js +70 -0
  99. package/dist/utils/forest-schema/filterable.d.ts +16 -0
  100. package/dist/utils/forest-schema/filterable.js +68 -0
  101. package/dist/utils/forest-schema/generator-actions.d.ts +14 -0
  102. package/dist/utils/forest-schema/generator-actions.js +99 -0
  103. package/dist/utils/forest-schema/generator-collection.d.ts +7 -0
  104. package/dist/utils/forest-schema/generator-collection.js +36 -0
  105. package/dist/utils/forest-schema/generator-fields.d.ts +14 -0
  106. package/dist/utils/forest-schema/generator-fields.js +160 -0
  107. package/dist/utils/forest-schema/generator-segments.d.ts +6 -0
  108. package/dist/utils/forest-schema/generator-segments.js +9 -0
  109. package/dist/utils/forest-schema/types.d.ts +85 -0
  110. package/dist/utils/forest-schema/types.js +16 -0
  111. package/dist/utils/forest-schema/validation.d.ts +10 -0
  112. package/dist/utils/forest-schema/validation.js +28 -0
  113. package/dist/utils/id.d.ts +8 -0
  114. package/dist/utils/id.js +43 -0
  115. package/dist/utils/options-validator.d.ts +12 -0
  116. package/dist/utils/options-validator.js +92 -0
  117. package/dist/utils/query-string.d.ts +14 -0
  118. package/dist/utils/query-string.js +134 -0
  119. package/package.json +66 -0
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
7
+ const json_api_serializer_1 = __importDefault(require("json-api-serializer"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const id_1 = __importDefault(require("../utils/id"));
10
+ class Serializer {
11
+ constructor() {
12
+ // No need to keep references to serializers for outdated schemas => weakmap.
13
+ this.serializers = new WeakMap();
14
+ }
15
+ serialize(collection, data) {
16
+ const result = this.getSerializer(collection).serialize(collection.name, data);
17
+ this.stripUndefinedsInPlace(result);
18
+ return result;
19
+ }
20
+ deserialize(collection, body) {
21
+ return this.getSerializer(collection).deserialize(collection.name, body);
22
+ }
23
+ serializeWithSearchMetadata(collection, data, searchValue) {
24
+ const results = this.serialize(collection, data);
25
+ if (searchValue && searchValue.trim().length > 0) {
26
+ const resultsData = results.data;
27
+ const decorators = resultsData.reduce((decorator, record) => {
28
+ const search = Object.keys(record.attributes).filter(attribute => {
29
+ const value = record.attributes[attribute];
30
+ return value && value.toString().toLowerCase().includes(searchValue.toLowerCase());
31
+ });
32
+ if (search.length === 0) {
33
+ return decorator;
34
+ }
35
+ return { ...decorator, [Object.keys(decorator).length]: { id: record.id, search } };
36
+ }, {});
37
+ if (Object.values(decorators).length === 0) {
38
+ return results;
39
+ }
40
+ results.meta = { decorators };
41
+ }
42
+ return results;
43
+ }
44
+ getSerializer(collection) {
45
+ if (this.serializers.has(collection.schema)) {
46
+ return this.serializers.get(collection.schema);
47
+ }
48
+ const serializer = new json_api_serializer_1.default();
49
+ for (const sibling of collection.dataSource.collections) {
50
+ this.registerCollection(sibling, serializer);
51
+ this.serializers.set(sibling.schema, serializer);
52
+ }
53
+ return serializer;
54
+ }
55
+ registerCollection(collection, serializer) {
56
+ serializer.register(collection.name, {
57
+ id: 'forestId',
58
+ relationships: this.buildRelationshipsConfiguration(collection),
59
+ beforeSerialize: (data) => {
60
+ const copy = { ...data };
61
+ copy.forestId = id_1.default.packId(collection.schema, data);
62
+ return copy;
63
+ },
64
+ afterDeserialize: (data) => {
65
+ const copy = { ...data };
66
+ if (data.forestId) {
67
+ const parts = id_1.default.unpackId(collection.schema, data.forestId);
68
+ const primaryKeys = datasource_toolkit_1.SchemaUtils.getPrimaryKeys(collection.schema);
69
+ primaryKeys.forEach((field, index) => {
70
+ copy[field] = parts[index];
71
+ });
72
+ }
73
+ delete copy.forestId;
74
+ return copy;
75
+ },
76
+ });
77
+ }
78
+ buildRelationshipsConfiguration(collection) {
79
+ const relationships = {};
80
+ const urlPrefix = path_1.default.posix.join('/forest', collection.name);
81
+ for (const [name, field] of Object.entries(collection.schema.fields)) {
82
+ if (field.type === 'ManyToOne' || field.type === 'OneToOne') {
83
+ relationships[name] = {
84
+ type: field.foreignCollection,
85
+ deserialize: (data) => {
86
+ const foreignCollection = collection.dataSource.getCollection(field.foreignCollection);
87
+ return id_1.default.unpackId(foreignCollection.schema, data.id);
88
+ },
89
+ };
90
+ }
91
+ if (field.type === 'ManyToMany' || field.type === 'OneToMany') {
92
+ relationships[name] = {
93
+ type: field.foreignCollection,
94
+ links: (data) => ({
95
+ related: {
96
+ href: `${urlPrefix}/${data.forestId}/relationships/${name}`,
97
+ },
98
+ }),
99
+ };
100
+ }
101
+ }
102
+ return relationships;
103
+ }
104
+ stripUndefinedsInPlace(record) {
105
+ if (record === null || typeof record !== 'object') {
106
+ return;
107
+ }
108
+ const indexable = record;
109
+ for (const key of Object.keys(indexable)) {
110
+ if (indexable[key] === undefined) {
111
+ delete indexable[key];
112
+ }
113
+ else {
114
+ this.stripUndefinedsInPlace(indexable[key]);
115
+ }
116
+ }
117
+ }
118
+ }
119
+ exports.default = Serializer;
120
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9zZXJpYWxpemVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBS3lDO0FBQ3pDLDhFQUFvRDtBQUNwRCxnREFBd0I7QUFFeEIscURBQWtDO0FBSWxDLE1BQXFCLFVBQVU7SUFBL0I7UUFDRSw2RUFBNkU7UUFDNUQsZ0JBQVcsR0FBaUQsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQXlJN0YsQ0FBQztJQXZJQyxTQUFTLENBQUMsVUFBc0IsRUFBRSxJQUErQjtRQUMvRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9FLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVwQyxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsV0FBVyxDQUFDLFVBQXNCLEVBQUUsSUFBYTtRQUMvQyxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVELDJCQUEyQixDQUN6QixVQUFzQixFQUN0QixJQUFrQixFQUNsQixXQUFtQjtRQUVuQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQWUsQ0FBQztRQUUvRCxJQUFJLFdBQVcsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNoRCxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsSUFBb0IsQ0FBQztZQUNqRCxNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsU0FBUyxFQUFFLE1BQWtCLEVBQUUsRUFBRTtn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
@@ -0,0 +1,41 @@
1
+ /// <reference types="node" />
2
+ import { CompositeId, Logger, LoggerLevel } from '@forestadmin/datasource-toolkit';
3
+ import { IncomingMessage, ServerResponse } from 'http';
4
+ /** Options to configure behavior of an agent's forestadmin driver */
5
+ export declare type AgentOptions = {
6
+ authSecret: string;
7
+ envSecret: string;
8
+ customizeErrorMessage?: ((error: Error) => string | null) | null;
9
+ forestServerUrl?: string;
10
+ logger?: Logger;
11
+ loggerLevel?: LoggerLevel;
12
+ prefix?: string;
13
+ isProduction: boolean;
14
+ schemaPath?: string;
15
+ typingsPath?: string | null;
16
+ typingsMaxDepth?: number;
17
+ permissionsCacheDurationInSeconds?: number;
18
+ };
19
+ export declare type AgentOptionsWithDefaults = Readonly<Required<AgentOptions>>;
20
+ export declare type HttpCallback = (req: IncomingMessage, res: ServerResponse) => void;
21
+ export declare enum HttpCode {
22
+ BadRequest = 400,
23
+ Forbidden = 403,
24
+ InternalServerError = 500,
25
+ NoContent = 204,
26
+ NotFound = 404,
27
+ Ok = 200,
28
+ Unprocessable = 422
29
+ }
30
+ export declare enum RouteType {
31
+ LoggerHandler = 0,
32
+ ErrorHandler = 1,
33
+ PublicRoute = 2,
34
+ Authentication = 3,
35
+ PrivateRoute = 4
36
+ }
37
+ export declare type SelectionIds = {
38
+ areExcluded: boolean;
39
+ ids: CompositeId[];
40
+ };
41
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RouteType = exports.HttpCode = void 0;
4
+ var HttpCode;
5
+ (function (HttpCode) {
6
+ HttpCode[HttpCode["BadRequest"] = 400] = "BadRequest";
7
+ HttpCode[HttpCode["Forbidden"] = 403] = "Forbidden";
8
+ HttpCode[HttpCode["InternalServerError"] = 500] = "InternalServerError";
9
+ HttpCode[HttpCode["NoContent"] = 204] = "NoContent";
10
+ HttpCode[HttpCode["NotFound"] = 404] = "NotFound";
11
+ HttpCode[HttpCode["Ok"] = 200] = "Ok";
12
+ HttpCode[HttpCode["Unprocessable"] = 422] = "Unprocessable";
13
+ })(HttpCode = exports.HttpCode || (exports.HttpCode = {}));
14
+ var RouteType;
15
+ (function (RouteType) {
16
+ // Changing the values of this enum changes the order in which routes are loaded into koa-router.
17
+ RouteType[RouteType["LoggerHandler"] = 0] = "LoggerHandler";
18
+ RouteType[RouteType["ErrorHandler"] = 1] = "ErrorHandler";
19
+ RouteType[RouteType["PublicRoute"] = 2] = "PublicRoute";
20
+ RouteType[RouteType["Authentication"] = 3] = "Authentication";
21
+ RouteType[RouteType["PrivateRoute"] = 4] = "PrivateRoute";
22
+ })(RouteType = exports.RouteType || (exports.RouteType = {}));
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBc0JBLElBQVksUUFRWDtBQVJELFdBQVksUUFBUTtJQUNsQixxREFBZ0IsQ0FBQTtJQUNoQixtREFBZSxDQUFBO0lBQ2YsdUVBQXlCLENBQUE7SUFDekIsbURBQWUsQ0FBQTtJQUNmLGlEQUFjLENBQUE7SUFDZCxxQ0FBUSxDQUFBO0lBQ1IsMkRBQW1CLENBQUE7QUFDckIsQ0FBQyxFQVJXLFFBQVEsR0FBUixnQkFBUSxLQUFSLGdCQUFRLFFBUW5CO0FBRUQsSUFBWSxTQU9YO0FBUEQsV0FBWSxTQUFTO0lBQ25CLGlHQUFpRztJQUNqRywyREFBaUIsQ0FBQTtJQUNqQix5REFBZ0IsQ0FBQTtJQUNoQix1REFBZSxDQUFBO0lBQ2YsNkRBQWtCLENBQUE7SUFDbEIseURBQWdCLENBQUE7QUFDbEIsQ0FBQyxFQVBXLFNBQVMsR0FBVCxpQkFBUyxLQUFULGlCQUFTLFFBT3BCIn0=
@@ -0,0 +1,7 @@
1
+ import { CollectionSchema } from '@forestadmin/datasource-toolkit';
2
+ import { Context } from 'koa';
3
+ import { SelectionIds } from '../types';
4
+ export default class BodyParser {
5
+ static parseSelectionIds(schema: CollectionSchema, context: Context): SelectionIds;
6
+ }
7
+ //# sourceMappingURL=body-parser.d.ts.map
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const id_1 = __importDefault(require("./id"));
7
+ class BodyParser {
8
+ static parseSelectionIds(schema, context) {
9
+ const data = context.request.body?.data;
10
+ const attributes = data?.attributes;
11
+ const areExcluded = Boolean(attributes?.all_records);
12
+ let ids = attributes?.ids || (Array.isArray(data) && data.map(r => r.id)) || undefined;
13
+ ids = id_1.default.unpackIds(schema, areExcluded ? attributes?.all_records_ids_excluded : ids);
14
+ return { areExcluded, ids };
15
+ }
16
+ }
17
+ exports.default = BodyParser;
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9keS1wYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvYm9keS1wYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSw4Q0FBMkI7QUFFM0IsTUFBcUIsVUFBVTtJQUM3QixNQUFNLENBQUMsaUJBQWlCLENBQUMsTUFBd0IsRUFBRSxPQUFnQjtRQUNqRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUM7UUFDeEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxFQUFFLFVBQVUsQ0FBQztRQUNwQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3JELElBQUksR0FBRyxHQUFHLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7UUFDdkYsR0FBRyxHQUFHLFlBQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUUxRixPQUFPLEVBQUUsV0FBVyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQzlCLENBQUM7Q0FDRjtBQVZELDZCQVVDIn0=
@@ -0,0 +1,11 @@
1
+ import { Collection, ConditionTree } from '@forestadmin/datasource-toolkit';
2
+ export default class ConditionTreeParser {
3
+ static fromPlainObject(collection: Collection, json: unknown): ConditionTree;
4
+ /** Handle 'In' where the frontend unexpectedly sends strings */
5
+ private static parseValue;
6
+ /** Convert snake_case to PascalCase */
7
+ private static toPascalCase;
8
+ private static isLeaf;
9
+ private static isBranch;
10
+ }
11
+ //# sourceMappingURL=condition-tree-parser.d.ts.map
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
4
+ class ConditionTreeParser {
5
+ static fromPlainObject(collection, json) {
6
+ if (ConditionTreeParser.isLeaf(json)) {
7
+ const operator = ConditionTreeParser.toPascalCase(json.operator);
8
+ const value = ConditionTreeParser.parseValue(collection, { ...json, operator });
9
+ return new datasource_toolkit_1.ConditionTreeLeaf(json.field, operator, value);
10
+ }
11
+ if (ConditionTreeParser.isBranch(json)) {
12
+ const aggregator = ConditionTreeParser.toPascalCase(json.aggregator);
13
+ const conditions = json.conditions.map(subTree => ConditionTreeParser.fromPlainObject(collection, subTree));
14
+ return conditions.length !== 1
15
+ ? new datasource_toolkit_1.ConditionTreeBranch(aggregator, conditions)
16
+ : conditions[0];
17
+ }
18
+ throw new Error('Failed to instantiate condition tree from json');
19
+ }
20
+ /** Handle 'In' where the frontend unexpectedly sends strings */
21
+ static parseValue(collection, leaf) {
22
+ const schema = datasource_toolkit_1.CollectionUtils.getFieldSchema(collection, leaf.field);
23
+ if (leaf.operator === 'In' && typeof leaf.value === 'string') {
24
+ if (schema.columnType === 'Boolean') {
25
+ return leaf.value
26
+ .split(',')
27
+ .map(bool => !['false', '0', 'no'].includes(bool.toLowerCase().trim()));
28
+ }
29
+ if (schema.columnType === 'Number') {
30
+ return leaf.value
31
+ .split(',')
32
+ .map(string => Number(string.trim()))
33
+ .filter(number => !Number.isNaN(number) && Number.isFinite(number));
34
+ }
35
+ return leaf.value.split(',').map(v => v.trim());
36
+ }
37
+ return leaf.value;
38
+ }
39
+ /** Convert snake_case to PascalCase */
40
+ static toPascalCase(value) {
41
+ const pascalCased = value.slice(0, 1).toUpperCase() +
42
+ value.slice(1).replace(/_[a-z]/g, match => match.slice(1).toUpperCase());
43
+ return pascalCased;
44
+ }
45
+ static isLeaf(raw) {
46
+ return typeof raw === 'object' && 'field' in raw && 'operator' in raw;
47
+ }
48
+ static isBranch(raw) {
49
+ return typeof raw === 'object' && 'aggregator' in raw && 'conditions' in raw;
50
+ }
51
+ }
52
+ exports.default = ConditionTreeParser;
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZGl0aW9uLXRyZWUtcGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2NvbmRpdGlvbi10cmVlLXBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHdFQVN5QztBQUV6QyxNQUFxQixtQkFBbUI7SUFDdEMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxVQUFzQixFQUFFLElBQWE7UUFDMUQsSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDcEMsTUFBTSxRQUFRLEdBQUcsbUJBQW1CLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNqRSxNQUFNLEtBQUssR0FBRyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLEVBQUUsR0FBRyxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUVoRixPQUFPLElBQUksc0NBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDM0Q7UUFFRCxJQUFJLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN0QyxNQUFNLFVBQVUsR0FBRyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBZSxDQUFDO1lBQ25GLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQy9DLG1CQUFtQixDQUFDLGVBQWUsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQ3pELENBQUM7WUFFRixPQUFPLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQztnQkFDNUIsQ0FBQyxDQUFDLElBQUksd0NBQW1CLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQztnQkFDakQsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNuQjtRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRUQsZ0VBQWdFO0lBQ3hELE1BQU0sQ0FBQyxVQUFVLENBQ3ZCLFVBQXNCLEVBQ3RCLElBQXlEO1FBRXpELE1BQU0sTUFBTSxHQUFHLG9DQUFlLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFpQixDQUFDO1FBRXRGLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLElBQUksT0FBTyxJQUFJLENBQUMsS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM1RCxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFO2dCQUNuQyxPQUFPLElBQUksQ0FBQyxLQUFLO3FCQUNkLEtBQUssQ0FBQyxHQUFHLENBQUM7cUJBQ1YsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDM0U7WUFFRCxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssUUFBUSxFQUFFO2dCQUNsQyxPQUFPLElBQUksQ0FBQyxLQUFLO3FCQUNkLEtBQUssQ0FBQyxHQUFHLENBQUM7cUJBQ1YsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO3FCQUNwQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ3ZFO1lBRUQsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUNqRDtRQUVELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBRUQsdUNBQXVDO0lBQy9CLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBYTtRQUN2QyxNQUFNLFdBQVcsR0FDZixLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUU7WUFDL0IsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBRTNFLE9BQU8sV0FBdUIsQ0FBQztJQUNqQyxDQUFDO0lBRU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFZO1FBQ2hDLE9BQU8sT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLE9BQU8sSUFBSSxHQUFHLElBQUksVUFBVSxJQUFJLEdBQUcsQ0FBQztJQUN4RSxDQUFDO0lBRU8sTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFZO1FBQ2xDLE9BQU8sT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLFlBQVksSUFBSSxHQUFHLElBQUksWUFBWSxJQUFJLEdBQUcsQ0FBQztJQUMvRSxDQUFDO0NBQ0Y7QUFsRUQsc0NBa0VDIn0=
@@ -0,0 +1,7 @@
1
+ import { Collection, ConditionTree, Filter, PaginatedFilter } from '@forestadmin/datasource-toolkit';
2
+ import { Context } from 'koa';
3
+ export default class ContextFilterFactory {
4
+ static buildPaginated(collection: Collection, context: Context, scope: ConditionTree, partialFilter?: Partial<PaginatedFilter>): PaginatedFilter;
5
+ static build(collection: Collection, context: Context, scope: ConditionTree, partialFilter?: Partial<Filter>): PaginatedFilter;
6
+ }
7
+ //# sourceMappingURL=context-filter-factory.d.ts.map
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
7
+ const query_string_1 = __importDefault(require("./query-string"));
8
+ class ContextFilterFactory {
9
+ static buildPaginated(collection, context, scope, partialFilter) {
10
+ return new datasource_toolkit_1.PaginatedFilter({
11
+ sort: query_string_1.default.parseSort(collection, context),
12
+ page: query_string_1.default.parsePagination(context),
13
+ ...ContextFilterFactory.build(collection, context, scope),
14
+ ...partialFilter,
15
+ });
16
+ }
17
+ static build(collection, context, scope, partialFilter) {
18
+ return new datasource_toolkit_1.Filter({
19
+ search: query_string_1.default.parseSearch(collection, context),
20
+ segment: query_string_1.default.parseSegment(collection, context),
21
+ searchExtended: query_string_1.default.parseSearchExtended(context),
22
+ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(query_string_1.default.parseConditionTree(collection, context), scope),
23
+ ...partialFilter,
24
+ });
25
+ }
26
+ }
27
+ exports.default = ContextFilterFactory;
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1maWx0ZXItZmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9jb250ZXh0LWZpbHRlci1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBTXlDO0FBRXpDLGtFQUErQztBQUUvQyxNQUFxQixvQkFBb0I7SUFDdkMsTUFBTSxDQUFDLGNBQWMsQ0FDbkIsVUFBc0IsRUFDdEIsT0FBZ0IsRUFDaEIsS0FBb0IsRUFDcEIsYUFBd0M7UUFFeEMsT0FBTyxJQUFJLG9DQUFlLENBQUM7WUFDekIsSUFBSSxFQUFFLHNCQUFpQixDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDO1lBQ3RELElBQUksRUFBRSxzQkFBaUIsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDO1lBQ2hELEdBQUcsb0JBQW9CLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDO1lBQ3pELEdBQUcsYUFBYTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FDVixVQUFzQixFQUN0QixPQUFnQixFQUNoQixLQUFvQixFQUNwQixhQUErQjtRQUUvQixPQUFPLElBQUksMkJBQU0sQ0FBQztZQUNoQixNQUFNLEVBQUUsc0JBQWlCLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUM7WUFDMUQsT0FBTyxFQUFFLHNCQUFpQixDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDO1lBQzVELGNBQWMsRUFBRSxzQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUM7WUFDOUQsYUFBYSxFQUFFLHlDQUFvQixDQUFDLFNBQVMsQ0FDM0Msc0JBQWlCLENBQUMsa0JBQWtCLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxFQUN6RCxLQUFLLENBQ047WUFDRCxHQUFHLGFBQWE7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBaENELHVDQWdDQyJ9
@@ -0,0 +1,12 @@
1
+ import { Caller, Collection, PaginatedFilter, Projection } from '@forestadmin/datasource-toolkit';
2
+ export declare const CHUNK_SIZE = 1000;
3
+ export default class CsvGenerator {
4
+ /**
5
+ * Use an async generator to ensure that
6
+ * - backpressure is properly applied without needing to extend Readable (for slow clients)
7
+ * - we stop making queries to the database if the client closes the connection.
8
+ */
9
+ static generate(caller: Caller, projection: Projection, header: string, filter: PaginatedFilter, collection: Collection, list: Collection['list']): AsyncGenerator<string>;
10
+ private static convert;
11
+ }
12
+ //# sourceMappingURL=csv-generator.d.ts.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CHUNK_SIZE = void 0;
4
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
5
+ const format_1 = require("@fast-csv/format");
6
+ exports.CHUNK_SIZE = 1000;
7
+ class CsvGenerator {
8
+ /**
9
+ * Use an async generator to ensure that
10
+ * - backpressure is properly applied without needing to extend Readable (for slow clients)
11
+ * - we stop making queries to the database if the client closes the connection.
12
+ */
13
+ static async *generate(caller, projection, header, filter, collection, list) {
14
+ yield (0, format_1.writeToString)([header.split(',')], { headers: true, includeEndRowDelimiter: true });
15
+ const limit = filter.page?.limit;
16
+ let skip = filter.page?.skip || 0;
17
+ let areAllRecordsFetched = false;
18
+ const copiedFilter = { ...filter };
19
+ while (!areAllRecordsFetched) {
20
+ let currentPageSize = exports.CHUNK_SIZE;
21
+ if (limit < skip)
22
+ currentPageSize = skip - limit;
23
+ copiedFilter.page = new datasource_toolkit_1.Page(skip, currentPageSize);
24
+ if (!copiedFilter.sort || copiedFilter.sort.length === 0) {
25
+ copiedFilter.sort = datasource_toolkit_1.SortFactory.byPrimaryKeys(collection);
26
+ }
27
+ // eslint-disable-next-line no-await-in-loop
28
+ const records = await list(caller, new datasource_toolkit_1.PaginatedFilter(copiedFilter), projection);
29
+ yield CsvGenerator.convert(records, projection);
30
+ areAllRecordsFetched = records.length < exports.CHUNK_SIZE;
31
+ skip += currentPageSize;
32
+ }
33
+ }
34
+ static convert(records, projection) {
35
+ return (0, format_1.writeToString)(records.map(record => projection.map(field => datasource_toolkit_1.RecordUtils.getFieldValue(record, field))));
36
+ }
37
+ }
38
+ exports.default = CsvGenerator;
39
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3N2LWdlbmVyYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9jc3YtZ2VuZXJhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHdFQVN5QztBQUN6Qyw2Q0FBaUQ7QUFFcEMsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBRS9CLE1BQXFCLFlBQVk7SUFDL0I7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQ3BCLE1BQWMsRUFDZCxVQUFzQixFQUN0QixNQUFjLEVBQ2QsTUFBdUIsRUFDdkIsVUFBc0IsRUFDdEIsSUFBd0I7UUFFeEIsTUFBTSxJQUFBLHNCQUFhLEVBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLHNCQUFzQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFFMUYsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUM7UUFDakMsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDO1FBRWxDLElBQUksb0JBQW9CLEdBQUcsS0FBSyxDQUFDO1FBQ2pDLE1BQU0sWUFBWSxHQUFHLEVBQUUsR0FBRyxNQUFNLEVBQUUsQ0FBQztRQUVuQyxPQUFPLENBQUMsb0JBQW9CLEVBQUU7WUFDNUIsSUFBSSxlQUFlLEdBQUcsa0JBQVUsQ0FBQztZQUNqQyxJQUFJLEtBQUssR0FBRyxJQUFJO2dCQUFFLGVBQWUsR0FBRyxJQUFJLEdBQUcsS0FBSyxDQUFDO1lBRWpELFlBQVksQ0FBQyxJQUFJLEdBQUcsSUFBSSx5QkFBSSxDQUFDLElBQUksRUFBRSxlQUFlLENBQUMsQ0FBQztZQUVwRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7Z0JBQ3hELFlBQVksQ0FBQyxJQUFJLEdBQUcsZ0NBQVcsQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDM0Q7WUFFRCw0Q0FBNEM7WUFDNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksb0NBQWUsQ0FBQyxZQUFZLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUVsRixNQUFNLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBRWhELG9CQUFvQixHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsa0JBQVUsQ0FBQztZQUNuRCxJQUFJLElBQUksZUFBZSxDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQUVPLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBcUIsRUFBRSxVQUFzQjtRQUNsRSxPQUFPLElBQUEsc0JBQWEsRUFDbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxnQ0FBVyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUN6RixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBL0NELCtCQStDQyJ9
@@ -0,0 +1,5 @@
1
+ import { Context } from 'koa';
2
+ export default class CsvRouteContext {
3
+ static buildResponse(context: Context): void;
4
+ }
5
+ //# sourceMappingURL=csv-route-context.d.ts.map
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class CsvRouteContext {
4
+ static buildResponse(context) {
5
+ const { filename } = context.request.query;
6
+ context.response.type = 'text/csv; charset=utf-8';
7
+ context.response.attachment(`attachment; filename=${filename}`);
8
+ context.response.lastModified = new Date();
9
+ context.response.set({ 'X-Accel-Buffering': 'no' });
10
+ context.response.set({ 'Cache-Control': 'no-cache' });
11
+ }
12
+ }
13
+ exports.default = CsvRouteContext;
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3N2LXJvdXRlLWNvbnRleHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvY3N2LXJvdXRlLWNvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSxNQUFxQixlQUFlO0lBQ2xDLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBZ0I7UUFDbkMsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBRTNDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHLHlCQUF5QixDQUFDO1FBQ2xELE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLHdCQUF3QixRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDM0MsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQztDQUNGO0FBVkQsa0NBVUMifQ==
@@ -0,0 +1,68 @@
1
+ import { IssuerMetadata } from 'openid-client';
2
+ import { JSONAPIDocument } from 'json-api-serializer';
3
+ import { PlainConditionTree } from '@forestadmin/datasource-toolkit';
4
+ import { AgentOptions } from '../types';
5
+ import { EnvironmentPermissionsV4, UserPermissionV4 } from '../services/authorization';
6
+ export declare type IpWhitelistConfiguration = {
7
+ isFeatureEnabled: boolean;
8
+ ipRules: Array<{
9
+ type: number;
10
+ ipMinimum?: string;
11
+ ipMaximum?: string;
12
+ ip?: string;
13
+ range?: string;
14
+ }>;
15
+ };
16
+ export declare type UserInfo = {
17
+ id: number;
18
+ email: string;
19
+ firstName: string;
20
+ lastName: string;
21
+ team: string;
22
+ renderingId: number;
23
+ role: string;
24
+ tags: {
25
+ [key: string]: string;
26
+ };
27
+ permissionLevel: string;
28
+ };
29
+ export declare type RenderingPermissions = {
30
+ actions: Set<string>;
31
+ actionsByUser: {
32
+ [actionName: string]: Set<number>;
33
+ };
34
+ scopes: {
35
+ [collectionName: string]: {
36
+ conditionTree: PlainConditionTree;
37
+ dynamicScopeValues: {
38
+ [userId: number]: {
39
+ [replacementKey: string]: unknown;
40
+ };
41
+ };
42
+ };
43
+ };
44
+ };
45
+ declare type HttpOptions = Pick<AgentOptions, 'envSecret' | 'forestServerUrl' | 'isProduction'>;
46
+ export default class ForestHttpApi {
47
+ static getIpWhitelistConfiguration(options: HttpOptions): Promise<IpWhitelistConfiguration>;
48
+ static getOpenIdIssuerMetadata(options: HttpOptions): Promise<IssuerMetadata>;
49
+ static getUserInformation(options: HttpOptions, renderingId: number, accessToken: string): Promise<UserInfo>;
50
+ static hasSchema(options: HttpOptions, hash: string): Promise<boolean>;
51
+ static uploadSchema(options: HttpOptions, apimap: JSONAPIDocument): Promise<void>;
52
+ static getPermissions(options: HttpOptions, renderingId: number): Promise<RenderingPermissions>;
53
+ static getEnvironmentPermissions(options: HttpOptions): Promise<EnvironmentPermissionsV4>;
54
+ static getUsers(options: HttpOptions): Promise<UserPermissionV4[]>;
55
+ /** Helper to format permissions into something easy to validate against */
56
+ private static decodeChartPermissions;
57
+ /**
58
+ * Helper to format permissions into something easy to validate against
59
+ * Note that the format the server is sending varies depending on if we're using a remote or
60
+ * local environment.
61
+ */
62
+ private static decodeActionPermissions;
63
+ /** Helper to format permissions into something easy to validate against */
64
+ private static decodeScopePermissions;
65
+ private static handleResponseError;
66
+ }
67
+ export {};
68
+ //# sourceMappingURL=forest-http-api.d.ts.map