5htp-core 0.3.6-9 → 0.3.7-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.
- package/package.json +1 -1
- package/src/client/assets/css/utils/layouts.less +14 -0
- package/src/client/components/Table/index.tsx +8 -6
- package/src/client/services/router/request/api.ts +2 -2
- package/src/common/errors/index.ts +2 -1
- package/src/common/validation/validators.ts +7 -7
- package/src/server/app/index.ts +1 -1
- package/src/server/app/service/index.ts +28 -8
- package/src/server/services/fetch/index.ts +64 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp-core",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.7-1",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -130,6 +130,20 @@
|
|
|
130
130
|
&.sep-1 > * + * { border-top: solid 1px var(--cLine); }
|
|
131
131
|
|
|
132
132
|
> .col-1 { align-self: stretch; }
|
|
133
|
+
|
|
134
|
+
&.unibody {
|
|
135
|
+
|
|
136
|
+
gap: 0;
|
|
137
|
+
|
|
138
|
+
> :not(:first-child) {
|
|
139
|
+
border-top-left-radius: 0;
|
|
140
|
+
border-top-right-radius: 0;
|
|
141
|
+
}
|
|
142
|
+
> :not(:last-child) {
|
|
143
|
+
border-bottom-left-radius: 0;
|
|
144
|
+
border-bottom-right-radius: 0;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
133
147
|
}
|
|
134
148
|
|
|
135
149
|
.row,
|
|
@@ -23,7 +23,7 @@ export type Props<TRow> = {
|
|
|
23
23
|
columns: (row: TRow, rows: TRow[], index: number) => TColumn[];
|
|
24
24
|
|
|
25
25
|
setData?: (rows: TRow[]) => void,
|
|
26
|
-
empty?: ComponentChild,
|
|
26
|
+
empty?: ComponentChild | false,
|
|
27
27
|
className?: string,
|
|
28
28
|
|
|
29
29
|
actions?: TAction<TRow>[]
|
|
@@ -40,15 +40,17 @@ export type TColumn = {
|
|
|
40
40
|
- COMPOSANTS
|
|
41
41
|
----------------------------------*/
|
|
42
42
|
export default function Liste<TRow extends TDonneeInconnue>({
|
|
43
|
-
data: rows, setData, empty
|
|
43
|
+
data: rows, setData, empty,
|
|
44
44
|
columns, actions, ...props
|
|
45
45
|
}: Props<TRow>) {
|
|
46
46
|
|
|
47
47
|
if (rows.length === 0)
|
|
48
|
-
return (
|
|
49
|
-
<div class="
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
return empty === false ? null : (
|
|
49
|
+
<div class="pd-2 col al-center">
|
|
50
|
+
{empty || <>
|
|
51
|
+
<i src="meh-rolling-eyes" class="xl" />
|
|
52
|
+
Uh ... No rows here.
|
|
53
|
+
</>}
|
|
52
54
|
</div>
|
|
53
55
|
);
|
|
54
56
|
|
|
@@ -12,7 +12,7 @@ import ApiClientService, {
|
|
|
12
12
|
TApiFetchOptions, TFetcherList, TFetcherArgs, TFetcher,
|
|
13
13
|
TDataReturnedByFetchers
|
|
14
14
|
} from '@common/router/request/api';
|
|
15
|
-
import {
|
|
15
|
+
import { viaHttpCode, NetworkError } from '@common/errors';
|
|
16
16
|
import type ClientApplication from '@client/app';
|
|
17
17
|
|
|
18
18
|
import { toMultipart } from './multipart';
|
|
@@ -233,7 +233,7 @@ export default class ApiClient implements ApiClientService {
|
|
|
233
233
|
if (e.response !== undefined) {
|
|
234
234
|
|
|
235
235
|
console.warn(`[api] Failure:`, e);
|
|
236
|
-
throw
|
|
236
|
+
throw viaHttpCode(
|
|
237
237
|
e.response.status || 500,
|
|
238
238
|
e.response.data
|
|
239
239
|
);
|
|
@@ -169,12 +169,13 @@ export class NetworkError extends Error {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
|
|
172
|
-
export const
|
|
172
|
+
export const viaHttpCode = (
|
|
173
173
|
code: number,
|
|
174
174
|
message?: string | TListeErreursSaisie,
|
|
175
175
|
details?: TDetailsErreur
|
|
176
176
|
): CoreError => {
|
|
177
177
|
|
|
178
|
+
// TODO: more reliablme detection of form errors
|
|
178
179
|
if (typeof message === 'object')
|
|
179
180
|
return new InputErrorSchema(message, details);
|
|
180
181
|
|
|
@@ -145,11 +145,13 @@ export default class SchemaValidators {
|
|
|
145
145
|
/*----------------------------------
|
|
146
146
|
- CHAINES
|
|
147
147
|
----------------------------------*/
|
|
148
|
-
public string = ({ min, max, ...opts }: TValidator<string> & {
|
|
148
|
+
public string = ({ min, max, include, ...opts }: TValidator<string> & {
|
|
149
149
|
min?: number,
|
|
150
|
-
max?: number
|
|
150
|
+
max?: number,
|
|
151
|
+
include?: string
|
|
151
152
|
} = {}) => new Validator<string>('string', (val, input, output, corriger?: boolean) => {
|
|
152
153
|
|
|
154
|
+
// Check type
|
|
153
155
|
if (val === '')
|
|
154
156
|
return undefined;
|
|
155
157
|
else if (typeof val === 'number')
|
|
@@ -157,14 +159,14 @@ export default class SchemaValidators {
|
|
|
157
159
|
else if (typeof val !== 'string')
|
|
158
160
|
throw new InputError("This value must be a string.");
|
|
159
161
|
|
|
160
|
-
//
|
|
162
|
+
// Whitespace
|
|
161
163
|
val = trim(val);
|
|
162
164
|
|
|
163
|
-
//
|
|
165
|
+
// Min size
|
|
164
166
|
if (min !== undefined && val.length < min)
|
|
165
167
|
throw new InputError(`Must be at least ` + min + ' characters');
|
|
166
168
|
|
|
167
|
-
//
|
|
169
|
+
// Max size
|
|
168
170
|
if (max !== undefined && val.length > max)
|
|
169
171
|
if (corriger)
|
|
170
172
|
val = val.substring(0, max);
|
|
@@ -192,8 +194,6 @@ export default class SchemaValidators {
|
|
|
192
194
|
if (opts.normalize !== undefined)
|
|
193
195
|
val = normalizeUrl(val, opts.normalize);
|
|
194
196
|
|
|
195
|
-
console.log("@@@@@@@@@@@@@NORMALISZE URL", opts.normalize, val);
|
|
196
|
-
|
|
197
197
|
return val;
|
|
198
198
|
}, opts)
|
|
199
199
|
|
package/src/server/app/index.ts
CHANGED
|
@@ -101,7 +101,7 @@ export class Application<
|
|
|
101
101
|
this.parent = this;
|
|
102
102
|
this.app = this;
|
|
103
103
|
|
|
104
|
-
//
|
|
104
|
+
// Handle unhandled crash
|
|
105
105
|
process.on('unhandledRejection', (error: any, promise: any) => {
|
|
106
106
|
// We don't log the error here because it's the role of the app to decidehiw to log errors
|
|
107
107
|
this.runHook('error', error);
|
|
@@ -193,16 +193,36 @@ export default abstract class Service<
|
|
|
193
193
|
|
|
194
194
|
// Instanciate
|
|
195
195
|
console.log(`[app] Load service`, registered.metas.id);
|
|
196
|
-
|
|
196
|
+
let ServiceClass;
|
|
197
|
+
try {
|
|
198
|
+
ServiceClass = registered.metas.class().default;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.error("Failed to get the class of the", registered.metas.id, "service:", error);
|
|
201
|
+
process.exit();
|
|
202
|
+
}
|
|
197
203
|
|
|
198
204
|
// Create class instance
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
let service;
|
|
206
|
+
try {
|
|
207
|
+
service = new ServiceClass(
|
|
208
|
+
this,
|
|
209
|
+
registered.config,
|
|
210
|
+
registered.subServices,
|
|
211
|
+
this.app || this
|
|
212
|
+
)
|
|
213
|
+
} catch (error) {
|
|
214
|
+
console.error("Failed to instanciate class of the", registered.metas.id, "service:", error);
|
|
215
|
+
process.exit();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Hande custom instance getter (ex: SQL callable class)
|
|
219
|
+
let serviceInstance;
|
|
220
|
+
try {
|
|
221
|
+
serviceInstance = service.getServiceInstance();
|
|
222
|
+
} catch (error) {
|
|
223
|
+
console.error("Failed to get service instance for the ", registered.metas.id, "service:", error);
|
|
224
|
+
process.exit();
|
|
225
|
+
}
|
|
206
226
|
|
|
207
227
|
// Bind his own metas
|
|
208
228
|
service.metas = registered.metas;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Npm
|
|
6
6
|
import sharp from 'sharp';
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
|
+
import got, { Method, Options } from 'got';
|
|
8
9
|
|
|
9
10
|
// Node
|
|
10
11
|
import request from 'request';
|
|
@@ -12,6 +13,10 @@ import request from 'request';
|
|
|
12
13
|
// Core: general
|
|
13
14
|
import type { Application } from '@server/app';
|
|
14
15
|
import Service, { AnyService } from '@server/app/service';
|
|
16
|
+
import { viaHttpCode } from '@common/errors';
|
|
17
|
+
|
|
18
|
+
// Local
|
|
19
|
+
import type RouterService from '../router';
|
|
15
20
|
import type DisksManager from '../disks';
|
|
16
21
|
import type FsDriver from '../disks/driver';
|
|
17
22
|
|
|
@@ -29,7 +34,8 @@ export type Hooks = {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
export type Services = {
|
|
32
|
-
disks: DisksManager
|
|
37
|
+
disks: DisksManager,
|
|
38
|
+
router?: RouterService
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
/*----------------------------------
|
|
@@ -89,7 +95,63 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
|
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
/*----------------------------------
|
|
92
|
-
-
|
|
98
|
+
- EXTERNAL API REQUESTS
|
|
99
|
+
----------------------------------*/
|
|
100
|
+
|
|
101
|
+
public post(
|
|
102
|
+
url: string,
|
|
103
|
+
data: {[k: string]: any},
|
|
104
|
+
options: {} = {}
|
|
105
|
+
) {
|
|
106
|
+
|
|
107
|
+
return this.request('POST', url, data, options);
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public async request(
|
|
112
|
+
method: Method,
|
|
113
|
+
url: string,
|
|
114
|
+
data: {[k: string]: any},
|
|
115
|
+
options: Options = {}
|
|
116
|
+
) {
|
|
117
|
+
|
|
118
|
+
// Parse url if router service is provided
|
|
119
|
+
if (this.services.router !== undefined)
|
|
120
|
+
url = this.services.router.url(url);
|
|
121
|
+
|
|
122
|
+
// Send request
|
|
123
|
+
const res = await got(url, {
|
|
124
|
+
throwHttpErrors: false,
|
|
125
|
+
headers: {
|
|
126
|
+
'Accept': 'application/json',
|
|
127
|
+
},
|
|
128
|
+
method,
|
|
129
|
+
...(method === 'GET' ? {
|
|
130
|
+
searchParams: data
|
|
131
|
+
} : {
|
|
132
|
+
json: data
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Handle errors
|
|
137
|
+
if (res.statusCode !== 200) {
|
|
138
|
+
|
|
139
|
+
// Instanciate error from HTTP code
|
|
140
|
+
const error = viaHttpCode( res.statusCode, res.body );
|
|
141
|
+
if (error)
|
|
142
|
+
throw error;
|
|
143
|
+
|
|
144
|
+
// Not catched via viaHttpCode
|
|
145
|
+
console.log("RESPONSE", res.body);
|
|
146
|
+
throw new Error("Error while contacting the API");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Format & return response
|
|
150
|
+
return JSON.parse( res.body );
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/*----------------------------------
|
|
154
|
+
- IMAGES
|
|
93
155
|
----------------------------------*/
|
|
94
156
|
|
|
95
157
|
public toBuffer( uri: string ): Promise<Buffer> {
|