@platformatic/service 0.17.1 → 0.19.0

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 (57) hide show
  1. package/fixtures/hello/platformatic.service.json +3 -0
  2. package/fixtures/hello-client/hello/hello.cjs +21 -0
  3. package/fixtures/hello-client/hello/hello.d.ts +34 -0
  4. package/fixtures/hello-client/hello/hello.openapi.json +22 -0
  5. package/fixtures/hello-client/hello/package.json +5 -0
  6. package/fixtures/hello-client/platformatic.service.json +17 -0
  7. package/fixtures/hello-client/plugin.js +8 -0
  8. package/fixtures/hello-client-ts/dist/plugin.js +21 -0
  9. package/fixtures/hello-client-ts/dist/plugin.js.map +1 -0
  10. package/fixtures/hello-client-ts/hello/hello.cjs +21 -0
  11. package/fixtures/hello-client-ts/hello/hello.d.ts +34 -0
  12. package/fixtures/hello-client-ts/hello/hello.openapi.json +22 -0
  13. package/fixtures/hello-client-ts/hello/package.json +5 -0
  14. package/fixtures/hello-client-ts/platformatic.service.json +18 -0
  15. package/fixtures/hello-client-ts/plugin.ts +8 -0
  16. package/fixtures/hello-client-ts/tsconfig.json +22 -0
  17. package/help/schema.txt +1 -1
  18. package/index.d.ts +18 -0
  19. package/index.js +57 -2
  20. package/index.test-d.ts +27 -0
  21. package/lib/compile.js +2 -2
  22. package/lib/config.js +0 -22
  23. package/lib/graphql.js +21 -0
  24. package/lib/load-config.js +6 -1
  25. package/lib/openapi-schema-defs.js +1140 -0
  26. package/lib/openapi.js +42 -0
  27. package/lib/schema.js +334 -27
  28. package/lib/utils.js +12 -1
  29. package/package.json +16 -6
  30. package/service.mjs +0 -0
  31. package/test/cli/compile.test.mjs +55 -33
  32. package/test/cli/gen-schema.test.mjs +1 -2
  33. package/test/cli/watch.test.mjs +13 -6
  34. package/test/clients.test.js +59 -0
  35. package/test/config.test.js +2 -1
  36. package/test/fixtures/bad-typescript-plugin/dist/tsconfig.tsbuildinfo +1 -1
  37. package/test/fixtures/hello-world-resolver.js +16 -0
  38. package/test/fixtures/typescript-autoload/platformatic.service.json +13 -0
  39. package/test/fixtures/typescript-autoload/routes/plugin.ts +5 -0
  40. package/test/fixtures/typescript-autoload/tsconfig.json +22 -0
  41. package/test/graphql.test.js +154 -0
  42. package/test/helper.js +1 -2
  43. package/test/https.test.js +58 -0
  44. package/test/routes.test.js +123 -5
  45. package/test/tmp/typescript-plugin-clone-3/dist/tsconfig.tsbuildinfo +1 -1
  46. package/test/tmp/typescript-plugin-clone-4/dist/tsconfig.tsbuildinfo +1 -1
  47. package/test/tmp/typescript-plugin-clone-7/inner-folder/dist/plugin.js +18 -0
  48. package/test/tmp/typescript-plugin-clone-7/inner-folder/dist/plugin.js.map +1 -0
  49. package/test/tmp/typescript-plugin-clone-7/inner-folder/platformatic.service.json +13 -0
  50. package/test/tmp/typescript-plugin-clone-7/inner-folder/plugin.ts +5 -0
  51. package/test/tmp/typescript-plugin-clone-7/inner-folder/tsconfig.json +22 -0
  52. package/test/tmp/typescript-plugin-clone-8/dist/routes/plugin.js +7 -0
  53. package/test/tmp/typescript-plugin-clone-8/dist/routes/plugin.js.map +1 -0
  54. package/test/tmp/typescript-plugin-clone-8/dist/tsconfig.tsbuildinfo +1 -0
  55. package/test/tmp/typescript-plugin-clone-8/platformatic.service.json +13 -0
  56. package/test/tmp/typescript-plugin-clone-8/routes/plugin.ts +5 -0
  57. package/test/tmp/typescript-plugin-clone-8/tsconfig.json +22 -0
