Skip to content

Commit a536f1c

Browse files
authored
feat: add typescript declaration file (#743)
1 parent d3e4711 commit a536f1c

File tree

5 files changed

+418
-4
lines changed

5 files changed

+418
-4
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
- [ ] Test manually the implemented changes
66
- [ ] Review my own code (indentation, syntax, style, simplicity, readability)
77
- [ ] Wonder if you can improve the existing code
8+
- [ ] If needed, Types have been updated

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"url": "git://github.com/ForestAdmin/forest-express-sequelize.git"
2424
},
2525
"main": "dist/index.js",
26+
"types": "./types/index.d.ts",
2627
"dependencies": {
2728
"@babel/runtime": "7.10.1",
2829
"bluebird": "2.9.25",
@@ -47,6 +48,8 @@
4748
"@semantic-release/changelog": "5.0.1",
4849
"@semantic-release/git": "9.0.0",
4950
"@types/jest": "26.0.9",
51+
"@typescript-eslint/eslint-plugin": "4.26.0",
52+
"@typescript-eslint/parser": "4.26.0",
5053
"babel-eslint": "10.0.3",
5154
"eslint": "6.8.0",
5255
"eslint-config-airbnb-base": "14.0.0",
@@ -65,12 +68,13 @@
6568
"sequelize": "5.21.3",
6669
"sequelize-fixtures": "1.1.1",
6770
"simple-git": "1.65.0",
68-
"tedious": "11.0.8"
71+
"tedious": "11.0.8",
72+
"typescript": "4.3.2"
6973
},
7074
"scripts": {
7175
"build": "babel src --out-dir dist",
7276
"build:watch": "onchange 'src/**/*.js' 'node_modules/forest-express/dist/*' --no-exclude -i -- babel --source-maps inline --out-dir dist src",
73-
"lint": "./node_modules/eslint/bin/eslint.js .eslint-bin src test",
77+
"lint": "./node_modules/eslint/bin/eslint.js .eslint-bin src test types/index.d.ts",
7478
"test": "jest",
7579
"test:coverage": "jest --coverage"
7680
}

types/.eslintrc.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = {
2+
"root": true,
3+
"parser": "@typescript-eslint/parser",
4+
"plugins": [
5+
"@typescript-eslint"
6+
],
7+
"rules": {
8+
"@typescript-eslint/no-explicit-any": "off"
9+
},
10+
"extends": [
11+
"eslint:recommended",
12+
"plugin:@typescript-eslint/eslint-recommended",
13+
"plugin:@typescript-eslint/recommended"
14+
]
15+
}

