@platformatic/runtime 0.30.0 → 0.30.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 (22) hide show
  1. package/fixtures/typescript-custom-flags/platformatic.runtime.json +12 -0
  2. package/fixtures/typescript-custom-flags/services/composer/platformatic.composer.json +28 -0
  3. package/fixtures/typescript-custom-flags/services/movies/global.d.ts +24 -0
  4. package/fixtures/typescript-custom-flags/services/movies/migrations/001.do.sql +6 -0
  5. package/fixtures/typescript-custom-flags/services/movies/migrations/001.undo.sql +3 -0
  6. package/fixtures/typescript-custom-flags/services/movies/platformatic.db.json +35 -0
  7. package/fixtures/typescript-custom-flags/services/movies/plugin.ts +5 -0
  8. package/fixtures/typescript-custom-flags/services/movies/tsconfig.json +21 -0
  9. package/fixtures/typescript-custom-flags/services/movies/types/Movie.d.ts +9 -0
  10. package/fixtures/typescript-custom-flags/services/movies/types/index.d.ts +7 -0
  11. package/fixtures/typescript-custom-flags/services/titles/client/client.d.ts +141 -0
  12. package/fixtures/typescript-custom-flags/services/titles/client/client.openapi.json +630 -0
  13. package/fixtures/typescript-custom-flags/services/titles/client/package.json +4 -0
  14. package/fixtures/typescript-custom-flags/services/titles/platformatic.service.json +33 -0
  15. package/fixtures/typescript-custom-flags/services/titles/plugins/example.ts +6 -0
  16. package/fixtures/typescript-custom-flags/services/titles/routes/root.ts +21 -0
  17. package/fixtures/typescript-custom-flags/services/titles/tsconfig.json +21 -0
  18. package/lib/app.js +3 -2
  19. package/lib/compile.js +8 -10
  20. package/package.json +8 -8
  21. package/test/app.test.js +3 -1
  22. package/test/cli/compile.test.mjs +45 -0
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://platformatic.dev/schemas/v0.28.1/runtime",
3
+ "entrypoint": "composer",
4
+ "allowCycles": false,
5
+ "hotReload": true,
6
+ "autoload": {
7
+ "path": "services",
8
+ "exclude": [
9
+ "docs"
10
+ ]
11
+ }
12
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://platformatic.dev/schemas/v0.28.1/composer",
3
+ "server": {
4
+ "hostname": "{PLT_SERVER_HOSTNAME}",
5
+ "port": "{PORT}",
6
+ "logger": {
7
+ "level": "{PLT_SERVER_LOGGER_LEVEL}"
8
+ }
9
+ },
10
+ "composer": {
11
+ "services": [
12
+ {
13
+ "id": "movies",
14
+ "openapi": {
15
+ "url": "/documentation/json"
16
+ }
17
+ },
18
+ {
19
+ "id": "titles",
20
+ "openapi": {
21
+ "url": "/documentation/json"
22
+ }
23
+ }
24
+ ],
25
+ "refreshTimeout": 1000
26
+ },
27
+ "watch": true
28
+ }
@@ -0,0 +1,24 @@
1
+ import { Entity } from '@platformatic/sql-mapper';
2
+ import graphqlPlugin from '@platformatic/sql-graphql'
3
+ import { EntityTypes, Movie } from './types'
4
+
5
+ declare module 'fastify' {
6
+ interface FastifyInstance {
7
+ getSchema<T extends 'Movie'>(schemaId: T): {
8
+ '$id': string,
9
+ title: string,
10
+ description: string,
11
+ type: string,
12
+ properties: {
13
+ [x in keyof EntityTypes[T]]: { type: string, nullable?: boolean }
14
+ },
15
+ required: string[]
16
+ };
17
+ }
18
+ }
19
+
20
+ declare module '@platformatic/sql-mapper' {
21
+ interface Entities {
22
+ movie: Entity<Movie>,
23
+ }
24
+ }
@@ -0,0 +1,6 @@
1
+
2
+ -- Add SQL in this file to create the database tables for your API
3
+ CREATE TABLE IF NOT EXISTS movies (
4
+ id INTEGER PRIMARY KEY,
5
+ title TEXT NOT NULL
6
+ );
@@ -0,0 +1,3 @@
1
+
2
+ -- Add SQL in this file to drop the database tables
3
+ DROP TABLE movies;
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://platformatic.dev/schemas/v0.30.0/db",
3
+ "server": {
4
+ "hostname": "{PLT_SERVER_HOSTNAME}",
5
+ "port": "{PORT}",
6
+ "logger": {
7
+ "level": "{PLT_SERVER_LOGGER_LEVEL}"
8
+ }
9
+ },
10
+ "db": {
11
+ "connectionString": "{DATABASE_URL}",
12
+ "graphql": true,
13
+ "openapi": true
14
+ },
15
+ "watch": {
16
+ "ignore": [
17
+ "*.sqlite",
18
+ "*.sqlite-journal"
19
+ ]
20
+ },
21
+ "migrations": {
22
+ "dir": "migrations"
23
+ },
24
+ "plugins": {
25
+ "paths": [
26
+ "plugin.ts"
27
+ ],
28
+ "typescript": {
29
+ "flags": ["-b"]
30
+ }
31
+ },
32
+ "types": {
33
+ "autogenerate": true
34
+ }
35
+ }
@@ -0,0 +1,5 @@
1
+ /// <reference path="./global.d.ts" />
2
+ import { FastifyInstance } from 'fastify'
3
+
4
+ export default async function (app: FastifyInstance) {
5
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "esModuleInterop": true,
5
+ "target": "es2019",
6
+ "sourceMap": true,
7
+ "pretty": true,
8
+ "noEmitOnError": true,
9
+ "outDir": "dist"
10
+ },
11
+ "watchOptions": {
12
+ "watchFile": "fixedPollingInterval",
13
+ "watchDirectory": "fixedPollingInterval",
14
+ "fallbackPolling": "dynamicPriority",
15
+ "synchronousWatchDirectory": true,
16
+ "excludeDirectories": [
17
+ "**/node_modules",
18
+ "dist"
19
+ ]
20
+ }
21
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Movie
3
+ * A Movie
4
+ */
5
+ declare interface Movie {
6
+ id?: number;
7
+ title: string;
8
+ }
9
+ export { Movie };
@@ -0,0 +1,7 @@
1
+ import { Movie } from './Movie'
2
+
3
+ interface EntityTypes {
4
+ Movie:Movie
5
+ }
6
+
7
+ export { EntityTypes ,Movie }
@@ -0,0 +1,141 @@
1
+ import { FastifyPluginAsync } from 'fastify'
2
+
3
+ interface GetMoviesRequest {
4
+ 'limit'?: number;
5
+ 'offset'?: number;
6
+ 'totalCount'?: boolean;
7
+ 'fields'?: Array<string>;
8
+ 'where.id.eq'?: number;
9
+ 'where.id.neq'?: number;
10
+ 'where.id.gt'?: number;
11
+ 'where.id.gte'?: number;
12
+ 'where.id.lt'?: number;
13
+ 'where.id.lte'?: number;
14
+ 'where.id.like'?: number;
15
+ 'where.id.in'?: string;
16
+ 'where.id.nin'?: string;
17
+ 'where.title.eq'?: string;
18
+ 'where.title.neq'?: string;
19
+ 'where.title.gt'?: string;
20
+ 'where.title.gte'?: string;
21
+ 'where.title.lt'?: string;
22
+ 'where.title.lte'?: string;
23
+ 'where.title.like'?: string;
24
+ 'where.title.in'?: string;
25
+ 'where.title.nin'?: string;
26
+ 'where.or'?: Array<string>;
27
+ 'orderby.id'?: string;
28
+ 'orderby.title'?: string;
29
+ }
30
+
31
+ interface GetMoviesResponseOK {
32
+ 'id'?: number;
33
+ 'title': string;
34
+ }
35
+
36
+ interface CreateMovieRequest {
37
+ 'id'?: number;
38
+ 'title': string;
39
+ }
40
+
41
+ interface CreateMovieResponseOK {
42
+ 'id'?: number;
43
+ 'title': string;
44
+ }
45
+
46
+ interface UpdateMoviesRequest {
47
+ 'fields'?: Array<string>;
48
+ 'where.id.eq'?: number;
49
+ 'where.id.neq'?: number;
50
+ 'where.id.gt'?: number;
51
+ 'where.id.gte'?: number;
52
+ 'where.id.lt'?: number;
53
+ 'where.id.lte'?: number;
54
+ 'where.id.like'?: number;
55
+ 'where.id.in'?: string;
56
+ 'where.id.nin'?: string;
57
+ 'where.title.eq'?: string;
58
+ 'where.title.neq'?: string;
59
+ 'where.title.gt'?: string;
60
+ 'where.title.gte'?: string;
61
+ 'where.title.lt'?: string;
62
+ 'where.title.lte'?: string;
63
+ 'where.title.like'?: string;
64
+ 'where.title.in'?: string;
65
+ 'where.title.nin'?: string;
66
+ 'where.or'?: Array<string>;
67
+ 'id'?: number;
68
+ 'title': string;
69
+ }
70
+
71
+ interface UpdateMoviesResponseOK {
72
+ 'id'?: number;
73
+ 'title': string;
74
+ }
75
+
76
+ interface GetMovieByIdRequest {
77
+ 'fields'?: Array<string>;
78
+ 'id': number;
79
+ }
80
+
81
+ interface GetMovieByIdResponseOK {
82
+ 'id'?: number;
83
+ 'title': string;
84
+ }
85
+
86
+ interface UpdateMovieRequest {
87
+ 'fields'?: Array<string>;
88
+ 'id': number;
89
+ 'title': string;
90
+ }
91
+
92
+ interface UpdateMovieResponseOK {
93
+ 'id'?: number;
94
+ 'title': string;
95
+ }
96
+
97
+ interface DeleteMoviesRequest {
98
+ 'fields'?: Array<string>;
99
+ 'id': number;
100
+ }
101
+
102
+ interface DeleteMoviesResponseOK {
103
+ 'id'?: number;
104
+ 'title': string;
105
+ }
106
+
107
+ interface Client {
108
+ getMovies(req: GetMoviesRequest): Promise<Array<GetMoviesResponseOK>>;
109
+ createMovie(req: CreateMovieRequest): Promise<CreateMovieResponseOK>;
110
+ updateMovies(req: UpdateMoviesRequest): Promise<Array<UpdateMoviesResponseOK>>;
111
+ getMovieById(req: GetMovieByIdRequest): Promise<GetMovieByIdResponseOK>;
112
+ updateMovie(req: UpdateMovieRequest): Promise<UpdateMovieResponseOK>;
113
+ deleteMovies(req: DeleteMoviesRequest): Promise<DeleteMoviesResponseOK>;
114
+ }
115
+
116
+ type ClientPlugin = FastifyPluginAsync<NonNullable<client.ClientOptions>>
117
+
118
+ declare module 'fastify' {
119
+ interface ConfigureClient {
120
+ getHeaders(req: FastifyRequest, reply: FastifyReply): Promise<Record<string,string>>;
121
+ }
122
+ interface FastifyInstance {
123
+ 'client': Client;
124
+ configureClient(opts: ConfigureClient): unknown
125
+ }
126
+
127
+ interface FastifyRequest {
128
+ 'client': Client;
129
+ }
130
+ }
131
+
132
+ declare namespace client {
133
+ export interface ClientOptions {
134
+ url: string
135
+ }
136
+ export const client: ClientPlugin;
137
+ export { client as default };
138
+ }
139
+
140
+ declare function client(...params: Parameters<ClientPlugin>): ReturnType<ClientPlugin>;
141
+ export = client;
@@ -0,0 +1,630 @@
1
+ {
2
+ "openapi": "3.0.3",
3
+ "info": {
4
+ "title": "Platformatic DB",
5
+ "description": "Exposing a SQL database as REST",
6
+ "version": "1.0.0"
7
+ },
8
+ "components": {
9
+ "schemas": {
10
+ "Movie": {
11
+ "title": "Movie",
12
+ "description": "A Movie",
13
+ "type": "object",
14
+ "properties": {
15
+ "id": {
16
+ "type": "integer"
17
+ },
18
+ "title": {
19
+ "type": "string"
20
+ }
21
+ },
22
+ "required": [
23
+ "title"
24
+ ]
25
+ }
26
+ }
27
+ },
28
+ "paths": {
29
+ "/movies/": {
30
+ "get": {
31
+ "operationId": "getMovies",
32
+ "parameters": [
33
+ {
34
+ "schema": {
35
+ "type": "integer"
36
+ },
37
+ "in": "query",
38
+ "name": "limit",
39
+ "required": false,
40
+ "description": "Limit will be applied by default if not passed. If the provided value exceeds the maximum allowed value a validation error will be thrown"
41
+ },
42
+ {
43
+ "schema": {
44
+ "type": "integer"
45
+ },
46
+ "in": "query",
47
+ "name": "offset",
48
+ "required": false
49
+ },
50
+ {
51
+ "schema": {
52
+ "type": "boolean",
53
+ "default": false
54
+ },
55
+ "in": "query",
56
+ "name": "totalCount",
57
+ "required": false
58
+ },
59
+ {
60
+ "schema": {
61
+ "type": "array",
62
+ "items": {
63
+ "type": "string",
64
+ "enum": [
65
+ "id",
66
+ "title"
67
+ ]
68
+ }
69
+ },
70
+ "in": "query",
71
+ "name": "fields",
72
+ "required": false
73
+ },
74
+ {
75
+ "schema": {
76
+ "type": "integer"
77
+ },
78
+ "in": "query",
79
+ "name": "where.id.eq",
80
+ "required": false
81
+ },
82
+ {
83
+ "schema": {
84
+ "type": "integer"
85
+ },
86
+ "in": "query",
87
+ "name": "where.id.neq",
88
+ "required": false
89
+ },
90
+ {
91
+ "schema": {
92
+ "type": "integer"
93
+ },
94
+ "in": "query",
95
+ "name": "where.id.gt",
96
+ "required": false
97
+ },
98
+ {
99
+ "schema": {
100
+ "type": "integer"
101
+ },
102
+ "in": "query",
103
+ "name": "where.id.gte",
104
+ "required": false
105
+ },
106
+ {
107
+ "schema": {
108
+ "type": "integer"
109
+ },
110
+ "in": "query",
111
+ "name": "where.id.lt",
112
+ "required": false
113
+ },
114
+ {
115
+ "schema": {
116
+ "type": "integer"
117
+ },
118
+ "in": "query",
119
+ "name": "where.id.lte",
120
+ "required": false
121
+ },
122
+ {
123
+ "schema": {
124
+ "type": "integer"
125
+ },
126
+ "in": "query",
127
+ "name": "where.id.like",
128
+ "required": false
129
+ },
130
+ {
131
+ "schema": {
132
+ "type": "string"
133
+ },
134
+ "in": "query",
135
+ "name": "where.id.in",
136
+ "required": false
137
+ },
138
+ {
139
+ "schema": {
140
+ "type": "string"
141
+ },
142
+ "in": "query",
143
+ "name": "where.id.nin",
144
+ "required": false
145
+ },
146
+ {
147
+ "schema": {
148
+ "type": "string"
149
+ },
150
+ "in": "query",
151
+ "name": "where.title.eq",
152
+ "required": false
153
+ },
154
+ {
155
+ "schema": {
156
+ "type": "string"
157
+ },
158
+ "in": "query",
159
+ "name": "where.title.neq",
160
+ "required": false
161
+ },
162
+ {
163
+ "schema": {
164
+ "type": "string"
165
+ },
166
+ "in": "query",
167
+ "name": "where.title.gt",
168
+ "required": false
169
+ },
170
+ {
171
+ "schema": {
172
+ "type": "string"
173
+ },
174
+ "in": "query",
175
+ "name": "where.title.gte",
176
+ "required": false
177
+ },
178
+ {
179
+ "schema": {
180
+ "type": "string"
181
+ },
182
+ "in": "query",
183
+ "name": "where.title.lt",
184
+ "required": false
185
+ },
186
+ {
187
+ "schema": {
188
+ "type": "string"
189
+ },
190
+ "in": "query",
191
+ "name": "where.title.lte",
192
+ "required": false
193
+ },
194
+ {
195
+ "schema": {
196
+ "type": "string"
197
+ },
198
+ "in": "query",
199
+ "name": "where.title.like",
200
+ "required": false
201
+ },
202
+ {
203
+ "schema": {
204
+ "type": "string"
205
+ },
206
+ "in": "query",
207
+ "name": "where.title.in",
208
+ "required": false
209
+ },
210
+ {
211
+ "schema": {
212
+ "type": "string"
213
+ },
214
+ "in": "query",
215
+ "name": "where.title.nin",
216
+ "required": false
217
+ },
218
+ {
219
+ "schema": {
220
+ "type": "array",
221
+ "items": {
222
+ "type": "string"
223
+ }
224
+ },
225
+ "in": "query",
226
+ "name": "where.or",
227
+ "required": false
228
+ },
229
+ {
230
+ "schema": {
231
+ "type": "string",
232
+ "enum": [
233
+ "asc",
234
+ "desc"
235
+ ]
236
+ },
237
+ "in": "query",
238
+ "name": "orderby.id",
239
+ "required": false
240
+ },
241
+ {
242
+ "schema": {
243
+ "type": "string",
244
+ "enum": [
245
+ "asc",
246
+ "desc"
247
+ ]
248
+ },
249
+ "in": "query",
250
+ "name": "orderby.title",
251
+ "required": false
252
+ }
253
+ ],
254
+ "responses": {
255
+ "200": {
256
+ "description": "Default Response",
257
+ "content": {
258
+ "application/json": {
259
+ "schema": {
260
+ "type": "array",
261
+ "items": {
262
+ "$ref": "#/components/schemas/Movie"
263
+ }
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ },
270
+ "post": {
271
+ "operationId": "createMovie",
272
+ "requestBody": {
273
+ "content": {
274
+ "application/json": {
275
+ "schema": {
276
+ "$ref": "#/components/schemas/Movie"
277
+ }
278
+ }
279
+ }
280
+ },
281
+ "responses": {
282
+ "200": {
283
+ "description": "Default Response",
284
+ "content": {
285
+ "application/json": {
286
+ "schema": {
287
+ "$ref": "#/components/schemas/Movie"
288
+ }
289
+ }
290
+ },
291
+ "links": {}
292
+ }
293
+ }
294
+ },
295
+ "put": {
296
+ "operationId": "updateMovies",
297
+ "requestBody": {
298
+ "content": {
299
+ "application/json": {
300
+ "schema": {
301
+ "$ref": "#/components/schemas/Movie"
302
+ }
303
+ }
304
+ }
305
+ },
306
+ "parameters": [
307
+ {
308
+ "schema": {
309
+ "type": "array",
310
+ "items": {
311
+ "type": "string",
312
+ "enum": [
313
+ "id",
314
+ "title"
315
+ ]
316
+ }
317
+ },
318
+ "in": "query",
319
+ "name": "fields",
320
+ "required": false
321
+ },
322
+ {
323
+ "schema": {
324
+ "type": "integer"
325
+ },
326
+ "in": "query",
327
+ "name": "where.id.eq",
328
+ "required": false
329
+ },
330
+ {
331
+ "schema": {
332
+ "type": "integer"
333
+ },
334
+ "in": "query",
335
+ "name": "where.id.neq",
336
+ "required": false
337
+ },
338
+ {
339
+ "schema": {
340
+ "type": "integer"
341
+ },
342
+ "in": "query",
343
+ "name": "where.id.gt",
344
+ "required": false
345
+ },
346
+ {
347
+ "schema": {
348
+ "type": "integer"
349
+ },
350
+ "in": "query",
351
+ "name": "where.id.gte",
352
+ "required": false
353
+ },
354
+ {
355
+ "schema": {
356
+ "type": "integer"
357
+ },
358
+ "in": "query",
359
+ "name": "where.id.lt",
360
+ "required": false
361
+ },
362
+ {
363
+ "schema": {
364
+ "type": "integer"
365
+ },
366
+ "in": "query",
367
+ "name": "where.id.lte",
368
+ "required": false
369
+ },
370
+ {
371
+ "schema": {
372
+ "type": "integer"
373
+ },
374
+ "in": "query",
375
+ "name": "where.id.like",
376
+ "required": false
377
+ },
378
+ {
379
+ "schema": {
380
+ "type": "string"
381
+ },
382
+ "in": "query",
383
+ "name": "where.id.in",
384
+ "required": false
385
+ },
386
+ {
387
+ "schema": {
388
+ "type": "string"
389
+ },
390
+ "in": "query",
391
+ "name": "where.id.nin",
392
+ "required": false
393
+ },
394
+ {
395
+ "schema": {
396
+ "type": "string"
397
+ },
398
+ "in": "query",
399
+ "name": "where.title.eq",
400
+ "required": false
401
+ },
402
+ {
403
+ "schema": {
404
+ "type": "string"
405
+ },
406
+ "in": "query",
407
+ "name": "where.title.neq",
408
+ "required": false
409
+ },
410
+ {
411
+ "schema": {
412
+ "type": "string"
413
+ },
414
+ "in": "query",
415
+ "name": "where.title.gt",
416
+ "required": false
417
+ },
418
+ {
419
+ "schema": {
420
+ "type": "string"
421
+ },
422
+ "in": "query",
423
+ "name": "where.title.gte",
424
+ "required": false
425
+ },
426
+ {
427
+ "schema": {
428
+ "type": "string"
429
+ },
430
+ "in": "query",
431
+ "name": "where.title.lt",
432
+ "required": false
433
+ },
434
+ {
435
+ "schema": {
436
+ "type": "string"
437
+ },
438
+ "in": "query",
439
+ "name": "where.title.lte",
440
+ "required": false
441
+ },
442
+ {
443
+ "schema": {
444
+ "type": "string"
445
+ },
446
+ "in": "query",
447
+ "name": "where.title.like",
448
+ "required": false
449
+ },
450
+ {
451
+ "schema": {
452
+ "type": "string"
453
+ },
454
+ "in": "query",
455
+ "name": "where.title.in",
456
+ "required": false
457
+ },
458
+ {
459
+ "schema": {
460
+ "type": "string"
461
+ },
462
+ "in": "query",
463
+ "name": "where.title.nin",
464
+ "required": false
465
+ },
466
+ {
467
+ "schema": {
468
+ "type": "array",
469
+ "items": {
470
+ "type": "string"
471
+ }
472
+ },
473
+ "in": "query",
474
+ "name": "where.or",
475
+ "required": false
476
+ }
477
+ ],
478
+ "responses": {
479
+ "200": {
480
+ "description": "Default Response",
481
+ "content": {
482
+ "application/json": {
483
+ "schema": {
484
+ "type": "array",
485
+ "items": {
486
+ "$ref": "#/components/schemas/Movie"
487
+ }
488
+ }
489
+ }
490
+ },
491
+ "links": {}
492
+ }
493
+ }
494
+ }
495
+ },
496
+ "/movies/{id}": {
497
+ "get": {
498
+ "operationId": "getMovieById",
499
+ "parameters": [
500
+ {
501
+ "schema": {
502
+ "type": "array",
503
+ "items": {
504
+ "type": "string",
505
+ "enum": [
506
+ "id",
507
+ "title"
508
+ ]
509
+ }
510
+ },
511
+ "in": "query",
512
+ "name": "fields",
513
+ "required": false
514
+ },
515
+ {
516
+ "schema": {
517
+ "type": "integer"
518
+ },
519
+ "in": "path",
520
+ "name": "id",
521
+ "required": true
522
+ }
523
+ ],
524
+ "responses": {
525
+ "200": {
526
+ "description": "Default Response",
527
+ "content": {
528
+ "application/json": {
529
+ "schema": {
530
+ "$ref": "#/components/schemas/Movie"
531
+ }
532
+ }
533
+ },
534
+ "links": {}
535
+ }
536
+ }
537
+ },
538
+ "put": {
539
+ "operationId": "updateMovie",
540
+ "requestBody": {
541
+ "content": {
542
+ "application/json": {
543
+ "schema": {
544
+ "$ref": "#/components/schemas/Movie"
545
+ }
546
+ }
547
+ }
548
+ },
549
+ "parameters": [
550
+ {
551
+ "schema": {
552
+ "type": "array",
553
+ "items": {
554
+ "type": "string",
555
+ "enum": [
556
+ "id",
557
+ "title"
558
+ ]
559
+ }
560
+ },
561
+ "in": "query",
562
+ "name": "fields",
563
+ "required": false
564
+ },
565
+ {
566
+ "schema": {
567
+ "type": "integer"
568
+ },
569
+ "in": "path",
570
+ "name": "id",
571
+ "required": true
572
+ }
573
+ ],
574
+ "responses": {
575
+ "200": {
576
+ "description": "Default Response",
577
+ "content": {
578
+ "application/json": {
579
+ "schema": {
580
+ "$ref": "#/components/schemas/Movie"
581
+ }
582
+ }
583
+ },
584
+ "links": {}
585
+ }
586
+ }
587
+ },
588
+ "delete": {
589
+ "operationId": "deleteMovies",
590
+ "parameters": [
591
+ {
592
+ "schema": {
593
+ "type": "array",
594
+ "items": {
595
+ "type": "string",
596
+ "enum": [
597
+ "id",
598
+ "title"
599
+ ]
600
+ }
601
+ },
602
+ "in": "query",
603
+ "name": "fields",
604
+ "required": false
605
+ },
606
+ {
607
+ "schema": {
608
+ "type": "integer"
609
+ },
610
+ "in": "path",
611
+ "name": "id",
612
+ "required": true
613
+ }
614
+ ],
615
+ "responses": {
616
+ "200": {
617
+ "description": "Default Response",
618
+ "content": {
619
+ "application/json": {
620
+ "schema": {
621
+ "$ref": "#/components/schemas/Movie"
622
+ }
623
+ }
624
+ }
625
+ }
626
+ }
627
+ }
628
+ }
629
+ }
630
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "client",
3
+ "types": "./client.d.ts"
4
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://platformatic.dev/schemas/v0.30.0/service",
3
+ "server": {
4
+ "hostname": "{PLT_SERVER_HOSTNAME}",
5
+ "port": "{PORT}",
6
+ "logger": {
7
+ "level": "{PLT_SERVER_LOGGER_LEVEL}"
8
+ }
9
+ },
10
+ "service": {
11
+ "openapi": true
12
+ },
13
+ "plugins": {
14
+ "paths": [
15
+ {
16
+ "path": "./plugins",
17
+ "encapsulate": false
18
+ },
19
+ "./routes"
20
+ ],
21
+ "typescript": {
22
+ "flags": ["-b"]
23
+ }
24
+ },
25
+ "clients": [
26
+ {
27
+ "schema": "client/client.openapi.json",
28
+ "name": "client",
29
+ "type": "openapi",
30
+ "serviceId": "movies"
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="@platformatic/service" />
2
+ import { FastifyInstance, FastifyPluginOptions } from 'fastify'
3
+
4
+ export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
5
+ fastify.decorate('example', 'foobar')
6
+ }
@@ -0,0 +1,21 @@
1
+ /// <reference types="@platformatic/service" />
2
+ /// <reference types="../client" />
3
+ import { FastifyInstance, FastifyPluginOptions } from 'fastify'
4
+
5
+ declare module 'fastify' {
6
+ interface FastifyInstance {
7
+ example: string
8
+ }
9
+ }
10
+
11
+ export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
12
+ fastify.get('/', async (request, reply) => {
13
+ return { hello: fastify.example }
14
+ })
15
+
16
+ fastify.get('/titles', async (request, reply) => {
17
+ const movies = await fastify.client.getMovies({})
18
+ const titles = movies.map((movie) => movie.title)
19
+ return { titles }
20
+ })
21
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "esModuleInterop": true,
5
+ "target": "es2019",
6
+ "sourceMap": true,
7
+ "pretty": true,
8
+ "noEmitOnError": true,
9
+ "outDir": "dist"
10
+ },
11
+ "watchOptions": {
12
+ "watchFile": "fixedPollingInterval",
13
+ "watchDirectory": "fixedPollingInterval",
14
+ "fallbackPolling": "dynamicPriority",
15
+ "synchronousWatchDirectory": true,
16
+ "excludeDirectories": [
17
+ "**/node_modules",
18
+ "dist"
19
+ ]
20
+ }
21
+ }
package/lib/app.js CHANGED
@@ -167,13 +167,14 @@ class PlatformaticApp {
167
167
  const parts = key.split('.')
168
168
  let next = configManager.current
169
169
  let obj
170
+ let i
170
171
 
171
- for (let i = 0; next !== undefined && i < parts.length; ++i) {
172
+ for (i = 0; next !== undefined && i < parts.length; ++i) {
172
173
  obj = next
173
174
  next = obj[parts[i]]
174
175
  }
175
176
 
176
- if (next !== undefined) {
177
+ if (i === parts.length) {
177
178
  obj[parts.at(-1)] = value
178
179
  }
179
180
  })
package/lib/compile.js CHANGED
@@ -1,8 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const { loadConfig, tsCompiler } = require('@platformatic/service')
4
- const { access } = require('node:fs/promises')
5
- const { join } = require('path')
6
4
  const pino = require('pino')
7
5
  const pretty = require('pino-pretty')
8
6
  const { isatty } = require('node:tty')
@@ -27,16 +25,16 @@ async function compile (argv) {
27
25
  const logger = pino(stream)
28
26
 
29
27
  for (const service of configManager.current.services) {
30
- const tsconfig = join(service.path, 'tsconfig.json')
28
+ const childLogger = logger.child({ name: service.id })
31
29
 
32
- try {
33
- await access(tsconfig)
34
- } catch {
35
- logger.trace(`No tsconfig.json found in ${service.path}, skipping...`)
36
- continue
37
- }
30
+ const serviceConfig = await loadConfig({}, argv, platformaticRuntime, {
31
+ watch: false
32
+ })
38
33
 
39
- await tsCompiler.compile(service.path, {}, logger.child({ name: service.id }))
34
+ const compiled = await tsCompiler.compile(service.path, serviceConfig.config, childLogger)
35
+ if (!compiled) {
36
+ logger.trace('No typescript found, skipping compilation')
37
+ }
40
38
  }
41
39
  }
42
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "0.30.0",
3
+ "version": "0.30.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -24,8 +24,8 @@
24
24
  "standard": "^17.1.0",
25
25
  "tsd": "^0.28.1",
26
26
  "typescript": "^5.1.6",
27
- "@platformatic/sql-mapper": "0.30.0",
28
- "@platformatic/sql-graphql": "0.30.0"
27
+ "@platformatic/sql-mapper": "0.30.1",
28
+ "@platformatic/sql-graphql": "0.30.1"
29
29
  },
30
30
  "dependencies": {
31
31
  "@hapi/topo": "^6.0.2",
@@ -40,11 +40,11 @@
40
40
  "pino": "^8.14.1",
41
41
  "pino-pretty": "^10.0.0",
42
42
  "undici": "^5.22.1",
43
- "@platformatic/composer": "0.30.0",
44
- "@platformatic/config": "0.30.0",
45
- "@platformatic/db": "0.30.0",
46
- "@platformatic/service": "0.30.0",
47
- "@platformatic/utils": "0.30.0"
43
+ "@platformatic/composer": "0.30.1",
44
+ "@platformatic/config": "0.30.1",
45
+ "@platformatic/db": "0.30.1",
46
+ "@platformatic/service": "0.30.1",
47
+ "@platformatic/utils": "0.30.1"
48
48
  },
49
49
  "standard": {
50
50
  "ignore": [
package/test/app.test.js CHANGED
@@ -251,7 +251,8 @@ test('supports configuration overrides', async (t) => {
251
251
  const { logger } = getLoggerAndStream()
252
252
  config._configOverrides = new Map([
253
253
  ['server.keepAliveTimeout', 1],
254
- ['server.port', 0]
254
+ ['server.port', 0],
255
+ ['server.pluginTimeout', 99]
255
256
  ])
256
257
  const app = new PlatformaticApp(config, null, logger)
257
258
 
@@ -265,6 +266,7 @@ test('supports configuration overrides', async (t) => {
265
266
 
266
267
  await app.start()
267
268
  assert.strictEqual(app.config.configManager.current.server.keepAliveTimeout, 1)
269
+ assert.strictEqual(app.config.configManager.current.server.pluginTimeout, 99)
268
270
  })
269
271
  })
270
272
 
@@ -63,3 +63,48 @@ test('compile with tsconfig', async (t) => {
63
63
  assert.deepStrictEqual(lines[i].msg, expected[i].msg)
64
64
  }
65
65
  })
66
+
67
+ test('compile with tsconfig custom flags', async (t) => {
68
+ const tmpDir = await mkdtemp(path.join(base, 'test-runtime-compile-'))
69
+ const prev = process.cwd()
70
+ process.chdir(tmpDir)
71
+ t.after(() => {
72
+ process.chdir(prev)
73
+ })
74
+
75
+ t.after(async () => {
76
+ // We give up after 10s.
77
+ // This is because on Windows, it's very hard to delete files if the file
78
+ // system is not collaborating.
79
+ for (let i = 0; i < 10; i++) {
80
+ try {
81
+ await rm(tmpDir, { recursive: true, force: true })
82
+ break
83
+ } catch (err) {
84
+ if (err.code === 'EBUSY') {
85
+ await sleep(1000)
86
+ continue
87
+ }
88
+ }
89
+ }
90
+ })
91
+
92
+ const folder = join(import.meta.url, '..', '..', 'fixtures', 'typescript-custom-flags')
93
+ await cp(folder, tmpDir, { recursive: true })
94
+
95
+ const { stdout } = await execa(cliPath, ['compile'])
96
+
97
+ const lines = stdout.split('\n').map(JSON.parse)
98
+ const expected = [{
99
+ name: 'movies',
100
+ msg: 'Typescript compilation completed successfully.'
101
+ }, {
102
+ name: 'titles',
103
+ msg: 'Typescript compilation completed successfully.'
104
+ }]
105
+
106
+ for (let i = 0; i < expected.length; i++) {
107
+ assert.deepStrictEqual(lines[i].name, expected[i].name)
108
+ assert.deepStrictEqual(lines[i].msg, expected[i].msg)
109
+ }
110
+ })