@weapnl/js-junction 0.0.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 (43) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/README.md +348 -0
  3. package/babel.config.json +5 -0
  4. package/dist/index.js +4369 -0
  5. package/docker-compose.yml +14 -0
  6. package/index.d.ts +150 -0
  7. package/package.json +34 -0
  8. package/src/api.js +226 -0
  9. package/src/batch.js +39 -0
  10. package/src/builder/caster.js +67 -0
  11. package/src/builder/model.js +259 -0
  12. package/src/builder/properties/accessors.js +116 -0
  13. package/src/builder/properties/attributes.js +118 -0
  14. package/src/builder/properties/counts.js +79 -0
  15. package/src/builder/properties/property.js +37 -0
  16. package/src/builder/properties/relations.js +124 -0
  17. package/src/connection.js +83 -0
  18. package/src/filters/count.js +27 -0
  19. package/src/filters/filter.js +9 -0
  20. package/src/filters/filters.js +33 -0
  21. package/src/filters/limit.js +27 -0
  22. package/src/filters/order.js +30 -0
  23. package/src/filters/pluck.js +28 -0
  24. package/src/filters/relations.js +27 -0
  25. package/src/filters/scopes.js +30 -0
  26. package/src/filters/search.js +34 -0
  27. package/src/filters/whereIn.js +31 -0
  28. package/src/filters/wheres.js +32 -0
  29. package/src/index.js +12 -0
  30. package/src/mixins/actionMixin.js +20 -0
  31. package/src/mixins/filterMixin.js +104 -0
  32. package/src/mixins/modifierMixin.js +22 -0
  33. package/src/mixins/paginationMixin.js +20 -0
  34. package/src/modifiers/appends.js +28 -0
  35. package/src/modifiers/hiddenFields.js +27 -0
  36. package/src/modifiers/modifier.js +9 -0
  37. package/src/modifiers/modifiers.js +19 -0
  38. package/src/request/action.js +29 -0
  39. package/src/request/pagination.js +35 -0
  40. package/src/request.js +317 -0
  41. package/src/response.js +33 -0
  42. package/src/utilities/format.js +11 -0
  43. package/webpack.config.js +28 -0
