@twin.org/api-service 0.0.2-next.7 → 0.0.2-next.9

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.
@@ -22,17 +22,26 @@ const tagsInformation = [
22
22
  function generateRestRoutesInformation(baseRouteName, componentName) {
23
23
  const rootRoute = {
24
24
  operationId: "serverRoot",
25
- summary: "Get the root blank page",
25
+ summary: "Get the root text page",
26
26
  tag: tagsInformation[0].name,
27
27
  method: "GET",
28
28
  path: `${baseRouteName}/`,
29
- handler: async () => ({}),
29
+ handler: async (httpRequestContext, request) => serverRoot(httpRequestContext, componentName),
30
30
  responseType: [
31
31
  {
32
- type: "INoContentResponse"
32
+ type: "IServerRootResponse",
33
+ mimeType: web.MimeTypes.PlainText,
34
+ examples: [
35
+ {
36
+ id: "serverRootResponse",
37
+ description: "The response for the root request.",
38
+ response: {
39
+ body: "API Server - 1.0.0"
40
+ }
41
+ }
42
+ ]
33
43
  }
34
44
  ],
35
- excludeFromSpec: true,
36
45
  skipAuth: true
37
46
  };
38
47
  const informationRoute = {
@@ -61,6 +70,21 @@ function generateRestRoutesInformation(baseRouteName, componentName) {
61
70
  ],
62
71
  skipAuth: true
63
72
  };
73
+ const favIconRoute = {
74
+ operationId: "serverFavIcon",
75
+ summary: "Get the favicon for the server",
76
+ tag: tagsInformation[0].name,
77
+ method: "GET",
78
+ path: `${baseRouteName}/favicon.ico`,
79
+ handler: async (httpRequestContext, request) => serverFavIcon(httpRequestContext, componentName),
80
+ responseType: [
81
+ {
82
+ type: "IServerFavIconResponse",
83
+ mimeType: "image/x-icon"
84
+ }
85
+ ],
86
+ skipAuth: true
87
+ };
64
88
  const healthRoute = {
65
89
  operationId: "serverHealth",
66
90
  summary: "Get the health for the server",
@@ -163,7 +187,20 @@ function generateRestRoutesInformation(baseRouteName, componentName) {
163
187
  ],
164
188
  skipAuth: true
165
189
  };
166
- return [rootRoute, informationRoute, healthRoute, specRoute];
190
+ return [rootRoute, favIconRoute, informationRoute, healthRoute, specRoute];
191
+ }
192
+ /**
193
+ * Get the root for the server.
194
+ * @param httpRequestContext The request context for the API.
195
+ * @param componentName The name of the component to use in the routes.
196
+ * @param request The request.
197
+ * @returns The response object with additional http response properties.
198
+ */
199
+ async function serverRoot(httpRequestContext, componentName, request) {
200
+ const component = core.ComponentFactory.get(componentName);
201
+ return {
202
+ body: await component.root()
203
+ };
167
204
  }
168
205
  /**
169
206
  * Get the information for the server.
@@ -191,6 +228,28 @@ async function serverHealth(httpRequestContext, componentName, request) {
191
228
  body: await component.health()
192
229
  };
193
230
  }
231
+ /**
232
+ * Get the favicon for the server.
233
+ * @param httpRequestContext The request context for the API.
234
+ * @param componentName The name of the component to use in the routes.
235
+ * @param request The request.
236
+ * @returns The response object with additional http response properties.
237
+ */
238
+ async function serverFavIcon(httpRequestContext, componentName, request) {
239
+ const component = core.ComponentFactory.get(componentName);
240
+ const favIcon = await component.favicon();
241
+ if (core.Is.uint8Array(favIcon)) {
242
+ return {
243
+ headers: {
244
+ [web.HeaderTypes.ContentType]: "image/x-icon"
245
+ },
246
+ body: favIcon
247
+ };
248
+ }
249
+ return {
250
+ statusCode: web.HttpStatusCode.notFound
251
+ };
252
+ }
194
253
  /**
195
254
  * Get the spec for the server.
196
255
  * @param httpRequestContext The request context for the API.
@@ -231,6 +290,16 @@ class InformationService {
231
290
  * @internal
232
291
  */
233
292
  _healthInfo;
293
+ /**
294
+ * The path to the favicon Spec.
295
+ * @internal
296
+ */
297
+ _faviconPath;
298
+ /**
299
+ * The favicon.
300
+ * @internal
301
+ */
302
+ _favicon;
234
303
  /**
235
304
  * The path to the OpenAPI Spec.
236
305
  * @internal
@@ -253,6 +322,7 @@ class InformationService {
253
322
  this._healthInfo = {
254
323
  status: "ok"
255
324
  };
325
+ this._faviconPath = options.config.favIconPath;
256
326
  this._openApiSpecPath = options.config.openApiSpecPath;
257
327
  }
258
328
  /**
@@ -260,11 +330,22 @@ class InformationService {
260
330
  * @returns Nothing.
261
331
  */
262
332
  async start() {
263
- const filename = this._openApiSpecPath;
264
- if (core.Is.stringValue(filename)) {
265
- const contentBuffer = await promises.readFile(filename, "utf8");
333
+ const openApiPath = this._openApiSpecPath;
334
+ if (core.Is.stringValue(openApiPath)) {
335
+ const contentBuffer = await promises.readFile(openApiPath, "utf8");
266
336
  this._openApiSpec = JSON.parse(contentBuffer);
267
337
  }
338
+ const favIconPath = this._faviconPath;
339
+ if (core.Is.stringValue(favIconPath)) {
340
+ this._favicon = await promises.readFile(favIconPath);
341
+ }
342
+ }
343
+ /**
344
+ * Get the root information.
345
+ * @returns The root information.
346
+ */
347
+ async root() {
348
+ return `${this._serverInfo.name} - ${this._serverInfo.version}`;
268
349
  }
269
350
  /**
270
351
  * Get the server information.
@@ -273,6 +354,13 @@ class InformationService {
273
354
  async info() {
274
355
  return this._serverInfo;
275
356
  }
357
+ /**
358
+ * Get the favicon.
359
+ * @returns The favicon.
360
+ */
361
+ async favicon() {
362
+ return this._favicon;
363
+ }
276
364
  /**
277
365
  * Get the OpenAPI spec.
278
366
  * @returns The OpenAPI spec.
@@ -351,7 +439,9 @@ const restEntryPoints = [
351
439
  exports.InformationService = InformationService;
352
440
  exports.generateRestRoutesInformation = generateRestRoutesInformation;
353
441
  exports.restEntryPoints = restEntryPoints;
442
+ exports.serverFavIcon = serverFavIcon;
354
443
  exports.serverHealth = serverHealth;
355
444
  exports.serverInfo = serverInfo;
445
+ exports.serverRoot = serverRoot;
356
446
  exports.serverSpec = serverSpec;
357
447
  exports.tagsInformation = tagsInformation;
@@ -1,5 +1,5 @@
1
1
  import { ComponentFactory, Is, Guards } from '@twin.org/core';
2
- import { HttpStatusCode } from '@twin.org/web';
2
+ import { MimeTypes, HeaderTypes, HttpStatusCode } from '@twin.org/web';
3
3
  import { readFile } from 'node:fs/promises';
4
4
 
5
5
  /**
@@ -20,17 +20,26 @@ const tagsInformation = [
20
20
  function generateRestRoutesInformation(baseRouteName, componentName) {
21
21
  const rootRoute = {
22
22
  operationId: "serverRoot",
23
- summary: "Get the root blank page",
23
+ summary: "Get the root text page",
24
24
  tag: tagsInformation[0].name,
25
25
  method: "GET",
26
26
  path: `${baseRouteName}/`,
27
- handler: async () => ({}),
27
+ handler: async (httpRequestContext, request) => serverRoot(httpRequestContext, componentName),
28
28
  responseType: [
29
29
  {
30
- type: "INoContentResponse"
30
+ type: "IServerRootResponse",
31
+ mimeType: MimeTypes.PlainText,
32
+ examples: [
33
+ {
34
+ id: "serverRootResponse",
35
+ description: "The response for the root request.",
36
+ response: {
37
+ body: "API Server - 1.0.0"
38
+ }
39
+ }
40
+ ]
31
41
  }
32
42
  ],
33
- excludeFromSpec: true,
34
43
  skipAuth: true
35
44
  };
36
45
  const informationRoute = {
@@ -59,6 +68,21 @@ function generateRestRoutesInformation(baseRouteName, componentName) {
59
68
  ],
60
69
  skipAuth: true
61
70
  };
71
+ const favIconRoute = {
72
+ operationId: "serverFavIcon",
73
+ summary: "Get the favicon for the server",
74
+ tag: tagsInformation[0].name,
75
+ method: "GET",
76
+ path: `${baseRouteName}/favicon.ico`,
77
+ handler: async (httpRequestContext, request) => serverFavIcon(httpRequestContext, componentName),
78
+ responseType: [
79
+ {
80
+ type: "IServerFavIconResponse",
81
+ mimeType: "image/x-icon"
82
+ }
83
+ ],
84
+ skipAuth: true
85
+ };
62
86
  const healthRoute = {
63
87
  operationId: "serverHealth",
64
88
  summary: "Get the health for the server",
@@ -161,7 +185,20 @@ function generateRestRoutesInformation(baseRouteName, componentName) {
161
185
  ],
162
186
  skipAuth: true
163
187
  };
164
- return [rootRoute, informationRoute, healthRoute, specRoute];
188
+ return [rootRoute, favIconRoute, informationRoute, healthRoute, specRoute];
189
+ }
190
+ /**
191
+ * Get the root for the server.
192
+ * @param httpRequestContext The request context for the API.
193
+ * @param componentName The name of the component to use in the routes.
194
+ * @param request The request.
195
+ * @returns The response object with additional http response properties.
196
+ */
197
+ async function serverRoot(httpRequestContext, componentName, request) {
198
+ const component = ComponentFactory.get(componentName);
199
+ return {
200
+ body: await component.root()
201
+ };
165
202
  }
166
203
  /**
167
204
  * Get the information for the server.
@@ -189,6 +226,28 @@ async function serverHealth(httpRequestContext, componentName, request) {
189
226
  body: await component.health()
190
227
  };
191
228
  }
229
+ /**
230
+ * Get the favicon for the server.
231
+ * @param httpRequestContext The request context for the API.
232
+ * @param componentName The name of the component to use in the routes.
233
+ * @param request The request.
234
+ * @returns The response object with additional http response properties.
235
+ */
236
+ async function serverFavIcon(httpRequestContext, componentName, request) {
237
+ const component = ComponentFactory.get(componentName);
238
+ const favIcon = await component.favicon();
239
+ if (Is.uint8Array(favIcon)) {
240
+ return {
241
+ headers: {
242
+ [HeaderTypes.ContentType]: "image/x-icon"
243
+ },
244
+ body: favIcon
245
+ };
246
+ }
247
+ return {
248
+ statusCode: HttpStatusCode.notFound
249
+ };
250
+ }
192
251
  /**
193
252
  * Get the spec for the server.
194
253
  * @param httpRequestContext The request context for the API.
@@ -229,6 +288,16 @@ class InformationService {
229
288
  * @internal
230
289
  */
231
290
  _healthInfo;
291
+ /**
292
+ * The path to the favicon Spec.
293
+ * @internal
294
+ */
295
+ _faviconPath;
296
+ /**
297
+ * The favicon.
298
+ * @internal
299
+ */
300
+ _favicon;
232
301
  /**
233
302
  * The path to the OpenAPI Spec.
234
303
  * @internal
@@ -251,6 +320,7 @@ class InformationService {
251
320
  this._healthInfo = {
252
321
  status: "ok"
253
322
  };
323
+ this._faviconPath = options.config.favIconPath;
254
324
  this._openApiSpecPath = options.config.openApiSpecPath;
255
325
  }
256
326
  /**
@@ -258,11 +328,22 @@ class InformationService {
258
328
  * @returns Nothing.
259
329
  */
260
330
  async start() {
261
- const filename = this._openApiSpecPath;
262
- if (Is.stringValue(filename)) {
263
- const contentBuffer = await readFile(filename, "utf8");
331
+ const openApiPath = this._openApiSpecPath;
332
+ if (Is.stringValue(openApiPath)) {
333
+ const contentBuffer = await readFile(openApiPath, "utf8");
264
334
  this._openApiSpec = JSON.parse(contentBuffer);
265
335
  }
336
+ const favIconPath = this._faviconPath;
337
+ if (Is.stringValue(favIconPath)) {
338
+ this._favicon = await readFile(favIconPath);
339
+ }
340
+ }
341
+ /**
342
+ * Get the root information.
343
+ * @returns The root information.
344
+ */
345
+ async root() {
346
+ return `${this._serverInfo.name} - ${this._serverInfo.version}`;
266
347
  }
267
348
  /**
268
349
  * Get the server information.
@@ -271,6 +352,13 @@ class InformationService {
271
352
  async info() {
272
353
  return this._serverInfo;
273
354
  }
355
+ /**
356
+ * Get the favicon.
357
+ * @returns The favicon.
358
+ */
359
+ async favicon() {
360
+ return this._favicon;
361
+ }
274
362
  /**
275
363
  * Get the OpenAPI spec.
276
364
  * @returns The OpenAPI spec.
@@ -346,4 +434,4 @@ const restEntryPoints = [
346
434
  }
347
435
  ];
348
436
 
349
- export { InformationService, generateRestRoutesInformation, restEntryPoints, serverHealth, serverInfo, serverSpec, tagsInformation };
437
+ export { InformationService, generateRestRoutesInformation, restEntryPoints, serverFavIcon, serverHealth, serverInfo, serverRoot, serverSpec, tagsInformation };
@@ -1,4 +1,4 @@
1
- import type { IHttpRequestContext, INoContentRequest, IRestRoute, IServerHealthResponse, IServerInfoResponse, IServerSpecResponse, ITag } from "@twin.org/api-models";
1
+ import type { IHttpRequestContext, INoContentRequest, IRestRoute, IServerFavIconResponse, IServerHealthResponse, IServerInfoResponse, IServerRootResponse, IServerSpecResponse, ITag } from "@twin.org/api-models";
2
2
  /**
3
3
  * The tag to associate with the routes.
4
4
  */
@@ -10,6 +10,14 @@ export declare const tagsInformation: ITag[];
10
10
  * @returns The generated routes.
11
11
  */
12
12
  export declare function generateRestRoutesInformation(baseRouteName: string, componentName: string): IRestRoute[];
13
+ /**
14
+ * Get the root for the server.
15
+ * @param httpRequestContext The request context for the API.
16
+ * @param componentName The name of the component to use in the routes.
17
+ * @param request The request.
18
+ * @returns The response object with additional http response properties.
19
+ */
20
+ export declare function serverRoot(httpRequestContext: IHttpRequestContext, componentName: string, request: INoContentRequest): Promise<IServerRootResponse>;
13
21
  /**
14
22
  * Get the information for the server.
15
23
  * @param httpRequestContext The request context for the API.
@@ -26,6 +34,14 @@ export declare function serverInfo(httpRequestContext: IHttpRequestContext, comp
26
34
  * @returns The response object with additional http response properties.
27
35
  */
28
36
  export declare function serverHealth(httpRequestContext: IHttpRequestContext, componentName: string, request: INoContentRequest): Promise<IServerHealthResponse>;
37
+ /**
38
+ * Get the favicon for the server.
39
+ * @param httpRequestContext The request context for the API.
40
+ * @param componentName The name of the component to use in the routes.
41
+ * @param request The request.
42
+ * @returns The response object with additional http response properties.
43
+ */
44
+ export declare function serverFavIcon(httpRequestContext: IHttpRequestContext, componentName: string, request: INoContentRequest): Promise<IServerFavIconResponse>;
29
45
  /**
30
46
  * Get the spec for the server.
31
47
  * @param httpRequestContext The request context for the API.
@@ -18,11 +18,21 @@ export declare class InformationService implements IInformationComponent {
18
18
  * @returns Nothing.
19
19
  */
20
20
  start(): Promise<void>;
21
+ /**
22
+ * Get the root information.
23
+ * @returns The root information.
24
+ */
25
+ root(): Promise<string>;
21
26
  /**
22
27
  * Get the server information.
23
28
  * @returns The service information.
24
29
  */
25
30
  info(): Promise<IServerInfo>;
31
+ /**
32
+ * Get the favicon.
33
+ * @returns The favicon.
34
+ */
35
+ favicon(): Promise<Uint8Array | undefined>;
26
36
  /**
27
37
  * Get the OpenAPI spec.
28
38
  * @returns The OpenAPI spec.
@@ -11,4 +11,8 @@ export interface IInformationServiceConfig {
11
11
  * The path to the OpenAPI Spec.
12
12
  */
13
13
  openApiSpecPath?: string;
14
+ /**
15
+ * The path to the favicon.
16
+ */
17
+ favIconPath?: string;
14
18
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @twin.org/api-service - Changelog
2
2
 
3
+ ## [0.0.2-next.9](https://github.com/twinfoundation/api/compare/api-service-v0.0.2-next.8...api-service-v0.0.2-next.9) (2025-08-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * eslint migration to flat config ([0dd5820](https://github.com/twinfoundation/api/commit/0dd5820e3af97350fd08b8d226f4a6c1a9246805))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/api-models bumped from 0.0.2-next.8 to 0.0.2-next.9
16
+
17
+ ## [0.0.2-next.8](https://github.com/twinfoundation/api/compare/api-service-v0.0.2-next.7...api-service-v0.0.2-next.8) (2025-08-21)
18
+
19
+
20
+ ### Features
21
+
22
+ * add root, favicon routes ([71da1c3](https://github.com/twinfoundation/api/commit/71da1c3a93c349588aff7084d1d8d6a29a277da8))
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @twin.org/api-models bumped from 0.0.2-next.7 to 0.0.2-next.8
30
+
3
31
  ## [0.0.2-next.7](https://github.com/twinfoundation/api/compare/api-service-v0.0.2-next.6...api-service-v0.0.2-next.7) (2025-08-20)
4
32
 
5
33
 
@@ -58,6 +58,24 @@ Nothing.
58
58
 
59
59
  ***
60
60
 
61
+ ### root()
62
+
63
+ > **root**(): `Promise`\<`string`\>
64
+
65
+ Get the root information.
66
+
67
+ #### Returns
68
+
69
+ `Promise`\<`string`\>
70
+
71
+ The root information.
72
+
73
+ #### Implementation of
74
+
75
+ `IInformationComponent.root`
76
+
77
+ ***
78
+
61
79
  ### info()
62
80
 
63
81
  > **info**(): `Promise`\<`IServerInfo`\>
@@ -76,6 +94,24 @@ The service information.
76
94
 
77
95
  ***
78
96
 
97
+ ### favicon()
98
+
99
+ > **favicon**(): `Promise`\<`undefined` \| `Uint8Array`\<`ArrayBufferLike`\>\>
100
+
101
+ Get the favicon.
102
+
103
+ #### Returns
104
+
105
+ `Promise`\<`undefined` \| `Uint8Array`\<`ArrayBufferLike`\>\>
106
+
107
+ The favicon.
108
+
109
+ #### Implementation of
110
+
111
+ `IInformationComponent.favicon`
112
+
113
+ ***
114
+
79
115
  ### spec()
80
116
 
81
117
  > **spec**(): `Promise`\<`unknown`\>
@@ -0,0 +1,31 @@
1
+ # Function: serverFavIcon()
2
+
3
+ > **serverFavIcon**(`httpRequestContext`, `componentName`, `request`): `Promise`\<`IServerFavIconResponse`\>
4
+
5
+ Get the favicon for the server.
6
+
7
+ ## Parameters
8
+
9
+ ### httpRequestContext
10
+
11
+ `IHttpRequestContext`
12
+
13
+ The request context for the API.
14
+
15
+ ### componentName
16
+
17
+ `string`
18
+
19
+ The name of the component to use in the routes.
20
+
21
+ ### request
22
+
23
+ `INoContentRequest`
24
+
25
+ The request.
26
+
27
+ ## Returns
28
+
29
+ `Promise`\<`IServerFavIconResponse`\>
30
+
31
+ The response object with additional http response properties.
@@ -0,0 +1,31 @@
1
+ # Function: serverRoot()
2
+
3
+ > **serverRoot**(`httpRequestContext`, `componentName`, `request`): `Promise`\<`IServerRootResponse`\>
4
+
5
+ Get the root for the server.
6
+
7
+ ## Parameters
8
+
9
+ ### httpRequestContext
10
+
11
+ `IHttpRequestContext`
12
+
13
+ The request context for the API.
14
+
15
+ ### componentName
16
+
17
+ `string`
18
+
19
+ The name of the component to use in the routes.
20
+
21
+ ### request
22
+
23
+ `INoContentRequest`
24
+
25
+ The request.
26
+
27
+ ## Returns
28
+
29
+ `Promise`\<`IServerRootResponse`\>
30
+
31
+ The response object with additional http response properties.
@@ -17,6 +17,8 @@
17
17
  ## Functions
18
18
 
19
19
  - [generateRestRoutesInformation](functions/generateRestRoutesInformation.md)
20
+ - [serverRoot](functions/serverRoot.md)
20
21
  - [serverInfo](functions/serverInfo.md)
21
22
  - [serverHealth](functions/serverHealth.md)
23
+ - [serverFavIcon](functions/serverFavIcon.md)
22
24
  - [serverSpec](functions/serverSpec.md)
@@ -17,3 +17,11 @@ The server information.
17
17
  > `optional` **openApiSpecPath**: `string`
18
18
 
19
19
  The path to the OpenAPI Spec.
20
+
21
+ ***
22
+
23
+ ### favIconPath?
24
+
25
+ > `optional` **favIconPath**: `string`
26
+
27
+ The path to the favicon.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/api-service",
3
- "version": "0.0.2-next.7",
3
+ "version": "0.0.2-next.9",
4
4
  "description": "Information contract implementation and REST endpoint definitions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/api-models": "0.0.2-next.7",
17
+ "@twin.org/api-models": "0.0.2-next.9",
18
18
  "@twin.org/core": "next",
19
19
  "@twin.org/nameof": "next",
20
20
  "@twin.org/web": "next"