c8y-nitro 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/{cli/commands/bootstrap.mjs → bootstrap-BqWPkH8q.mjs} +5 -8
  2. package/dist/{cli/utils/c8y-api.mjs → c8y-api-BBSKRwKs.mjs} +73 -3
  3. package/dist/cli/index.mjs +5 -7
  4. package/dist/{cli/utils/config.mjs → config-Dqi-ttQi.mjs} +1 -3
  5. package/dist/{cli/utils/env-file.mjs → env-file-B0BK-uZW.mjs} +1 -3
  6. package/dist/{types/manifest.d.mts → index-CzUqbp5C.d.mts} +94 -1
  7. package/dist/index.d.mts +1 -1
  8. package/dist/index.mjs +549 -14
  9. package/dist/{cli/commands/options.mjs → options-BDDJWdph.mjs} +3 -6
  10. package/dist/{package.mjs → package-CobwNpP9.mjs} +2 -3
  11. package/dist/{cli/commands/roles.mjs → roles-DJxp2d8p.mjs} +3 -6
  12. package/dist/runtime/handlers/liveness-readiness.mjs +7 -0
  13. package/dist/runtime/middlewares/dev-user.mjs +23 -0
  14. package/dist/runtime/plugins/c8y-variables.mjs +17 -0
  15. package/dist/runtime/plugins/enrich-logs.mjs +15 -0
  16. package/dist/types.d.mts +2 -25
  17. package/dist/types.mjs +1 -1
  18. package/dist/utils.d.mts +292 -6
  19. package/dist/utils.mjs +444 -8
  20. package/package.json +12 -11
  21. package/dist/module/apiClient.mjs +0 -207
  22. package/dist/module/autoBootstrap.mjs +0 -54
  23. package/dist/module/c8yzip.mjs +0 -66
  24. package/dist/module/constants.mjs +0 -6
  25. package/dist/module/docker.mjs +0 -101
  26. package/dist/module/manifest.mjs +0 -72
  27. package/dist/module/probeCheck.mjs +0 -30
  28. package/dist/module/register.mjs +0 -58
  29. package/dist/module/runtime/handlers/liveness-readiness.ts +0 -7
  30. package/dist/module/runtime/middlewares/dev-user.ts +0 -25
  31. package/dist/module/runtime/plugins/c8y-variables.ts +0 -24
  32. package/dist/module/runtime.mjs +0 -38
  33. package/dist/module/runtimeConfig.mjs +0 -20
  34. package/dist/types/apiClient.d.mts +0 -16
  35. package/dist/types/cache.d.mts +0 -28
  36. package/dist/types/roles.d.mts +0 -4
  37. package/dist/types/tenantOptions.d.mts +0 -13
  38. package/dist/types/zip.d.mts +0 -22
  39. package/dist/utils/client.d.mts +0 -52
  40. package/dist/utils/client.mjs +0 -90
  41. package/dist/utils/credentials.d.mts +0 -71
  42. package/dist/utils/credentials.mjs +0 -120
  43. package/dist/utils/internal/common.mjs +0 -26
  44. package/dist/utils/logging.d.mts +0 -3
  45. package/dist/utils/logging.mjs +0 -4
  46. package/dist/utils/middleware.d.mts +0 -89
  47. package/dist/utils/middleware.mjs +0 -62
  48. package/dist/utils/resources.d.mts +0 -30
  49. package/dist/utils/resources.mjs +0 -49
  50. package/dist/utils/tenantOptions.d.mts +0 -65
  51. package/dist/utils/tenantOptions.mjs +0 -127