types/index.d.ts

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
import { RequestHandler, Response, Request, NextFunction, Application } from 'express';
2+
import * as Sequelize from 'sequelize';
3+
4+
// Everything related to Forest initialization
5+
6+
export interface LianaOptions {
7+
objectMapping: typeof Sequelize;
8+
envSecret: string;
9+
authSecret: string;
10+
connections: Record<string, Sequelize.Sequelize>;
11+
includedModels?: string[];
12+
excludedModels?: string[];
13+
configDir?: string;
14+
}
15+
16+
export function init(options: LianaOptions): Promise<Application>;
17+
18+
export interface DatabaseConfiguration {
19+
name: string,
20+
modelsDir: string,
21+
connection: {
22+
url: string,
23+
options: Sequelize.Options,
24+
}
25+
}
26+
27+
// Everything related to Forest Authentication
28+
29+
export function ensureAuthenticated(request: Request, response: Response, next: NextFunction): void;
30+
31+
// Everything related to Forest constants
32+
33+
export const PUBLIC_ROUTES: string[];
34+
35+
// Everything related to record manipulation
36+
37+
interface RecordsSerialized {
38+
data: Record<string, unknown>[],
39+
included: Record<string, unknown>[],
40+
}
41+
42+
export class AbstractRecordTool<M extends Sequelize.Model> {
43+
constructor(model: Sequelize.ModelCtor<M>)
44+
serialize(records: M | M[]): Promise<RecordsSerialized>;
45+
}
46+
47+
export class RecordGetter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
48+
get(recordId: string): Promise<M>;
49+
}
50+
51+
export class RecordsGetter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
52+
getAll(query: Query): Promise<M[]>;
53+
getIdsFromRequest(request: Request): Promise<string[]>;
54+
}
55+
56+
export class RecordsCounter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
57+
count(query: Query): Promise<number>;
58+
}
59+
60+
export class RecordsExporter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
61+
streamExport(response: Response, query: Query): Promise<void>;
62+
}
63+
64+
export class RecordUpdater<M extends Sequelize.Model> extends AbstractRecordTool<M> {
65+
deserialize(body: Record<string, unknown>): Promise<Record<string, unknown>>;
66+
update(record: Record<string, unknown>, recordId: string): Promise<M>;
67+
}
68+
69+
export class RecordCreator<M extends Sequelize.Model> extends AbstractRecordTool<M> {
70+
deserialize(body: Record<string, unknown>): Promise<Record<string, unknown>>;
71+
create(record: Record<string, unknown>): Promise<M>;
72+
}
73+
74+
export class RecordRemover<M extends Sequelize.Model> extends AbstractRecordTool<M> {
75+
remove(recordId: string | number): Promise<void>;
76+
}
77+
78+
export class RecordsRemover<M extends Sequelize.Model> extends AbstractRecordTool<M> {
79+
remove(recordIds: string[] | number[]): Promise<void>;
80+
}
81+
82+
// Everything related to Forest permissions
83+
84+
export class PermissionMiddlewareCreator {
85+
constructor(collectionName: string)
86+
list(): RequestHandler;
87+
export(): RequestHandler;
88+
details(): RequestHandler;
89+
create(): RequestHandler;
90+
update(): RequestHandler;
91+
delete(): RequestHandler;
92+
smartAction(): RequestHandler;
93+
}
94+
95+
// Everything related to Forest Charts
96+
97+
export interface StatSerialized {
98+
data: {
99+
type: string,
100+
id: string,
101+
attributes: {
102+
value: any[]
103+
}
104+
};
105+
}
106+
107+
export class StatSerializer {
108+
constructor(stats: { value: any[] })
109+
perform(): StatSerialized;
110+
}
111+
112+
// Everything related to Forest request params
113+
114+
export interface Page {
115+
number: number;
116+
size: number;
117+
}
118+
119+
export interface Filter {
120+
field: string;
121+
operator: string;
122+
value: string;
123+
}
124+
125+
export enum Aggregator {
126+
AND = 'and',
127+
OR = 'or'
128+
}
129+
130+
export interface AggregatedFilters {
131+
aggregator: Aggregator;
132+
conditions: Filter[];
133+
}
134+
135+
export interface Query {
136+
timezone?: string;
137+
search?: string;
138+
fields?: {[key: string]: string};
139+
sort?: string;
140+
filters?: Filter|AggregatedFilters;
141+
page?: Page;
142+
searchExtended?: string;
143+
}
144+
145+
// Everything related to Forest collection configuration
146+
147+
export interface SmartFieldValueGetter<M extends Sequelize.Model = any> {
148+
(record: M): any;
149+
}
150+
151+
export interface SmartFieldValueSetter<M extends Sequelize.Model = any> {
152+
(record: M, fieldValue: any): any;
153+
}
154+
155+
export interface SmartFieldSearchQuery {
156+
include: string[],
157+
where: Sequelize.WhereOptions,
158+
}
159+
160+
export interface SmartFieldSearcher {
161+
(query: SmartFieldSearchQuery, search: string): SmartFieldSearchQuery;
162+
}
163+
164+
export interface SmartFieldFiltererFilter {
165+
condition: Filter,
166+
where: Record<symbol, Record<symbol, any> | any>,
167+
}
168+
169+
export interface SmartFieldFilterer {
170+
(filter: SmartFieldFiltererFilter): Sequelize.WhereOptions;
171+
}
172+
173+
export interface SegmentAggregationCreator<M extends Sequelize.Model = any> {
174+
(model: M): Sequelize.WhereOptions;
175+
}
176+
177+
type FieldType = 'Boolean' | 'Date' | 'Dateonly' | 'Enum' | 'File' | 'Number' | 'String' | ['Enum'] | ['Number'] | ['String'];
178+
179+
type FieldEnumsType = string[] | number[] | Date[] | boolean[];
180+
181+
export interface SmartFieldOptions {
182+
field: string;
183+
description?: string;
184+
type: FieldType;
185+
isFilterable?: boolean;
186+
isReadOnly?: boolean;
187+
isRequired?: boolean;
188+
reference?: string;
189+
enums?: FieldEnumsType;
190+
defaultValue?: any;
191+
get?: SmartFieldValueGetter;
192+
set?: SmartFieldValueSetter;
193+
search?: SmartFieldSearcher;
194+
filter?: SmartFieldFilterer;
195+
}
196+
197+
export interface SmartActionField {
198+
field: string,
199+
description?: string,
200+
type: FieldType,
201+
isRequired?: boolean,
202+
isReadOnly?: boolean,
203+
enums?: FieldEnumsType,
204+
defaultValue?: any,
205+
reference?: string,
206+
}
207+
208+
export interface SmartActionHookField extends SmartActionField {
209+
value: any,
210+
}
211+
212+
export interface SmartActionLoadHookField extends SmartActionHookField {
213+
position: number,
214+
}
215+
216+
export interface SmartActionLoadHook<M extends Sequelize.Model = any> {
217+
(context: { fields: Record<string, SmartActionLoadHookField>, record: M }): Record<string, SmartActionLoadHookField>
218+
}
219+
220+
export interface SmartActionChangeHookField extends SmartActionHookField {
221+
previousValue: any,
222+
}
223+
224+
export interface SmartActionChangeHook<M extends Sequelize.Model = any> {
225+
(context: { fields: Record<string, SmartActionChangeHookField>, record: M }): Record<string, SmartActionChangeHookField>
226+
}
227+
228+
export interface SmartActionHooks {
229+
load: SmartActionLoadHook;
230+
change: Record<string, SmartActionChangeHook>;
231+
}
232+
233+
export interface SmartActionOptions {
234+
name: string;
235+
type?: 'global' | 'bulk' | 'single';
236+
fields?: SmartActionField[];
237+
download?: boolean;
238+
endpoint?: string;
239+
httpMethod?: string;
240+
hooks?: SmartActionHooks;
241+
}
242+
243+
export interface SmartSegmentOptions {
244+
name: string;
245+
where: SegmentAggregationCreator;
246+
}
247+
248+
export interface CollectionOptions {
249+
fields?: SmartFieldOptions[];
250+
actions?: SmartActionOptions[];
251+
segments?: SmartSegmentOptions[];
252+
}
253+
254+
export function collection(name: string, options: CollectionOptions): void;
255+
256+
export function errorHandler(): RequestHandler;

0 commit comments

Comments
 (0)