@carlonicora/nextjs-jsonapi 1.142.0 → 1.143.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/AbstractService-B0T7h8fX.d.mts +124 -0
- package/dist/AbstractService-Cew0PD0L.d.ts +124 -0
- package/dist/{AuthComponent-DdxCFgUZ.d.mts → AuthComponent-Cik96ElA.d.mts} +1 -1
- package/dist/{AuthComponent-Cd7lcYif.d.ts → AuthComponent-DTTKu3VK.d.ts} +1 -1
- package/dist/{BlockNoteEditor-35DDJH3M.mjs → BlockNoteEditor-34QM4UR5.mjs} +4 -4
- package/dist/{BlockNoteEditor-XXTBZ7DD.js → BlockNoteEditor-LMKWUOJG.js} +19 -19
- package/dist/{BlockNoteEditor-XXTBZ7DD.js.map → BlockNoteEditor-LMKWUOJG.js.map} +1 -1
- package/dist/billing/index.js +357 -357
- package/dist/billing/index.mjs +3 -3
- package/dist/{chunk-KZHHKPQZ.mjs → chunk-BIL2WQEV.mjs} +247 -1
- package/dist/chunk-BIL2WQEV.mjs.map +1 -0
- package/dist/{chunk-5SFFHIEE.js → chunk-DS4IBFWA.js} +252 -6
- package/dist/chunk-DS4IBFWA.js.map +1 -0
- package/dist/{chunk-7CR4YB7Y.js → chunk-F6PZZ4KI.js} +730 -730
- package/dist/{chunk-7CR4YB7Y.js.map → chunk-F6PZZ4KI.js.map} +1 -1
- package/dist/{chunk-ZV2GZKFR.mjs → chunk-HN5ED7OF.mjs} +2 -2
- package/dist/{chunk-FZ5SPJEU.mjs → chunk-UGSOBBZH.mjs} +4 -4
- package/dist/{chunk-C6UXEPNY.js → chunk-UXJAS6C5.js} +7 -7
- package/dist/{chunk-C6UXEPNY.js.map → chunk-UXJAS6C5.js.map} +1 -1
- package/dist/client/index.d.mts +3 -3
- package/dist/client/index.d.ts +3 -3
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +3 -3
- package/dist/components/index.d.mts +3 -3
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.js +4 -4
- package/dist/components/index.mjs +3 -3
- package/dist/{config-BrkU_Ynz.d.ts → config-Cd5xTEfZ.d.ts} +1 -1
- package/dist/{config-snd2ToEB.d.mts → config-YyhFHxkU.d.mts} +1 -1
- package/dist/contexts/index.d.mts +1 -1
- package/dist/contexts/index.d.ts +1 -1
- package/dist/contexts/index.js +4 -4
- package/dist/contexts/index.mjs +3 -3
- package/dist/core/index.d.mts +13 -49
- package/dist/core/index.d.ts +13 -49
- package/dist/core/index.js +8 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +7 -1
- package/dist/features/help/index.d.mts +2 -2
- package/dist/features/help/index.d.ts +2 -2
- package/dist/features/help/index.js +37 -37
- package/dist/features/help/index.mjs +3 -3
- package/dist/features/tokenusage/index.css +29 -0
- package/dist/features/tokenusage/index.css.map +1 -0
- package/dist/features/tokenusage/index.d.mts +388 -0
- package/dist/features/tokenusage/index.d.ts +388 -0
- package/dist/features/tokenusage/index.js +1012 -0
- package/dist/features/tokenusage/index.js.map +1 -0
- package/dist/features/tokenusage/index.mjs +1012 -0
- package/dist/features/tokenusage/index.mjs.map +1 -0
- package/dist/index.d.mts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -2
- package/dist/{s3.service-Dmfxpn-k.d.ts → s3.service-CpwA3sl_.d.ts} +2 -123
- package/dist/{s3.service-DYflLXCt.d.mts → s3.service-Dt6MfuHr.d.mts} +2 -123
- package/dist/server/index.d.mts +3 -2
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +1 -1
- package/dist/tokenusage-admin.module-5wJ_tZTj.d.ts +61 -0
- package/dist/tokenusage-admin.module-DQVT4O4j.d.mts +61 -0
- package/dist/{types-CQSjy7et.d.mts → types-Bq_UA8Lg.d.mts} +1 -1
- package/dist/{types-DHOxe8rc.d.ts → types-bsm8Fp55.d.ts} +1 -1
- package/dist/{usePageUrlGenerator-tjq2mlDV.d.ts → usePageUrlGenerator-J_ECv-oQ.d.ts} +1 -1
- package/dist/{usePageUrlGenerator-uOnyJ6j2.d.mts → usePageUrlGenerator-uKBjAKqC.d.mts} +1 -1
- package/package.json +6 -1
- package/src/core/index.ts +5 -0
- package/src/core/registry/ModuleRegistry.ts +4 -0
- package/src/features/tokenusage/components/TokenUsageAdminContainer.tsx +189 -0
- package/src/features/tokenusage/components/TokenUsageAdminFilterBar.tsx +138 -0
- package/src/features/tokenusage/components/TokenUsageAdminTiles.tsx +177 -0
- package/src/features/tokenusage/components/TokenUsageBreakdownTable.tsx +160 -0
- package/src/features/tokenusage/components/TokenUsageRankedBar.tsx +99 -0
- package/src/features/tokenusage/components/TokenUsageTimelineChart.tsx +225 -0
- package/src/features/tokenusage/components/__tests__/TokenUsageAdminTiles.spec.tsx +42 -0
- package/src/features/tokenusage/components/__tests__/TokenUsageRankedBar.spec.tsx +41 -0
- package/src/features/tokenusage/components/__tests__/TokenUsageTimelineChart.spec.tsx +47 -0
- package/src/features/tokenusage/contexts/TokenUsageAdminContext.tsx +252 -0
- package/src/features/tokenusage/contexts/__tests__/TokenUsageAdminContext.spec.tsx +80 -0
- package/src/features/tokenusage/data/TokenUsageAdminService.ts +54 -0
- package/src/features/tokenusage/data/__tests__/tokenusage-admin-models.spec.ts +147 -0
- package/src/features/tokenusage/data/index.ts +8 -0
- package/src/features/tokenusage/data/tokenusage-admin-breakdown.interface.ts +18 -0
- package/src/features/tokenusage/data/tokenusage-admin-breakdown.ts +115 -0
- package/src/features/tokenusage/data/tokenusage-admin-summary.interface.ts +14 -0
- package/src/features/tokenusage/data/tokenusage-admin-summary.ts +90 -0
- package/src/features/tokenusage/data/tokenusage-admin-timeline.interface.ts +13 -0
- package/src/features/tokenusage/data/tokenusage-admin-timeline.ts +94 -0
- package/src/features/tokenusage/data/tokenusage-admin.types.ts +56 -0
- package/src/features/tokenusage/i18n-keys.ts +65 -0
- package/src/features/tokenusage/index.ts +30 -0
- package/src/features/tokenusage/lib/metrics.ts +69 -0
- package/src/features/tokenusage/lib/operation-label.ts +41 -0
- package/src/features/tokenusage/lib/palette.ts +197 -0
- package/src/features/tokenusage/tokenusage-admin.module.ts +22 -0
- package/dist/chunk-5SFFHIEE.js.map +0 -1
- package/dist/chunk-KZHHKPQZ.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-35DDJH3M.mjs.map → BlockNoteEditor-34QM4UR5.mjs.map} +0 -0
- /package/dist/{chunk-ZV2GZKFR.mjs.map → chunk-HN5ED7OF.mjs.map} +0 -0
- /package/dist/{chunk-FZ5SPJEU.mjs.map → chunk-UGSOBBZH.mjs.map} +0 -0
|
@@ -1,129 +1,8 @@
|
|
|
1
|
+
import { A as AbstractService, N as NextRef, P as PreviousRef } from './AbstractService-B0T7h8fX.mjs';
|
|
1
2
|
import { F as FeatureInterface } from './feature.interface-CXb1-vNq.mjs';
|
|
2
3
|
import { e as RoleInterface, U as UserInterface, f as UserInput, c as CompanyInterface, b as CompanyInput, C as ContentInterface, N as NotificationInterface } from './notification.interface-CG1vqoxg.mjs';
|
|
3
4
|
import { A as ApiDataInterface, J as JsonApiHydratedDataInterface } from './ApiDataInterface-BcZeXy5X.mjs';
|
|
4
5
|
import { A as AuthInput, b as AuthInterface } from './auth.interface-CkmZqat3.mjs';
|
|
5
|
-
import { A as ApiRequestDataTypeInterface } from './ApiRequestDataTypeInterface-CYEcRUrh.mjs';
|
|
6
|
-
|
|
7
|
-
declare enum HttpMethod {
|
|
8
|
-
GET = "GET",
|
|
9
|
-
POST = "POST",
|
|
10
|
-
PUT = "PUT",
|
|
11
|
-
PATCH = "PATCH",
|
|
12
|
-
DELETE = "DELETE"
|
|
13
|
-
}
|
|
14
|
-
interface NextRef {
|
|
15
|
-
next?: string;
|
|
16
|
-
}
|
|
17
|
-
interface PreviousRef {
|
|
18
|
-
previous?: string;
|
|
19
|
-
}
|
|
20
|
-
interface SelfRef {
|
|
21
|
-
self?: string;
|
|
22
|
-
}
|
|
23
|
-
interface TotalRef {
|
|
24
|
-
total?: number;
|
|
25
|
-
}
|
|
26
|
-
declare function getLastApiTotal(): number | undefined;
|
|
27
|
-
declare function clearLastApiTotal(): void;
|
|
28
|
-
declare function getLastApiMeta(): Record<string, any> | undefined;
|
|
29
|
-
declare function clearLastApiMeta(): void;
|
|
30
|
-
/**
|
|
31
|
-
* Set a global error handler for API errors (client-side only).
|
|
32
|
-
* This handler will be called instead of throwing errors.
|
|
33
|
-
*/
|
|
34
|
-
declare function setGlobalErrorHandler(handler: (status: number, message: string) => void): void;
|
|
35
|
-
/**
|
|
36
|
-
* Get the current global error handler.
|
|
37
|
-
*/
|
|
38
|
-
declare function getGlobalErrorHandler(): ((status: number, message: string) => void) | null;
|
|
39
|
-
/**
|
|
40
|
-
* Abstract base class for services that interact with the JSON:API.
|
|
41
|
-
* Extend this class to create feature-specific services.
|
|
42
|
-
*/
|
|
43
|
-
declare abstract class AbstractService {
|
|
44
|
-
/**
|
|
45
|
-
* Extract locale from client-side URL pathname
|
|
46
|
-
* URL structure: /{locale}/route-path (e.g., /it/accounts)
|
|
47
|
-
* Fallback chain: URL locale → navigator.language → "en"
|
|
48
|
-
*/
|
|
49
|
-
private static getClientLocale;
|
|
50
|
-
static next<T>(params: {
|
|
51
|
-
type: ApiRequestDataTypeInterface;
|
|
52
|
-
endpoint: string;
|
|
53
|
-
next?: NextRef;
|
|
54
|
-
previous?: PreviousRef;
|
|
55
|
-
self?: SelfRef;
|
|
56
|
-
total?: TotalRef;
|
|
57
|
-
}): Promise<T>;
|
|
58
|
-
/**
|
|
59
|
-
* Fetch the previous page of results.
|
|
60
|
-
*/
|
|
61
|
-
static previous<T>(params: {
|
|
62
|
-
type: ApiRequestDataTypeInterface;
|
|
63
|
-
endpoint: string;
|
|
64
|
-
next?: NextRef;
|
|
65
|
-
previous?: PreviousRef;
|
|
66
|
-
self?: SelfRef;
|
|
67
|
-
total?: TotalRef;
|
|
68
|
-
}): Promise<T>;
|
|
69
|
-
/**
|
|
70
|
-
* Make an API call with automatic environment detection and error handling.
|
|
71
|
-
*/
|
|
72
|
-
protected static callApi<T>(params: {
|
|
73
|
-
type: ApiRequestDataTypeInterface;
|
|
74
|
-
method: HttpMethod;
|
|
75
|
-
endpoint: string;
|
|
76
|
-
companyId?: string;
|
|
77
|
-
input?: any;
|
|
78
|
-
overridesJsonApiCreation?: boolean;
|
|
79
|
-
next?: NextRef;
|
|
80
|
-
previous?: PreviousRef;
|
|
81
|
-
self?: SelfRef;
|
|
82
|
-
total?: TotalRef;
|
|
83
|
-
responseType?: ApiRequestDataTypeInterface;
|
|
84
|
-
files?: {
|
|
85
|
-
[key: string]: File | Blob;
|
|
86
|
-
} | File | Blob;
|
|
87
|
-
token?: string;
|
|
88
|
-
suppressGlobalError?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
* Per-call override of the API base URL. When omitted, the existing global
|
|
91
|
-
* `NEXT_PUBLIC_API_URL` (or `configureJsonApi({ apiUrl })`) resolution is used —
|
|
92
|
-
* fully backward compatible. Ignored when `endpoint` starts with "http" (passthrough).
|
|
93
|
-
*/
|
|
94
|
-
baseUrl?: string;
|
|
95
|
-
}): Promise<T>;
|
|
96
|
-
/**
|
|
97
|
-
* Make an API call and return both data and meta from the response.
|
|
98
|
-
*/
|
|
99
|
-
protected static callApiWithMeta<T>(params: {
|
|
100
|
-
type: ApiRequestDataTypeInterface;
|
|
101
|
-
method: HttpMethod;
|
|
102
|
-
endpoint: string;
|
|
103
|
-
companyId?: string;
|
|
104
|
-
input?: any;
|
|
105
|
-
overridesJsonApiCreation?: boolean;
|
|
106
|
-
responseType?: ApiRequestDataTypeInterface;
|
|
107
|
-
files?: {
|
|
108
|
-
[key: string]: File | Blob;
|
|
109
|
-
} | File | Blob;
|
|
110
|
-
suppressGlobalError?: boolean;
|
|
111
|
-
}): Promise<{
|
|
112
|
-
data: T;
|
|
113
|
-
meta?: Record<string, any>;
|
|
114
|
-
}>;
|
|
115
|
-
/**
|
|
116
|
-
* Get raw JSON:API response data without deserialization.
|
|
117
|
-
*/
|
|
118
|
-
protected static getRawData(params: {
|
|
119
|
-
type: ApiRequestDataTypeInterface;
|
|
120
|
-
method: HttpMethod;
|
|
121
|
-
endpoint: string;
|
|
122
|
-
companyId?: string;
|
|
123
|
-
baseUrl?: string;
|
|
124
|
-
suppressGlobalError?: boolean;
|
|
125
|
-
}): Promise<any>;
|
|
126
|
-
}
|
|
127
6
|
|
|
128
7
|
declare class FeatureService extends AbstractService {
|
|
129
8
|
static findMany(params: {
|
|
@@ -388,4 +267,4 @@ declare class S3Service extends AbstractService {
|
|
|
388
267
|
}): Promise<void>;
|
|
389
268
|
}
|
|
390
269
|
|
|
391
|
-
export { AuthService as A, CompanyService as C, FeatureService as F,
|
|
270
|
+
export { AuthService as A, CompanyService as C, FeatureService as F, NotificationService as N, PushService as P, RoleService as R, S3Service as S, type TwoFactorChallengeInterface as T, UserService as U, ContentService as a, type S3Input as b, type S3Interface as c };
|
package/dist/server/index.d.mts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { A as ApiData } from '../ApiData-DPKNfY-9.mjs';
|
|
2
|
-
import { M as ModuleWithPermissions, A as Action } from '../types-
|
|
2
|
+
import { M as ModuleWithPermissions, A as Action } from '../types-Bq_UA8Lg.mjs';
|
|
3
3
|
import { A as ApiRequestDataTypeInterface } from '../ApiRequestDataTypeInterface-CYEcRUrh.mjs';
|
|
4
4
|
import { A as ApiResponseInterface } from '../ApiResponseInterface-rsXRL_Hn.mjs';
|
|
5
|
-
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-
|
|
5
|
+
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-Dt6MfuHr.mjs';
|
|
6
6
|
import 'lucide-react';
|
|
7
7
|
import '../ApiDataInterface-BcZeXy5X.mjs';
|
|
8
|
+
import '../AbstractService-B0T7h8fX.mjs';
|
|
8
9
|
import '../feature.interface-CXb1-vNq.mjs';
|
|
9
10
|
import '../notification.interface-CG1vqoxg.mjs';
|
|
10
11
|
import '../auth.interface-CkmZqat3.mjs';
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { A as ApiData } from '../ApiData-DPKNfY-9.js';
|
|
2
|
-
import { M as ModuleWithPermissions, A as Action } from '../types-
|
|
2
|
+
import { M as ModuleWithPermissions, A as Action } from '../types-bsm8Fp55.js';
|
|
3
3
|
import { A as ApiRequestDataTypeInterface } from '../ApiRequestDataTypeInterface-CYEcRUrh.js';
|
|
4
4
|
import { A as ApiResponseInterface } from '../ApiResponseInterface-CWLvSCvS.js';
|
|
5
|
-
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-
|
|
5
|
+
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-CpwA3sl_.js';
|
|
6
6
|
import 'lucide-react';
|
|
7
7
|
import '../ApiDataInterface-BcZeXy5X.js';
|
|
8
|
+
import '../AbstractService-Cew0PD0L.js';
|
|
8
9
|
import '../feature.interface-BO25VLlx.js';
|
|
9
10
|
import '../notification.interface--27exGde.js';
|
|
10
11
|
import '../auth.interface-COmBjh89.js';
|
package/dist/server/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var _chunkIOLU4ASDjs = require('../chunk-IOLU4ASD.js');
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
var
|
|
18
|
+
var _chunkDS4IBFWAjs = require('../chunk-DS4IBFWA.js');
|
|
19
19
|
require('../chunk-LXKSUWAV.js');
|
|
20
20
|
require('../chunk-IBS6NI7D.js');
|
|
21
21
|
|
|
@@ -86,7 +86,7 @@ var ServerSession = class {
|
|
|
86
86
|
if (!rawModules) return false;
|
|
87
87
|
const modules = JSON.parse(_pako.ungzip.call(void 0, Buffer.from(rawModules, "base64"), { toText: true }));
|
|
88
88
|
const selectedModule = modules.find((module) => module.id === params.module.moduleId);
|
|
89
|
-
return
|
|
89
|
+
return _chunkDS4IBFWAjs.checkPermissionsFromServer.call(void 0, {
|
|
90
90
|
module: params.module,
|
|
91
91
|
action: params.action,
|
|
92
92
|
data: params.data,
|
|
@@ -296,5 +296,5 @@ _chunk7QVYU63Ejs.__name.call(void 0, ServerJsonApiDelete, "ServerJsonApiDelete")
|
|
|
296
296
|
|
|
297
297
|
|
|
298
298
|
|
|
299
|
-
exports.ServerAuthService =
|
|
299
|
+
exports.ServerAuthService = _chunkDS4IBFWAjs.AuthService; exports.ServerCompanyService = _chunkDS4IBFWAjs.CompanyService; exports.ServerContentService = _chunkDS4IBFWAjs.ContentService; exports.ServerFeatureService = _chunkDS4IBFWAjs.FeatureService; exports.ServerJsonApiDelete = ServerJsonApiDelete; exports.ServerJsonApiGet = ServerJsonApiGet; exports.ServerJsonApiPatch = ServerJsonApiPatch; exports.ServerJsonApiPost = ServerJsonApiPost; exports.ServerJsonApiPut = ServerJsonApiPut; exports.ServerNotificationService = _chunkDS4IBFWAjs.NotificationService; exports.ServerPushService = _chunkDS4IBFWAjs.PushService; exports.ServerRoleService = _chunkDS4IBFWAjs.RoleService; exports.ServerS3Service = _chunkDS4IBFWAjs.S3Service; exports.ServerSession = ServerSession; exports.ServerUserService = _chunkDS4IBFWAjs.UserService; exports.configureServerJsonApi = configureServerJsonApi; exports.getServerApiUrl = getServerApiUrl; exports.getServerAppUrl = getServerAppUrl; exports.getServerToken = _chunkYUO55Q5Ajs.getServerToken; exports.getServerTrackablePages = getServerTrackablePages; exports.invalidateCacheTag = invalidateCacheTag; exports.invalidateCacheTags = invalidateCacheTags; exports.serverRequest = _chunkIOLU4ASDjs.serverRequest;
|
|
300
300
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.mjs
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { A as ApiDataInterface, J as JsonApiHydratedDataInterface } from './ApiDataInterface-BcZeXy5X.js';
|
|
2
|
+
import { A as ApiRequestDataTypeInterface } from './ApiRequestDataTypeInterface-CYEcRUrh.js';
|
|
3
|
+
import { a as ModuleFactory, M as ModuleWithPermissions } from './types-bsm8Fp55.js';
|
|
4
|
+
|
|
5
|
+
declare abstract class AbstractApiData implements ApiDataInterface {
|
|
6
|
+
static identifierFields: string[];
|
|
7
|
+
get identifier(): string;
|
|
8
|
+
protected _jsonApi?: any;
|
|
9
|
+
protected _included?: any[];
|
|
10
|
+
protected _id?: string;
|
|
11
|
+
protected _type?: string;
|
|
12
|
+
protected _createdAt?: Date;
|
|
13
|
+
protected _updatedAt?: Date;
|
|
14
|
+
protected _self?: string;
|
|
15
|
+
get type(): string;
|
|
16
|
+
get id(): string;
|
|
17
|
+
get self(): string | undefined;
|
|
18
|
+
get createdAt(): Date;
|
|
19
|
+
get updatedAt(): Date;
|
|
20
|
+
get included(): any[];
|
|
21
|
+
get jsonApi(): any;
|
|
22
|
+
ingestJsonApi(_data: JsonApiHydratedDataInterface): void;
|
|
23
|
+
generateApiUrl(_params?: any): string;
|
|
24
|
+
createJsonApi(_data?: any): any;
|
|
25
|
+
protected _readIncluded<T extends ApiDataInterface>(data: JsonApiHydratedDataInterface, type: string, dataType: ApiRequestDataTypeInterface): T | T[] | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Read included relationships with polymorphic type resolution.
|
|
28
|
+
* Determines the correct model class based on the JSON:API type in included data.
|
|
29
|
+
*/
|
|
30
|
+
protected _readIncludedPolymorphic<T extends ApiDataInterface>(data: JsonApiHydratedDataInterface, relationshipKey: string, candidateModules: ApiRequestDataTypeInterface[]): T | T[] | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Read included relationship data and augment with relationship meta properties.
|
|
33
|
+
* Handles both single relationships (one-to-one) and array relationships (one-to-many).
|
|
34
|
+
*
|
|
35
|
+
* For single relationships: meta is read from `relationships[type].meta`
|
|
36
|
+
* For array relationships: per-item meta is read from `relationships[type].data[].meta`
|
|
37
|
+
*
|
|
38
|
+
* @param data - Hydrated JSON:API data
|
|
39
|
+
* @param type - Relationship type key (e.g., "guide", "persons")
|
|
40
|
+
* @param dataType - Module reference for rehydration
|
|
41
|
+
* @returns Related object(s) augmented with meta properties, or undefined
|
|
42
|
+
*/
|
|
43
|
+
protected _readIncludedWithMeta<T extends ApiDataInterface, M extends Record<string, any>>(data: JsonApiHydratedDataInterface, type: string, dataType: ApiRequestDataTypeInterface): (T & M) | (T & M)[] | undefined;
|
|
44
|
+
dehydrate(): JsonApiHydratedDataInterface;
|
|
45
|
+
rehydrate(data: JsonApiHydratedDataInterface): this;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Read-only reporting resources behind the administrative token-usage page.
|
|
50
|
+
* `name` is the endpoint path EndpointCreator builds URLs from; there is no
|
|
51
|
+
* pageUrl because these are not navigable resources.
|
|
52
|
+
*
|
|
53
|
+
* Distinct from the consuming app's own TokenUsage module (name "tokenusages",
|
|
54
|
+
* pageUrl "/tokenusage") — that one is an AppModuleDefinitions entry the package
|
|
55
|
+
* cannot reference, which is why these three exist.
|
|
56
|
+
*/
|
|
57
|
+
declare const TokenUsageAdminSummaryModule: (factory: ModuleFactory) => ModuleWithPermissions;
|
|
58
|
+
declare const TokenUsageAdminTimelineModule: (factory: ModuleFactory) => ModuleWithPermissions;
|
|
59
|
+
declare const TokenUsageAdminBreakdownModule: (factory: ModuleFactory) => ModuleWithPermissions;
|
|
60
|
+
|
|
61
|
+
export { AbstractApiData as A, TokenUsageAdminSummaryModule as T, TokenUsageAdminTimelineModule as a, TokenUsageAdminBreakdownModule as b };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { A as ApiDataInterface, J as JsonApiHydratedDataInterface } from './ApiDataInterface-BcZeXy5X.mjs';
|
|
2
|
+
import { A as ApiRequestDataTypeInterface } from './ApiRequestDataTypeInterface-CYEcRUrh.mjs';
|
|
3
|
+
import { a as ModuleFactory, M as ModuleWithPermissions } from './types-Bq_UA8Lg.mjs';
|
|
4
|
+
|
|
5
|
+
declare abstract class AbstractApiData implements ApiDataInterface {
|
|
6
|
+
static identifierFields: string[];
|
|
7
|
+
get identifier(): string;
|
|
8
|
+
protected _jsonApi?: any;
|
|
9
|
+
protected _included?: any[];
|
|
10
|
+
protected _id?: string;
|
|
11
|
+
protected _type?: string;
|
|
12
|
+
protected _createdAt?: Date;
|
|
13
|
+
protected _updatedAt?: Date;
|
|
14
|
+
protected _self?: string;
|
|
15
|
+
get type(): string;
|
|
16
|
+
get id(): string;
|
|
17
|
+
get self(): string | undefined;
|
|
18
|
+
get createdAt(): Date;
|
|
19
|
+
get updatedAt(): Date;
|
|
20
|
+
get included(): any[];
|
|
21
|
+
get jsonApi(): any;
|
|
22
|
+
ingestJsonApi(_data: JsonApiHydratedDataInterface): void;
|
|
23
|
+
generateApiUrl(_params?: any): string;
|
|
24
|
+
createJsonApi(_data?: any): any;
|
|
25
|
+
protected _readIncluded<T extends ApiDataInterface>(data: JsonApiHydratedDataInterface, type: string, dataType: ApiRequestDataTypeInterface): T | T[] | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Read included relationships with polymorphic type resolution.
|
|
28
|
+
* Determines the correct model class based on the JSON:API type in included data.
|
|
29
|
+
*/
|
|
30
|
+
protected _readIncludedPolymorphic<T extends ApiDataInterface>(data: JsonApiHydratedDataInterface, relationshipKey: string, candidateModules: ApiRequestDataTypeInterface[]): T | T[] | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Read included relationship data and augment with relationship meta properties.
|
|
33
|
+
* Handles both single relationships (one-to-one) and array relationships (one-to-many).
|
|
34
|
+
*
|
|
35
|
+
* For single relationships: meta is read from `relationships[type].meta`
|
|
36
|
+
* For array relationships: per-item meta is read from `relationships[type].data[].meta`
|
|
37
|
+
*
|
|
38
|
+
* @param data - Hydrated JSON:API data
|
|
39
|
+
* @param type - Relationship type key (e.g., "guide", "persons")
|
|
40
|
+
* @param dataType - Module reference for rehydration
|
|
41
|
+
* @returns Related object(s) augmented with meta properties, or undefined
|
|
42
|
+
*/
|
|
43
|
+
protected _readIncludedWithMeta<T extends ApiDataInterface, M extends Record<string, any>>(data: JsonApiHydratedDataInterface, type: string, dataType: ApiRequestDataTypeInterface): (T & M) | (T & M)[] | undefined;
|
|
44
|
+
dehydrate(): JsonApiHydratedDataInterface;
|
|
45
|
+
rehydrate(data: JsonApiHydratedDataInterface): this;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Read-only reporting resources behind the administrative token-usage page.
|
|
50
|
+
* `name` is the endpoint path EndpointCreator builds URLs from; there is no
|
|
51
|
+
* pageUrl because these are not navigable resources.
|
|
52
|
+
*
|
|
53
|
+
* Distinct from the consuming app's own TokenUsage module (name "tokenusages",
|
|
54
|
+
* pageUrl "/tokenusage") — that one is an AppModuleDefinitions entry the package
|
|
55
|
+
* cannot reference, which is why these three exist.
|
|
56
|
+
*/
|
|
57
|
+
declare const TokenUsageAdminSummaryModule: (factory: ModuleFactory) => ModuleWithPermissions;
|
|
58
|
+
declare const TokenUsageAdminTimelineModule: (factory: ModuleFactory) => ModuleWithPermissions;
|
|
59
|
+
declare const TokenUsageAdminBreakdownModule: (factory: ModuleFactory) => ModuleWithPermissions;
|
|
60
|
+
|
|
61
|
+
export { AbstractApiData as A, TokenUsageAdminSummaryModule as T, TokenUsageAdminTimelineModule as a, TokenUsageAdminBreakdownModule as b };
|
|
@@ -98,4 +98,4 @@ type ModuleFactory = (params: {
|
|
|
98
98
|
}>;
|
|
99
99
|
}) => ModuleWithPermissions;
|
|
100
100
|
|
|
101
|
-
export { Action as A, type ModuleWithPermissions as M, type PageUrl as P, type
|
|
101
|
+
export { Action as A, type ModuleWithPermissions as M, type PageUrl as P, type ModuleFactory as a, type PermissionCheck as b, type ModulePermissionDefinition as c, type ModuleDefinition as d, type PermissionConfig as e, type PermissionModule as f, type PermissionUser as g };
|
|
@@ -98,4 +98,4 @@ type ModuleFactory = (params: {
|
|
|
98
98
|
}>;
|
|
99
99
|
}) => ModuleWithPermissions;
|
|
100
100
|
|
|
101
|
-
export { Action as A, type ModuleWithPermissions as M, type PageUrl as P, type
|
|
101
|
+
export { Action as A, type ModuleWithPermissions as M, type PageUrl as P, type ModuleFactory as a, type PermissionCheck as b, type ModulePermissionDefinition as c, type ModuleDefinition as d, type PermissionConfig as e, type PermissionModule as f, type PermissionUser as g };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carlonicora/nextjs-jsonapi",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.143.0",
|
|
4
4
|
"description": "Next.js JSON:API client with server/client support and caching",
|
|
5
5
|
"author": "Carlo Nicora",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -62,6 +62,11 @@
|
|
|
62
62
|
"types": "./dist/features/help/server.d.ts",
|
|
63
63
|
"import": "./dist/features/help/server.mjs",
|
|
64
64
|
"require": "./dist/features/help/server.js"
|
|
65
|
+
},
|
|
66
|
+
"./tokenusage": {
|
|
67
|
+
"types": "./dist/features/tokenusage/index.d.ts",
|
|
68
|
+
"import": "./dist/features/tokenusage/index.mjs",
|
|
69
|
+
"require": "./dist/features/tokenusage/index.js"
|
|
65
70
|
}
|
|
66
71
|
},
|
|
67
72
|
"scripts": {
|
package/src/core/index.ts
CHANGED
|
@@ -91,4 +91,9 @@ export * from "../features/rbac/rbac.module";
|
|
|
91
91
|
export * from "../features/referral/data";
|
|
92
92
|
export * from "../features/referral/referral.module";
|
|
93
93
|
export * from "../features/referral/referral-stats.module";
|
|
94
|
+
// Administrative token-usage reporting modules. Exported from core (not only
|
|
95
|
+
// from the client-marked ./tokenusage barrel) so a consuming app can register
|
|
96
|
+
// them in its bootstrapper without pulling the feature's client bundle —
|
|
97
|
+
// same placement as waitlist-stats and referral-stats above.
|
|
98
|
+
export * from "../features/tokenusage/tokenusage-admin.module";
|
|
94
99
|
export * from "../features/audit-log";
|
|
@@ -58,6 +58,10 @@ export interface FoundationModuleDefinitions {
|
|
|
58
58
|
RbacMatrix: ModuleWithPermissions;
|
|
59
59
|
// Audit modules
|
|
60
60
|
AuditLog: ModuleWithPermissions;
|
|
61
|
+
// Administrative token-usage reporting modules
|
|
62
|
+
TokenUsageAdminSummary: ModuleWithPermissions;
|
|
63
|
+
TokenUsageAdminTimeline: ModuleWithPermissions;
|
|
64
|
+
TokenUsageAdminBreakdown: ModuleWithPermissions;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
// App-specific modules - apps will augment this interface ONLY
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../../lib/utils";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { RoundPageContainer } from "../../../components";
|
|
7
|
+
import {
|
|
8
|
+
Card,
|
|
9
|
+
CardAction,
|
|
10
|
+
CardContent,
|
|
11
|
+
CardHeader,
|
|
12
|
+
CardTitle,
|
|
13
|
+
Select,
|
|
14
|
+
SelectContent,
|
|
15
|
+
SelectItem,
|
|
16
|
+
SelectTrigger,
|
|
17
|
+
SelectValue,
|
|
18
|
+
} from "../../../shadcnui";
|
|
19
|
+
import { useTokenUsageAdmin } from "../contexts/TokenUsageAdminContext";
|
|
20
|
+
import type { StackBy } from "../data/tokenusage-admin.types";
|
|
21
|
+
import { TokenUsageAdminTiles } from "./TokenUsageAdminTiles";
|
|
22
|
+
import { TokenUsageBreakdownTable } from "./TokenUsageBreakdownTable";
|
|
23
|
+
import { TokenUsageRankedBar } from "./TokenUsageRankedBar";
|
|
24
|
+
import { TokenUsageTimelineChart } from "./TokenUsageTimelineChart";
|
|
25
|
+
|
|
26
|
+
const STACK_BY_VALUES: StackBy[] = ["scope", "type", "company"];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Page body for the administrative token-usage dashboard.
|
|
30
|
+
*
|
|
31
|
+
* Stateless by design — every value it renders comes from
|
|
32
|
+
* `useTokenUsageAdmin()`. The filter bar is deliberately NOT here: it belongs to
|
|
33
|
+
* the page title bar, which `RoundPageContainer` fills from `SharedContext`, so
|
|
34
|
+
* the provider publishes it (see TokenUsageAdminContext).
|
|
35
|
+
*/
|
|
36
|
+
export function TokenUsageAdminContainer() {
|
|
37
|
+
const t = useTranslations();
|
|
38
|
+
const {
|
|
39
|
+
summary,
|
|
40
|
+
timeline,
|
|
41
|
+
byCompany,
|
|
42
|
+
byUser,
|
|
43
|
+
byOperation,
|
|
44
|
+
byCustomerOperation,
|
|
45
|
+
filters,
|
|
46
|
+
setFilters,
|
|
47
|
+
singleCustomerMode,
|
|
48
|
+
isLoading,
|
|
49
|
+
error,
|
|
50
|
+
} = useTokenUsageAdmin();
|
|
51
|
+
|
|
52
|
+
const stackByItems = useMemo(
|
|
53
|
+
() => ({
|
|
54
|
+
scope: t("token_usage.admin.stack.scope"),
|
|
55
|
+
type: t("token_usage.admin.stack.type"),
|
|
56
|
+
company: t("token_usage.admin.stack.company"),
|
|
57
|
+
}),
|
|
58
|
+
[t],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (error) {
|
|
62
|
+
return (
|
|
63
|
+
<RoundPageContainer fullWidth forceHeader>
|
|
64
|
+
<div className="p-4">
|
|
65
|
+
<Card>
|
|
66
|
+
<CardContent>
|
|
67
|
+
<p className="text-destructive text-xs/relaxed">{error}</p>
|
|
68
|
+
</CardContent>
|
|
69
|
+
</Card>
|
|
70
|
+
</div>
|
|
71
|
+
</RoundPageContainer>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Loading renders nothing in the body: the title bar (with the filter bar) is
|
|
76
|
+
// already mounted, so a spinner would only make the controls jump on arrival.
|
|
77
|
+
if (isLoading) return <RoundPageContainer fullWidth forceHeader />;
|
|
78
|
+
|
|
79
|
+
const emptyLabel = t("token_usage.admin.no_data");
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<RoundPageContainer fullWidth forceHeader>
|
|
83
|
+
<div className="flex w-full flex-col gap-4 p-4">
|
|
84
|
+
<TokenUsageAdminTiles summary={summary} metric={filters.metric} singleCustomerMode={singleCustomerMode} />
|
|
85
|
+
|
|
86
|
+
<Card>
|
|
87
|
+
<CardHeader>
|
|
88
|
+
<CardTitle>{t("token_usage.admin.usage_over_time")}</CardTitle>
|
|
89
|
+
<CardAction>
|
|
90
|
+
<div className="flex items-center gap-2">
|
|
91
|
+
<span className="text-muted-foreground text-xs">{t("token_usage.admin.stack_by")}</span>
|
|
92
|
+
<Select
|
|
93
|
+
items={stackByItems}
|
|
94
|
+
value={filters.stackBy}
|
|
95
|
+
onValueChange={(value) => {
|
|
96
|
+
if (value) setFilters({ stackBy: value as StackBy });
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<SelectTrigger size="sm" className="w-36">
|
|
100
|
+
<SelectValue />
|
|
101
|
+
</SelectTrigger>
|
|
102
|
+
<SelectContent>
|
|
103
|
+
{STACK_BY_VALUES.map((value) => (
|
|
104
|
+
<SelectItem key={value} value={value}>
|
|
105
|
+
{stackByItems[value]}
|
|
106
|
+
</SelectItem>
|
|
107
|
+
))}
|
|
108
|
+
</SelectContent>
|
|
109
|
+
</Select>
|
|
110
|
+
</div>
|
|
111
|
+
</CardAction>
|
|
112
|
+
</CardHeader>
|
|
113
|
+
<CardContent>
|
|
114
|
+
<TokenUsageTimelineChart rows={timeline} metric={filters.metric} stackBy={filters.stackBy} />
|
|
115
|
+
</CardContent>
|
|
116
|
+
</Card>
|
|
117
|
+
|
|
118
|
+
<div className="grid gap-4 md:grid-cols-2">
|
|
119
|
+
<Card>
|
|
120
|
+
<CardHeader>
|
|
121
|
+
<CardTitle>{t("token_usage.admin.by_company")}</CardTitle>
|
|
122
|
+
</CardHeader>
|
|
123
|
+
<CardContent>
|
|
124
|
+
<TokenUsageRankedBar rows={byCompany} metric={filters.metric} emptyLabel={emptyLabel} />
|
|
125
|
+
</CardContent>
|
|
126
|
+
</Card>
|
|
127
|
+
|
|
128
|
+
<Card>
|
|
129
|
+
<CardHeader>
|
|
130
|
+
<CardTitle>{t("token_usage.admin.by_user")}</CardTitle>
|
|
131
|
+
</CardHeader>
|
|
132
|
+
<CardContent>
|
|
133
|
+
<TokenUsageRankedBar rows={byUser} metric={filters.metric} emptyLabel={emptyLabel} />
|
|
134
|
+
</CardContent>
|
|
135
|
+
</Card>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
{/* The two cost centres, broken down the same way so they can be read
|
|
139
|
+
against each other. Operation types are vocabulary, not data — unlike
|
|
140
|
+
the company and user panels above, these labels get translated.
|
|
141
|
+
|
|
142
|
+
Platform spend has no owning company, so a company filter makes that
|
|
143
|
+
half meaningless: the provider skips the request and the card is
|
|
144
|
+
hidden rather than rendered empty, leaving the customer half full
|
|
145
|
+
width. */}
|
|
146
|
+
<div className={cn("grid gap-4", !singleCustomerMode && "md:grid-cols-2")}>
|
|
147
|
+
<Card>
|
|
148
|
+
<CardHeader>
|
|
149
|
+
<CardTitle>{t("token_usage.admin.customer_by_operation")}</CardTitle>
|
|
150
|
+
</CardHeader>
|
|
151
|
+
<CardContent>
|
|
152
|
+
<TokenUsageRankedBar
|
|
153
|
+
rows={byCustomerOperation}
|
|
154
|
+
metric={filters.metric}
|
|
155
|
+
emptyLabel={emptyLabel}
|
|
156
|
+
labelsAreOperationTypes
|
|
157
|
+
/>
|
|
158
|
+
</CardContent>
|
|
159
|
+
</Card>
|
|
160
|
+
|
|
161
|
+
{!singleCustomerMode && (
|
|
162
|
+
<Card>
|
|
163
|
+
<CardHeader>
|
|
164
|
+
<CardTitle>{t("token_usage.admin.platform_by_operation")}</CardTitle>
|
|
165
|
+
</CardHeader>
|
|
166
|
+
<CardContent>
|
|
167
|
+
<TokenUsageRankedBar
|
|
168
|
+
rows={byOperation}
|
|
169
|
+
metric={filters.metric}
|
|
170
|
+
emptyLabel={emptyLabel}
|
|
171
|
+
labelsAreOperationTypes
|
|
172
|
+
/>
|
|
173
|
+
</CardContent>
|
|
174
|
+
</Card>
|
|
175
|
+
)}
|
|
176
|
+
</div>
|
|
177
|
+
|
|
178
|
+
<Card>
|
|
179
|
+
<CardHeader>
|
|
180
|
+
<CardTitle>{t("token_usage.admin.detail")}</CardTitle>
|
|
181
|
+
</CardHeader>
|
|
182
|
+
<CardContent>
|
|
183
|
+
<TokenUsageBreakdownTable rows={byCompany} metric={filters.metric} />
|
|
184
|
+
</CardContent>
|
|
185
|
+
</Card>
|
|
186
|
+
</div>
|
|
187
|
+
</RoundPageContainer>
|
|
188
|
+
);
|
|
189
|
+
}
|