package/lib/openapi.js ADDED
@@ -0,0 +1,42 @@
1
+ 'use strict'
2
+
3
+ const Swagger = require('@fastify/swagger')
4
+ const SwaggerUI = require('@fastify/swagger-ui')
5
+ const deepmerge = require('@fastify/deepmerge')({ all: true })
6
+ const fp = require('fastify-plugin')
7
+
8
+ // For some unknown reason, c8 is not detecting any of this
9
+ // pf
10
+ // despite being covered by test/routes.test.js
11
+ /* c8 ignore next 33 */
12
+ async function setupOpenAPI (app, opts) {
13
+ const openapiConfig = deepmerge({
14
+ exposeRoute: true,
15
+ info: {
16
+ title: 'Platformatic',
17
+ description: 'This is a service built on top of Platformatic',
18
+ version: '1.0.0'
19
+ }
20
+ }, typeof opts === 'object' ? opts : {})
21
+ app.log.trace({ openapi: openapiConfig })
22
+ await app.register(Swagger, {
23
+ exposeRoute: openapiConfig.exposeRoute,
24
+ openapi: {
25
+ ...openapiConfig
26
+ },
27
+ refResolver: {
28
+ buildLocalReference (json, baseUri, fragment, i) {
29
+ // TODO figure out if we need def-${i}
30
+ /* istanbul ignore next */
31
+ return json.$id || `def-${i}`
32
+ }
33
+ }
34
+ })
35
+
36
+ app.register(SwaggerUI, {
37
+ ...opts,
38
+ prefix: '/documentation'
39
+ })
40
+ }
41
+
42
+ module.exports = fp(setupOpenAPI)
package/lib/schema.js CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  const pkg = require('../package.json')
6
6
  const version = 'v' + pkg.version
7
+ const openApiDefs = require('./openapi-schema-defs')
7
8
 
8
9
  const cors = {
9
10
  type: 'object',
@@ -123,6 +124,200 @@ const server = {
123
124
  }
124
125
  ]
125
126
  },
127
+ ignoreTrailingSlash: {
128
+ type: 'boolean'
129
+ },
130
+ ignoreDuplicateSlashes: {
131
+ type: 'boolean'
132
+ },
133
+ connectionTimeout: {
134
+ type: 'integer'
135
+ },
136
+ keepAliveTimeout: {
137
+ type: 'integer'
138
+ },
139
+ maxRequestsPerSocket: {
140
+ type: 'integer'
141
+ },
142
+ forceCloseConnections: {
143
+ anyOf: [
144
+ { type: 'boolean' },
145
+ { type: 'string', pattern: '^idle$' }
146
+ ]
147
+ },
148
+ requestTimeout: {
149
+ type: 'integer'
150
+ },
151
+ bodyLimit: {
152
+ type: 'integer'
153
+ },
154
+ maxParamLength: {
155
+ type: 'integer'
156
+ },
157
+ disableRequestLogging: {
158
+ type: 'boolean'
159
+ },
160
+ exposeHeadRoutes: {
161
+ type: 'boolean'
162
+ },
163
+ logger: {
164
+ anyOf: [
165
+ { type: 'boolean' },
166
+ {
167
+ type: 'object',
168
+ properties: {
169
+ level: {
170
+ type: 'string'
171
+ }
172
+ },
173
+ additionalProperties: true
174
+ }
175
+ ]
176
+ },
177
+ serializerOpts: {
178
+ type: 'object',
179
+ properties: {
180
+ schema: {
181
+ type: 'object'
182
+ },
183
+ ajv: {
184
+ type: 'object'
185
+ },
186
+ rounding: {
187
+ type: 'string',
188
+ enum: ['floor', 'ceil', 'round', 'trunc'],
189
+ default: 'trunc'
190
+ },
191
+ debugMode: {
192
+ type: 'boolean'
193
+ },
194
+ mode: {
195
+ type: 'string',
196
+ enum: ['debug', 'standalone']
197
+ },
198
+ largeArraySize: {
199
+ anyOf: [
200
+ { type: 'integer' },
201
+ { type: 'string' }
202
+ ],
203
+ default: 20000
204
+ },
205
+ largeArrayMechanism: {
206
+ type: 'string',
207
+ enum: ['default', 'json-stringify'],
208
+ default: 'default'
209
+ }
210
+ }
211
+ },
212
+ caseSensitive: {
213
+ type: 'boolean'
214
+ },
215
+ requestIdHeader: {
216
+ anyOf: [
217
+ { type: 'string' },
218
+ { type: 'boolean', const: false }
219
+ ]
220
+ },
221
+ requestIdLogLabel: {
222
+ type: 'string'
223
+ },
224
+ jsonShorthand: {
225
+ type: 'boolean'
226
+ },
227
+ trustProxy: {
228
+ anyOf: [
229
+ { type: 'boolean' },
230
+ { type: 'string' },
231
+ {
232
+ type: 'array',
233
+ items: {
234
+ type: 'string'
235
+ }
236
+ },
237
+ { type: 'integer' }
238
+ ]
239
+ },
240
+ https: {
241
+ type: 'object',
242
+ properties: {
243
+ key: {
244
+ anyOf: [
245
+ {
246
+ type: 'string'
247
+ },
248
+ {
249
+ type: 'object',
250
+ properties: {
251
+ path: {
252
+ type: 'string',
253
+ resolvePath: true
254
+ }
255
+ },
256
+ additionalProperties: false
257
+ },
258
+ {
259
+ type: 'array',
260
+ items: {
261
+ anyOf: [
262
+ {
263
+ type: 'string'
264
+ },
265
+ {
266
+ type: 'object',
267
+ properties: {
268
+ path: {
269
+ type: 'string',
270
+ resolvePath: true
271
+ }
272
+ },
273
+ additionalProperties: false
274
+ }
275
+ ]
276
+ }
277
+ }
278
+ ]
279
+ },
280
+ cert: {
281
+ anyOf: [
282
+ {
283
+ type: 'string'
284
+ },
285
+ {
286
+ type: 'object',
287
+ properties: {
288
+ path: {
289
+ type: 'string',
290
+ resolvePath: true
291
+ }
292
+ },
293
+ additionalProperties: false
294
+ },
295
+ {
296
+ type: 'array',
297
+ items: {
298
+ anyOf: [
299
+ {
300
+ type: 'string'
301
+ },
302
+ {
303
+ type: 'object',
304
+ properties: {
305
+ path: {
306
+ type: 'string',
307
+ resolvePath: true
308
+ }
309
+ },
310
+ additionalProperties: false
311
+ }
312
+ ]
313
+ }
314
+ }
315
+ ]
316
+ }
317
+ },
318
+ additionalProperties: false,
319
+ required: ['key', 'cert']
320
+ },
126
321
  cors
