@scalar/cli 2.0.0 → 2.1.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 (80) hide show
  1. package/README.md +42 -2
  2. package/chunks/action-45OGQB2M.js +138 -0
  3. package/chunks/action-5R5FDF6S.js +2097 -0
  4. package/chunks/action-ANU5HGC4.js +34 -0
  5. package/chunks/action-BMFXENMX.js +176 -0
  6. package/chunks/action-BNEGJBUH.js +38 -0
  7. package/chunks/action-BYZUBXVB.js +82 -0
  8. package/chunks/action-C5VB4ITT.js +132 -0
  9. package/chunks/action-CCW66QJN.js +72 -0
  10. package/chunks/action-CLSD7O2R.js +60 -0
  11. package/chunks/action-CQ56FVES.js +65 -0
  12. package/chunks/action-CYP4VDK3.js +148 -0
  13. package/chunks/action-DFKHSDFV.js +36 -0
  14. package/chunks/action-F4Y6Q2VB.js +92 -0
  15. package/chunks/action-GB6DM53B.js +70 -0
  16. package/chunks/action-GEBRPNRT.js +87 -0
  17. package/chunks/action-H5OHT2GV.js +56 -0
  18. package/chunks/action-HD2T6BFJ.js +54 -0
  19. package/chunks/action-HNKM3Q65.js +65 -0
  20. package/chunks/action-JOSVV6YA.js +71 -0
  21. package/chunks/action-MENXFJH3.js +204 -0
  22. package/chunks/action-P7LN6FGY.js +13 -0
  23. package/chunks/action-PVDDRIM6.js +130 -0
  24. package/chunks/action-Q5UJ32D6.js +46 -0
  25. package/chunks/action-R6ZZO26F.js +299 -0
  26. package/chunks/action-STIEAXOE.js +53 -0
  27. package/chunks/action-TPBKPHNS.js +110 -0
  28. package/chunks/action-TWFJNQ2R.js +95 -0
  29. package/chunks/action-TZ5KGAQT.js +64 -0
  30. package/chunks/action-UDZUUJSI.js +49 -0
  31. package/chunks/action-W5BATF4Q.js +197 -0
  32. package/chunks/agent-XGLOHXNA.js +112 -0
  33. package/chunks/build.action-LKOILPA6.js +108 -0
  34. package/chunks/chunk-23I5PKZZ.js +78 -0
  35. package/chunks/chunk-2BSG2QHO.js +455 -0
  36. package/chunks/chunk-3MZYUBJ6.js +49 -0
  37. package/chunks/chunk-47Y4L5IT.js +63361 -0
  38. package/chunks/chunk-4DGQIAJX.js +359 -0
  39. package/chunks/chunk-4QS7SJTG.js +138 -0
  40. package/chunks/chunk-5BISXQX4.js +447 -0
  41. package/chunks/chunk-5BPPGTUU.js +463 -0
  42. package/chunks/chunk-AEFPCC4U.js +16 -0
  43. package/chunks/chunk-AHWWJ3MD.js +32 -0
  44. package/chunks/chunk-ASMHW5AY.js +19 -0
  45. package/chunks/chunk-B6QZJWCQ.js +92 -0
  46. package/chunks/chunk-DOVIWNKQ.js +108 -0
  47. package/chunks/chunk-H2WRMLYY.js +13780 -0
  48. package/chunks/chunk-HQKBZOYU.js +34 -0
  49. package/chunks/chunk-ISGLWBXZ.js +4265 -0
  50. package/chunks/chunk-IX7LJ3AD.js +17 -0
  51. package/chunks/chunk-JFIXNSPP.js +26 -0
  52. package/chunks/chunk-K74E42RV.js +7311 -0
  53. package/chunks/chunk-KHDYYVYF.js +16 -0
  54. package/chunks/chunk-KWOL7A6J.js +23 -0
  55. package/chunks/chunk-NUXPNUSS.js +38 -0
  56. package/chunks/chunk-OAXFCOJV.js +25 -0
  57. package/chunks/chunk-P2VH7DOC.js +107 -0
  58. package/chunks/chunk-P646T2WH.js +1608 -0
  59. package/chunks/chunk-SHSHFGA7.js +297 -0
  60. package/chunks/chunk-SXYALPYK.js +2709 -0
  61. package/chunks/chunk-T7B6WNZC.js +18 -0
  62. package/chunks/chunk-T7MDADON.js +17 -0
  63. package/chunks/chunk-TLFMATXR.js +344 -0
  64. package/chunks/chunk-TQ5XC2E3.js +284 -0
  65. package/chunks/chunk-UPUTMFD4.js +465 -0
  66. package/chunks/chunk-VTYTPSXO.js +161 -0
  67. package/chunks/chunk-X4QLDBB5.js +221 -0
  68. package/chunks/chunk-ZTVWAKNJ.js +21 -0
  69. package/chunks/create.action-FFQLBSJH.js +108 -0
  70. package/chunks/delete.action-QNN3LC2F.js +96 -0
  71. package/chunks/delete.action-STHQHP4F.js +88 -0
  72. package/chunks/get.action-OTKYOP3Z.js +87 -0
  73. package/chunks/list.action-6I5EZAVB.js +95 -0
  74. package/chunks/list.action-KDM5RHEH.js +116 -0
  75. package/chunks/publish.action-PODTVRXS.js +182 -0
  76. package/chunks/update.action-4F6STTEQ.js +101 -0
  77. package/chunks/update.action-KMD4ZM75.js +95 -0
  78. package/docs.html +393 -230
  79. package/index.js +645 -98865
  80. package/package.json +16 -14
