@carlonicora/nextjs-jsonapi 1.25.1 → 1.27.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.
- package/dist/{BlockNoteEditor-7WAWEZVW.js → BlockNoteEditor-5NYZBYPY.js} +13 -13
- package/dist/{BlockNoteEditor-7WAWEZVW.js.map → BlockNoteEditor-5NYZBYPY.js.map} +1 -1
- package/dist/{BlockNoteEditor-UNVKGZ2G.mjs → BlockNoteEditor-B6K7OEN6.mjs} +3 -3
- package/dist/billing/index.js +342 -342
- package/dist/billing/index.mjs +2 -2
- package/dist/{chunk-O3LLMGP7.js → chunk-2VZZFQP4.js} +74 -63
- package/dist/chunk-2VZZFQP4.js.map +1 -0
- package/dist/{chunk-LNBT2YPZ.mjs → chunk-NAB52T2P.mjs} +20 -9
- package/dist/chunk-NAB52T2P.mjs.map +1 -0
- package/dist/{chunk-6BDOZDZ3.mjs → chunk-RU4GQIB6.mjs} +1924 -1742
- package/dist/chunk-RU4GQIB6.mjs.map +1 -0
- package/dist/{chunk-JI6BDV7L.js → chunk-ZR26XYRO.js} +885 -703
- package/dist/chunk-ZR26XYRO.js.map +1 -0
- package/dist/client/index.d.mts +4 -4
- package/dist/client/index.d.ts +4 -4
- package/dist/client/index.js +3 -3
- package/dist/client/index.mjs +2 -2
- package/dist/components/index.d.mts +20 -3
- package/dist/components/index.d.ts +20 -3
- package/dist/components/index.js +5 -3
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +4 -2
- package/dist/{config-D_91hrI-.d.ts → config-B4pZpLT9.d.ts} +1 -1
- package/dist/{config-h0hNLceh.d.mts → config-DT1K-t6I.d.mts} +1 -1
- package/dist/{content.interface-QcsFR5Ad.d.mts → content.interface-B2Ldg0vg.d.mts} +1 -1
- package/dist/{content.interface-CUIEQ0jk.d.ts → content.interface-D8NHv3DX.d.ts} +1 -1
- package/dist/contexts/index.d.mts +20 -3
- package/dist/contexts/index.d.ts +20 -3
- package/dist/contexts/index.js +7 -3
- package/dist/contexts/index.js.map +1 -1
- package/dist/contexts/index.mjs +6 -2
- package/dist/core/index.d.mts +11 -7
- package/dist/core/index.d.ts +11 -7
- package/dist/core/index.js +2 -2
- package/dist/core/index.mjs +1 -1
- package/dist/index.d.mts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{notification.interface-blT8r47t.d.mts → notification.interface-DEn-Yp_b.d.mts} +6 -3
- package/dist/{notification.interface-D7_g5SnS.d.ts → notification.interface-H0L9WBge.d.ts} +6 -3
- package/dist/{s3.service-DSDfcr0S.d.mts → s3.service-BNytYanU.d.mts} +2 -2
- package/dist/{s3.service-B83hUhqV.d.ts → s3.service-C7f_Ygz5.d.ts} +2 -2
- package/dist/server/index.d.mts +3 -4
- package/dist/server/index.d.ts +3 -4
- package/dist/server/index.js +18 -25
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +1 -8
- package/dist/server/index.mjs.map +1 -1
- package/dist/{useSocket-B5M_a4bD.d.mts → useSocket-BcnThTD0.d.mts} +1 -1
- package/dist/{useSocket-Dd03muLJ.d.ts → useSocket-QZTOCzRF.d.ts} +1 -1
- package/package.json +1 -1
- package/src/components/containers/PageContainer.tsx +4 -1
- package/src/components/navigations/Header.tsx +34 -2
- package/src/contexts/HeaderChildrenContext.tsx +33 -0
- package/src/contexts/index.ts +1 -0
- package/src/features/auth/components/forms/RefreshUser.tsx +1 -2
- package/src/features/auth/config.ts +0 -1
- package/src/features/auth/data/auth.service.ts +1 -3
- package/src/features/auth/utils/AuthCookies.ts +0 -14
- package/src/features/company/components/details/TokenStatusIndicator.tsx +136 -0
- package/src/features/company/components/details/index.ts +1 -0
- package/src/features/company/components/forms/index.ts +0 -1
- package/src/features/company/data/company.interface.ts +6 -3
- package/src/features/company/data/company.ts +21 -9
- package/src/features/user/contexts/CurrentUserContext.tsx +57 -2
- package/src/server/ServerSession.ts +0 -10
- package/dist/chunk-6BDOZDZ3.mjs.map +0 -1
- package/dist/chunk-JI6BDV7L.js.map +0 -1
- package/dist/chunk-LNBT2YPZ.mjs.map +0 -1
- package/dist/chunk-O3LLMGP7.js.map +0 -1
- package/src/features/company/components/forms/CompanyLicense.tsx +0 -208
- /package/dist/{BlockNoteEditor-UNVKGZ2G.mjs.map → BlockNoteEditor-B6K7OEN6.mjs.map} +0 -0
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/server/index.js","../../src/server/cache.ts","../../src/server/ServerSession.ts","../../src/server/JsonApiServer.ts"],"names":[],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/server/index.js","sourcesContent":[null,"// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { revalidateTag } from \"next/cache\";\n\nexport type CacheProfile = \"seconds\" | \"minutes\" | \"hours\" | \"days\" | \"weeks\" | \"max\" | \"default\";\n\n/**\n * Revalidate a cache tag to invalidate cached data.\n * Next.js 16+ requires a profile parameter.\n *\n * @param tag - The cache tag to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTag(tag: string, profile: CacheProfile = \"max\"): Promise<void> {\n revalidateTag(tag, profile);\n}\n\n/**\n * Revalidate multiple cache tags.\n *\n * @param tags - Array of cache tags to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTags(tags: string[], profile: CacheProfile = \"max\"): Promise<void> {\n for (const tag of tags) {\n revalidateTag(tag, profile);\n }\n}\n","import { cookies } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport pako from \"pako\";\nimport { Action, checkPermissionsFromServer, ModuleWithPermissions } from \"../permissions\";\n\nexport class ServerSession {\n static async isLogged() {\n const cookieStore = await cookies();\n const token = cookieStore.get(\"token\");\n\n if (!token || !token.value) return false;\n return true;\n }\n\n static async isLicenseActive(): Promise<boolean> {\n const cookieStore = await cookies();\n const licenseExpirationDate = cookieStore.get(\"licenseExpirationDate\")?.value;\n\n if (!licenseExpirationDate) return false;\n\n const now = new Date();\n return new Date(licenseExpirationDate) > now;\n }\n\n static async companyId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"companyId\")?.value ?? \"\";\n }\n\n static async userId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"userId\")?.value ?? \"\";\n }\n\n static async checkPermission<M extends ModuleWithPermissions>(params: { module: M; action: Action; data?: any }) {\n if (!(await this.hasPermissionToModule(params))) redirect(`/401`);\n }\n\n static async hasRole(roleId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const roles = cookieStore.get(\"roles\")?.value;\n\n if (!roles || !roles.includes(roleId)) return false;\n\n return true;\n }\n\n static async hasFeature(featureId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const features = cookieStore.get(\"features\")?.value;\n\n if (!features || !features.includes(featureId)) return false;\n\n return true;\n }\n\n static async hasPermissionToModule<M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: any;\n }): Promise<boolean> {\n const cookieStore = await cookies();\n\n if (params.module.feature) {\n const features = cookieStore.get(\"features\")?.value;\n\n if (features && !features.includes(params.module.feature)) return false;\n }\n\n const rawModules = cookieStore.get(\"modules\")?.value;\n if (!rawModules) return false;\n\n const modules: {\n id: string;\n permissions: {\n create: boolean | string;\n read: boolean | string;\n update: boolean | string;\n delete: boolean | string;\n };\n }[] = JSON.parse(pako.ungzip(Buffer.from(rawModules, \"base64\"), { to: \"string\" }));\n\n const selectedModule = modules.find((module) => module.id === params.module.moduleId);\n\n return checkPermissionsFromServer({\n module: params.module,\n action: params.action,\n data: params.data,\n userId: await this.userId(),\n selectedModule: selectedModule,\n });\n\n // if (!selectedModule) return false;\n\n // if (!selectedModule.permissions[params.action]) return false;\n // if (typeof selectedModule.permissions[params.action] === \"boolean\")\n // return selectedModule.permissions[params.action] as boolean;\n\n // if (!params.data) return false;\n\n // return params.data[selectedModule.permissions[params.action] as string] === this.userId;\n }\n}\n","// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { JsonApiDataFactory } from \"../core/factories/JsonApiDataFactory\";\nimport { ApiRequestDataTypeInterface } from \"../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../core/interfaces/ApiResponseInterface\";\nimport { translateResponse } from \"../core/utils/translateResponse\";\nimport { ModuleWithPermissions } from \"../permissions/types\";\nimport { serverRequest } from \"./request\";\nimport { getServerToken } from \"./token\";\n\n// Config storage for server contexts\nlet _serverConfig: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n} | null = null;\n\n/**\n * Configure the JSON:API server client.\n * Call this in your Bootstrapper or server initialization.\n */\nexport function configureServerJsonApi(config: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n}): void {\n _serverConfig = config;\n if (config.bootstrapper) {\n config.bootstrapper();\n }\n}\n\nexport function getServerApiUrl(): string {\n if (_serverConfig?.apiUrl) {\n return _serverConfig.apiUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_API_URL;\n if (!envUrl) {\n throw new Error(\n \"API URL not configured. Use configureServerJsonApi() or set NEXT_PUBLIC_API_URL environment variable.\",\n );\n }\n return envUrl;\n}\n\nexport function getServerAppUrl(): string {\n if (_serverConfig?.appUrl) {\n return _serverConfig.appUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_ADDRESS;\n if (!envUrl) {\n throw new Error(\n \"App URL not configured. Use configureServerJsonApi({ appUrl }) or set NEXT_PUBLIC_ADDRESS environment variable.\",\n );\n }\n return envUrl.trim().replace(/\\/+$/, \"\");\n}\n\nexport function getServerTrackablePages(): ModuleWithPermissions[] {\n return _serverConfig?.trackablePages ?? [];\n}\n\nfunction runServerBootstrapper(): void {\n if (_serverConfig?.bootstrapper) {\n _serverConfig.bootstrapper();\n }\n}\n\nfunction buildServerUrl(endpoint: string): string {\n const apiUrl = getServerApiUrl();\n return endpoint.startsWith(\"http\") ? endpoint : `${apiUrl}${endpoint}`;\n}\n\nexport async function ServerJsonApiGet(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"GET\",\n url: buildServerUrl(params.endpoint),\n token,\n cache: params.classKey.cache,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n paginationHandler: async (endpoint: string) =>\n ServerJsonApiGet({\n classKey: params.classKey,\n endpoint,\n companyId: params.companyId,\n language: params.language,\n }),\n });\n}\n\nexport async function ServerJsonApiPost(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n overridesJsonApiCreation?: boolean;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"POST\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPut(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PUT\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPatch(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n overridesJsonApiCreation?: boolean;\n responseType?: ApiRequestDataTypeInterface;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PATCH\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiDelete(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"DELETE\",\n url: buildServerUrl(params.endpoint),\n token,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/server/index.js","../../src/server/cache.ts","../../src/server/ServerSession.ts","../../src/server/JsonApiServer.ts"],"names":[],"mappings":"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AAC1C,EAAA;AAEwC,EAAA;AAC9B,IAAA;AAC2B,IAAA;AACnC,IAAA;AACA,IAAA;AACc,IAAA;AACI,IAAA;AACD,IAAA;AACiB,IAAA;AACnC,EAAA;AAEwB,EAAA;AACiB,IAAA;AACxC,IAAA;AACkB,IAAA;AACD,IAAA;AAClB,EAAA;AACH;AApCsB;AA+CY;AACV,EAAA;AACa,EAAA;AAEjB,EAAA;AACP,EAAA;AACD,IAAA;AACqC,EAAA;AACL,IAAA;AAC1C,EAAA;AAEwC,EAAA;AAC9B,IAAA;AAC2B,IAAA;AACnC,IAAA;AACA,IAAA;AACc,IAAA;AACI,IAAA;AACD,IAAA;AACiB,IAAA;AACnC,EAAA;AAEwB,EAAA;AACiB,IAAA;AACxC,IAAA;AACkB,IAAA;AACD,IAAA;AAClB,EAAA;AACH;AArCsB;AA6CY;AACV,EAAA;AACa,EAAA;AAEK,EAAA;AAC9B,IAAA;AAC2B,IAAA;AACnC,IAAA;AACkB,IAAA;AACD,IAAA;AACiB,IAAA;AACnC,EAAA;AAEwB,EAAA;AACiB,IAAA;AACxC,IAAA;AACkB,IAAA;AACD,IAAA;AAClB,EAAA;AACH;AAzBsB;AH+C6B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/server/index.js","sourcesContent":[null,"// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { revalidateTag } from \"next/cache\";\n\nexport type CacheProfile = \"seconds\" | \"minutes\" | \"hours\" | \"days\" | \"weeks\" | \"max\" | \"default\";\n\n/**\n * Revalidate a cache tag to invalidate cached data.\n * Next.js 16+ requires a profile parameter.\n *\n * @param tag - The cache tag to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTag(tag: string, profile: CacheProfile = \"max\"): Promise<void> {\n revalidateTag(tag, profile);\n}\n\n/**\n * Revalidate multiple cache tags.\n *\n * @param tags - Array of cache tags to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTags(tags: string[], profile: CacheProfile = \"max\"): Promise<void> {\n for (const tag of tags) {\n revalidateTag(tag, profile);\n }\n}\n","import { cookies } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport pako from \"pako\";\nimport { Action, checkPermissionsFromServer, ModuleWithPermissions } from \"../permissions\";\n\nexport class ServerSession {\n static async isLogged() {\n const cookieStore = await cookies();\n const token = cookieStore.get(\"token\");\n\n if (!token || !token.value) return false;\n return true;\n }\n\n static async companyId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"companyId\")?.value ?? \"\";\n }\n\n static async userId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"userId\")?.value ?? \"\";\n }\n\n static async checkPermission<M extends ModuleWithPermissions>(params: { module: M; action: Action; data?: any }) {\n if (!(await this.hasPermissionToModule(params))) redirect(`/401`);\n }\n\n static async hasRole(roleId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const roles = cookieStore.get(\"roles\")?.value;\n\n if (!roles || !roles.includes(roleId)) return false;\n\n return true;\n }\n\n static async hasFeature(featureId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const features = cookieStore.get(\"features\")?.value;\n\n if (!features || !features.includes(featureId)) return false;\n\n return true;\n }\n\n static async hasPermissionToModule<M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: any;\n }): Promise<boolean> {\n const cookieStore = await cookies();\n\n if (params.module.feature) {\n const features = cookieStore.get(\"features\")?.value;\n\n if (features && !features.includes(params.module.feature)) return false;\n }\n\n const rawModules = cookieStore.get(\"modules\")?.value;\n if (!rawModules) return false;\n\n const modules: {\n id: string;\n permissions: {\n create: boolean | string;\n read: boolean | string;\n update: boolean | string;\n delete: boolean | string;\n };\n }[] = JSON.parse(pako.ungzip(Buffer.from(rawModules, \"base64\"), { to: \"string\" }));\n\n const selectedModule = modules.find((module) => module.id === params.module.moduleId);\n\n return checkPermissionsFromServer({\n module: params.module,\n action: params.action,\n data: params.data,\n userId: await this.userId(),\n selectedModule: selectedModule,\n });\n\n // if (!selectedModule) return false;\n\n // if (!selectedModule.permissions[params.action]) return false;\n // if (typeof selectedModule.permissions[params.action] === \"boolean\")\n // return selectedModule.permissions[params.action] as boolean;\n\n // if (!params.data) return false;\n\n // return params.data[selectedModule.permissions[params.action] as string] === this.userId;\n }\n}\n","// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { JsonApiDataFactory } from \"../core/factories/JsonApiDataFactory\";\nimport { ApiRequestDataTypeInterface } from \"../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../core/interfaces/ApiResponseInterface\";\nimport { translateResponse } from \"../core/utils/translateResponse\";\nimport { ModuleWithPermissions } from \"../permissions/types\";\nimport { serverRequest } from \"./request\";\nimport { getServerToken } from \"./token\";\n\n// Config storage for server contexts\nlet _serverConfig: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n} | null = null;\n\n/**\n * Configure the JSON:API server client.\n * Call this in your Bootstrapper or server initialization.\n */\nexport function configureServerJsonApi(config: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n}): void {\n _serverConfig = config;\n if (config.bootstrapper) {\n config.bootstrapper();\n }\n}\n\nexport function getServerApiUrl(): string {\n if (_serverConfig?.apiUrl) {\n return _serverConfig.apiUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_API_URL;\n if (!envUrl) {\n throw new Error(\n \"API URL not configured. Use configureServerJsonApi() or set NEXT_PUBLIC_API_URL environment variable.\",\n );\n }\n return envUrl;\n}\n\nexport function getServerAppUrl(): string {\n if (_serverConfig?.appUrl) {\n return _serverConfig.appUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_ADDRESS;\n if (!envUrl) {\n throw new Error(\n \"App URL not configured. Use configureServerJsonApi({ appUrl }) or set NEXT_PUBLIC_ADDRESS environment variable.\",\n );\n }\n return envUrl.trim().replace(/\\/+$/, \"\");\n}\n\nexport function getServerTrackablePages(): ModuleWithPermissions[] {\n return _serverConfig?.trackablePages ?? [];\n}\n\nfunction runServerBootstrapper(): void {\n if (_serverConfig?.bootstrapper) {\n _serverConfig.bootstrapper();\n }\n}\n\nfunction buildServerUrl(endpoint: string): string {\n const apiUrl = getServerApiUrl();\n return endpoint.startsWith(\"http\") ? endpoint : `${apiUrl}${endpoint}`;\n}\n\nexport async function ServerJsonApiGet(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"GET\",\n url: buildServerUrl(params.endpoint),\n token,\n cache: params.classKey.cache,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n paginationHandler: async (endpoint: string) =>\n ServerJsonApiGet({\n classKey: params.classKey,\n endpoint,\n companyId: params.companyId,\n language: params.language,\n }),\n });\n}\n\nexport async function ServerJsonApiPost(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n overridesJsonApiCreation?: boolean;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"POST\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPut(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PUT\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPatch(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n overridesJsonApiCreation?: boolean;\n responseType?: ApiRequestDataTypeInterface;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PATCH\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiDelete(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"DELETE\",\n url: buildServerUrl(params.endpoint),\n token,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n"]}
|
package/dist/server/index.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
S3Service,
|
|
16
16
|
UserService,
|
|
17
17
|
checkPermissionsFromServer
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-NAB52T2P.mjs";
|
|
19
19
|
import "../chunk-AUXK7QSA.mjs";
|
|
20
20
|
import "../chunk-C7C7VY4F.mjs";
|
|
21
21
|
import {
|
|
@@ -53,13 +53,6 @@ var ServerSession = class {
|
|
|
53
53
|
if (!token || !token.value) return false;
|
|
54
54
|
return true;
|
|
55
55
|
}
|
|
56
|
-
static async isLicenseActive() {
|
|
57
|
-
const cookieStore = await cookies();
|
|
58
|
-
const licenseExpirationDate = cookieStore.get("licenseExpirationDate")?.value;
|
|
59
|
-
if (!licenseExpirationDate) return false;
|
|
60
|
-
const now = /* @__PURE__ */ new Date();
|
|
61
|
-
return new Date(licenseExpirationDate) > now;
|
|
62
|
-
}
|
|
63
56
|
static async companyId() {
|
|
64
57
|
const cookieStore = await cookies();
|
|
65
58
|
return cookieStore.get("companyId")?.value ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/cache.ts","../../src/server/ServerSession.ts","../../src/server/JsonApiServer.ts"],"sourcesContent":["// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { revalidateTag } from \"next/cache\";\n\nexport type CacheProfile = \"seconds\" | \"minutes\" | \"hours\" | \"days\" | \"weeks\" | \"max\" | \"default\";\n\n/**\n * Revalidate a cache tag to invalidate cached data.\n * Next.js 16+ requires a profile parameter.\n *\n * @param tag - The cache tag to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTag(tag: string, profile: CacheProfile = \"max\"): Promise<void> {\n revalidateTag(tag, profile);\n}\n\n/**\n * Revalidate multiple cache tags.\n *\n * @param tags - Array of cache tags to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTags(tags: string[], profile: CacheProfile = \"max\"): Promise<void> {\n for (const tag of tags) {\n revalidateTag(tag, profile);\n }\n}\n","import { cookies } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport pako from \"pako\";\nimport { Action, checkPermissionsFromServer, ModuleWithPermissions } from \"../permissions\";\n\nexport class ServerSession {\n static async isLogged() {\n const cookieStore = await cookies();\n const token = cookieStore.get(\"token\");\n\n if (!token || !token.value) return false;\n return true;\n }\n\n static async isLicenseActive(): Promise<boolean> {\n const cookieStore = await cookies();\n const licenseExpirationDate = cookieStore.get(\"licenseExpirationDate\")?.value;\n\n if (!licenseExpirationDate) return false;\n\n const now = new Date();\n return new Date(licenseExpirationDate) > now;\n }\n\n static async companyId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"companyId\")?.value ?? \"\";\n }\n\n static async userId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"userId\")?.value ?? \"\";\n }\n\n static async checkPermission<M extends ModuleWithPermissions>(params: { module: M; action: Action; data?: any }) {\n if (!(await this.hasPermissionToModule(params))) redirect(`/401`);\n }\n\n static async hasRole(roleId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const roles = cookieStore.get(\"roles\")?.value;\n\n if (!roles || !roles.includes(roleId)) return false;\n\n return true;\n }\n\n static async hasFeature(featureId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const features = cookieStore.get(\"features\")?.value;\n\n if (!features || !features.includes(featureId)) return false;\n\n return true;\n }\n\n static async hasPermissionToModule<M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: any;\n }): Promise<boolean> {\n const cookieStore = await cookies();\n\n if (params.module.feature) {\n const features = cookieStore.get(\"features\")?.value;\n\n if (features && !features.includes(params.module.feature)) return false;\n }\n\n const rawModules = cookieStore.get(\"modules\")?.value;\n if (!rawModules) return false;\n\n const modules: {\n id: string;\n permissions: {\n create: boolean | string;\n read: boolean | string;\n update: boolean | string;\n delete: boolean | string;\n };\n }[] = JSON.parse(pako.ungzip(Buffer.from(rawModules, \"base64\"), { to: \"string\" }));\n\n const selectedModule = modules.find((module) => module.id === params.module.moduleId);\n\n return checkPermissionsFromServer({\n module: params.module,\n action: params.action,\n data: params.data,\n userId: await this.userId(),\n selectedModule: selectedModule,\n });\n\n // if (!selectedModule) return false;\n\n // if (!selectedModule.permissions[params.action]) return false;\n // if (typeof selectedModule.permissions[params.action] === \"boolean\")\n // return selectedModule.permissions[params.action] as boolean;\n\n // if (!params.data) return false;\n\n // return params.data[selectedModule.permissions[params.action] as string] === this.userId;\n }\n}\n","// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { JsonApiDataFactory } from \"../core/factories/JsonApiDataFactory\";\nimport { ApiRequestDataTypeInterface } from \"../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../core/interfaces/ApiResponseInterface\";\nimport { translateResponse } from \"../core/utils/translateResponse\";\nimport { ModuleWithPermissions } from \"../permissions/types\";\nimport { serverRequest } from \"./request\";\nimport { getServerToken } from \"./token\";\n\n// Config storage for server contexts\nlet _serverConfig: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n} | null = null;\n\n/**\n * Configure the JSON:API server client.\n * Call this in your Bootstrapper or server initialization.\n */\nexport function configureServerJsonApi(config: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n}): void {\n _serverConfig = config;\n if (config.bootstrapper) {\n config.bootstrapper();\n }\n}\n\nexport function getServerApiUrl(): string {\n if (_serverConfig?.apiUrl) {\n return _serverConfig.apiUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_API_URL;\n if (!envUrl) {\n throw new Error(\n \"API URL not configured. Use configureServerJsonApi() or set NEXT_PUBLIC_API_URL environment variable.\",\n );\n }\n return envUrl;\n}\n\nexport function getServerAppUrl(): string {\n if (_serverConfig?.appUrl) {\n return _serverConfig.appUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_ADDRESS;\n if (!envUrl) {\n throw new Error(\n \"App URL not configured. Use configureServerJsonApi({ appUrl }) or set NEXT_PUBLIC_ADDRESS environment variable.\",\n );\n }\n return envUrl.trim().replace(/\\/+$/, \"\");\n}\n\nexport function getServerTrackablePages(): ModuleWithPermissions[] {\n return _serverConfig?.trackablePages ?? [];\n}\n\nfunction runServerBootstrapper(): void {\n if (_serverConfig?.bootstrapper) {\n _serverConfig.bootstrapper();\n }\n}\n\nfunction buildServerUrl(endpoint: string): string {\n const apiUrl = getServerApiUrl();\n return endpoint.startsWith(\"http\") ? endpoint : `${apiUrl}${endpoint}`;\n}\n\nexport async function ServerJsonApiGet(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"GET\",\n url: buildServerUrl(params.endpoint),\n token,\n cache: params.classKey.cache,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n paginationHandler: async (endpoint: string) =>\n ServerJsonApiGet({\n classKey: params.classKey,\n endpoint,\n companyId: params.companyId,\n language: params.language,\n }),\n });\n}\n\nexport async function ServerJsonApiPost(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n overridesJsonApiCreation?: boolean;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"POST\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPut(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PUT\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPatch(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n overridesJsonApiCreation?: boolean;\n responseType?: ApiRequestDataTypeInterface;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PATCH\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiDelete(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"DELETE\",\n url: buildServerUrl(params.endpoint),\n token,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/cache.ts","../../src/server/ServerSession.ts","../../src/server/JsonApiServer.ts"],"sourcesContent":["// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { revalidateTag } from \"next/cache\";\n\nexport type CacheProfile = \"seconds\" | \"minutes\" | \"hours\" | \"days\" | \"weeks\" | \"max\" | \"default\";\n\n/**\n * Revalidate a cache tag to invalidate cached data.\n * Next.js 16+ requires a profile parameter.\n *\n * @param tag - The cache tag to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTag(tag: string, profile: CacheProfile = \"max\"): Promise<void> {\n revalidateTag(tag, profile);\n}\n\n/**\n * Revalidate multiple cache tags.\n *\n * @param tags - Array of cache tags to invalidate\n * @param profile - The cache profile (defaults to \"max\" for immediate invalidation)\n */\nexport async function invalidateCacheTags(tags: string[], profile: CacheProfile = \"max\"): Promise<void> {\n for (const tag of tags) {\n revalidateTag(tag, profile);\n }\n}\n","import { cookies } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport pako from \"pako\";\nimport { Action, checkPermissionsFromServer, ModuleWithPermissions } from \"../permissions\";\n\nexport class ServerSession {\n static async isLogged() {\n const cookieStore = await cookies();\n const token = cookieStore.get(\"token\");\n\n if (!token || !token.value) return false;\n return true;\n }\n\n static async companyId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"companyId\")?.value ?? \"\";\n }\n\n static async userId() {\n const cookieStore = await cookies();\n return cookieStore.get(\"userId\")?.value ?? \"\";\n }\n\n static async checkPermission<M extends ModuleWithPermissions>(params: { module: M; action: Action; data?: any }) {\n if (!(await this.hasPermissionToModule(params))) redirect(`/401`);\n }\n\n static async hasRole(roleId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const roles = cookieStore.get(\"roles\")?.value;\n\n if (!roles || !roles.includes(roleId)) return false;\n\n return true;\n }\n\n static async hasFeature(featureId: string): Promise<boolean> {\n const cookieStore = await cookies();\n const features = cookieStore.get(\"features\")?.value;\n\n if (!features || !features.includes(featureId)) return false;\n\n return true;\n }\n\n static async hasPermissionToModule<M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: any;\n }): Promise<boolean> {\n const cookieStore = await cookies();\n\n if (params.module.feature) {\n const features = cookieStore.get(\"features\")?.value;\n\n if (features && !features.includes(params.module.feature)) return false;\n }\n\n const rawModules = cookieStore.get(\"modules\")?.value;\n if (!rawModules) return false;\n\n const modules: {\n id: string;\n permissions: {\n create: boolean | string;\n read: boolean | string;\n update: boolean | string;\n delete: boolean | string;\n };\n }[] = JSON.parse(pako.ungzip(Buffer.from(rawModules, \"base64\"), { to: \"string\" }));\n\n const selectedModule = modules.find((module) => module.id === params.module.moduleId);\n\n return checkPermissionsFromServer({\n module: params.module,\n action: params.action,\n data: params.data,\n userId: await this.userId(),\n selectedModule: selectedModule,\n });\n\n // if (!selectedModule) return false;\n\n // if (!selectedModule.permissions[params.action]) return false;\n // if (typeof selectedModule.permissions[params.action] === \"boolean\")\n // return selectedModule.permissions[params.action] as boolean;\n\n // if (!params.data) return false;\n\n // return params.data[selectedModule.permissions[params.action] as string] === this.userId;\n }\n}\n","// Server-only utilities (NOT server actions - these cannot be called from client components)\n\nimport { JsonApiDataFactory } from \"../core/factories/JsonApiDataFactory\";\nimport { ApiRequestDataTypeInterface } from \"../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../core/interfaces/ApiResponseInterface\";\nimport { translateResponse } from \"../core/utils/translateResponse\";\nimport { ModuleWithPermissions } from \"../permissions/types\";\nimport { serverRequest } from \"./request\";\nimport { getServerToken } from \"./token\";\n\n// Config storage for server contexts\nlet _serverConfig: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n} | null = null;\n\n/**\n * Configure the JSON:API server client.\n * Call this in your Bootstrapper or server initialization.\n */\nexport function configureServerJsonApi(config: {\n apiUrl: string;\n appUrl?: string;\n trackablePages?: ModuleWithPermissions[];\n bootstrapper?: () => void;\n additionalHeaders?: Record<string, string>;\n}): void {\n _serverConfig = config;\n if (config.bootstrapper) {\n config.bootstrapper();\n }\n}\n\nexport function getServerApiUrl(): string {\n if (_serverConfig?.apiUrl) {\n return _serverConfig.apiUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_API_URL;\n if (!envUrl) {\n throw new Error(\n \"API URL not configured. Use configureServerJsonApi() or set NEXT_PUBLIC_API_URL environment variable.\",\n );\n }\n return envUrl;\n}\n\nexport function getServerAppUrl(): string {\n if (_serverConfig?.appUrl) {\n return _serverConfig.appUrl;\n }\n const envUrl = process.env.NEXT_PUBLIC_ADDRESS;\n if (!envUrl) {\n throw new Error(\n \"App URL not configured. Use configureServerJsonApi({ appUrl }) or set NEXT_PUBLIC_ADDRESS environment variable.\",\n );\n }\n return envUrl.trim().replace(/\\/+$/, \"\");\n}\n\nexport function getServerTrackablePages(): ModuleWithPermissions[] {\n return _serverConfig?.trackablePages ?? [];\n}\n\nfunction runServerBootstrapper(): void {\n if (_serverConfig?.bootstrapper) {\n _serverConfig.bootstrapper();\n }\n}\n\nfunction buildServerUrl(endpoint: string): string {\n const apiUrl = getServerApiUrl();\n return endpoint.startsWith(\"http\") ? endpoint : `${apiUrl}${endpoint}`;\n}\n\nexport async function ServerJsonApiGet(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"GET\",\n url: buildServerUrl(params.endpoint),\n token,\n cache: params.classKey.cache,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n paginationHandler: async (endpoint: string) =>\n ServerJsonApiGet({\n classKey: params.classKey,\n endpoint,\n companyId: params.companyId,\n language: params.language,\n }),\n });\n}\n\nexport async function ServerJsonApiPost(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n overridesJsonApiCreation?: boolean;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"POST\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPut(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PUT\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiPatch(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n body?: any;\n files?: { [key: string]: File | Blob } | File | Blob;\n overridesJsonApiCreation?: boolean;\n responseType?: ApiRequestDataTypeInterface;\n language: string;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n let body = params.body;\n if (!body) {\n body = {};\n } else if (params.overridesJsonApiCreation !== true) {\n body = JsonApiDataFactory.create(params.classKey, body);\n }\n\n const apiResponse = await serverRequest({\n method: \"PATCH\",\n url: buildServerUrl(params.endpoint),\n token,\n body,\n files: params.files,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n\nexport async function ServerJsonApiDelete(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n language: string;\n responseType?: ApiRequestDataTypeInterface;\n}): Promise<ApiResponseInterface> {\n runServerBootstrapper();\n const token = await getServerToken();\n\n const apiResponse = await serverRequest({\n method: \"DELETE\",\n url: buildServerUrl(params.endpoint),\n token,\n companyId: params.companyId,\n language: params.language,\n additionalHeaders: _serverConfig?.additionalHeaders,\n });\n\n return translateResponse({\n classKey: params.responseType ?? params.classKey,\n apiResponse,\n companyId: params.companyId,\n language: params.language,\n });\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useHeaderChildren } from "../../contexts/HeaderChildrenContext";
|
|
3
4
|
import { cn } from "../../utils";
|
|
4
5
|
import { Header } from "../navigations";
|
|
5
6
|
|
|
6
7
|
type PageContainerProps = { children: React.ReactNode; testId?: string; className?: string };
|
|
7
8
|
|
|
8
9
|
export function PageContainer({ children, testId, className }: PageContainerProps) {
|
|
10
|
+
const headerChildren = useHeaderChildren();
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
13
|
<div className={`flex h-full w-full flex-col`} data-testid={testId}>
|
|
11
|
-
<Header
|
|
14
|
+
<Header>{headerChildren}</Header>
|
|
12
15
|
<main className={cn(`flex w-full flex-1 flex-col gap-y-4 pt-4 pl-4 pr-4 pb-20`, className)}>{children}</main>
|
|
13
16
|
</div>
|
|
14
17
|
);
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { getRoleId } from "@/roles";
|
|
4
|
+
import { RefreshCwIcon } from "lucide-react";
|
|
5
|
+
import { useTranslations } from "next-intl";
|
|
3
6
|
import { useSharedContext } from "../../contexts/SharedContext";
|
|
4
|
-
import {
|
|
7
|
+
import { TokenStatusIndicator } from "../../features/company/components/details";
|
|
8
|
+
import { useCurrentUserContext } from "../../features/user/contexts";
|
|
9
|
+
import { Button, SidebarTrigger, Tooltip, TooltipContent, TooltipTrigger } from "../../shadcnui";
|
|
5
10
|
import { BreadcrumbNavigation } from "./Breadcrumb";
|
|
6
11
|
|
|
7
12
|
type HeaderProps = {
|
|
@@ -9,7 +14,10 @@ type HeaderProps = {
|
|
|
9
14
|
};
|
|
10
15
|
|
|
11
16
|
export function Header({ children }: HeaderProps) {
|
|
17
|
+
const t = useTranslations();
|
|
12
18
|
const { breadcrumbs } = useSharedContext();
|
|
19
|
+
const { company, hasRole, refreshUser, isRefreshing } = useCurrentUserContext();
|
|
20
|
+
const showTokenStatus = !hasRole(getRoleId().Administrator) && company;
|
|
13
21
|
|
|
14
22
|
return (
|
|
15
23
|
<header className={`sticky top-0 z-10 flex h-12 flex-col items-center justify-start gap-x-4 border-b`}>
|
|
@@ -19,7 +27,31 @@ export function Header({ children }: HeaderProps) {
|
|
|
19
27
|
<BreadcrumbNavigation items={breadcrumbs} />
|
|
20
28
|
</div>
|
|
21
29
|
<div className="flex w-64 flex-row items-center justify-end gap-x-4 whitespace-nowrap">
|
|
22
|
-
|
|
30
|
+
<div className="flex flex-row items-center justify-end gap-x-4 whitespace-nowrap">
|
|
31
|
+
{showTokenStatus && (
|
|
32
|
+
<div className="flex items-center gap-x-2">
|
|
33
|
+
<TokenStatusIndicator size="sm" showExtraPages={true} />
|
|
34
|
+
<Tooltip>
|
|
35
|
+
<TooltipTrigger
|
|
36
|
+
render={
|
|
37
|
+
<Button
|
|
38
|
+
variant="ghost"
|
|
39
|
+
size="icon"
|
|
40
|
+
className="h-6 w-6"
|
|
41
|
+
onClick={() => refreshUser()}
|
|
42
|
+
disabled={isRefreshing}
|
|
43
|
+
aria-label={t("generic.refresh", { defaultValue: "Refresh" })}
|
|
44
|
+
/>
|
|
45
|
+
}
|
|
46
|
+
>
|
|
47
|
+
<RefreshCwIcon className={`h-3.5 w-3.5 ${isRefreshing ? "animate-spin" : ""}`} />
|
|
48
|
+
</TooltipTrigger>
|
|
49
|
+
<TooltipContent side="bottom">{t("generic.refresh", { defaultValue: "Refresh" })}</TooltipContent>
|
|
50
|
+
</Tooltip>
|
|
51
|
+
</div>
|
|
52
|
+
)}
|
|
53
|
+
{children ? children : null}
|
|
54
|
+
</div>
|
|
23
55
|
</div>
|
|
24
56
|
</div>
|
|
25
57
|
</header>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
interface HeaderChildrenContextType {
|
|
6
|
+
headerChildren: ReactNode | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const HeaderChildrenContext = createContext<HeaderChildrenContextType>({
|
|
10
|
+
headerChildren: null,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
interface HeaderChildrenProviderProps {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
content: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Provider to supply custom content to be rendered in the Header component.
|
|
20
|
+
* Wrap your layout with this provider and pass the content you want in the header.
|
|
21
|
+
*/
|
|
22
|
+
export function HeaderChildrenProvider({ children, content }: HeaderChildrenProviderProps) {
|
|
23
|
+
return <HeaderChildrenContext.Provider value={{ headerChildren: content }}>{children}</HeaderChildrenContext.Provider>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Hook to get the header children content from context.
|
|
28
|
+
* Used internally by PageContainer to pass children to Header.
|
|
29
|
+
*/
|
|
30
|
+
export function useHeaderChildren(): ReactNode | null {
|
|
31
|
+
const context = useContext(HeaderChildrenContext);
|
|
32
|
+
return context.headerChildren;
|
|
33
|
+
}
|
package/src/contexts/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "../features/notification/contexts/NotificationContext";
|
|
|
3
3
|
export * from "../features/role/contexts/RoleContext";
|
|
4
4
|
export * from "../features/user/contexts";
|
|
5
5
|
export * from "./CommonContext";
|
|
6
|
+
export * from "./HeaderChildrenContext";
|
|
6
7
|
export * from "./SharedContext";
|
|
7
8
|
export * from "./SocketContext";
|
|
8
9
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import { deleteCookie, getCookie } from "cookies-next";
|
|
4
4
|
import { useEffect } from "react";
|
|
5
5
|
import { UserInterface } from "../../../user";
|
|
6
|
-
import { UserService } from "../../../user/data/user.service";
|
|
7
6
|
import { useCurrentUserContext } from "../../../user/contexts";
|
|
7
|
+
import { UserService } from "../../../user/data/user.service";
|
|
8
8
|
import { getTokenHandler } from "../../config";
|
|
9
9
|
|
|
10
10
|
export function RefreshUser() {
|
|
@@ -18,7 +18,6 @@ export function RefreshUser() {
|
|
|
18
18
|
const token = {
|
|
19
19
|
userId: fullUser.id,
|
|
20
20
|
companyId: fullUser.company?.id,
|
|
21
|
-
licenseExpirationDate: fullUser.company?.licenseExpirationDate,
|
|
22
21
|
roles: fullUser.roles.map((role) => role.id),
|
|
23
22
|
features: fullUser.company?.features?.map((feature) => feature.id) ?? [],
|
|
24
23
|
modules: fullUser.modules.map((module) => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AuthInput, AuthInterface } from ".";
|
|
2
|
-
import { JsonApiDelete, JsonApiGet, JsonApiPost } from "../../../unified";
|
|
3
2
|
import {
|
|
4
3
|
AbstractService,
|
|
5
4
|
ApiResponseInterface,
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
Modules,
|
|
10
9
|
rehydrate,
|
|
11
10
|
} from "../../../core";
|
|
11
|
+
import { JsonApiDelete, JsonApiGet, JsonApiPost } from "../../../unified";
|
|
12
12
|
import { UserInterface } from "../../user";
|
|
13
13
|
import { getTokenHandler } from "../config";
|
|
14
14
|
|
|
@@ -35,7 +35,6 @@ export class AuthService extends AbstractService {
|
|
|
35
35
|
refreshToken: auth.refreshToken,
|
|
36
36
|
userId: auth.user.id,
|
|
37
37
|
companyId: auth.user.company?.id,
|
|
38
|
-
licenseExpirationDate: auth.user.company?.licenseExpirationDate,
|
|
39
38
|
roles: auth.user.roles.map((role) => role.id),
|
|
40
39
|
features: auth.user.company?.features?.map((feature) => feature.id) ?? [],
|
|
41
40
|
modules: auth.user.modules.map((module) => ({
|
|
@@ -146,7 +145,6 @@ export class AuthService extends AbstractService {
|
|
|
146
145
|
refreshToken: auth.refreshToken,
|
|
147
146
|
userId: auth.user.id,
|
|
148
147
|
companyId: auth.user.company?.id,
|
|
149
|
-
licenseExpirationDate: auth.user.company?.licenseExpirationDate,
|
|
150
148
|
roles: auth.user.roles.map((role) => role.id),
|
|
151
149
|
features: auth.user.company?.features?.map((feature) => feature.id) ?? [],
|
|
152
150
|
modules: auth.user.modules.map((module) => ({
|
|
@@ -8,7 +8,6 @@ export async function updateToken(params: {
|
|
|
8
8
|
refreshToken?: string;
|
|
9
9
|
userId?: string;
|
|
10
10
|
companyId?: string;
|
|
11
|
-
licenseExpirationDate?: Date;
|
|
12
11
|
roles?: string[];
|
|
13
12
|
features?: string[];
|
|
14
13
|
modules?: {
|
|
@@ -62,16 +61,6 @@ export async function updateToken(params: {
|
|
|
62
61
|
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365),
|
|
63
62
|
});
|
|
64
63
|
|
|
65
|
-
if (params.licenseExpirationDate)
|
|
66
|
-
(await cookies()).set({
|
|
67
|
-
name: "licenseExpirationDate",
|
|
68
|
-
value: params.licenseExpirationDate.toISOString(),
|
|
69
|
-
httpOnly: true,
|
|
70
|
-
path: "/",
|
|
71
|
-
secure: isProduction,
|
|
72
|
-
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
64
|
if (params.roles)
|
|
76
65
|
(await cookies()).set({
|
|
77
66
|
name: "roles",
|
|
@@ -119,9 +108,6 @@ export async function removeToken(): Promise<void> {
|
|
|
119
108
|
(await cookies()).delete({
|
|
120
109
|
name: "companyId",
|
|
121
110
|
});
|
|
122
|
-
(await cookies()).delete({
|
|
123
|
-
name: "licenseExpirationDate",
|
|
124
|
-
});
|
|
125
111
|
(await cookies()).delete({
|
|
126
112
|
name: "roles",
|
|
127
113
|
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Battery, BatteryFull, BatteryLow, BatteryMedium, PlusCircle } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { useTranslations } from "next-intl";
|
|
7
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../../../../shadcnui";
|
|
8
|
+
import { useCurrentUserContext } from "../../../user/contexts";
|
|
9
|
+
|
|
10
|
+
interface TokenStatusIndicatorProps {
|
|
11
|
+
className?: string;
|
|
12
|
+
size?: "sm" | "md" | "lg";
|
|
13
|
+
showExtraPages?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* TokenStatusIndicator displays the current status of available monthly and extra pages
|
|
18
|
+
* using battery icons to represent the percentage of monthly pages remaining.
|
|
19
|
+
*
|
|
20
|
+
* Battery levels:
|
|
21
|
+
* - BatteryFull: >75% available
|
|
22
|
+
* - BatteryMedium: 25-75% available
|
|
23
|
+
* - BatteryLow: 5-25% available
|
|
24
|
+
* - Battery (empty): <5% available
|
|
25
|
+
*/
|
|
26
|
+
export function TokenStatusIndicator({ className, size = "md", showExtraPages = true }: TokenStatusIndicatorProps) {
|
|
27
|
+
const { company } = useCurrentUserContext();
|
|
28
|
+
const t = useTranslations();
|
|
29
|
+
|
|
30
|
+
// Don't render if no company data
|
|
31
|
+
if (!company) return null;
|
|
32
|
+
|
|
33
|
+
const monthlyTokens = company.monthlyTokens;
|
|
34
|
+
const availableMonthlyTokens = company.availableMonthlyTokens;
|
|
35
|
+
const availableExtraTokens = company.availableExtraTokens;
|
|
36
|
+
|
|
37
|
+
// Calculate percentage of available monthly pages
|
|
38
|
+
const percentage = monthlyTokens > 0 ? (availableMonthlyTokens / monthlyTokens) * 100 : 0;
|
|
39
|
+
|
|
40
|
+
const sizeClasses = {
|
|
41
|
+
sm: "h-4 w-4",
|
|
42
|
+
md: "h-5 w-5",
|
|
43
|
+
lg: "h-6 w-6",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const smallIconSizeClasses = {
|
|
47
|
+
sm: "h-3 w-3",
|
|
48
|
+
md: "h-4 w-4",
|
|
49
|
+
lg: "h-5 w-5",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const textSizeClasses = {
|
|
53
|
+
sm: "text-xs",
|
|
54
|
+
md: "text-sm",
|
|
55
|
+
lg: "text-base",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const iconSize = sizeClasses[size];
|
|
59
|
+
const smallIconSize = smallIconSizeClasses[size];
|
|
60
|
+
const textSize = textSizeClasses[size];
|
|
61
|
+
|
|
62
|
+
const getBatteryIcon = () => {
|
|
63
|
+
if (percentage > 75) {
|
|
64
|
+
return <BatteryFull className={cn(iconSize, "text-green-500")} />;
|
|
65
|
+
} else if (percentage >= 25) {
|
|
66
|
+
return <BatteryMedium className={cn(iconSize, "text-yellow-500")} />;
|
|
67
|
+
} else if (percentage >= 5) {
|
|
68
|
+
return <BatteryLow className={cn(iconSize, "text-orange-500")} />;
|
|
69
|
+
} else {
|
|
70
|
+
return <Battery className={cn(iconSize, "text-destructive")} />;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const getStatusColor = () => {
|
|
75
|
+
if (percentage > 75) {
|
|
76
|
+
return "text-green-500";
|
|
77
|
+
} else if (percentage >= 25) {
|
|
78
|
+
return "text-yellow-500";
|
|
79
|
+
} else if (percentage >= 5) {
|
|
80
|
+
return "text-orange-500";
|
|
81
|
+
} else {
|
|
82
|
+
return "text-destructive";
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const tooltipContent = (
|
|
87
|
+
<div className="flex flex-col gap-2 p-1">
|
|
88
|
+
<div className="font-semibold text-sm">{t("generic.tokens.status", { defaultValue: "Page Status" })}</div>
|
|
89
|
+
<div className="flex flex-col gap-1 text-xs">
|
|
90
|
+
<div className="flex items-center justify-between gap-4">
|
|
91
|
+
<span className="text-muted-foreground">
|
|
92
|
+
{t("generic.tokens.monthly", { defaultValue: "Monthly Pages" })}:
|
|
93
|
+
</span>
|
|
94
|
+
<span className={cn("font-medium", getStatusColor())}>
|
|
95
|
+
{availableMonthlyTokens} / {monthlyTokens}
|
|
96
|
+
</span>
|
|
97
|
+
</div>
|
|
98
|
+
<div className="flex items-center justify-between gap-4">
|
|
99
|
+
<span className="text-muted-foreground">{t("generic.tokens.available", { defaultValue: "Available" })}:</span>
|
|
100
|
+
<span className={cn("font-medium", getStatusColor())}>{percentage.toFixed(0)}%</span>
|
|
101
|
+
</div>
|
|
102
|
+
{showExtraPages && (
|
|
103
|
+
<div className="flex items-center justify-between gap-4 border-t pt-1 mt-1">
|
|
104
|
+
<span className="text-muted-foreground">
|
|
105
|
+
{t("generic.tokens.available_extra", { defaultValue: "Extra Pages" })}:
|
|
106
|
+
</span>
|
|
107
|
+
<span className="font-medium text-blue-500">{availableExtraTokens}</span>
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Tooltip>
|
|
116
|
+
<TooltipTrigger>
|
|
117
|
+
<div
|
|
118
|
+
className={cn("inline-flex items-center gap-1.5 cursor-default", className)}
|
|
119
|
+
aria-label={t("generic.tokens.status", { defaultValue: "Page Status" })}
|
|
120
|
+
>
|
|
121
|
+
{getBatteryIcon()}
|
|
122
|
+
<span className={cn(textSize, "text-muted-foreground font-medium")}>{availableMonthlyTokens}</span>
|
|
123
|
+
{showExtraPages && availableExtraTokens > 0 && (
|
|
124
|
+
<div className="inline-flex items-center gap-0.5">
|
|
125
|
+
<PlusCircle className={cn(smallIconSize, "text-blue-500")} />
|
|
126
|
+
<span className={cn(textSize, "text-blue-500 font-medium")}>{availableExtraTokens}</span>
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
</TooltipTrigger>
|
|
131
|
+
<TooltipContent side="top" className="max-w-xs">
|
|
132
|
+
{tooltipContent}
|
|
133
|
+
</TooltipContent>
|
|
134
|
+
</Tooltip>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -8,8 +8,9 @@ export type CompanyInput = {
|
|
|
8
8
|
logo?: string;
|
|
9
9
|
configurations?: any;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
monthlyTokens?: number;
|
|
12
|
+
availableMonthlyTokens?: number;
|
|
13
|
+
availableExtraTokens?: number;
|
|
13
14
|
|
|
14
15
|
featureIds?: string[];
|
|
15
16
|
moduleIds?: string[];
|
|
@@ -21,7 +22,9 @@ export interface CompanyInterface extends ApiDataInterface {
|
|
|
21
22
|
get logo(): string | undefined;
|
|
22
23
|
get logoUrl(): string | undefined;
|
|
23
24
|
|
|
24
|
-
get
|
|
25
|
+
get monthlyTokens(): number;
|
|
26
|
+
get availableMonthlyTokens(): number;
|
|
27
|
+
get availableExtraTokens(): number;
|
|
25
28
|
|
|
26
29
|
get features(): FeatureInterface[];
|
|
27
30
|
get modules(): ModuleInterface[];
|