@@ -0,0 +1,14 @@
1
+ services:
2
+ dev:
3
+ image: registry.weap.nl:5005/docker/npmnginx:8.1
4
+ volumes:
5
+ - ./:/var/www
6
+ - ../Shared:/var/shared
7
+ command: "tail -f /dev/null"
8
+
9
+ build:
10
+ image: registry.weap.nl:5005/docker/npmnginx:8.1
11
+ volumes:
12
+ - ./:/var/www
13
+ - ../Shared:/var/shared
14
+ command: "npm run prod"
package/index.d.ts ADDED
@@ -0,0 +1,150 @@
1
+ import { AxiosResponse } from 'axios';
2
+
3
+ interface JsonMap {
4
+ [key: string]: any;
5
+ }
6
+
7
+ // Definieer de class en zijn methoden
8
+ declare class Api {
9
+ constructor();
10
+
11
+ host(host: string): this;
12
+ suffix(suffix: string): this;
13
+ readonly baseUrl: string;
14
+
15
+ request(uri: string): Request;
16
+ cancelRequests(): this;
17
+ batch(requests: Request[]): Batch;
18
+
19
+ setBearer(token: string): void;
20
+ resetBearer(): void;
21
+ setCsrf(token: string): void;
22
+ resetCsrf(): void;
23
+
24
+ setHeader(key: string, value: string): void;
25
+ removeHeader(key: string): void;
26
+
27
+ onSuccess(callback?: (data: any) => void): this;
28
+ onError(callback?: (response: AxiosResponse) => void): this;
29
+ onValidationError(callback?: (validation: any) => void): this;
30
+ onUnauthorized(callback?: (response: AxiosResponse) => void): this;
31
+ onForbidden(callback?: (response: AxiosResponse) => void): this;
32
+
33
+ responseInterceptors(
34
+ onSuccess?: (response: AxiosResponse) => void,
35
+ onError?: (error: any) => void
36
+ ): this;
37
+ }
38
+
39
+ interface Response {
40
+ data: any;
41
+ statusCode: number;
42
+ validation?: {
43
+ message: string;
44
+ errors: object;
45
+ };
46
+ }
47
+
48
+ declare class Mixins {
49
+ count(relations: any[]): this;
50
+ limit(amount: number): this;
51
+ order(input: string | any[], direction?: string): this;
52
+ with(relations: any[]): this;
53
+ scope(name: string, ...params: any[]): this;
54
+ scopes(...params: any[]): this;
55
+ search(value: any, columns?: any[]): this;
56
+ where(column: string, operator: string, value: any): this;
57
+ wheres(...params: any[]): this;
58
+ whereIn(column: string, values: any[]): this;
59
+ whereIns(...params: any[]): this;
60
+ pluck(fields: any[]): this;
61
+
62
+ appends(appends: string | string[]): this;
63
+ hiddenFields(hiddenFields: string | string[]): this;
64
+
65
+ action(name: string, id?: number): this;
66
+
67
+ pagination(page: number, perPage?: number, findPageForId?: number | null): this;
68
+ }
69
+
70
+ declare class Request extends Mixins {
71
+ constructor();
72
+ readonly response: Response;
73
+ setUrl(url: string): this;
74
+ cancel(): this;
75
+ get(): Promise<this>;
76
+ post(data?: object): Promise<this>;
77
+ put(data?: object): Promise<this>;
78
+ delete(): Promise<this>;
79
+ storeFiles(files?: object, data?: object): Promise<this>;
80
+ readonly bodyParameters: object;
81
+ onSuccess<T = any>(callback?: (result: T, data: any) => void): this;
82
+ onError(callback?: (response: Response) => void): this;
83
+ onValidationError(callback?: (validation: object) => void): this;
84
+ onUnauthorized(callback?: (response: Response) => void): this;
85
+ onForbidden(callback?: (response: Response) => void): this;
86
+ triggerResponseEvents(response: Response, successResponse?: any): Promise<void>;
87
+ customParameters(parameters?: any[]): this;
88
+ }
89
+
90
+ export class Model extends Request {
91
+ constructor(defaults?: JsonMap);
92
+
93
+ static fromJson(json: JsonMap): Model;
94
+
95
+ toJson(): JsonMap;
96
+
97
+ fill(values?: JsonMap): this;
98
+
99
+ static accessors(): JsonMap;
100
+
101
+ static attributes(): JsonMap;
102
+
103
+ static counts(): JsonMap;
104
+
105
+ static relations(): JsonMap;
106
+
107
+ static readonly endpoint: string;
108
+
109
+ readonly _identifier: number | string;
110
+
111
+ index(): Promise<Model[]>;
112
+
113
+ show(identifier?: number | string): Promise<Model | null>;
114
+
115
+ store(extraData?: JsonMap): Promise<Model>;
116
+
117
+ update(extraData?: JsonMap): Promise<Model>;
118
+
119
+ destroy(): Promise<boolean>;
120
+
121
+ save(extraData?: JsonMap): Promise<Model>;
122
+
123
+ clone(): Model;
124
+
125
+ _queryString(identifier?: number | string): string;
126
+ }
127
+
128
+ declare class Batch {
129
+ constructor(requests: any[]);
130
+
131
+ readonly successful: boolean;
132
+ readonly successfulRequests: any[];
133
+ readonly failedRequests: any[];
134
+
135
+ get(): Promise<any[]>;
136
+ post(): Promise<any[]>;
137
+ put(): Promise<any[]>;
138
+ delete(): Promise<any[]>;
139
+ index(): Promise<any[]>;
140
+ show(): Promise<any[]>;
141
+ store(): Promise<any[]>;
142
+ update(): Promise<any[]>;
143
+ destroy(): Promise<any[]>;
144
+ save(): Promise<any[]>;
145
+ storeFiles(): Promise<any[]>;
146
+
147
+ execute(method: string): Promise<any[]>;
148
+ }
149
+
150
+ export default Api;
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@weapnl/js-junction",
3
+ "version": "0.0.1",
4
+ "description": "This project allows you to easily consume API's built with Junction.",
5
+ "main": "./src/index.js",
6
+ "scripts": {
7
+ "dev": "webpack --mode development",
8
+ "watch": "webpack --mode development --watch",
9
+ "prod": "webpack"
10
+ },
11
+ "author": "Robin",
12
+ "license": "ISC",
13
+ "devDependencies": {
14
+ "@babel/core": "^7.12.13",
15
+ "@babel/preset-env": "^7.12.13",
16
+ "babel-core": "^6.26.3",
17
+ "babel-loader": "^8.2.2",
18
+ "babel-polyfill": "^6.26.0",
19
+ "webpack": "^5.77.0",
20
+ "webpack-cli": "^4.9.0"
21
+ },
22
+ "dependencies": {
23
+ "axios": "^1.3.0",
24
+ "lodash": "^4.17.20"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/weapnl/js-junction.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/weapnl/js-junction/issues"
32
+ },
33
+ "homepage": "https://github.com/weapnl/js-junction#readme"
34
+ }
package/src/api.js ADDED
@@ -0,0 +1,226 @@
1
+ import Request from './request';
2
+ import Batch from './batch';
3
+ import axios from 'axios';
4
+
5
+ export default class Api {
6
+ constructor () {
7
+ this.setHeader('X-Requested-With', 'XMLHttpRequest');
8
+
9
+ this._requests = [];
10
+
11
+ this.host('/').suffix('');
12
+
13
+ this._onSuccess = () => {};
14
+ this._onError = () => {};
15
+ this._onValidationError = () => {};
16
+ this._onUnauthorized = () => {};
17
+ this._onForbidden = () => {};
18
+ }
19
+
20
+ /**
21
+ * @param {string} host
22
+ *
23
+ * @returns {this} The current instance.
24
+ */
25
+ host (host) {
26
+ this._host = host;
27
+
28
+ return this;
29
+ }
30
+
31
+ /**
32
+ * @param {string} suffix
33
+ *
34
+ * @returns {this} The current instance.
35
+ */
36
+ suffix (suffix) {
37
+ if (! _.startsWith(suffix, '/') && suffix) {
38
+ suffix = `/${suffix}`;
39
+ }
40
+
41
+ this._suffix = suffix;
42
+
43
+ return this;
44
+ }
45
+
46
+ /**
47
+ * @returns {string} Url containing the host and suffix.
48
+ */
49
+ get baseUrl () {
50
+ let url = '';
51
+
52
+ if (this._host) url += this._host;
53
+ if (this._suffix) url += this._suffix;
54
+
55
+ return url;
56
+ }
57
+
58
+ /**
59
+ * @param {string} uri
60
+ *
61
+ * @returns {Request} The created request.
62
+ */
63
+ request (uri) {
64
+ if (! uri) throw new Error(`Request url is empty.`);
65
+
66
+ if (! _.startsWith(uri, '/')) {
67
+ uri = `/${uri}`;
68
+ }
69
+
70
+ const request = new Request();
71
+
72
+ request.setUrl(uri)
73
+ .onSuccess(this._onSuccess)
74
+ .onError(this._onError)
75
+ .onValidationError(this._onValidationError)
76
+ .onUnauthorized(this._onUnauthorized)
77
+ .onForbidden(this._onForbidden);
78
+
79
+ this._requests.push(request);
80
+
81
+ return request;
82
+ }
83
+
84
+ /**
85
+ * @returns {this} The current instance.
86
+ */
87
+ cancelRequests () {
88
+ this._requests.forEach((request) => {
89
+ request.cancel();
90
+ });
91
+
92
+ this._requests = [];
93
+
94
+ return this;
95
+ }
96
+
97
+ /**
98
+ * @param {array} requests
99
+ * @returns Batch
100
+ */
101
+ batch (requests) {
102
+ return new Batch(requests);
103
+ }
104
+
105
+ /**
106
+ * @param {string} token
107
+ */
108
+ setBearer (token) {
109
+ this.setHeader('Authorization', 'Bearer ' + token);
110
+ }
111
+
112
+ resetBearer () {
113
+ this.removeHeader('Authorization');
114
+ }
115
+
116
+ /**
117
+ * @param {string} token
118
+ */
119
+ setCsrf (token) {
120
+ this.setHeader('X-CSRF-TOKEN', token);
121
+ }
122
+
123
+ resetCsrf () {
124
+ this.removeHeader('X-CSRF-TOKEN');
125
+ }
126
+
127
+ /**
128
+ * @param {string} key
129
+ * @param {string} value
130
+ */
131
+ setHeader (key, value) {
132
+ axios.defaults.headers.common[key] = value;
133
+ }
134
+
135
+ /**
136
+ * @param {string} key
137
+ */
138
+ removeHeader (key) {
139
+ delete axios.defaults.headers.common[key];
140
+ }
141
+
142
+ /**
143
+ * Set the default 'onSuccess'. Can be overridden in the Request class.
144
+ *
145
+ * @param {function(Response.data)} callback
146
+ *
147
+ * @returns {this} The current instance.
148
+ */
149
+ onSuccess (callback = () => {}) {
150
+ this._onSuccess = callback;
151
+
152
+ return this;
153
+ }
154
+
155
+ /**
156
+ * Set the default 'onError'. Can be overridden in the Request class.
157
+ *
158
+ * @param {function(Response)} callback
159
+ *
160
+ * @returns {this} The current instance.
161
+ */
162
+ onError (callback = () => {}) {
163
+ this._onError = callback;
164
+
165
+ return this;
166
+ }
167
+
168
+ /**
169
+ * Set the default 'onValidationError'. Can be overridden in the Request class.
170
+ *
171
+ * @param {function(Response.validation)} callback
172
+ *
173
+ * @returns {this} The current instance.
174
+ */
175
+ onValidationError (callback = () => {}) {
176
+ this._onValidationError = callback;
177
+
178
+ return this;
179
+ }
180
+
181
+ /**
182
+ * Set the default 'onUnauthorized'. Can be overridden in the Request class.
183
+ *
184
+ * @param {function(Response)} callback
185
+ *
186
+ * @returns {this} The current instance.
187
+ */
188
+ onUnauthorized (callback = () => {}) {
189
+ this._onUnauthorized = callback;
190
+
191
+ return this;
192
+ }
193
+
194
+ /**
195
+ * Set the default 'onForbidden'. Can be overridden in the Request class.
196
+ *
197
+ * @param {function(Response)} callback
198
+ *
199
+ * @returns {this} The current instance.
200
+ */
201
+ onForbidden (callback = () => {}) {
202
+ this._onForbidden = callback;
203
+
204
+ return this;
205
+ }
206
+
207
+ /**
208
+ * @param {function(Response)} onSuccess
209
+ * @param {function(Error)} onError
210
+ *
211
+ * @returns {this}
212
+ */
213
+ responseInterceptors (onSuccess = () => {}, onError = () => {}) {
214
+ axios.interceptors.response.use((response) => {
215
+ onSuccess(response);
216
+
217
+ return response;
218
+ }, (error) => {
219
+ onError(error);
220
+
221
+ return Promise.reject(error);
222
+ });
223
+
224
+ return this;
225
+ }
226
+ }
package/src/batch.js ADDED
@@ -0,0 +1,39 @@
1
+ export default class Batch {
2
+ constructor (requests) {
3
+ this._requests = requests;
4
+ }
5
+
6
+ get successful () {
7
+ return _.isEmpty(this.failedRequests);
8
+ }
9
+
10
+ get successfulRequests () {
11
+ return _.filter(this._requests, ['response.failed', false]);
12
+ }
13
+
14
+ get failedRequests () {
15
+ return _.filter(this._requests, ['response.failed', true]);
16
+ }
17
+
18
+ async get () { return this.execute('get'); }
19
+ async post () { return this.execute('post'); }
20
+ async put () { return this.execute('put'); }
21
+ async delete () { return this.execute('delete'); }
22
+ async index () { return this.execute('index'); }
23
+ async show () { return this.execute('show'); }
24
+ async store () { return this.execute('store'); }
25
+ async update () { return this.execute('update'); }
26
+ async destroy () { return this.execute('destroy'); }
27
+ async save () { return this.execute('save'); }
28
+ async storeFiles () { return this.execute('storeFiles'); }
29
+
30
+ /**
31
+ * @param {string} method The methods used to execute the requests. Should be `index`, `show`, `store`, `update` or `delete`.
32
+ * @returns {array} List of results if all requests were successful.
33
+ */
34
+ async execute (method) {
35
+ return await Promise.all(_.map(this._requests, (request) => {
36
+ return request[method]();
37
+ }));
38
+ }
39
+ }
@@ -0,0 +1,67 @@
1
+ import Model from './model';
2
+
3
+ export default class Caster {
4
+ /**
5
+ * Get the casted value from a json value.
6
+ *
7
+ * @param {Object} cast
8
+ * @param {any} value
9
+ *
10
+ * @returns {any}
11
+ */
12
+ static fromJson (cast, value) {
13
+ if (cast.prototype instanceof Model) {
14
+ return this._castValue(value, (json) => cast.fromJson(json));
15
+ }
16
+
17
+ if (cast === Array) {
18
+ return this._castValue(value, (json) => Array.from(json));
19
+ }
20
+
21
+ if (cast === Object) {
22
+ return this._castValue(value, (json) => Object.assign({}, json));
23
+ }
24
+
25
+ return this._castValue(value, _.flow(cast));
26
+ }
27
+
28
+ /**
29
+ * Get the casted value of a property so it's safe to send with json.
30
+ *
31
+ * @param {Object} cast
32
+ * @param {any} value
33
+ *
34
+ * @returns {any}
35
+ */
36
+ static toJson (cast, value) {
37
+ if (_.isNil(value)) {
38
+ return null;
39
+ }
40
+
41
+ if (cast.prototype instanceof Model) {
42
+ return this._castValue(value, (model) => model.toJson());
43
+ }
44
+
45
+ if (cast === Array) {
46
+ return this._castValue(value, (value) => Array.from(value));
47
+ }
48
+
49
+ return this._castValue(value, _.flow(cast));
50
+ }
51
+
52
+ /**
53
+ * Cast the value with the given cast method.
54
+ *
55
+ * @param {Function} cast
56
+ * @param {any} value
57
+ *
58
+ * @returns {any}
59
+ */
60
+ static _castValue (value, cast) {
61
+ if (_.isNil(value)) {
62
+ return null;
63
+ }
64
+
65
+ return cast(value);
66
+ }
67
+ }