@@ -1,38 +0,0 @@
1
- import { join } from "pathe";
2
- import { mkdirSync, writeFileSync } from "fs";
3
-
4
- //#region src/module/runtime.ts
5
- function setupRuntime(nitro, manifestOptions = {}) {
6
- nitro.logger.debug("Setting up C8Y nitro runtime");
7
- const roles = manifestOptions.roles ?? [];
8
- const settingKeys = (manifestOptions.settings ?? []).map((s) => s.key);
9
- const completeTypesDir = join(nitro.options.rootDir, nitro.options.typescript.generatedTypesDir ?? "node_modules/.nitro/types");
10
- const typesFile = join(completeTypesDir, "c8y-nitro.d.ts");
11
- const typesContent = `// generated by c8y-nitro
12
- declare module 'c8y-nitro/types' {
13
- interface C8YRoles {
14
- ${roles.map((role) => ` '${role}': '${role}';`).join("\n")}
15
- }
16
- type C8YTenantOptionKey = ${settingKeys.length > 0 ? `${settingKeys.map((k) => `'${k}'`).join(" | ")}` : "never"}
17
- type C8YTenantOptionKeysCacheConfig = Partial<Record<C8YTenantOptionKey, number>>;
18
- }
19
-
20
- declare module 'c8y-nitro/runtime' {
21
- import type { C8YRoles } from 'c8y-nitro/types';
22
- export const c8yRoles: C8YRoles;
23
- export const c8yTenantOptionKeys: readonly [${settingKeys.map((key) => `'${key}'`).join(", ")}];
24
- }`;
25
- nitro.options.virtual["c8y-nitro/runtime"] = `
26
- export const c8yRoles = {
27
- ${roles.map((role) => ` '${role}': '${role}',`).join("\n")}
28
- }
29
-
30
- export const c8yTenantOptionKeys = [${settingKeys.map((key) => `'${key}'`).join(", ")}]
31
- `;
32
- mkdirSync(completeTypesDir, { recursive: true });
33
- writeFileSync(typesFile, typesContent, { encoding: "utf-8" });
34
- nitro.logger.debug(`Written C8Y types to ${typesFile}`);
35
- }
36
-
37
- //#endregion
38
- export { setupRuntime };
@@ -1,20 +0,0 @@
1
- import { createC8yManifest } from "./manifest.mjs";
2
-
3
- //#region src/module/runtimeConfig.ts
4
- /**
5
- * Sets up runtime configuration values from module options.
6
- * These can be overridden by environment variables.
7
- * @param nitro - The Nitro instance
8
- * @param options - The c8y-nitro module options
9
- */
10
- async function setupRuntimeConfig(nitro, options) {
11
- nitro.logger.debug("Setting up C8Y runtime config");
12
- nitro.options.runtimeConfig.c8yCredentialsCacheTTL = options.cache?.credentialsTTL ?? 600;
13
- nitro.options.runtimeConfig.c8yDefaultTenantOptionsTTL = options.cache?.defaultTenantOptionsTTL ?? 600;
14
- nitro.options.runtimeConfig.c8yTenantOptionsPerKeyTTL = options.cache?.tenantOptions ?? {};
15
- const manifest = await createC8yManifest(nitro.options.rootDir, options.manifest, nitro.logger);
16
- nitro.options.runtimeConfig.c8ySettingsCategory = options.manifest?.settingsCategory ?? manifest.contextPath ?? manifest.name;
17
- }
18
-
19
- //#endregion
20
- export { setupRuntimeConfig };
@@ -1,16 +0,0 @@
1
- //#region src/types/apiClient.d.ts
2
- interface C8YAPIClientOptions {
3
- /**
4
- * Relative directory from nitro configuration file to generate the API client into.
5
- */
6
- dir: string;
7
- /**
8
- * Service context path for microservice endpoints.\
9
- * Defaults to contextPath from manifest (package.json name, with scope stripped).\
10
- * Override this if deploying with a different context path.
11
- * @example "my-microservice" results in "https://<tenant>.com/service/my-microservice/..."
12
- */
13
- contextPath?: string;
14
- }
15
- //#endregion
16
- export { C8YAPIClientOptions };
@@ -1,28 +0,0 @@
1
- import { C8YTenantOptionKeysCacheConfig } from "c8y-nitro/types";
2
-
3
- //#region src/types/cache.d.ts
4
- interface C8yCacheOptions {
5
- /**
6
- * Cache TTL for subscribed tenant credentials in seconds.
7
- * @default 600 (10 minutes)
8
- */
9
- credentialsTTL?: number;
10
- /**
11
- * Default cache TTL for tenant options in seconds.
12
- * Applied to all keys unless overridden in `tenantOptions`.
13
- * @default 600 (10 minutes)
14
- */
15
- defaultTenantOptionsTTL?: number;
16
- /**
17
- * Per-key cache TTL overrides for tenant options in seconds.
18
- * Keys should match those defined in `manifest.settings[].key`.
19
- * @example
20
- * {
21
- * 'myOption': 300, // 5 minutes
22
- * 'credentials.secret': 60, // 1 minute
23
- * }
24
- */
25
- tenantOptions?: C8YTenantOptionKeysCacheConfig;
26
- }
27
- //#endregion
28
- export { C8yCacheOptions };
@@ -1,4 +0,0 @@
1
- //#region src/types/roles.d.ts
2
- interface C8YRoles {}
3
- //#endregion
4
- export { C8YRoles };
@@ -1,13 +0,0 @@
1
- //#region src/types/tenantOptions.d.ts
2
- /**
3
- * Per-key cache TTL configuration for tenant options.
4
- * Overwritten by generated types from manifest settings (manifest.settings[].key).
5
- */
6
- type C8YTenantOptionKeysCacheConfig = Partial<Record<C8YTenantOptionKey, number>>;
7
- /**
8
- * Type for tenant option keys.
9
- * Overwritten by generated types from manifest settings (manifest.settings[].key).
10
- */
11
- type C8YTenantOptionKey = string;
12
- //#endregion
13
- export { C8YTenantOptionKey, C8YTenantOptionKeysCacheConfig };
@@ -1,22 +0,0 @@
1
- import { C8YManifestOptions } from "./manifest.mjs";
2
-
3
- //#region src/types/zip.d.ts
4
- interface C8YZipOptions {
5
- /**
6
- * Name of the generated zip file
7
- * @default '${packageName}-${version}.zip'
8
- */
9
- name?: string | ((packageName: string, version: string) => string);
10
- /**
11
- * Output directory for the generated zip file.\
12
- * Relative to the config file.
13
- * @default './'
14
- */
15
- outputDir?: string;
16
- /**
17
- * Configuration of the "cumulocity.json" manifest file used for the zip.
18
- */
19
- manifest?: C8YManifestOptions;
20
- }
21
- //#endregion
22
- export { C8YZipOptions };
@@ -1,52 +0,0 @@
1
- import { Client } from "@c8y/client";
2
- import { H3Event } from "nitro/h3";
3
- import { ServerRequest } from "nitro/types";
4
-
5
- //#region src/utils/client.d.ts
6
- /**
7
- * Creates a Cumulocity client authenticated with the current user's credentials.\
8
- * Extracts credentials from the Authorization header of the current request.
9
- * @param requestOrEvent - The H3Event or ServerRequest from the current request
10
- * @returns A configured Cumulocity Client instance
11
- * @example
12
- * // In a request handler:
13
- * const client = useUserClient(event)
14
- * const { data } = await client.inventory.list()
15
- */
16
- declare function useUserClient(requestOrEvent: ServerRequest | H3Event): Client;
17
- /**
18
- * Creates a Cumulocity client for the tenant of the current user.\
19
- * Uses the tenant's service user credentials rather than the user's own credentials.
20
- * @param requestOrEvent - The H3Event or ServerRequest from the current request
21
- * @returns A configured Cumulocity Client instance for the user's tenant
22
- * @example
23
- * // In a request handler:
24
- * const tenantClient = await useUserTenantClient(event)
25
- * const { data } = await tenantClient.inventory.list()
26
- */
27
- declare function useUserTenantClient(requestOrEvent: ServerRequest | H3Event): Promise<Client>;
28
- /**
29
- * Creates Cumulocity clients for all tenants subscribed to this microservice.\
30
- * Each client is authenticated with that tenant's service user credentials.\
31
- * @returns Object mapping tenant IDs to their respective Client instances
32
- * @example
33
- * // Get clients for all subscribed tenants:
34
- * const clients = await useSubscribedTenantClients()
35
- * for (const [tenant, client] of Object.entries(clients)) {
36
- * const { data } = await client.inventory.list()
37
- * console.log(`Tenant ${tenant} has ${data.length} inventory items`)
38
- * }
39
- */
40
- declare function useSubscribedTenantClients(): Promise<Record<string, Client>>;
41
- /**
42
- * Creates a Cumulocity client for the tenant where this microservice is deployed.\
43
- * Uses the bootstrap tenant ID from runtime config to identify the deployed tenant.\
44
- * @returns A configured Cumulocity Client instance for the deployed tenant
45
- * @example
46
- * // Get client for the tenant hosting this microservice:
47
- * const client = await useDeployedTenantClient()
48
- * const { data } = await client.application.list()
49
- */
50
- declare function useDeployedTenantClient(): Promise<Client>;
51
- //#endregion
52
- export { useDeployedTenantClient, useSubscribedTenantClients, useUserClient, useUserTenantClient };
@@ -1,90 +0,0 @@
1
- import { convertRequestHeadersToC8yFormat } from "./internal/common.mjs";
2
- import { useSubscribedTenantCredentials } from "./credentials.mjs";
3
- import process from "node:process";
4
- import { BasicAuth, Client, MicroserviceClientRequestAuth } from "@c8y/client";
5
- import { HTTPError } from "nitro/h3";
6
-
7
- //#region src/utils/client.ts
8
- /**
9
- * Creates a Cumulocity client authenticated with the current user's credentials.\
10
- * Extracts credentials from the Authorization header of the current request.
11
- * @param requestOrEvent - The H3Event or ServerRequest from the current request
12
- * @returns A configured Cumulocity Client instance
13
- * @example
14
- * // In a request handler:
15
- * const client = useUserClient(event)
16
- * const { data } = await client.inventory.list()
17
- */
18
- function useUserClient(requestOrEvent) {
19
- const request = "req" in requestOrEvent ? requestOrEvent.req : requestOrEvent;
20
- if (request.context?.["c8y_user_client"]) return request.context["c8y_user_client"];
21
- const client = new Client(new MicroserviceClientRequestAuth(convertRequestHeadersToC8yFormat(request)), process.env.C8Y_BASEURL);
22
- request.context ??= {};
23
- request.context["c8y_user_client"] = client;
24
- return client;
25
- }
26
- /**
27
- * Creates a Cumulocity client for the tenant of the current user.\
28
- * Uses the tenant's service user credentials rather than the user's own credentials.
29
- * @param requestOrEvent - The H3Event or ServerRequest from the current request
30
- * @returns A configured Cumulocity Client instance for the user's tenant
31
- * @example
32
- * // In a request handler:
33
- * const tenantClient = await useUserTenantClient(event)
34
- * const { data } = await tenantClient.inventory.list()
35
- */
36
- async function useUserTenantClient(requestOrEvent) {
37
- const request = "req" in requestOrEvent ? requestOrEvent.req : requestOrEvent;
38
- if (request.context?.["c8y_user_tenant_client"]) return request.context["c8y_user_tenant_client"];
39
- const tenantId = useUserClient(requestOrEvent).core.tenant;
40
- const creds = await useSubscribedTenantCredentials();
41
- if (!creds[tenantId]) throw new HTTPError({
42
- message: `No subscribed tenant credentials found for user tenant '${tenantId}'`,
43
- status: 500,
44
- statusText: "Internal Server Error"
45
- });
46
- const tenantClient = new Client(new BasicAuth(creds[tenantId]), process.env.C8Y_BASEURL);
47
- request.context ??= {};
48
- request.context["c8y_user_tenant_client"] = tenantClient;
49
- return tenantClient;
50
- }
51
- /**
52
- * Creates Cumulocity clients for all tenants subscribed to this microservice.\
53
- * Each client is authenticated with that tenant's service user credentials.\
54
- * @returns Object mapping tenant IDs to their respective Client instances
55
- * @example
56
- * // Get clients for all subscribed tenants:
57
- * const clients = await useSubscribedTenantClients()
58
- * for (const [tenant, client] of Object.entries(clients)) {
59
- * const { data } = await client.inventory.list()
60
- * console.log(`Tenant ${tenant} has ${data.length} inventory items`)
61
- * }
62
- */
63
- async function useSubscribedTenantClients() {
64
- const creds = await useSubscribedTenantCredentials();
65
- const clients = {};
66
- for (const [tenant, tenantCreds] of Object.entries(creds)) clients[tenant] = new Client(new BasicAuth(tenantCreds), process.env.C8Y_BASEURL);
67
- return clients;
68
- }
69
- /**
70
- * Creates a Cumulocity client for the tenant where this microservice is deployed.\
71
- * Uses the bootstrap tenant ID from runtime config to identify the deployed tenant.\
72
- * @returns A configured Cumulocity Client instance for the deployed tenant
73
- * @example
74
- * // Get client for the tenant hosting this microservice:
75
- * const client = await useDeployedTenantClient()
76
- * const { data } = await client.application.list()
77
- */
78
- async function useDeployedTenantClient() {
79
- const creds = await useSubscribedTenantCredentials();
80
- const tenant = process.env.C8Y_BOOTSTRAP_TENANT;
81
- if (!creds[tenant]) throw new HTTPError({
82
- message: `No subscribed tenant credentials found for tenant '${tenant}'`,
83
- status: 500,
84
- statusText: "Internal Server Error"
85
- });
86
- return new Client(new BasicAuth(creds[tenant]), process.env.C8Y_BASEURL);
87
- }
88
-
89
- //#endregion
90
- export { useDeployedTenantClient, useSubscribedTenantClients, useUserClient, useUserTenantClient };
@@ -1,71 +0,0 @@
1
- import { ICredentials } from "@c8y/client";
2
- import { H3Event } from "nitro/h3";
3
- import { ServerRequest } from "nitro/types";
4
-
5
- //#region src/utils/credentials.d.ts
6
- /**
7
- * Fetches credentials for all tenants subscribed to this microservice.\
8
- * Uses bootstrap credentials from runtime config to query the microservice subscriptions API.\
9
- * Results are cached based on the configured TTL (default: 10 minutes).\
10
- * @returns Object mapping tenant IDs to their respective credentials
11
- * @config Cache TTL can be configured via:
12
- * - `c8y.cache.credentialsTTL` in the Nitro config (value in seconds)
13
- * - `NITRO_C8Y_CACHE_CREDENTIALS_TTL` environment variable
14
- * @example
15
- * // Get all subscribed tenant credentials:
16
- * const credentials = await useSubscribedTenantCredentials()
17
- * console.log(Object.keys(credentials)) // ['t12345', 't67890']
18
- *
19
- * // Access specific tenant:
20
- * const tenant1Creds = credentials['t12345']
21
- *
22
- * // Invalidate cache:
23
- * await useSubscribedTenantCredentials.invalidate()
24
- *
25
- * // Force refresh:
26
- * const freshCreds = await useSubscribedTenantCredentials.refresh()
27
- */
28
- declare const useSubscribedTenantCredentials: (() => Promise<Record<string, ICredentials>>) & {
29
- invalidate: () => Promise<void>;
30
- refresh: () => Promise<Record<string, ICredentials>>;
31
- };
32
- /**
33
- * Fetches credentials for the tenant where this microservice is deployed.\
34
- * Uses the C8Y_BOOTSTRAP_TENANT environment variable to identify the deployed tenant.\
35
- * Returns credentials from the subscribed tenant credentials cache (cached based on configured TTL, default: 10 minutes).
36
- * @returns Credentials for the deployed tenant
37
- * @throws {HTTPError} If no credentials found for the deployed tenant
38
- * @example
39
- * // Get deployed tenant credentials:
40
- * const creds = await useDeployedTenantCredentials()
41
- * console.log(creds.tenant, creds.user)
42
- *
43
- * // Invalidate cache:
44
- * await useDeployedTenantCredentials.invalidate()
45
- *
46
- * // Force refresh:
47
- * const freshCreds = await useDeployedTenantCredentials.refresh()
48
- * @note This function is not cached separately. It uses the cache of `useSubscribedTenantCredentials()`. Invalidating or refreshing one will refresh `useDeployedTenantCredentials()`s cache.
49
- */
50
- declare const useDeployedTenantCredentials: (() => Promise<ICredentials>) & {
51
- invalidate: () => Promise<void>;
52
- refresh: () => Promise<ICredentials>;
53
- };
54
- /**
55
- * Fetches credentials for the tenant of the current user making the request.\
56
- * Extracts the user's tenant ID from the request headers and returns corresponding credentials.\
57
- * Results are cached in the request context for subsequent calls within the same request.
58
- * @param requestOrEvent - The H3Event or ServerRequest from the current request
59
- * @returns Credentials for the user's tenant
60
- * @throws {HTTPError} If no subscribed tenant credentials found for the user's tenant
61
- * @example
62
- * // In a request handler:
63
- * const userCreds = await useUserTenantCredentials(event)
64
- * console.log(userCreds.tenant, userCreds.user)
65
- *
66
- * // Credentials are automatically cached for the request duration
67
- * const sameCreds = await useUserTenantCredentials(event) // Uses cached value
68
- */
69
- declare function useUserTenantCredentials(requestOrEvent: ServerRequest | H3Event): Promise<ICredentials>;
70
- //#endregion
71
- export { useDeployedTenantCredentials, useSubscribedTenantCredentials, useUserTenantCredentials };
@@ -1,120 +0,0 @@
1
- import { useUserClient } from "./client.mjs";
2
- import process from "node:process";
3
- import { Client } from "@c8y/client";
4
- import { defineCachedFunction } from "nitro/cache";
5
- import { HTTPError } from "nitro/h3";
6
- import { useStorage } from "nitro/storage";
7
- import { useRuntimeConfig } from "nitro/runtime-config";
8
-
9
- //#region src/utils/credentials.ts
10
- /**
11
- * Fetches credentials for all tenants subscribed to this microservice.\
12
- * Uses bootstrap credentials from runtime config to query the microservice subscriptions API.\
13
- * Results are cached based on the configured TTL (default: 10 minutes).\
14
- * @returns Object mapping tenant IDs to their respective credentials
15
- * @config Cache TTL can be configured via:
16
- * - `c8y.cache.credentialsTTL` in the Nitro config (value in seconds)
17
- * - `NITRO_C8Y_CACHE_CREDENTIALS_TTL` environment variable
18
- * @example
19
- * // Get all subscribed tenant credentials:
20
- * const credentials = await useSubscribedTenantCredentials()
21
- * console.log(Object.keys(credentials)) // ['t12345', 't67890']
22
- *
23
- * // Access specific tenant:
24
- * const tenant1Creds = credentials['t12345']
25
- *
26
- * // Invalidate cache:
27
- * await useSubscribedTenantCredentials.invalidate()
28
- *
29
- * // Force refresh:
30
- * const freshCreds = await useSubscribedTenantCredentials.refresh()
31
- */
32
- const useSubscribedTenantCredentials = Object.assign(defineCachedFunction(async () => {
33
- return (await Client.getMicroserviceSubscriptions({
34
- tenant: process.env.C8Y_BOOTSTRAP_TENANT,
35
- user: process.env.C8Y_BOOTSTRAP_USER,
36
- password: process.env.C8Y_BOOTSTRAP_PASSWORD
37
- }, process.env.C8Y_BASEURL)).reduce((acc, cred) => {
38
- if (cred.tenant) acc[cred.tenant] = cred;
39
- return acc;
40
- }, {});
41
- }, {
42
- maxAge: useRuntimeConfig().c8yCredentialsCacheTTL ?? 600,
43
- name: "_c8y_nitro_get_subscribed_tenant_credentials",
44
- group: "c8y_nitro",
45
- swr: false
46
- }), {
47
- invalidate: async () => {
48
- await useStorage("cache").removeItem(`c8y_nitro:functions:_c8y_nitro_get_subscribed_tenant_credentials.json`);
49
- },
50
- refresh: async () => {
51
- await useSubscribedTenantCredentials.invalidate();
52
- return await useSubscribedTenantCredentials();
53
- }
54
- });
55
- /**
56
- * Fetches credentials for the tenant where this microservice is deployed.\
57
- * Uses the C8Y_BOOTSTRAP_TENANT environment variable to identify the deployed tenant.\
58
- * Returns credentials from the subscribed tenant credentials cache (cached based on configured TTL, default: 10 minutes).
59
- * @returns Credentials for the deployed tenant
60
- * @throws {HTTPError} If no credentials found for the deployed tenant
61
- * @example
62
- * // Get deployed tenant credentials:
63
- * const creds = await useDeployedTenantCredentials()
64
- * console.log(creds.tenant, creds.user)
65
- *
66
- * // Invalidate cache:
67
- * await useDeployedTenantCredentials.invalidate()
68
- *
69
- * // Force refresh:
70
- * const freshCreds = await useDeployedTenantCredentials.refresh()
71
- * @note This function is not cached separately. It uses the cache of `useSubscribedTenantCredentials()`. Invalidating or refreshing one will refresh `useDeployedTenantCredentials()`s cache.
72
- */
73
- const useDeployedTenantCredentials = Object.assign(async () => {
74
- const tenant = process.env.C8Y_BOOTSTRAP_TENANT;
75
- const allCredsPromise = await useSubscribedTenantCredentials();
76
- if (!allCredsPromise[tenant]) throw new HTTPError({
77
- message: `No credentials found for tenant deployed tenant '${tenant}'`,
78
- status: 500,
79
- statusText: "Internal Server Error"
80
- });
81
- return allCredsPromise[tenant];
82
- }, {
83
- invalidate: useSubscribedTenantCredentials.invalidate,
84
- refresh: async () => {
85
- await useDeployedTenantCredentials.invalidate();
86
- return await useDeployedTenantCredentials();
87
- }
88
- });
89
- /**
90
- * Fetches credentials for the tenant of the current user making the request.\
91
- * Extracts the user's tenant ID from the request headers and returns corresponding credentials.\
92
- * Results are cached in the request context for subsequent calls within the same request.
93
- * @param requestOrEvent - The H3Event or ServerRequest from the current request
94
- * @returns Credentials for the user's tenant
95
- * @throws {HTTPError} If no subscribed tenant credentials found for the user's tenant
96
- * @example
97
- * // In a request handler:
98
- * const userCreds = await useUserTenantCredentials(event)
99
- * console.log(userCreds.tenant, userCreds.user)
100
- *
101
- * // Credentials are automatically cached for the request duration
102
- * const sameCreds = await useUserTenantCredentials(event) // Uses cached value
103
- */
104
- async function useUserTenantCredentials(requestOrEvent) {
105
- const request = "req" in requestOrEvent ? requestOrEvent.req : requestOrEvent;
106
- if (request.context?.["c8y_user_tenant_credentials"]) return request.context["c8y_user_tenant_credentials"];
107
- const tenantId = useUserClient(requestOrEvent).core.tenant;
108
- const userTenantCreds = (await useSubscribedTenantCredentials())[tenantId];
109
- if (!userTenantCreds) throw new HTTPError({
110
- message: `No subscribed tenant credentials found for user tenant '${tenantId}'`,
111
- status: 500,
112
- statusText: "Internal Server Error"
113
- });
114
- request.context ??= {};
115
- request.context["c8y_user_tenant_credentials"] = userTenantCreds;
116
- return userTenantCreds;
117
- }
118
-
119
- //#endregion
120
- export { useDeployedTenantCredentials, useSubscribedTenantCredentials, useUserTenantCredentials };
@@ -1,26 +0,0 @@
1
- //#region src/utils/internal/common.ts
2
- /**
3
- * Converts undici Request headers to the format expected by MicroserviceClientRequestAuth.\
4
- * Extracts the following headers from the request:
5
- * - `authorization`: Used for Basic Auth or Bearer token authentication
6
- * - `cookie`: Used to extract XSRF-TOKEN and authorization token from cookies
7
- *
8
- * The MicroserviceClientRequestAuth class will automatically:
9
- * - Extract XSRF-TOKEN from cookies for CSRF protection
10
- * - Extract authorization token from cookies (prioritized over header auth)
11
- * - Fall back to Authorization header if no cookie-based auth is present
12
- *
13
- * @param request - The HTTP request containing headers
14
- * @returns Headers object compatible with \@c8y/client's MicroserviceClientRequestAuth
15
- */
16
- function convertRequestHeadersToC8yFormat(request) {
17
- const headers = {};
18
- const authorization = request.headers.get("authorization");
19
- if (authorization) headers.authorization = authorization;
20
- const cookie = request.headers.get("cookie");
21
- if (cookie) headers.cookie = cookie;
22
- return headers;
23
- }
24
-
25
- //#endregion
26
- export { convertRequestHeadersToC8yFormat };
@@ -1,3 +0,0 @@
1
- import { useLogger } from "evlog/nitro/v3";
2
- import { createError, createLogger } from "evlog";
3
- export { createError, createLogger, useLogger };
@@ -1,4 +0,0 @@
1
- import { useLogger } from "evlog/nitro/v3";
2
- import { createError, createLogger } from "evlog";
3
-
4
- export { createError, createLogger, useLogger };
@@ -1,89 +0,0 @@
1
- import { EventHandler } from "nitro/h3";
2
- import { C8YRoles } from "c8y-nitro/types";
3
-
4
- //#region src/utils/middleware.d.ts
5
- type UserRole = keyof C8YRoles | (string & {});
6
- /**
7
- * Middleware to check if the current user has the required role.\
8
- * If the user doesn't have the required role, throws a 403 Forbidden error.\
9
- * Must be used within a request handler context.\
10
- * @param role - Single role ID to check for
11
- * @returns Event handler that validates user roles
12
- * @example
13
- * // Single role:
14
- * export default defineHandler({
15
- * middleware: [hasUserRequiredRole('ROLE_INVENTORY_ADMIN')],
16
- * handler: async () => {
17
- * return { message: 'You have access' }
18
- * }
19
- * })
20
- *
21
- */
22
- declare function hasUserRequiredRole(role: UserRole): EventHandler;
23
- /**
24
- * Middleware to check if the current user has at least one of the required roles.\
25
- * If the user doesn't have any of the required roles, throws a 403 Forbidden error.\
26
- * Must be used within a request handler context.\
27
- * @param roles - Array of role IDs to check for
28
- * @returns Event handler that validates user roles
29
- * @example
30
- * // Multiple roles:
31
- * export default defineHandler({
32
- * middleware: [hasUserRequiredRole(['ROLE_INVENTORY_ADMIN', 'ROLE_DEVICE_CONTROL'])],
33
- * handler: async () => {
34
- * return { message: 'You have access' }
35
- * }
36
- * })
37
- */
38
- declare function hasUserRequiredRole(roles: UserRole[]): EventHandler;
39
- /**
40
- * Middleware to check if the current user belongs to a specific allowed tenant.\
41
- * If the user's tenant doesn't match, throws a 403 Forbidden error.\
42
- * Must be used within a request handler context.\
43
- * @param tenantId - Single tenant ID to allow
44
- * @returns Event handler that validates user tenant
45
- * @example
46
- * // Single tenant:
47
- * export default defineHandler({
48
- * middleware: [isUserFromAllowedTenant('t123456')],
49
- * handler: async () => {
50
- * return { message: 'You have access' }
51
- * }
52
- * })
53
- *
54
- */
55
- declare function isUserFromAllowedTenant(tenantId: string): EventHandler;
56
- /**
57
- * Middleware to check if the current user belongs to one of the allowed tenants.\
58
- * If the user's tenant doesn't match any of the allowed tenants, throws a 403 Forbidden error.\
59
- * Must be used within a request handler context.\
60
- * @param tenantIds - Array of tenant IDs to allow
61
- * @returns Event handler that validates user tenant
62
- * @example
63
- * // Multiple tenants:
64
- * export default defineHandler({
65
- * middleware: [isUserFromAllowedTenant(['t123456', 't789012'])],
66
- * handler: async () => {
67
- * return { message: 'You have access' }
68
- * }
69
- * })
70
- */
71
- declare function isUserFromAllowedTenant(tenantIds: string[]): EventHandler;
72
- /**
73
- * Middleware to check if the current user belongs to the deployed tenant.\
74
- * The deployed tenant is where this microservice is hosted (C8Y_BOOTSTRAP_TENANT).\
75
- * If the user's tenant doesn't match the deployed tenant, throws a 403 Forbidden error.\
76
- * Must be used within a request handler context.\
77
- * @returns Event handler that validates user is from deployed tenant
78
- * @example
79
- * // Only allow users from the deployed tenant:
80
- * export default defineHandler({
81
- * middleware: [isUserFromDeployedTenant()],
82
- * handler: async () => {
83
- * return { message: 'You have access' }
84
- * }
85
- * })
86
- */
87
- declare function isUserFromDeployedTenant(): EventHandler;
88
- //#endregion
89
- export { hasUserRequiredRole, isUserFromAllowedTenant, isUserFromDeployedTenant };