@@ -0,0 +1,2097 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ CONFIG_FILE_DEFAULT,
4
+ DEFAULT_MARKDOWN_FILE_NAME,
5
+ DEFAULT_OPENAPI_FILE_NAME,
6
+ findConfig,
7
+ getCurrentFolderName,
8
+ scalarConfigSchema
9
+ } from "./chunk-47Y4L5IT.js";
10
+ import "./chunk-5BPPGTUU.js";
11
+ import "./chunk-4QS7SJTG.js";
12
+ import "./chunk-VTYTPSXO.js";
13
+ import "./chunk-TLFMATXR.js";
14
+ import {
15
+ slugify
16
+ } from "./chunk-ISGLWBXZ.js";
17
+ import "./chunk-H2WRMLYY.js";
18
+ import "./chunk-K74E42RV.js";
19
+ import {
20
+ output
21
+ } from "./chunk-X4QLDBB5.js";
22
+ import "./chunk-3MZYUBJ6.js";
23
+
24
+ // src/domains/project/init/action.ts
25
+ import fs from "node:fs/promises";
26
+ import path from "node:path";
27
+ import { cancel, confirm, isCancel, text } from "@clack/prompts";
28
+ import as from "ansis";
29
+
30
+ // ../../node_modules/.pnpm/@scalar+galaxy@0.6.12/node_modules/@scalar/galaxy/dist/3.1.json
31
+ var __default = {
32
+ openapi: "3.1.1",
33
+ info: {
34
+ title: "Scalar Galaxy",
35
+ description: "The Scalar Galaxy is an example OpenAPI document to test OpenAPI tools and libraries. It's a fictional universe with fictional planets and fictional data.\n\n## Resources\n\n* https://github.com/scalar/scalar\n* https://github.com/OAI/OpenAPI-Specification\n* https://scalar.com\n\n## Markdown Support\n\nAll descriptions *can* contain ~~tons of text~~ **Markdown**. [If GitHub supports the syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax), chances are we're supporting it, too.\n\n<details>\n <summary>Examples</summary>\n\n **Blockquotes**\n\n > I love OpenAPI. <3\n\n **Tables**\n\n | Feature | Availability |\n | ---------------- | ------------ |\n | Markdown Support | \u2713 |\n\n **Accordion**\n\n ```html\n <details>\n <summary>Using Details Tags</summary>\n <p>HTML Example</p>\n </details>\n ```\n\n **Images**\n\n Yes, there's support for images, too!\n\n ![Empty placeholder image showing the width/height](https://images.placeholders.dev/?width=1280&height=720)\n\n **Alerts**\n\n > [!tip]\n > You can use Markdown alerts in your descriptions.\n\n</details>\n",
36
+ version: "0.6.12",
37
+ contact: {
38
+ name: "Scalar Support",
39
+ url: "https://scalar.com",
40
+ email: "support@scalar.com"
41
+ },
42
+ license: {
43
+ name: "MIT",
44
+ url: "https://opensource.org/license/MIT"
45
+ }
46
+ },
47
+ externalDocs: {
48
+ description: "Documentation",
49
+ url: "https://github.com/scalar/scalar"
50
+ },
51
+ servers: [
52
+ {
53
+ url: "https://galaxy.scalar.com"
54
+ },
55
+ {
56
+ url: "{protocol}://void.scalar.com/{path}",
57
+ description: "Responds with your request data",
58
+ variables: {
59
+ protocol: {
60
+ enum: [
61
+ "https",
62
+ "http"
63
+ ],
64
+ default: "https"
65
+ },
66
+ path: {
67
+ default: ""
68
+ }
69
+ }
70
+ }
71
+ ],
72
+ security: [
73
+ {
74
+ bearerAuth: []
75
+ },
76
+ {
77
+ basicAuth: []
78
+ },
79
+ {
80
+ apiKeyQuery: []
81
+ },
82
+ {
83
+ apiKeyHeader: []
84
+ },
85
+ {
86
+ apiKeyHeader: [],
87
+ apiKeyQuery: []
88
+ },
89
+ {
90
+ apiKeyCookie: []
91
+ },
92
+ {
93
+ oAuth2: []
94
+ },
95
+ {
96
+ openIdConnect: []
97
+ }
98
+ ],
99
+ "x-speakeasy-webhooks": {
100
+ security: {
101
+ type: "signature",
102
+ headerName: "x-signature",
103
+ signatureTextEncoding: "base64",
104
+ algorithm: "hmac-sha256"
105
+ }
106
+ },
107
+ tags: [
108
+ {
109
+ name: "Authentication",
110
+ description: "Some endpoints are public, but some require authentication. We provide all the required endpoints to create an account and authorize yourself."
111
+ },
112
+ {
113
+ name: "Planets",
114
+ description: "Everything about planets"
115
+ },
116
+ {
117
+ name: "Celestial Bodies",
118
+ description: "Celestial bodies are the planets and satellites in the Scalar Galaxy."
119
+ }
120
+ ],
121
+ paths: {
122
+ "/planets": {
123
+ get: {
124
+ tags: [
125
+ "Planets"
126
+ ],
127
+ summary: "Get all planets",
128
+ description: "It's easy to say you know them all, but do you really? Retrieve all the planets and check whether you missed one.",
129
+ operationId: "getAllData",
130
+ security: [],
131
+ parameters: [
132
+ {
133
+ $ref: "#/components/parameters/limit"
134
+ },
135
+ {
136
+ $ref: "#/components/parameters/offset"
137
+ }
138
+ ],
139
+ responses: {
140
+ "200": {
141
+ description: "OK",
142
+ headers: {
143
+ "X-Request-ID": {
144
+ $ref: "#/components/headers/X-Request-ID"
145
+ },
146
+ "X-Pagination-Total": {
147
+ $ref: "#/components/headers/X-Pagination-Total"
148
+ },
149
+ "X-Pagination-Page": {
150
+ $ref: "#/components/headers/X-Pagination-Page"
151
+ },
152
+ "X-Pagination-Per-Page": {
153
+ $ref: "#/components/headers/X-Pagination-Per-Page"
154
+ },
155
+ "X-Cache-Control": {
156
+ $ref: "#/components/headers/X-Cache-Control"
157
+ }
158
+ },
159
+ content: {
160
+ "application/json": {
161
+ schema: {
162
+ $id: "https://galaxy.scalar.com/schemas/PaginatedPlanets",
163
+ $defs: {
164
+ itemType: {
165
+ $dynamicAnchor: "itemType",
166
+ $ref: "#/components/schemas/Planet"
167
+ }
168
+ },
169
+ $ref: "#/components/schemas/PaginatedResource"
170
+ }
171
+ },
172
+ "application/xml": {
173
+ schema: {
174
+ $id: "https://galaxy.scalar.com/schemas/PaginatedPlanetsXml",
175
+ xml: {
176
+ name: "planets"
177
+ },
178
+ $defs: {
179
+ itemType: {
180
+ $dynamicAnchor: "itemType",
181
+ $ref: "#/components/schemas/Planet"
182
+ }
183
+ },
184
+ $ref: "#/components/schemas/PaginatedResource"
185
+ }
186
+ }
187
+ }
188
+ }
189
+ },
190
+ "x-post-response": 'pm.test("Status code is 200", () => {\n pm.response.to.have.status(200);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response has data array and meta", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("data");\n pm.expect(jsonData.data).to.be.an("array");\n pm.expect(jsonData).to.have.property("meta");\n});\n'
191
+ },
192
+ post: {
193
+ tags: [
194
+ "Planets"
195
+ ],
196
+ summary: "Create a planet",
197
+ description: "Time to play god and create a new planet. What do you think? Ah, don't think too much. What could go wrong anyway?",
198
+ operationId: "createPlanet",
199
+ callbacks: {
200
+ planetCreated: {
201
+ "{$request.body#/successCallbackUrl}": {
202
+ post: {
203
+ security: [],
204
+ requestBody: {
205
+ description: "Information about the newly created planet",
206
+ content: {
207
+ "application/json": {
208
+ schema: {
209
+ $ref: "#/components/schemas/Planet"
210
+ }
211
+ }
212
+ }
213
+ },
214
+ responses: {
215
+ "200": {
216
+ description: "Your server returns this code if it accepts the callback"
217
+ },
218
+ "204": {
219
+ description: "Your server should return this HTTP status code if no longer interested in further updates"
220
+ }
221
+ }
222
+ }
223
+ }
224
+ },
225
+ planetCreationFailed: {
226
+ "{$request.body#/failureCallbackUrl}": {
227
+ post: {
228
+ security: [],
229
+ requestBody: {
230
+ description: "Information about which fields failed to validate",
231
+ content: {
232
+ "application/json": {
233
+ schema: {
234
+ $ref: "#/components/schemas/Planet"
235
+ }
236
+ }
237
+ }
238
+ },
239
+ responses: {
240
+ "200": {
241
+ description: "Your server returns this code if it accepts the failure callback notification"
242
+ }
243
+ }
244
+ }
245
+ }
246
+ },
247
+ planetExploded: {
248
+ "{$request.body#/successCallbackUrl}": {
249
+ post: {
250
+ security: [],
251
+ requestBody: {
252
+ description: "Information about the newly exploded planet",
253
+ content: {
254
+ "application/json": {
255
+ schema: {
256
+ $ref: "#/components/schemas/Planet"
257
+ }
258
+ }
259
+ }
260
+ },
261
+ responses: {
262
+ "200": {
263
+ description: "Your server returns this code if it accepts the planet explosion callback notification"
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ },
270
+ requestBody: {
271
+ description: "Planet",
272
+ content: {
273
+ "application/json": {
274
+ schema: {
275
+ $ref: "#/components/schemas/Planet"
276
+ }
277
+ },
278
+ "application/xml": {
279
+ schema: {
280
+ $ref: "#/components/schemas/Planet"
281
+ }
282
+ }
283
+ }
284
+ },
285
+ responses: {
286
+ "201": {
287
+ description: "Created",
288
+ headers: {
289
+ "X-Request-ID": {
290
+ $ref: "#/components/headers/X-Request-ID"
291
+ },
292
+ Location: {
293
+ $ref: "#/components/headers/Location"
294
+ },
295
+ "X-Processing-Time": {
296
+ $ref: "#/components/headers/X-Processing-Time"
297
+ }
298
+ },
299
+ content: {
300
+ "application/json": {
301
+ schema: {
302
+ $ref: "#/components/schemas/Planet"
303
+ }
304
+ },
305
+ "application/xml": {
306
+ schema: {
307
+ $ref: "#/components/schemas/Planet"
308
+ }
309
+ }
310
+ }
311
+ },
312
+ "400": {
313
+ $ref: "#/components/responses/BadRequest"
314
+ },
315
+ "403": {
316
+ $ref: "#/components/responses/Forbidden"
317
+ }
318
+ },
319
+ "x-post-response": 'pm.test("Status code is 201", () => {\n pm.response.to.have.status(201);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response is a planet with id and name", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("id");\n pm.expect(jsonData).to.have.property("name");\n});\n'
320
+ }
321
+ },
322
+ "/planets/{planetId}": {
323
+ get: {
324
+ tags: [
325
+ "Planets"
326
+ ],
327
+ summary: "Get a planet",
328
+ description: "You'll better learn a little bit more about the planets. It might come in handy once space travel is available for everyone.",
329
+ operationId: "getPlanet",
330
+ security: [],
331
+ parameters: [
332
+ {
333
+ $ref: "#/components/parameters/planetId"
334
+ }
335
+ ],
336
+ responses: {
337
+ "200": {
338
+ description: "Planet Found",
339
+ headers: {
340
+ "X-Request-ID": {
341
+ $ref: "#/components/headers/X-Request-ID"
342
+ },
343
+ ETag: {
344
+ $ref: "#/components/headers/ETag"
345
+ },
346
+ "Last-Modified": {
347
+ $ref: "#/components/headers/Last-Modified"
348
+ },
349
+ "X-Cache-Control": {
350
+ $ref: "#/components/headers/X-Cache-Control"
351
+ }
352
+ },
353
+ content: {
354
+ "application/json": {
355
+ schema: {
356
+ $ref: "#/components/schemas/Planet"
357
+ }
358
+ },
359
+ "application/xml": {
360
+ schema: {
361
+ $ref: "#/components/schemas/Planet"
362
+ }
363
+ }
364
+ }
365
+ },
366
+ "404": {
367
+ $ref: "#/components/responses/NotFound"
368
+ }
369
+ },
370
+ "x-post-response": 'pm.test("Status code is 200", () => {\n pm.response.to.have.status(200);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response is a planet with id and name", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("id");\n pm.expect(jsonData).to.have.property("name");\n});\n'
371
+ },
372
+ put: {
373
+ tags: [
374
+ "Planets"
375
+ ],
376
+ summary: "Update a planet",
377
+ description: "Sometimes you make mistakes, that's fine. No worries, you can update all planets.",
378
+ operationId: "updatePlanet",
379
+ requestBody: {
380
+ description: "New information about the planet",
381
+ content: {
382
+ "application/json": {
383
+ schema: {
384
+ $ref: "#/components/schemas/Planet"
385
+ }
386
+ },
387
+ "application/xml": {
388
+ schema: {
389
+ $ref: "#/components/schemas/Planet"
390
+ }
391
+ }
392
+ }
393
+ },
394
+ parameters: [
395
+ {
396
+ $ref: "#/components/parameters/planetId"
397
+ }
398
+ ],
399
+ responses: {
400
+ "200": {
401
+ description: "Planet updated successfully",
402
+ content: {
403
+ "application/json": {
404
+ schema: {
405
+ $ref: "#/components/schemas/Planet"
406
+ }
407
+ },
408
+ "application/xml": {
409
+ schema: {
410
+ $ref: "#/components/schemas/Planet"
411
+ }
412
+ }
413
+ }
414
+ },
415
+ "400": {
416
+ $ref: "#/components/responses/BadRequest"
417
+ },
418
+ "403": {
419
+ $ref: "#/components/responses/Forbidden"
420
+ },
421
+ "404": {
422
+ $ref: "#/components/responses/NotFound"
423
+ }
424
+ },
425
+ "x-post-response": 'pm.test("Status code is 200", () => {\n pm.response.to.have.status(200);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response is a planet with id and name", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("id");\n pm.expect(jsonData).to.have.property("name");\n});\n'
426
+ },
427
+ delete: {
428
+ tags: [
429
+ "Planets"
430
+ ],
431
+ summary: "Delete a planet",
432
+ operationId: "deletePlanet",
433
+ description: "This endpoint was used to delete planets. Unfortunately, that caused a lot of trouble for planets with life. So, this endpoint is now deprecated and should not be used anymore.",
434
+ "x-scalar-stability": "experimental",
435
+ parameters: [
436
+ {
437
+ $ref: "#/components/parameters/planetId"
438
+ }
439
+ ],
440
+ responses: {
441
+ "204": {
442
+ description: "No Content"
443
+ },
444
+ "404": {
445
+ $ref: "#/components/responses/NotFound"
446
+ }
447
+ },
448
+ "x-post-response": 'pm.test("Status code is 204", () => {\n pm.response.to.have.status(204);\n});\n'
449
+ }
450
+ },
451
+ "/planets/{planetId}/image": {
452
+ post: {
453
+ tags: [
454
+ "Planets"
455
+ ],
456
+ summary: "Upload an image to a planet",
457
+ description: "Got a crazy good photo of a planet? Share it with the world!",
458
+ operationId: "uploadImage",
459
+ parameters: [
460
+ {
461
+ $ref: "#/components/parameters/planetId"
462
+ }
463
+ ],
464
+ requestBody: {
465
+ description: "Image to upload",
466
+ content: {
467
+ "multipart/form-data": {
468
+ schema: {
469
+ type: "object",
470
+ properties: {
471
+ image: {
472
+ type: "string",
473
+ format: "binary",
474
+ description: "The image file to upload",
475
+ examples: [
476
+ "@mars.jpg",
477
+ "@jupiter.png"
478
+ ]
479
+ }
480
+ }
481
+ }
482
+ }
483
+ }
484
+ },
485
+ responses: {
486
+ "200": {
487
+ $ref: "#/components/responses/ImageUploaded"
488
+ },
489
+ "400": {
490
+ $ref: "#/components/responses/BadRequest"
491
+ },
492
+ "403": {
493
+ $ref: "#/components/responses/Forbidden"
494
+ },
495
+ "404": {
496
+ $ref: "#/components/responses/NotFound"
497
+ }
498
+ },
499
+ "x-post-response": 'pm.test("Status code is 200", () => {\n pm.response.to.have.status(200);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response has message and imageUrl", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("message");\n pm.expect(jsonData).to.have.property("imageUrl");\n});\n'
500
+ }
501
+ },
502
+ "/celestial-bodies": {
503
+ post: {
504
+ tags: [
505
+ "Celestial Bodies"
506
+ ],
507
+ summary: "Create a celestial body",
508
+ description: "Stars, moons, comets, the occasional rogue asteroid \u2014 if it glows or drifts through the void, you can add it here.",
509
+ operationId: "createCelestialBody",
510
+ requestBody: {
511
+ description: "Celestial body to create",
512
+ required: true,
513
+ content: {
514
+ "application/json": {
515
+ schema: {
516
+ $ref: "#/components/schemas/CelestialBody"
517
+ }
518
+ }
519
+ }
520
+ },
521
+ responses: {
522
+ "201": {
523
+ description: "Celestial body created",
524
+ content: {
525
+ "application/json": {
526
+ schema: {
527
+ $ref: "#/components/schemas/CelestialBody"
528
+ }
529
+ }
530
+ }
531
+ }
532
+ },
533
+ "x-post-response": 'pm.test("Status code is 201", () => {\n pm.response.to.have.status(201);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response is a celestial body with id and name", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("id");\n pm.expect(jsonData).to.have.property("name");\n});\n'
534
+ }
535
+ },
536
+ "/user/signup": {
537
+ post: {
538
+ tags: [
539
+ "Authentication"
540
+ ],
541
+ summary: "Create a user",
542
+ description: "Time to create a user account, eh?",
543
+ operationId: "createUser",
544
+ security: [],
545
+ requestBody: {
546
+ description: "User to create",
547
+ content: {
548
+ "application/json": {
549
+ schema: {
550
+ allOf: [
551
+ {
552
+ $ref: "#/components/schemas/User"
553
+ },
554
+ {
555
+ $ref: "#/components/schemas/Credentials"
556
+ }
557
+ ]
558
+ },
559
+ examples: {
560
+ Marc: {
561
+ value: {
562
+ name: "Marc",
563
+ email: "marc@scalar.com",
564
+ password: "i-love-scalar"
565
+ }
566
+ },
567
+ Cam: {
568
+ value: {
569
+ name: "Cam",
570
+ email: "cam@scalar.com",
571
+ password: "scalar-is-cool"
572
+ }
573
+ },
574
+ Hans: {
575
+ value: {
576
+ name: "Hans",
577
+ email: "hans@scalar.com",
578
+ password: "5c4l4r"
579
+ }
580
+ }
581
+ }
582
+ },
583
+ "application/xml": {
584
+ schema: {
585
+ allOf: [
586
+ {
587
+ $ref: "#/components/schemas/User"
588
+ },
589
+ {
590
+ $ref: "#/components/schemas/Credentials"
591
+ }
592
+ ]
593
+ },
594
+ examples: {
595
+ Marc: {
596
+ value: {
597
+ name: "Marc",
598
+ email: "marc@scalar.com",
599
+ password: "i-love-scalar"
600
+ }
601
+ },
602
+ Cam: {
603
+ value: {
604
+ name: "Cam",
605
+ email: "cam@scalar.com",
606
+ password: "scalar-is-cool"
607
+ }
608
+ },
609
+ Hans: {
610
+ value: {
611
+ name: "Hans",
612
+ email: "hans@scalar.com",
613
+ password: "5c4l4r"
614
+ }
615
+ }
616
+ }
617
+ }
618
+ }
619
+ },
620
+ responses: {
621
+ "201": {
622
+ description: "User account created successfully",
623
+ headers: {
624
+ "X-Request-ID": {
625
+ $ref: "#/components/headers/X-Request-ID"
626
+ },
627
+ Location: {
628
+ $ref: "#/components/headers/Location"
629
+ },
630
+ "X-Processing-Time": {
631
+ $ref: "#/components/headers/X-Processing-Time"
632
+ }
633
+ },
634
+ content: {
635
+ "application/json": {
636
+ schema: {
637
+ $ref: "#/components/schemas/User"
638
+ }
639
+ },
640
+ "application/xml": {
641
+ schema: {
642
+ $ref: "#/components/schemas/User"
643
+ }
644
+ }
645
+ }
646
+ },
647
+ "400": {
648
+ $ref: "#/components/responses/BadRequest"
649
+ },
650
+ "401": {
651
+ $ref: "#/components/responses/Unauthorized"
652
+ },
653
+ "403": {
654
+ $ref: "#/components/responses/Forbidden"
655
+ },
656
+ "409": {
657
+ $ref: "#/components/responses/Conflict"
658
+ },
659
+ "422": {
660
+ $ref: "#/components/responses/UnprocessableEntity"
661
+ }
662
+ },
663
+ "x-post-response": 'pm.test("Status code is 201", () => {\n pm.response.to.have.status(201);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response is a user with id and name", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("id");\n pm.expect(jsonData).to.have.property("name");\n});\n'
664
+ }
665
+ },
666
+ "/auth/token": {
667
+ post: {
668
+ tags: [
669
+ "Authentication"
670
+ ],
671
+ summary: "Get a token",
672
+ description: "Yeah, this is the boring security stuff. Just get your super secret token and move on.",
673
+ operationId: "getToken",
674
+ security: [],
675
+ requestBody: {
676
+ description: "Body for credentials to authenticate a user",
677
+ content: {
678
+ "application/json": {
679
+ schema: {
680
+ $ref: "#/components/schemas/Credentials"
681
+ }
682
+ },
683
+ "application/xml": {
684
+ schema: {
685
+ $ref: "#/components/schemas/Credentials"
686
+ }
687
+ }
688
+ }
689
+ },
690
+ responses: {
691
+ "201": {
692
+ description: "Token Created",
693
+ headers: {
694
+ "X-Request-ID": {
695
+ $ref: "#/components/headers/X-Request-ID"
696
+ },
697
+ "X-RateLimit-Limit": {
698
+ $ref: "#/components/headers/X-RateLimit-Limit"
699
+ },
700
+ "X-RateLimit-Remaining": {
701
+ $ref: "#/components/headers/X-RateLimit-Remaining"
702
+ },
703
+ "X-RateLimit-Reset": {
704
+ $ref: "#/components/headers/X-RateLimit-Reset"
705
+ }
706
+ },
707
+ content: {
708
+ "application/json": {
709
+ schema: {
710
+ $ref: "#/components/schemas/Token"
711
+ }
712
+ },
713
+ "application/xml": {
714
+ schema: {
715
+ $ref: "#/components/schemas/Token"
716
+ }
717
+ }
718
+ }
719
+ },
720
+ "400": {
721
+ $ref: "#/components/responses/BadRequest"
722
+ },
723
+ "401": {
724
+ $ref: "#/components/responses/Unauthorized"
725
+ },
726
+ "403": {
727
+ $ref: "#/components/responses/Forbidden"
728
+ },
729
+ "429": {
730
+ $ref: "#/components/responses/TooManyRequests"
731
+ }
732
+ },
733
+ "x-post-response": 'pm.test("Status code is 201", () => {\n pm.response.to.have.status(201);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response contains token", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("token");\n pm.expect(jsonData.token).to.be.an("string");\n});\n'
734
+ }
735
+ },
736
+ "/me": {
737
+ get: {
738
+ tags: [
739
+ "Authentication"
740
+ ],
741
+ summary: "Get authenticated user",
742
+ description: "Find yourself they say. That's what you can do here.",
743
+ operationId: "getMe",
744
+ security: [
745
+ {
746
+ basicAuth: []
747
+ },
748
+ {
749
+ oAuth2: [
750
+ "read:account"
751
+ ]
752
+ },
753
+ {
754
+ bearerAuth: []
755
+ },
756
+ {
757
+ apiKeyHeader: []
758
+ },
759
+ {
760
+ apiKeyQuery: []
761
+ },
762
+ {
763
+ apiKeyHeader: [],
764
+ apiKeyQuery: []
765
+ }
766
+ ],
767
+ responses: {
768
+ "200": {
769
+ description: "Authenticated user information retrieved successfully",
770
+ headers: {
771
+ "X-Request-ID": {
772
+ $ref: "#/components/headers/X-Request-ID"
773
+ },
774
+ ETag: {
775
+ $ref: "#/components/headers/ETag"
776
+ },
777
+ "Last-Modified": {
778
+ $ref: "#/components/headers/Last-Modified"
779
+ },
780
+ "X-Cache-Control": {
781
+ $ref: "#/components/headers/X-Cache-Control"
782
+ }
783
+ },
784
+ content: {
785
+ "application/json": {
786
+ schema: {
787
+ $ref: "#/components/schemas/User"
788
+ }
789
+ },
790
+ "application/xml": {
791
+ schema: {
792
+ $ref: "#/components/schemas/User"
793
+ }
794
+ }
795
+ }
796
+ },
797
+ "401": {
798
+ $ref: "#/components/responses/Unauthorized"
799
+ },
800
+ "403": {
801
+ $ref: "#/components/responses/Forbidden"
802
+ }
803
+ },
804
+ "x-post-response": 'pm.test("Status code is 200", () => {\n pm.response.to.have.status(200);\n});\n\npm.test("Content-Type header is present", () => {\n pm.response.to.have.header("Content-Type");\n});\n\npm.test("Response is a user with id and name", () => {\n const jsonData = pm.response.json();\n pm.expect(jsonData).to.have.property("id");\n pm.expect(jsonData).to.have.property("name");\n});\n'
805
+ }
806
+ }
807
+ },
808
+ webhooks: {
809
+ newPlanet: {
810
+ post: {
811
+ tags: [
812
+ "Planets"
813
+ ],
814
+ security: [],
815
+ requestBody: {
816
+ description: "Information about a new planet",
817
+ content: {
818
+ "application/json": {
819
+ schema: {
820
+ $ref: "#/components/schemas/Planet"
821
+ }
822
+ }
823
+ }
824
+ },
825
+ responses: {
826
+ "200": {
827
+ description: "Return a 200 status to indicate that the data was received successfully"
828
+ }
829
+ },
830
+ "x-post-response": 'pm.test("Status code is 200", () => {\n pm.response.to.have.status(200);\n});\n'
831
+ }
832
+ }
833
+ },
834
+ components: {
835
+ securitySchemes: {
836
+ bearerAuth: {
837
+ type: "http",
838
+ scheme: "bearer",
839
+ description: "JWT Bearer token authentication"
840
+ },
841
+ basicAuth: {
842
+ type: "http",
843
+ scheme: "basic",
844
+ description: "Basic HTTP authentication"
845
+ },
846
+ apiKeyHeader: {
847
+ type: "apiKey",
848
+ in: "header",
849
+ name: "X-API-Key",
850
+ description: "API key request header"
851
+ },
852
+ apiKeyQuery: {
853
+ type: "apiKey",
854
+ in: "query",
855
+ name: "api_key",
856
+ description: "API key query parameter"
857
+ },
858
+ apiKeyCookie: {
859
+ type: "apiKey",
860
+ in: "cookie",
861
+ name: "api_key",
862
+ description: "API key browser cookie"
863
+ },
864
+ oAuth2: {
865
+ type: "oauth2",
866
+ description: "OAuth 2.0 authentication",
867
+ flows: {
868
+ authorizationCode: {
869
+ authorizationUrl: "https://galaxy.scalar.com/oauth/authorize",
870
+ tokenUrl: "https://galaxy.scalar.com/oauth/token",
871
+ scopes: {
872
+ "read:account": "read your account information",
873
+ "write:planets": "modify planets in your account",
874
+ "read:planets": "read your planets"
875
+ }
876
+ },
877
+ clientCredentials: {
878
+ tokenUrl: "https://galaxy.scalar.com/oauth/token",
879
+ scopes: {
880
+ "read:account": "read your account information",
881
+ "write:planets": "modify planets in your account",
882
+ "read:planets": "read your planets"
883
+ }
884
+ },
885
+ implicit: {
886
+ authorizationUrl: "https://galaxy.scalar.com/oauth/authorize",
887
+ scopes: {
888
+ "read:account": "read your account information",
889
+ "write:planets": "modify planets in your account",
890
+ "read:planets": "read your planets"
891
+ }
892
+ },
893
+ password: {
894
+ tokenUrl: "https://galaxy.scalar.com/oauth/token",
895
+ scopes: {
896
+ "read:account": "read your account information",
897
+ "write:planets": "modify planets in your account",
898
+ "read:planets": "read your planets"
899
+ }
900
+ }
901
+ }
902
+ },
903
+ openIdConnect: {
904
+ type: "openIdConnect",
905
+ openIdConnectUrl: "https://galaxy.scalar.com/.well-known/openid-configuration",
906
+ description: "OpenID Connect Authentication"
907
+ }
908
+ },
909
+ parameters: {
910
+ planetId: {
911
+ name: "planetId",
912
+ description: "The ID of the planet to get",
913
+ in: "path",
914
+ required: true,
915
+ schema: {
916
+ type: "integer",
917
+ format: "int64",
918
+ examples: [
919
+ 1
920
+ ]
921
+ }
922
+ },
923
+ limit: {
924
+ name: "limit",
925
+ description: "The number of items to return",
926
+ in: "query",
927
+ required: false,
928
+ schema: {
929
+ type: "integer",
930
+ format: "int64",
931
+ default: 10
932
+ }
933
+ },
934
+ offset: {
935
+ name: "offset",
936
+ description: "The number of items to skip before starting to collect the result set",
937
+ in: "query",
938
+ required: false,
939
+ schema: {
940
+ type: "integer",
941
+ format: "int64",
942
+ default: 0
943
+ }
944
+ }
945
+ },
946
+ headers: {
947
+ "X-RateLimit-Limit": {
948
+ description: "The number of allowed requests in the current period",
949
+ schema: {
950
+ type: "integer",
951
+ example: 100
952
+ }
953
+ },
954
+ "X-RateLimit-Remaining": {
955
+ description: "The number of remaining requests in the current period",
956
+ schema: {
957
+ type: "integer",
958
+ example: 95
959
+ }
960
+ },
961
+ "X-RateLimit-Reset": {
962
+ description: "The number of seconds left in the current period",
963
+ schema: {
964
+ type: "integer",
965
+ example: 3600
966
+ }
967
+ },
968
+ "X-Request-ID": {
969
+ description: "Unique identifier for the request",
970
+ schema: {
971
+ type: "string",
972
+ format: "uuid",
973
+ example: "123e4567-e89b-12d3-a456-426614174000"
974
+ }
975
+ },
976
+ "X-Pagination-Total": {
977
+ description: "Total number of items available",
978
+ schema: {
979
+ type: "integer",
980
+ example: 1e3
981
+ }
982
+ },
983
+ "X-Pagination-Page": {
984
+ description: "Current page number",
985
+ schema: {
986
+ type: "integer",
987
+ example: 1
988
+ }
989
+ },
990
+ "X-Pagination-Per-Page": {
991
+ description: "Number of items per page",
992
+ schema: {
993
+ type: "integer",
994
+ example: 10
995
+ }
996
+ },
997
+ "X-Cache-Control": {
998
+ description: "Cache control directives",
999
+ schema: {
1000
+ type: "string",
1001
+ example: "max-age=3600, public"
1002
+ }
1003
+ },
1004
+ ETag: {
1005
+ description: "Entity tag for caching",
1006
+ schema: {
1007
+ type: "string",
1008
+ example: '"33a64df551"'
1009
+ }
1010
+ },
1011
+ "Last-Modified": {
1012
+ description: "The last modification date of the resource",
1013
+ schema: {
1014
+ type: "string",
1015
+ format: "date-time",
1016
+ example: "2023-12-01T12:00:00Z"
1017
+ }
1018
+ },
1019
+ Location: {
1020
+ description: "The URL of the newly created resource",
1021
+ schema: {
1022
+ type: "string",
1023
+ format: "uri",
1024
+ example: "https://galaxy.scalar.com/planets/123"
1025
+ }
1026
+ },
1027
+ "X-Processing-Time": {
1028
+ description: "The time taken to process the request in milliseconds",
1029
+ schema: {
1030
+ type: "integer",
1031
+ example: 150
1032
+ }
1033
+ }
1034
+ },
1035
+ responses: {
1036
+ ImageUploaded: {
1037
+ description: "Image uploaded",
1038
+ headers: {
1039
+ "X-Request-ID": {
1040
+ $ref: "#/components/headers/X-Request-ID"
1041
+ },
1042
+ "X-Cache-Control": {
1043
+ $ref: "#/components/headers/X-Cache-Control"
1044
+ }
1045
+ },
1046
+ content: {
1047
+ "application/json": {
1048
+ schema: {
1049
+ $ref: "#/components/schemas/ImageUploadedMessage"
1050
+ }
1051
+ },
1052
+ "application/xml": {
1053
+ schema: {
1054
+ $ref: "#/components/schemas/ImageUploadedMessage"
1055
+ }
1056
+ }
1057
+ }
1058
+ },
1059
+ BadRequest: {
1060
+ description: "Bad Request",
1061
+ headers: {
1062
+ "X-Request-ID": {
1063
+ $ref: "#/components/headers/X-Request-ID"
1064
+ }
1065
+ },
1066
+ content: {
1067
+ "application/json": {
1068
+ schema: {
1069
+ $ref: "#/components/schemas/BadRequestError"
1070
+ }
1071
+ },
1072
+ "application/xml": {
1073
+ schema: {
1074
+ $ref: "#/components/schemas/BadRequestError"
1075
+ }
1076
+ }
1077
+ }
1078
+ },
1079
+ Forbidden: {
1080
+ description: "Forbidden",
1081
+ content: {
1082
+ "application/json": {
1083
+ schema: {
1084
+ $ref: "#/components/schemas/ForbiddenError"
1085
+ }
1086
+ },
1087
+ "application/xml": {
1088
+ schema: {
1089
+ $ref: "#/components/schemas/ForbiddenError"
1090
+ }
1091
+ }
1092
+ }
1093
+ },
1094
+ NotFound: {
1095
+ description: "Not Found",
1096
+ content: {
1097
+ "application/json": {
1098
+ schema: {
1099
+ $ref: "#/components/schemas/NotFoundError"
1100
+ }
1101
+ },
1102
+ "application/xml": {
1103
+ schema: {
1104
+ $ref: "#/components/schemas/NotFoundError"
1105
+ }
1106
+ }
1107
+ }
1108
+ },
1109
+ Unauthorized: {
1110
+ description: "Unauthorized",
1111
+ content: {
1112
+ "application/json": {
1113
+ schema: {
1114
+ $ref: "#/components/schemas/UnauthorizedError"
1115
+ }
1116
+ },
1117
+ "application/xml": {
1118
+ schema: {
1119
+ $ref: "#/components/schemas/UnauthorizedError"
1120
+ }
1121
+ }
1122
+ }
1123
+ },
1124
+ Conflict: {
1125
+ description: "Conflict",
1126
+ content: {
1127
+ "application/json": {
1128
+ schema: {
1129
+ $ref: "#/components/schemas/Conflict"
1130
+ }
1131
+ },
1132
+ "application/xml": {
1133
+ schema: {
1134
+ $ref: "#/components/schemas/Conflict"
1135
+ }
1136
+ }
1137
+ }
1138
+ },
1139
+ UnprocessableEntity: {
1140
+ description: "Unprocessable Entity",
1141
+ content: {
1142
+ "application/json": {
1143
+ schema: {
1144
+ $ref: "#/components/schemas/UnprocessableEntity"
1145
+ }
1146
+ },
1147
+ "application/xml": {
1148
+ schema: {
1149
+ $ref: "#/components/schemas/UnprocessableEntity"
1150
+ }
1151
+ }
1152
+ }
1153
+ },
1154
+ TooManyRequests: {
1155
+ description: "Too Many Requests",
1156
+ headers: {
1157
+ "X-Request-ID": {
1158
+ $ref: "#/components/headers/X-Request-ID"
1159
+ },
1160
+ "X-RateLimit-Limit": {
1161
+ $ref: "#/components/headers/X-RateLimit-Limit"
1162
+ },
1163
+ "X-RateLimit-Remaining": {
1164
+ $ref: "#/components/headers/X-RateLimit-Remaining"
1165
+ },
1166
+ "X-RateLimit-Reset": {
1167
+ $ref: "#/components/headers/X-RateLimit-Reset"
1168
+ },
1169
+ "Retry-After": {
1170
+ description: "The number of seconds to wait before retrying",
1171
+ schema: {
1172
+ type: "integer",
1173
+ example: 60
1174
+ }
1175
+ }
1176
+ },
1177
+ content: {
1178
+ "application/json": {
1179
+ schema: {
1180
+ $ref: "#/components/schemas/TooManyRequestsError"
1181
+ }
1182
+ },
1183
+ "application/xml": {
1184
+ schema: {
1185
+ $ref: "#/components/schemas/TooManyRequestsError"
1186
+ }
1187
+ }
1188
+ }
1189
+ }
1190
+ },
1191
+ schemas: {
1192
+ User: {
1193
+ description: "A user",
1194
+ type: "object",
1195
+ xml: {
1196
+ name: "user"
1197
+ },
1198
+ properties: {
1199
+ id: {
1200
+ type: "integer",
1201
+ format: "int64",
1202
+ readOnly: true,
1203
+ examples: [
1204
+ 1
1205
+ ]
1206
+ },
1207
+ name: {
1208
+ type: "string",
1209
+ examples: [
1210
+ "Marc",
1211
+ "Cam",
1212
+ "Hans"
1213
+ ]
1214
+ }
1215
+ }
1216
+ },
1217
+ Credentials: {
1218
+ description: "Credentials to authenticate a user",
1219
+ type: "object",
1220
+ required: [
1221
+ "email",
1222
+ "password"
1223
+ ],
1224
+ properties: {
1225
+ email: {
1226
+ type: "string",
1227
+ format: "email",
1228
+ examples: [
1229
+ "marc@scalar.com",
1230
+ "cam@scalar.com",
1231
+ "hans@scalar.com"
1232
+ ]
1233
+ },
1234
+ password: {
1235
+ type: "string",
1236
+ writeOnly: true,
1237
+ examples: [
1238
+ "i-love-scalar",
1239
+ "i-love-oss",
1240
+ "qwerty123"
1241
+ ]
1242
+ }
1243
+ }
1244
+ },
1245
+ Token: {
1246
+ description: "A token to authenticate a user",
1247
+ type: "object",
1248
+ properties: {
1249
+ token: {
1250
+ type: "string",
1251
+ examples: [
1252
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
1253
+ ]
1254
+ }
1255
+ }
1256
+ },
1257
+ CelestialBody: {
1258
+ oneOf: [
1259
+ {
1260
+ $ref: "#/components/schemas/Planet"
1261
+ },
1262
+ {
1263
+ $ref: "#/components/schemas/Satellite"
1264
+ }
1265
+ ],
1266
+ discriminator: {
1267
+ propertyName: "type",
1268
+ mapping: {
1269
+ terrestrial: "#/components/schemas/Planet",
1270
+ gas_giant: "#/components/schemas/Planet",
1271
+ ice_giant: "#/components/schemas/Planet",
1272
+ dwarf: "#/components/schemas/Planet",
1273
+ super_earth: "#/components/schemas/Planet",
1274
+ moon: "#/components/schemas/Satellite",
1275
+ asteroid: "#/components/schemas/Satellite",
1276
+ comet: "#/components/schemas/Satellite"
1277
+ }
1278
+ },
1279
+ description: "A celestial body which can be either a planet or a satellite"
1280
+ },
1281
+ Planet: {
1282
+ description: "A planet in the Scalar Galaxy",
1283
+ type: "object",
1284
+ required: [
1285
+ "id",
1286
+ "name"
1287
+ ],
1288
+ additionalProperties: false,
1289
+ xml: {
1290
+ name: "planet"
1291
+ },
1292
+ properties: {
1293
+ id: {
1294
+ type: "integer",
1295
+ format: "int64",
1296
+ readOnly: true,
1297
+ examples: [
1298
+ 1
1299
+ ],
1300
+ "x-variable": "planetId"
1301
+ },
1302
+ name: {
1303
+ type: "string",
1304
+ examples: [
1305
+ "Mars",
1306
+ "Jupiter",
1307
+ "HD 40307g"
1308
+ ]
1309
+ },
1310
+ description: {
1311
+ type: [
1312
+ "string",
1313
+ "null"
1314
+ ],
1315
+ examples: [
1316
+ "The red planet",
1317
+ "A gas giant with a great red spot"
1318
+ ]
1319
+ },
1320
+ type: {
1321
+ type: "string",
1322
+ enum: [
1323
+ "terrestrial",
1324
+ "gas_giant",
1325
+ "ice_giant",
1326
+ "dwarf",
1327
+ "super_earth"
1328
+ ],
1329
+ "x-enum-varnames": [
1330
+ "Terrestrial",
1331
+ "GasGiant",
1332
+ "IceGiant",
1333
+ "Dwarf",
1334
+ "SuperEarth"
1335
+ ],
1336
+ "x-enum-descriptions": {
1337
+ terrestrial: "Rocky planets with solid surfaces, like Earth and Mars",
1338
+ gas_giant: "Large planets composed mainly of hydrogen and helium, like Jupiter and Saturn",
1339
+ ice_giant: "Planets composed of water, ammonia, and methane ices, like Uranus and Neptune",
1340
+ dwarf: "Small planetary bodies that don't meet full planet criteria, like Pluto",
1341
+ super_earth: "Rocky planets larger than Earth but smaller than gas giants"
1342
+ },
1343
+ examples: [
1344
+ "terrestrial"
1345
+ ]
1346
+ },
1347
+ habitabilityIndex: {
1348
+ type: "number",
1349
+ format: "float",
1350
+ minimum: 0,
1351
+ maximum: 1,
1352
+ description: "A score from 0 to 1 indicating potential habitability",
1353
+ examples: [
1354
+ 0.68
1355
+ ]
1356
+ },
1357
+ physicalProperties: {
1358
+ type: "object",
1359
+ additionalProperties: {
1360
+ "x-additionalPropertiesName": "measurement",
1361
+ type: "number",
1362
+ format: "float",
1363
+ description: "Additional physical measurements for the planet"
1364
+ },
1365
+ properties: {
1366
+ mass: {
1367
+ type: "number",
1368
+ format: "float",
1369
+ exclusiveMinimum: 0,
1370
+ description: "Mass in Earth masses (must be greater than 0)",
1371
+ examples: [
1372
+ 0.107
1373
+ ]
1374
+ },
1375
+ radius: {
1376
+ type: "number",
1377
+ format: "float",
1378
+ exclusiveMinimum: 0,
1379
+ description: "Radius in Earth radii (must be greater than 0)",
1380
+ examples: [
1381
+ 0.532
1382
+ ]
1383
+ },
1384
+ gravity: {
1385
+ type: "number",
1386
+ format: "float",
1387
+ description: "Surface gravity in Earth g",
1388
+ examples: [
1389
+ 0.378
1390
+ ]
1391
+ },
1392
+ temperature: {
1393
+ type: "object",
1394
+ additionalProperties: {
1395
+ "x-additionalPropertiesName": "temperatureMetric",
1396
+ type: "number",
1397
+ format: "float",
1398
+ description: "Additional temperature-related measurements in Kelvin"
1399
+ },
1400
+ properties: {
1401
+ min: {
1402
+ type: "number",
1403
+ format: "float",
1404
+ description: "Minimum temperature in Kelvin",
1405
+ examples: [
1406
+ 130
1407
+ ]
1408
+ },
1409
+ max: {
1410
+ type: "number",
1411
+ format: "float",
1412
+ description: "Maximum temperature in Kelvin",
1413
+ examples: [
1414
+ 308
1415
+ ]
1416
+ },
1417
+ average: {
1418
+ type: "number",
1419
+ format: "float",
1420
+ description: "Average temperature in Kelvin",
1421
+ examples: [
1422
+ 210
1423
+ ]
1424
+ }
1425
+ }
1426
+ }
1427
+ }
1428
+ },
1429
+ atmosphere: {
1430
+ type: "array",
1431
+ description: "Atmospheric composition",
1432
+ items: {
1433
+ type: "object",
1434
+ additionalProperties: {
1435
+ "x-additionalPropertiesName": "atmosphericData",
1436
+ type: "string",
1437
+ description: "Additional atmospheric composition data"
1438
+ },
1439
+ properties: {
1440
+ compound: {
1441
+ type: "string",
1442
+ examples: [
1443
+ "CO2",
1444
+ "N2"
1445
+ ]
1446
+ },
1447
+ percentage: {
1448
+ type: "number",
1449
+ format: "float",
1450
+ exclusiveMaximum: 100,
1451
+ examples: [
1452
+ 95.3
1453
+ ]
1454
+ }
1455
+ }
1456
+ }
1457
+ },
1458
+ discoveredAt: {
1459
+ type: "string",
1460
+ format: "date-time",
1461
+ examples: [
1462
+ "1610-01-07T00:00:00Z"
1463
+ ]
1464
+ },
1465
+ image: {
1466
+ type: [
1467
+ "string",
1468
+ "null"
1469
+ ],
1470
+ examples: [
1471
+ "https://cdn.scalar.com/photos/mars.jpg"
1472
+ ]
1473
+ },
1474
+ satellites: {
1475
+ type: "array",
1476
+ items: {
1477
+ $ref: "#/components/schemas/Satellite"
1478
+ }
1479
+ },
1480
+ creator: {
1481
+ $ref: "#/components/schemas/User"
1482
+ },
1483
+ tags: {
1484
+ type: "array",
1485
+ items: {
1486
+ type: "string"
1487
+ },
1488
+ examples: [
1489
+ [
1490
+ "solar-system",
1491
+ "rocky",
1492
+ "explored"
1493
+ ]
1494
+ ]
1495
+ },
1496
+ lastUpdated: {
1497
+ type: "string",
1498
+ format: "date-time",
1499
+ readOnly: true,
1500
+ examples: [
1501
+ "2024-01-15T14:30:00Z"
1502
+ ]
1503
+ },
1504
+ successCallbackUrl: {
1505
+ type: "string",
1506
+ format: "uri",
1507
+ description: "URL which gets invoked upon a successful operation",
1508
+ examples: [
1509
+ "https://example.com/webhook"
1510
+ ]
1511
+ },
1512
+ failureCallbackUrl: {
1513
+ type: "string",
1514
+ format: "uri",
1515
+ description: "URL which gets invoked upon a failed operation",
1516
+ examples: [
1517
+ "https://example.com/webhook"
1518
+ ]
1519
+ }
1520
+ }
1521
+ },
1522
+ Satellite: {
1523
+ description: "Every satellite in the Scalar Galaxy",
1524
+ type: "object",
1525
+ required: [
1526
+ "name"
1527
+ ],
1528
+ properties: {
1529
+ id: {
1530
+ type: "integer",
1531
+ format: "int64",
1532
+ readOnly: true,
1533
+ examples: [
1534
+ 1
1535
+ ]
1536
+ },
1537
+ name: {
1538
+ type: "string",
1539
+ examples: [
1540
+ "Phobos"
1541
+ ]
1542
+ },
1543
+ description: {
1544
+ type: [
1545
+ "string",
1546
+ "null"
1547
+ ],
1548
+ examples: [
1549
+ "Phobos is the larger and innermost of the two moons of Mars."
1550
+ ]
1551
+ },
1552
+ diameter: {
1553
+ type: "number",
1554
+ format: "float",
1555
+ description: "Diameter in kilometers",
1556
+ examples: [
1557
+ 22.2
1558
+ ]
1559
+ },
1560
+ type: {
1561
+ type: "string",
1562
+ enum: [
1563
+ "moon",
1564
+ "asteroid",
1565
+ "comet"
1566
+ ],
1567
+ "x-enum-varnames": [
1568
+ "Moon",
1569
+ "Asteroid",
1570
+ "Comet"
1571
+ ],
1572
+ "x-enum-descriptions": {
1573
+ moon: "Natural satellites that orbit planets",
1574
+ asteroid: "Rocky objects that orbit the sun, typically found in the asteroid belt",
1575
+ comet: "Icy bodies that release gas when approaching the sun, creating visible tails"
1576
+ },
1577
+ examples: [
1578
+ "moon"
1579
+ ]
1580
+ },
1581
+ orbit: {
1582
+ type: "object",
1583
+ properties: {
1584
+ planet: {
1585
+ $ref: "#/components/schemas/Planet"
1586
+ },
1587
+ orbitalPeriod: {
1588
+ type: "number",
1589
+ format: "float",
1590
+ description: "Orbital period in Earth days",
1591
+ examples: [
1592
+ 0.319
1593
+ ]
1594
+ },
1595
+ distance: {
1596
+ type: "number",
1597
+ format: "float",
1598
+ description: "Average distance from the planet in kilometers",
1599
+ examples: [
1600
+ 9376
1601
+ ]
1602
+ }
1603
+ }
1604
+ }
1605
+ }
1606
+ },
1607
+ PaginatedResource: {
1608
+ description: "A generic paginated resource. Specializing schemas bind the item type by declaring a `$dynamicAnchor` named `itemType`, the JSON Schema 2020-12 way to express `PaginatedResource<T>`.",
1609
+ $id: "https://galaxy.scalar.com/schemas/PaginatedResource",
1610
+ $defs: {
1611
+ itemType: {
1612
+ $dynamicAnchor: "itemType",
1613
+ not: {}
1614
+ }
1615
+ },
1616
+ type: "object",
1617
+ properties: {
1618
+ data: {
1619
+ type: "array",
1620
+ items: {
1621
+ $dynamicRef: "#itemType"
1622
+ }
1623
+ },
1624
+ meta: {
1625
+ type: "object",
1626
+ properties: {
1627
+ limit: {
1628
+ type: "integer",
1629
+ format: "int64",
1630
+ examples: [
1631
+ 10
1632
+ ]
1633
+ },
1634
+ offset: {
1635
+ type: "integer",
1636
+ format: "int64",
1637
+ examples: [
1638
+ 0
1639
+ ]
1640
+ },
1641
+ total: {
1642
+ type: "integer",
1643
+ format: "int64",
1644
+ examples: [
1645
+ 100
1646
+ ]
1647
+ },
1648
+ next: {
1649
+ type: [
1650
+ "string",
1651
+ "null"
1652
+ ],
1653
+ examples: [
1654
+ "/planets?limit=10&offset=10"
1655
+ ]
1656
+ }
1657
+ }
1658
+ }
1659
+ }
1660
+ },
1661
+ ImageUploadedMessage: {
1662
+ "x-scalar-ignore": true,
1663
+ description: "Message about an image upload",
1664
+ type: "object",
1665
+ properties: {
1666
+ message: {
1667
+ type: "string",
1668
+ examples: [
1669
+ "Image uploaded successfully"
1670
+ ]
1671
+ },
1672
+ imageUrl: {
1673
+ type: "string",
1674
+ description: "The URL where the uploaded image can be accessed",
1675
+ examples: [
1676
+ "https://cdn.scalar.com/images/8f47c132-9d1f-4f83-b5a4-91db5ee757ab.jpg"
1677
+ ]
1678
+ },
1679
+ uploadedAt: {
1680
+ type: "string",
1681
+ format: "date-time",
1682
+ description: "Timestamp when the image was uploaded",
1683
+ examples: [
1684
+ "2024-01-15T14:30:00Z"
1685
+ ]
1686
+ },
1687
+ fileSize: {
1688
+ type: "integer",
1689
+ description: "Size of the uploaded image in bytes",
1690
+ examples: [
1691
+ 1048576
1692
+ ]
1693
+ },
1694
+ mimeType: {
1695
+ type: "string",
1696
+ description: "The content type of the uploaded image",
1697
+ examples: [
1698
+ "image/jpeg",
1699
+ "image/png"
1700
+ ]
1701
+ }
1702
+ }
1703
+ },
1704
+ BadRequestError: {
1705
+ "x-scalar-ignore": true,
1706
+ description: "RFC 7807 (https://datatracker.ietf.org/doc/html/rfc7807)",
1707
+ type: "object",
1708
+ properties: {
1709
+ type: {
1710
+ type: "string",
1711
+ examples: [
1712
+ "https://example.com/errors/bad-request"
1713
+ ]
1714
+ },
1715
+ title: {
1716
+ type: "string",
1717
+ examples: [
1718
+ "Bad Request"
1719
+ ]
1720
+ },
1721
+ status: {
1722
+ type: "integer",
1723
+ format: "int64",
1724
+ examples: [
1725
+ 400
1726
+ ]
1727
+ },
1728
+ detail: {
1729
+ type: "string",
1730
+ examples: [
1731
+ "The request was invalid."
1732
+ ]
1733
+ }
1734
+ }
1735
+ },
1736
+ ForbiddenError: {
1737
+ "x-scalar-ignore": true,
1738
+ description: "Error response for forbidden access (RFC 7807). Returned when the user does not have permission to access the requested resource.",
1739
+ type: "object",
1740
+ properties: {
1741
+ type: {
1742
+ type: "string",
1743
+ examples: [
1744
+ "https://example.com/errors/forbidden"
1745
+ ]
1746
+ },
1747
+ title: {
1748
+ type: "string",
1749
+ examples: [
1750
+ "Forbidden"
1751
+ ]
1752
+ },
1753
+ status: {
1754
+ type: "integer",
1755
+ format: "int64",
1756
+ examples: [
1757
+ 403
1758
+ ]
1759
+ },
1760
+ detail: {
1761
+ type: "string",
1762
+ examples: [
1763
+ "You are not authorized to access this resource."
1764
+ ]
1765
+ }
1766
+ }
1767
+ },
1768
+ NotFoundError: {
1769
+ "x-scalar-ignore": true,
1770
+ description: "Error response for resource not found (RFC 7807). Returned when the requested resource does not exist.",
1771
+ type: "object",
1772
+ properties: {
1773
+ type: {
1774
+ type: "string",
1775
+ examples: [
1776
+ "https://example.com/errors/not-found"
1777
+ ]
1778
+ },
1779
+ title: {
1780
+ type: "string",
1781
+ examples: [
1782
+ "Not Found"
1783
+ ]
1784
+ },
1785
+ status: {
1786
+ type: "integer",
1787
+ format: "int64",
1788
+ examples: [
1789
+ 404
1790
+ ]
1791
+ },
1792
+ detail: {
1793
+ type: "string",
1794
+ examples: [
1795
+ "The resource you are trying to access does not exist."
1796
+ ]
1797
+ }
1798
+ }
1799
+ },
1800
+ UnauthorizedError: {
1801
+ "x-scalar-ignore": true,
1802
+ description: "Error response for unauthorized access (RFC 7807). Returned when authentication is required or has failed.",
1803
+ type: "object",
1804
+ properties: {
1805
+ type: {
1806
+ type: "string",
1807
+ examples: [
1808
+ "https://example.com/errors/not-found"
1809
+ ]
1810
+ },
1811
+ title: {
1812
+ type: "string",
1813
+ examples: [
1814
+ "Unauthorized"
1815
+ ]
1816
+ },
1817
+ status: {
1818
+ type: "integer",
1819
+ format: "int64",
1820
+ examples: [
1821
+ 401
1822
+ ]
1823
+ },
1824
+ detail: {
1825
+ type: "string",
1826
+ examples: [
1827
+ "You are not authorized to access this resource."
1828
+ ]
1829
+ }
1830
+ }
1831
+ },
1832
+ Conflict: {
1833
+ "x-scalar-ignore": true,
1834
+ description: "Error response for resource conflicts (RFC 7807). Returned when the request conflicts with the current state of the resource.",
1835
+ type: "object",
1836
+ properties: {
1837
+ type: {
1838
+ type: "string",
1839
+ examples: [
1840
+ "https://example.com/errors/conflict"
1841
+ ]
1842
+ },
1843
+ title: {
1844
+ type: "string",
1845
+ examples: [
1846
+ "Conflict"
1847
+ ]
1848
+ },
1849
+ status: {
1850
+ type: "integer",
1851
+ format: "int64",
1852
+ examples: [
1853
+ 409
1854
+ ]
1855
+ },
1856
+ detail: {
1857
+ type: "string",
1858
+ examples: [
1859
+ "The resource you are trying to access is in conflict."
1860
+ ]
1861
+ }
1862
+ }
1863
+ },
1864
+ UnprocessableEntity: {
1865
+ "x-scalar-ignore": true,
1866
+ description: "Error response for unprocessable entity (RFC 7807). Returned when the request is well-formed but contains semantic errors.",
1867
+ type: "object",
1868
+ properties: {
1869
+ type: {
1870
+ type: "string",
1871
+ examples: [
1872
+ "https://example.com/errors/unprocessable-entity"
1873
+ ]
1874
+ },
1875
+ title: {
1876
+ type: "string",
1877
+ examples: [
1878
+ "Unprocessable Entity"
1879
+ ]
1880
+ },
1881
+ status: {
1882
+ type: "integer",
1883
+ format: "int64",
1884
+ examples: [
1885
+ 422
1886
+ ]
1887
+ },
1888
+ detail: {
1889
+ type: "string",
1890
+ examples: [
1891
+ "The request was invalid."
1892
+ ]
1893
+ }
1894
+ }
1895
+ },
1896
+ TooManyRequestsError: {
1897
+ "x-scalar-ignore": true,
1898
+ description: "Error response for rate limiting (RFC 7807). Returned when the client has exceeded the rate limit for requests.",
1899
+ type: "object",
1900
+ properties: {
1901
+ type: {
1902
+ type: "string",
1903
+ examples: [
1904
+ "https://example.com/errors/too-many-requests"
1905
+ ]
1906
+ },
1907
+ title: {
1908
+ type: "string",
1909
+ examples: [
1910
+ "Too Many Requests"
1911
+ ]
1912
+ },
1913
+ status: {
1914
+ type: "integer",
1915
+ format: "int64",
1916
+ examples: [
1917
+ 429
1918
+ ]
1919
+ },
1920
+ detail: {
1921
+ type: "string",
1922
+ examples: [
1923
+ "Rate limit exceeded. Please try again later."
1924
+ ]
1925
+ }
1926
+ }
1927
+ }
1928
+ }
1929
+ }
1930
+ };
1931
+
1932
+ // src/domains/project/init/quickstart.ts
1933
+ var quickstartMarkdown = `# Quickstart
1934
+
1935
+ ## 1. Preview Your Docs
1936
+
1937
+ Run a local development server to see your changes in real-time:
1938
+
1939
+ \`\`\`bash
1940
+ npx @scalar/cli project preview
1941
+ \`\`\`
1942
+
1943
+ This starts a live preview at \`http://localhost:7970\` where every edit you make is instantly visible.
1944
+
1945
+ ## 2. Customize Everything
1946
+
1947
+ Make it yours with themes, custom CSS, and MDX. Configure your documentation structure, navigation, and styling through \`scalar.config.json\`.
1948
+
1949
+ ## 3. Publish Your Docs
1950
+
1951
+ First, authenticate with your Scalar account:
1952
+
1953
+ \`\`\`bash
1954
+ npx @scalar/cli auth login
1955
+ \`\`\`
1956
+
1957
+ Then publish your documentation:
1958
+
1959
+ \`\`\`bash
1960
+ npx @scalar/cli project publish --slug [dashboard-project-slug]
1961
+ \`\`\`
1962
+
1963
+ Your site will be available at \`<your-slug>.apidocumentation.com\`.
1964
+
1965
+ ## Stuck?
1966
+
1967
+ Check whether your \`scalar.config.json\` is valid:
1968
+
1969
+ \`\`\`bash
1970
+ npx @scalar/cli project check-config
1971
+ \`\`\`
1972
+
1973
+ We're here to help:
1974
+
1975
+ - [Email support@scalar.com](mailto:support@scalar.com)
1976
+ - [Chat with us on Discord](https://discord.gg/scalar)
1977
+ - [Schedule a call](https://scalar.cal.com/scalar/chat-with-scalar)
1978
+ `;
1979
+
1980
+ // src/domains/project/init/action.ts
1981
+ async function fileExists(path2) {
1982
+ try {
1983
+ await fs.access(path2, fs.constants.F_OK);
1984
+ return true;
1985
+ } catch {
1986
+ return false;
1987
+ }
1988
+ }
1989
+ async function initAction({
1990
+ subdomain,
1991
+ force
1992
+ }) {
1993
+ const configFile = findConfig() || CONFIG_FILE_DEFAULT;
1994
+ let validInput;
1995
+ const nextSteps = () => {
1996
+ output.info().line("What to do next:").line(
1997
+ ` ${as.cyan("scalar project preview")} to preview your project locally`
1998
+ ).line(
1999
+ ` ${as.cyan("scalar project check-config")} to validate your scalar.config.json file`
2000
+ ).line(
2001
+ ` ${as.cyan("scalar project publish --slug")} ${as.gray("[dashboard-project-slug]")} to publish your project`
2002
+ ).line(
2003
+ as.white(
2004
+ `Run ${as.magenta("scalar --help")} to see all available commands.`
2005
+ )
2006
+ ).print();
2007
+ };
2008
+ const handleCancel = () => {
2009
+ cancel("Operation cancelled.");
2010
+ nextSteps();
2011
+ process.exit(0);
2012
+ };
2013
+ if (await fileExists(configFile)) {
2014
+ output.info().line(
2015
+ `${as.green("\u26A0")} Found existing configuration: ${as.green.bold(`${configFile}`)}`
2016
+ ).print();
2017
+ if (force) {
2018
+ output.info().line(`${as.green("\u2714")} Overwriting existing file\u2026`).print();
2019
+ }
2020
+ const shouldOverwriteExisting = force ?? await confirm({
2021
+ message: "Do you want to override the file?",
2022
+ initialValue: false
2023
+ });
2024
+ if (isCancel(shouldOverwriteExisting)) {
2025
+ handleCancel();
2026
+ }
2027
+ if (!shouldOverwriteExisting) {
2028
+ handleCancel();
2029
+ }
2030
+ }
2031
+ const currentDir = path.resolve(path.dirname(configFile));
2032
+ const configuration = scalarConfigSchema.parse({
2033
+ info: {},
2034
+ navigation: {
2035
+ routes: {
2036
+ "/": {
2037
+ type: "group",
2038
+ title: "Documentation",
2039
+ children: {
2040
+ "/": {
2041
+ type: "page",
2042
+ title: "Quickstart",
2043
+ filepath: DEFAULT_MARKDOWN_FILE_NAME
2044
+ },
2045
+ "/openapi": {
2046
+ type: "openapi",
2047
+ title: "Scalar Galaxy",
2048
+ mode: "flat",
2049
+ filepath: DEFAULT_OPENAPI_FILE_NAME
2050
+ }
2051
+ }
2052
+ }
2053
+ }
2054
+ }
2055
+ });
2056
+ validInput = !!subdomain;
2057
+ const folderName = getCurrentFolderName();
2058
+ while (!validInput) {
2059
+ const response = await text({
2060
+ message: "What is the name of your project?",
2061
+ defaultValue: folderName,
2062
+ placeholder: folderName
2063
+ });
2064
+ if (isCancel(response)) {
2065
+ handleCancel();
2066
+ } else {
2067
+ validInput = true;
2068
+ }
2069
+ const title = response.toString();
2070
+ const slug = slugify(title);
2071
+ configuration.info = { title, description: `Documentation for ${title}` };
2072
+ subdomain = slug;
2073
+ output.info().line(`${as.green("\u2714")} Subdomain: ${as.green(subdomain)}`).print();
2074
+ }
2075
+ configuration.siteConfig.subdomain = subdomain.trim();
2076
+ const content = JSON.stringify(configuration, null, 2);
2077
+ await fs.writeFile(configFile, content);
2078
+ await fs.writeFile(
2079
+ path.join(currentDir, DEFAULT_MARKDOWN_FILE_NAME),
2080
+ quickstartMarkdown
2081
+ );
2082
+ await fs.writeFile(
2083
+ path.join(currentDir, DEFAULT_OPENAPI_FILE_NAME),
2084
+ JSON.stringify(__default, null, 2)
2085
+ );
2086
+ output.info().line(`${as.green("\u2714")} Configuration stored.
2087
+ `).line(`${as.green.bold(`${configFile}`)}
2088
+ `).line(
2089
+ `${as.grey(
2090
+ content.split("\n").map((line) => ` ${line}`).join("\n")
2091
+ )}`
2092
+ ).print();
2093
+ nextSteps();
2094
+ }
2095
+ export {
2096
+ initAction
2097
+ };