127
322
  },
128
323
  required: ['hostname', 'port']
@@ -131,28 +326,25 @@ const server = {
131
326
  const watch = {
132
327
  type: 'object',
133
328
  properties: {
134
- type: 'object',
135
- properties: {
136
- allow: {
137
- type: 'array',
138
- items: {
139
- type: 'string'
140
- },
141
- minItems: 1,
142
- nullable: true,
143
- default: null
329
+ allow: {
330
+ type: 'array',
331
+ items: {
332
+ type: 'string'
144
333
  },
145
- ignore: {
146
- type: 'array',
147
- items: {
148
- type: 'string'
149
- },
150
- nullable: true,
151
- default: null
152
- }
334
+ minItems: 1,
335
+ nullable: true,
336
+ default: null
153
337
  },
154
- additionalProperties: false
155
- }
338
+ ignore: {
339
+ type: 'array',
340
+ items: {
341
+ type: 'string'
342
+ },
343
+ nullable: true,
344
+ default: null
345
+ }
346
+ },
347
+ additionalProperties: false
156
348
  }
157
349
 
158
350
  const plugins = {
@@ -163,12 +355,14 @@ const plugins = {
163
355
  type: 'array',
164
356
  items: {
165
357
  anyOf: [{
166
- type: 'string'
358
+ type: 'string',
359
+ resolvePath: true
167
360
  }, {
168
361
  type: 'object',
169
362
  properties: {
170
363
  path: {
171
- type: 'string'
364
+ type: 'string',
365
+ resolvePath: true
172
366
  },
173
367
  options: {
174
368
  type: 'object',
@@ -219,15 +413,118 @@ const metrics = {
219
413
  ]
220
414
  }
221
415
 
416
+ const openApiBase = {
417
+ type: 'object',
418
+ properties: {
419
+ info: {
420
+ $ref: '#/$defs/info'
421
+ },
422
+ jsonSchemaDialect: {
423
+ type: 'string',
424
+
425
+ default: 'https://spec.openapis.org/oas/3.1/dialect/base'
426
+ },
427
+ servers: {
428
+ type: 'array',
429
+ items: {
430
+ $ref: '#/$defs/server'
431
+ },
432
+ default: [
433
+ {
434
+ url: '/'
435
+ }
436
+ ]
437
+ },
438
+ paths: {
439
+ $ref: '#/$defs/paths'
440
+ },
441
+ webhooks: {
442
+ type: 'object',
443
+ additionalProperties: {
444
+ $ref: '#/$defs/path-item-or-reference'
445
+ }
446
+ },
447
+ components: {
448
+ $ref: '#/$defs/components'
449
+ },
450
+ security: {
451
+ type: 'array',
452
+ items: {
453
+ $ref: '#/$defs/security-requirement'
454
+ }
455
+ },
456
+ tags: {
457
+ type: 'array',
458
+ items: {
459
+ $ref: '#/$defs/tag'
460
+ }
461
+ },
462
+ externalDocs: {
463
+ $ref: '#/$defs/external-documentation'
464
+ },
465
+ prefix: {
466
+ type: 'string',
467
+ description: 'Base URL for the OpenAPI'
468
+ }
469
+ }
470
+ }
471
+
472
+ const openapi = {
473
+ anyOf: [{
474
+ ...openApiBase,
475
+ additionalProperties: false
476
+ }, {
477
+ type: 'boolean'
478
+ }]
479
+ }
480
+
481
+ const graphql = {
482
+ anyOf: [{
483
+ type: 'boolean'
484
+ }, {
485
+ type: 'object',
486
+ properties: {
487
+ graphiql: {
488
+ type: 'boolean'
489
+ }
490
+ }
491
+ }]
492
+ }
493
+
494
+ const service = {
495
+ type: 'object',
496
+ properties: {
497
+ openapi,
498
+ graphql
499
+ },
500
+ additionalProperties: false
501
+ }
502
+
503
+ const clients = {
504
+ type: 'array',
505
+ items: {
506
+ type: 'object',
507
+ properties: {
508
+ path: {
509
+ type: 'string',
510
+ resolvePath: true
511
+ },
512
+ url: {
513
+ type: 'string'
514
+ }
515
+ },
516
+ additionalProperties: false,
517
+ required: ['path', 'url']
518
+ }
519
+ }
520
+
222
521
  const platformaticServiceSchema = {
223
522
  $id: `https://platformatic.dev/schemas/${version}/service`,
224
523
  type: 'object',
225
524
  properties: {
226
525
  server,
227
526
  plugins,
228
- metrics
229
- },
230
- additionalProperties: {
527
+ metrics,
231
528
  watch: {
232
529
  anyOf: [watch, {
233
530
  type: 'boolean'
@@ -235,9 +532,16 @@ const platformaticServiceSchema = {
235
532
  },
236
533
  hotReload: {
237
534
  type: 'boolean'
238
- }
535
+ },
536
+ $schema: {
537
+ type: 'string'
538
+ },
539
+ service,
540
+ clients
239
541
  },
240
- required: ['server']
542
+ additionalProperties: false,
543
+ required: ['server'],
544
+ $defs: openApiDefs
241
545
  }
242
546
 
243
547
  module.exports.schema = platformaticServiceSchema
@@ -246,6 +550,9 @@ module.exports.cors = cors
246
550
  module.exports.server = server
247
551
  module.exports.plugins = plugins
248
552
  module.exports.watch = watch
553
+ module.exports.openApiDefs = openApiDefs
554
+ module.exports.openApiBase = openApiBase
555
+ module.exports.clients = clients
249
556
 
250
557
  if (require.main === module) {
251
558
  console.log(JSON.stringify(platformaticServiceSchema, null, 2))
package/lib/utils.js CHANGED
@@ -46,10 +46,21 @@ function getJSPluginPath (configPath, tsPluginPath, compileDir) {
46
46
  return tsPluginPath
47
47
  }
48
48
 
49
+ const isTs = tsPluginPath.endsWith('ts')
50
+ let newBaseName
51
+
52
+ // TODO: investigate why c8 does not see those
53
+ /* c8 ignore next 5 */
54
+ if (isTs) {
55
+ newBaseName = basename(tsPluginPath, '.ts') + '.js'
56
+ } else {
57
+ newBaseName = basename(tsPluginPath)
58
+ }
59
+
49
60
  const tsPluginRelativePath = relative(dirname(configPath), tsPluginPath)
50
61
  const jsPluginRelativePath = join(
51
62
  dirname(tsPluginRelativePath),
52
- basename(tsPluginRelativePath, '.ts') + '.js'
63
+ newBaseName
53
64
  )
54
65
  return join(compileDir, jsPluginRelativePath)
55
66
  }
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@platformatic/service",
3
- "version": "0.17.1",
3
+ "version": "0.19.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
+ "bin": {
7
+ "plt-service": "./service.mjs"
8
+ },
6
9
  "author": "Matteo Collina <hello@matteocollina.com>",
7
10
  "repository": {
8
11
  "type": "git",
@@ -14,14 +17,17 @@
14
17
  },
15
18
  "homepage": "https://github.com/platformatic/platformatic#readme",
16
19
  "devDependencies": {
20
+ "@matteo.collina/worker": "^3.0.0",
17
21
  "bindings": "^1.5.0",
18
22
  "c8": "^7.13.0",
23
+ "self-cert": "^2.0.0",
19
24
  "snazzy": "^9.0.0",
20
25
  "split2": "^4.1.0",
21
26
  "standard": "^17.0.0",
22
27
  "strip-ansi": "^7.0.1",
23
28
  "tap": "^16.3.4",
24
- "typescript": "^4.9.5",
29
+ "typescript": "^5.0.0",
30
+ "tsd": "^0.28.0",
25
31
  "undici": "^5.20.0",
26
32
  "vscode-json-languageservice": "^5.3.0",
27
33
  "why-is-node-running": "^2.2.2",
@@ -36,7 +42,9 @@
36
42
  "@fastify/restartable": "^1.4.0",
37
43
  "@fastify/static": "^6.9.0",
38
44
  "@fastify/swagger": "^8.3.1",
45
+ "@fastify/swagger-ui": "^1.4.0",
39
46
  "@fastify/under-pressure": "^8.2.0",
47
+ "@mercuriusjs/federation": "^1.0.1",
40
48
  "close-with-grace": "^1.1.0",
41
49
  "commist": "^3.2.0",
42
50
  "desm": "^1.3.0",
@@ -49,13 +57,15 @@
49
57
  "fastify-sandbox": "^0.11.0",
50
58
  "graphql": "^16.6.0",
51
59
  "help-me": "^4.2.0",
60
+ "mercurius": "^12.2.0",
52
61
  "minimist": "^1.2.8",
53
62
  "pino": "^8.11.0",
54
- "pino-pretty": "^9.3.0",
63
+ "pino-pretty": "^10.0.0",
55
64
  "rfdc": "^1.3.0",
56
65
  "ua-parser-js": "^1.0.33",
57
- "@platformatic/utils": "0.17.1",
58
- "@platformatic/config": "0.17.1"
66
+ "@platformatic/config": "0.19.0",
67
+ "@platformatic/utils": "0.19.0",
68
+ "@platformatic/client": "0.19.0"
59
69
  },
60
70
  "standard": {
61
71
  "ignore": [
@@ -63,7 +73,7 @@
63
73
  ]
64
74
  },
65
75
  "scripts": {
66
- "test": "standard | snazzy && c8 --100 tap test/*test.js test/*/*.test.mjs",
76
+ "test": "standard | snazzy && c8 --100 tap test/*test.js test/*/*.test.mjs && tsd",
67
77
  "lint": "standard | snazzy"
68
78
  }
69
79
  }
package/service.mjs CHANGED
File without changes
@@ -12,6 +12,20 @@ function urlDirname (url) {
12
12
  return path.dirname(fileURLToPath(url))
13
13
  }
14
14
 
15
+ function exitOnTeardown (child) {
16
+ return async () => {
17
+ if (os.platform() === 'win32') {
18
+ try {
19
+ await execa('taskkill', ['/pid', child.pid, '/f', '/t'])
20
+ } catch (err) {
21
+ console.error(`Failed to kill process ${child.pid})`)
22
+ }
23
+ } else {
24
+ child.kill('SIGINT')
25
+ }
26
+ }
27
+ }
28
+
15
29
  t.test('should compile typescript plugin', async (t) => {
16
30
  const testDir = path.join(urlDirname(import.meta.url), '..', 'fixtures', 'typescript-plugin')
17
31
  const cwd = path.join(urlDirname(import.meta.url), '..', 'tmp', 'typescript-plugin-clone-1')
@@ -70,17 +84,7 @@ t.test('should compile typescript plugin with start command', async (t) => {
70
84
 
71
85
  const child = execa('node', [cliPath, 'start'], { cwd })
72
86
 
73
- t.teardown(async () => {
74
- if (os.platform() === 'win32') {
75
- try {
76
- await execa('taskkill', ['/pid', child.pid, '/f', '/t'])
77
- } catch (err) {
78
- console.error(`Failed to kill process ${child.pid})`)
79
- }
80
- } else {
81
- child.kill('SIGINT')
82
- }
83
- })
87
+ t.teardown(exitOnTeardown(child))
84
88
 
85
89
  const splitter = split()
86
90
  child.stdout.pipe(splitter)
@@ -195,17 +199,7 @@ t.test('start command should not compile typescript if `typescript` is false', a
195
199
  await cp(testDir, cwd, { recursive: true })
196
200
 
197
201
  const child = execa('node', [cliPath, 'start'], { cwd })
198
- t.teardown(async () => {
199
- if (os.platform() === 'win32') {
200
- try {
201
- await execa('taskkill', ['/pid', child.pid, '/f', '/t'])
202
- } catch (err) {
203
- console.error(`Failed to kill process ${child.pid})`)
204
- }
205
- } else {
206
- child.kill('SIGINT')
207
- }
208
- })
202
+ t.teardown(exitOnTeardown(child))
209
203
 
210
204
  const jsPluginPath = path.join(cwd, 'dist', 'plugin.js')
211
205
  try {
@@ -227,17 +221,7 @@ t.test('should compile typescript plugin with start command with different cwd',
227
221
 
228
222
  const child = execa('node', [cliPath, 'start', '-c', path.join(dest, 'platformatic.service.json')])
229
223
 
230
- t.teardown(async () => {
231
- if (os.platform() === 'win32') {
232
- try {
233
- await execa('taskkill', ['/pid', child.pid, '/f', '/t'])
234
- } catch (err) {
235
- console.error(`Failed to kill process ${child.pid})`)
236
- }
237
- } else {
238
- child.kill('SIGINT')
239
- }
240
- })
224
+ t.teardown(exitOnTeardown(child))
241
225
 
242
226
  const splitter = split()
243
227
  child.stdout.pipe(splitter)
@@ -253,3 +237,41 @@ t.test('should compile typescript plugin with start command with different cwd',
253
237
  }
254
238
  t.fail('should compile typescript plugin with start command')
255
239
  })
240
+
241
+ t.test('valid tsconfig file inside an inner folder', async (t) => {
242
+ const testDir = path.join(urlDirname(import.meta.url), '..', 'fixtures', 'typescript-plugin')
243
+ const cwd = path.join(urlDirname(import.meta.url), '..', 'tmp', 'typescript-plugin-clone-7/inner-folder')
244
+
245
+ await cp(testDir, cwd, { recursive: true })
246
+
247
+ try {
248
+ await execa('node', [cliPath, 'compile'], { cwd })
249
+ } catch (err) {
250
+ t.fail('should not catch any error')
251
+ }
252
+
253
+ t.pass()
254
+ })
255
+
256
+ t.test('should compile typescript plugin with start command from a folder', async (t) => {
257
+ const testDir = path.join(urlDirname(import.meta.url), '..', 'fixtures', 'typescript-autoload')
258
+ const cwd = path.join(urlDirname(import.meta.url), '..', 'tmp', 'typescript-plugin-clone-8')
259
+
260
+ await cp(testDir, cwd, { recursive: true })
261
+
262
+ const child = execa('node', [cliPath, 'start'], { cwd })
263
+
264
+ t.teardown(exitOnTeardown(child))
265
+
266
+ const splitter = split()
267
+ child.stdout.pipe(splitter)
268
+
269
+ for await (const data of splitter) {
270
+ const sanitized = stripAnsi(data)
271
+ if (sanitized.includes('Typescript plugin loaded')) {
272
+ t.pass()
273
+ return
274
+ }
275
+ }
276
+ t.fail('should compile typescript plugin with start command')
277
+ })
@@ -15,9 +15,8 @@ test('generateJsonSchemaConfig generates the file', async (t) => {
15
15
 
16
16
  const configSchema = await fs.readFile('platformatic.service.schema.json', 'utf8')
17
17
  const schema = JSON.parse(configSchema)
18
- const { required, additionalProperties } = schema
18
+ const { required } = schema
19
19
  t.has(required, ['server'])
20
- t.has(additionalProperties, { watch: {} })
21
20
  const { $id, type } = schema
22
21
  t.equal($id, `https://platformatic.dev/schemas/v${pkg.version}/service`)
23
22
  t.equal(type, 'object')