@intlayer/backend-contract 9.7.1 → 9.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cjs/ai.cjs +83 -0
  2. package/dist/cjs/ai.cjs.map +1 -1
  3. package/dist/cjs/analytics.cjs +113 -2
  4. package/dist/cjs/analytics.cjs.map +1 -1
  5. package/dist/cjs/project.cjs.map +1 -1
  6. package/dist/esm/ai.mjs +81 -1
  7. package/dist/esm/ai.mjs.map +1 -1
  8. package/dist/esm/analytics.mjs +107 -3
  9. package/dist/esm/analytics.mjs.map +1 -1
  10. package/dist/esm/project.mjs.map +1 -1
  11. package/dist/types/ai.d.ts +196 -1
  12. package/dist/types/ai.d.ts.map +1 -1
  13. package/dist/types/analytics.d.ts +232 -1
  14. package/dist/types/analytics.d.ts.map +1 -1
  15. package/dist/types/asset.d.ts.map +1 -1
  16. package/dist/types/blogComment.d.ts.map +1 -1
  17. package/dist/types/cliSessionToken.d.ts.map +1 -1
  18. package/dist/types/demo.d.ts.map +1 -1
  19. package/dist/types/dictionary.d.ts +1 -1
  20. package/dist/types/dictionary.d.ts.map +1 -1
  21. package/dist/types/environment.d.ts.map +1 -1
  22. package/dist/types/eventListener.d.ts.map +1 -1
  23. package/dist/types/gitProviders.d.ts.map +1 -1
  24. package/dist/types/newsletter.d.ts.map +1 -1
  25. package/dist/types/oAuth2.d.ts.map +1 -1
  26. package/dist/types/organization.d.ts.map +1 -1
  27. package/dist/types/project.d.ts +6 -1
  28. package/dist/types/project.d.ts.map +1 -1
  29. package/dist/types/public.d.ts.map +1 -1
  30. package/dist/types/reviewer.d.ts.map +1 -1
  31. package/dist/types/scan.d.ts.map +1 -1
  32. package/dist/types/search.d.ts.map +1 -1
  33. package/dist/types/session.d.ts +1 -1
  34. package/dist/types/session.d.ts.map +1 -1
  35. package/dist/types/showcaseProject.d.ts.map +1 -1
  36. package/dist/types/stripe.d.ts.map +1 -1
  37. package/dist/types/tag.d.ts.map +1 -1
  38. package/dist/types/translation.d.ts +1 -1
  39. package/dist/types/translation.d.ts.map +1 -1
  40. package/dist/types/user.d.ts.map +1 -1
  41. package/package.json +105 -105
package/dist/esm/ai.mjs CHANGED
@@ -94,6 +94,69 @@ const aiStatsSchema = z.object({
94
94
  totalTokens: z.number()
95
95
  }))
96
96
  });
97
+ /** AI features billed in credits (mirrors the backend `AI_CREDIT_FEATURES`). */
98
+ const aiCreditFeatureSchema = z.enum([
99
+ "translation",
100
+ "translate_json",
101
+ "custom_query",
102
+ "audit_dictionary",
103
+ "audit_dictionary_field",
104
+ "audit_dictionary_metadata",
105
+ "audit_tag",
106
+ "chat",
107
+ "autocomplete"
108
+ ]);
109
+ /** AI credit balance of the organization for the current monthly period. */
110
+ const aiCreditBalanceSchema = z.object({
111
+ organizationId: z.string(),
112
+ planType: z.enum([
113
+ "FREE",
114
+ "PREMIUM",
115
+ "ENTERPRISE",
116
+ "LIFETIME"
117
+ ]),
118
+ tokensPerCredit: z.number(),
119
+ monthlyCredits: z.number(),
120
+ usedCredits: z.number(),
121
+ remainingCredits: z.number(),
122
+ periodStart: dateTimeSchema,
123
+ periodEnd: dateTimeSchema,
124
+ usageByFeature: z.array(z.object({
125
+ feature: aiCreditFeatureSchema,
126
+ tokens: z.number(),
127
+ credits: z.number(),
128
+ requestCount: z.number()
129
+ })),
130
+ /** `false` when no monthly credit is granted (self-hosted). */
131
+ hasCreditAllowance: z.boolean(),
132
+ /** Every AI call of the period, own key included, per provider and model. */
133
+ usageByModel: z.array(z.object({
134
+ provider: z.optional(z.string()),
135
+ model: z.optional(z.string()),
136
+ isOwnKey: z.boolean(),
137
+ tokens: z.number(),
138
+ requestCount: z.number()
139
+ }))
140
+ });
141
+ const aiCreditUsageEntrySchema = z.object({
142
+ tokens: z.number(),
143
+ credits: z.number(),
144
+ requestCount: z.number()
145
+ });
146
+ /** Day-by-day AI credit usage of the organization (UTC days). */
147
+ const aiCreditDailyUsageSchema = z.object({
148
+ organizationId: z.string(),
149
+ tokensPerCredit: z.number(),
150
+ /** First day of the series, `YYYY-MM-DD`. */
151
+ from: z.string(),
152
+ /** Last day of the series (inclusive), `YYYY-MM-DD`. */
153
+ to: z.string(),
154
+ /** One entry per day, days without usage included. */
155
+ days: z.array(z.extend(aiCreditUsageEntrySchema, {
156
+ date: z.string(),
157
+ byFeature: z.array(z.extend(aiCreditUsageEntrySchema, { feature: aiCreditFeatureSchema }))
158
+ }))
159
+ });
97
160
  const aiOptionsShape = { aiOptions: z.optional(aiOptionsSchema) };
98
161
  const tagsKeysShape = { tagsKeys: z.optional(z.array(z.string())) };
99
162
  const conversationSchema = z.object({
@@ -252,9 +315,26 @@ const aiContract = defineRouteGroup({
252
315
  path: "/stats",
253
316
  summary: "AI token usage of the selected project",
254
317
  schemas: { response: { 200: responseDataSchema(aiStatsSchema) } }
318
+ }),
319
+ getAICredits: defineRoute({
320
+ method: "GET",
321
+ path: "/credits",
322
+ summary: "AI credit balance of the selected organization (cloud only)",
323
+ schemas: { response: { 200: responseDataSchema(aiCreditBalanceSchema) } }
324
+ }),
325
+ getAICreditUsage: defineRoute({
326
+ method: "GET",
327
+ path: "/credits/usage",
328
+ summary: "Day-by-day AI credit usage of the selected organization",
329
+ schemas: {
330
+ querystring: z.object({
331
+ /** Number of days to return, ending today (default 30, max 366). */
332
+ days: z.optional(z.string()) }),
333
+ response: { 200: responseDataSchema(aiCreditDailyUsageSchema) }
334
+ }
255
335
  })
256
336
  }
257
337
  });
258
338
 
259
- export { aiContract, aiOptionsSchema, aiStatsSchema, chatCompletionRequestMessageSchema, discussionMessageSchema, discussionSchema };
339
+ export { aiContract, aiCreditBalanceSchema, aiCreditDailyUsageSchema, aiCreditFeatureSchema, aiOptionsSchema, aiStatsSchema, chatCompletionRequestMessageSchema, discussionMessageSchema, discussionSchema };
260
340
  //# sourceMappingURL=ai.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai.mjs","names":[],"sources":["../../src/ai.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { AiProviders } from '@intlayer/types/config';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { z } from 'zod/mini';\nimport {\n dateTimeSchema,\n isJSONObject,\n paginationQueryShape,\n repeatableQueryValueSchema,\n typedStringSchema,\n typedValueSchema,\n} from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n type RouteQuerystring,\n} from './defineRoute';\nimport {\n type PaginatedResponse,\n paginatedResponseSchema,\n type ResponseData,\n responseDataSchema,\n} from './responseData';\nimport { tagSchema } from './tag';\n\n/**\n * AI settings sent by a client. Provider-specific options (from the AI SDKs)\n * pass through untouched, so the value is only checked to be an object;\n * `@intlayer/ai`'s `AIOptions` is asserted assignable in the backend.\n */\nexport type AIOptions = {\n provider?: `${AiProviders}`;\n model?: string;\n temperature?: number;\n baseURL?: string;\n /** Own provider key; omitted to use the project or Intlayer key. */\n apiKey?: string;\n applicationContext?: string;\n dataSerialization?: 'json' | 'toon';\n};\n\nexport const aiOptionsSchema = typedValueSchema<AIOptions>(isJSONObject);\n\n/** Chat message exchanged with the assistants. */\nexport const chatCompletionRequestMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant']),\n content: z.string(),\n /** ISO date-time, parsed to a `Date`. */\n timestamp: z.optional(\n z.pipe(\n z.string(),\n z.transform((value) => new Date(value))\n )\n ),\n});\n\nconst localeSchema = typedStringSchema<Locale>();\nconst tokenUsedShape = { tokenUsed: z.number() };\n\n/** Text result of an AI step (translation, audit, query). */\nconst fileContentResultSchema = z.object({\n fileContent: z.string(),\n ...tokenUsedShape,\n});\n\n/** Tag fields rewritten by the tag audit (parsed from the model's JSON). */\nconst tagAuditResultSchema = z.object({\n fileContent: z.looseObject({\n key: z.optional(z.string()),\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n instructions: z.optional(z.string()),\n }),\n ...tokenUsedShape,\n});\n\nconst metadataResultSchema = z.object({\n fileContent: z.object({\n title: z.string(),\n description: z.string(),\n tags: z.array(z.string()),\n }),\n ...tokenUsedShape,\n});\n\n/** JSON document translated by the AI. */\nconst jsonContentSchema = typedValueSchema<Record<string, unknown>>();\n\nconst tokenUsageSchema = z.object({\n inputTokens: z.number(),\n outputTokens: z.number(),\n totalTokens: z.number(),\n});\n\n/** Message stored in a discussion. */\nexport const discussionMessageSchema = z.object({\n role: z.enum(['user', 'assistant', 'system']),\n content: z.string(),\n relatedFiles: z.optional(z.array(z.string())),\n timestamp: dateTimeSchema,\n});\n\n/** Saved AI discussion (doc assistant or dashboard chat). */\nexport const discussionSchema = z.looseObject({\n id: z.string(),\n /** Generated by the client before the discussion is saved. */\n discussionId: z.string(),\n messages: z.optional(z.array(discussionMessageSchema)),\n numberOfMessages: z.number(),\n userId: z.optional(z.string()),\n projectId: z.optional(z.string()),\n organizationId: z.optional(z.string()),\n title: z.optional(z.string()),\n type: z.optional(z.enum(['doc', 'dashboard'])),\n isArchived: z.boolean(),\n aiModel: z.optional(z.string()),\n tokenUsage: z.optional(tokenUsageSchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Token usage of the project's dashboard discussions, per model. */\nexport const aiStatsSchema = z.object({\n projectId: z.string(),\n generatedAt: z.number(),\n totalDiscussions: z.number(),\n totalInputTokens: z.number(),\n totalOutputTokens: z.number(),\n totalTokens: z.number(),\n modelUsage: z.array(\n z.object({\n aiModel: z.string(),\n discussionCount: z.number(),\n totalInputTokens: z.number(),\n totalOutputTokens: z.number(),\n totalTokens: z.number(),\n })\n ),\n});\n\nconst aiOptionsShape = { aiOptions: z.optional(aiOptionsSchema) };\nconst tagsKeysShape = { tagsKeys: z.optional(z.array(z.string())) };\nconst conversationSchema = z.object({\n messages: z.array(chatCompletionRequestMessageSchema),\n discussionId: z.string(),\n});\n\n/** REST contract of the `/api/ai` routes. */\nexport const aiContract = defineRouteGroup({\n prefix: '/api/ai',\n tag: 'AI',\n routes: {\n customQuery: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Run a custom prompt',\n schemas: {\n body: z.looseObject({\n ...aiOptionsShape,\n ...tagsKeysShape,\n /** AI SDK model messages. */\n messages: typedValueSchema<unknown[]>(Array.isArray),\n system: z.optional(z.unknown()),\n applicationContext: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(fileContentResultSchema) },\n },\n }),\n translateJSON: defineRoute({\n method: 'POST',\n path: '/translate/json',\n summary: 'Translate a JSON document into a locale',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n entryFileContent: jsonContentSchema,\n presetOutputContent: jsonContentSchema,\n dictionaryDescription: z.optional(z.string()),\n entryLocale: localeSchema,\n outputLocale: localeSchema,\n mode: z.enum(['complete', 'review']),\n applicationContext: z.optional(z.string()),\n }),\n response: {\n 200: responseDataSchema(\n z.object({ fileContent: jsonContentSchema, ...tokenUsedShape })\n ),\n },\n },\n }),\n auditContentDeclaration: defineRoute({\n method: 'POST',\n path: '/audit/dictionary',\n summary: 'Audit and complete a content declaration file',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n locales: z.array(localeSchema),\n defaultLocale: localeSchema,\n fileContent: z.string(),\n filePath: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(metadataResultSchema) },\n },\n }),\n auditContentDeclarationField: defineRoute({\n method: 'POST',\n path: '/audit/dictionary/field',\n summary: 'Audit a single field of a content declaration',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n locales: z.array(localeSchema),\n fileContent: z.string(),\n filePath: z.optional(z.string()),\n keyPath: z.array(typedValueSchema<KeyPath>()),\n }),\n response: { 200: responseDataSchema(fileContentResultSchema) },\n },\n }),\n auditContentDeclarationMetadata: defineRoute({\n method: 'POST',\n path: '/audit/dictionary/metadata',\n summary: 'Suggest title, description and tags of a dictionary',\n schemas: {\n body: z.object({ ...aiOptionsShape, fileContent: z.string() }),\n response: { 200: responseDataSchema(metadataResultSchema) },\n },\n }),\n auditTag: defineRoute({\n method: 'POST',\n path: '/audit/tag',\n summary: 'Improve the instructions of a tag',\n schemas: {\n body: z.object({ ...aiOptionsShape, tag: tagSchema }),\n response: { 200: responseDataSchema(tagAuditResultSchema) },\n },\n }),\n ask: defineRoute({\n method: 'POST',\n path: '/ask',\n summary: 'Ask the documentation assistant (server-sent events stream)',\n schemas: { body: conversationSchema },\n }),\n chat: defineRoute({\n method: 'POST',\n path: '/chat',\n summary: 'Chat with the dashboard assistant (server-sent events stream)',\n schemas: { body: conversationSchema },\n }),\n autocomplete: defineRoute({\n method: 'POST',\n path: '/autocomplete',\n summary: 'Autocomplete a text being written',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n text: z.string(),\n contextBefore: z.optional(z.string()),\n currentLine: z.optional(z.string()),\n contextAfter: z.optional(z.string()),\n }),\n response: {\n 200: responseDataSchema(z.object({ autocompletion: z.string() })),\n },\n },\n }),\n getDiscussions: defineRoute({\n method: 'GET',\n path: '/discussions',\n summary: 'List AI discussions (own ones, all for admins)',\n schemas: {\n querystring: z.looseObject({\n ...paginationQueryShape,\n includeMessages: z.optional(z.enum(['true', 'false'])),\n ids: z.optional(repeatableQueryValueSchema),\n userId: z.optional(z.string()),\n userIds: z.optional(repeatableQueryValueSchema),\n discussionId: z.optional(z.string()),\n search: z.optional(z.string()),\n isArchived: z.optional(z.enum(['true', 'false'])),\n sortBy: z.optional(z.string()),\n sortOrder: z.optional(z.string()),\n fetchAll: z.optional(z.enum(['true', 'false'])),\n }),\n response: { 200: paginatedResponseSchema(discussionSchema) },\n },\n }),\n getAIStats: defineRoute({\n method: 'GET',\n path: '/stats',\n summary: 'AI token usage of the selected project',\n schemas: {\n response: { 200: responseDataSchema(aiStatsSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/ai` group, by name. */\nexport type AIRoutes = (typeof aiContract)['routes'];\n\n/**\n * Chat message as built by clients: `timestamp` may be a `Date` (serialized\n * to an ISO string on the wire) or already a string.\n */\nexport type ChatCompletionRequestMessage = Omit<\n z.output<typeof chatCompletionRequestMessageSchema>,\n 'timestamp'\n> & { timestamp?: Date | string };\nexport type DiscussionAPI = z.output<typeof discussionSchema>;\nexport type AIStats = z.output<typeof aiStatsSchema>;\n\nexport type CustomQueryBody = RouteBodyInput<AIRoutes['customQuery']>;\nexport type CustomQueryResult = ResponseData<\n z.output<typeof fileContentResultSchema>\n>;\nexport type TranslateJSONBody = RouteBodyInput<AIRoutes['translateJSON']>;\nexport type TranslateJSONResult = ResponseData<{\n fileContent: Record<string, unknown>;\n tokenUsed: number;\n}>;\nexport type AuditContentDeclarationBody = RouteBodyInput<\n AIRoutes['auditContentDeclaration']\n>;\nexport type AuditContentDeclarationResult = ResponseData<\n z.output<typeof metadataResultSchema>\n>;\nexport type AuditContentDeclarationFieldBody = RouteBodyInput<\n AIRoutes['auditContentDeclarationField']\n>;\nexport type AuditContentDeclarationFieldResult = ResponseData<\n z.output<typeof fileContentResultSchema>\n>;\nexport type AuditContentDeclarationMetadataBody = RouteBodyInput<\n AIRoutes['auditContentDeclarationMetadata']\n>;\nexport type AuditContentDeclarationMetadataResult = ResponseData<\n z.output<typeof metadataResultSchema>\n>;\nexport type AuditTagBody = RouteBodyInput<AIRoutes['auditTag']>;\nexport type AuditTagResultData = z.output<typeof tagAuditResultSchema>;\nexport type AuditTagResult = ResponseData<AuditTagResultData>;\nexport type AskDocQuestionBody = RouteBodyInput<AIRoutes['ask']>;\n/** Final payload of the documentation assistant stream. */\nexport type AskDocQuestionResult = ResponseData<{\n response: string;\n relatedFiles: string[];\n}>;\nexport type ChatBody = RouteBodyInput<AIRoutes['chat']>;\n/** Final payload of the dashboard assistant stream. */\nexport type ChatResult = ResponseData<{\n response: string;\n tokenUsage?: z.output<typeof tokenUsageSchema>;\n aiModel?: string;\n}>;\nexport type AutocompleteBody = RouteBodyInput<AIRoutes['autocomplete']>;\nexport type AutocompleteResponse = ResponseData<{ autocompletion: string }>;\nexport type GetDiscussionsParams = RouteQuerystring<AIRoutes['getDiscussions']>;\nexport type GetDiscussionsResult = PaginatedResponse<DiscussionAPI>;\nexport type GetAIStatsResult = ResponseData<AIStats>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ai.mjs","names":[],"sources":["../../src/ai.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { AiProviders } from '@intlayer/types/config';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { z } from 'zod/mini';\nimport {\n dateTimeSchema,\n isJSONObject,\n paginationQueryShape,\n repeatableQueryValueSchema,\n typedStringSchema,\n typedValueSchema,\n} from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n type RouteQuerystring,\n} from './defineRoute';\nimport {\n type PaginatedResponse,\n paginatedResponseSchema,\n type ResponseData,\n responseDataSchema,\n} from './responseData';\nimport { tagSchema } from './tag';\n\n/**\n * AI settings sent by a client. Provider-specific options (from the AI SDKs)\n * pass through untouched, so the value is only checked to be an object;\n * `@intlayer/ai`'s `AIOptions` is asserted assignable in the backend.\n */\nexport type AIOptions = {\n provider?: `${AiProviders}`;\n model?: string;\n temperature?: number;\n baseURL?: string;\n /** Own provider key; omitted to use the project or Intlayer key. */\n apiKey?: string;\n applicationContext?: string;\n dataSerialization?: 'json' | 'toon';\n};\n\nexport const aiOptionsSchema = typedValueSchema<AIOptions>(isJSONObject);\n\n/** Chat message exchanged with the assistants. */\nexport const chatCompletionRequestMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant']),\n content: z.string(),\n /** ISO date-time, parsed to a `Date`. */\n timestamp: z.optional(\n z.pipe(\n z.string(),\n z.transform((value) => new Date(value))\n )\n ),\n});\n\nconst localeSchema = typedStringSchema<Locale>();\nconst tokenUsedShape = { tokenUsed: z.number() };\n\n/** Text result of an AI step (translation, audit, query). */\nconst fileContentResultSchema = z.object({\n fileContent: z.string(),\n ...tokenUsedShape,\n});\n\n/** Tag fields rewritten by the tag audit (parsed from the model's JSON). */\nconst tagAuditResultSchema = z.object({\n fileContent: z.looseObject({\n key: z.optional(z.string()),\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n instructions: z.optional(z.string()),\n }),\n ...tokenUsedShape,\n});\n\nconst metadataResultSchema = z.object({\n fileContent: z.object({\n title: z.string(),\n description: z.string(),\n tags: z.array(z.string()),\n }),\n ...tokenUsedShape,\n});\n\n/** JSON document translated by the AI. */\nconst jsonContentSchema = typedValueSchema<Record<string, unknown>>();\n\nconst tokenUsageSchema = z.object({\n inputTokens: z.number(),\n outputTokens: z.number(),\n totalTokens: z.number(),\n});\n\n/** Message stored in a discussion. */\nexport const discussionMessageSchema = z.object({\n role: z.enum(['user', 'assistant', 'system']),\n content: z.string(),\n relatedFiles: z.optional(z.array(z.string())),\n timestamp: dateTimeSchema,\n});\n\n/** Saved AI discussion (doc assistant or dashboard chat). */\nexport const discussionSchema = z.looseObject({\n id: z.string(),\n /** Generated by the client before the discussion is saved. */\n discussionId: z.string(),\n messages: z.optional(z.array(discussionMessageSchema)),\n numberOfMessages: z.number(),\n userId: z.optional(z.string()),\n projectId: z.optional(z.string()),\n organizationId: z.optional(z.string()),\n title: z.optional(z.string()),\n type: z.optional(z.enum(['doc', 'dashboard'])),\n isArchived: z.boolean(),\n aiModel: z.optional(z.string()),\n tokenUsage: z.optional(tokenUsageSchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Token usage of the project's dashboard discussions, per model. */\nexport const aiStatsSchema = z.object({\n projectId: z.string(),\n generatedAt: z.number(),\n totalDiscussions: z.number(),\n totalInputTokens: z.number(),\n totalOutputTokens: z.number(),\n totalTokens: z.number(),\n modelUsage: z.array(\n z.object({\n aiModel: z.string(),\n discussionCount: z.number(),\n totalInputTokens: z.number(),\n totalOutputTokens: z.number(),\n totalTokens: z.number(),\n })\n ),\n});\n\n/** AI features billed in credits (mirrors the backend `AI_CREDIT_FEATURES`). */\nexport const aiCreditFeatureSchema = z.enum([\n 'translation',\n 'translate_json',\n 'custom_query',\n 'audit_dictionary',\n 'audit_dictionary_field',\n 'audit_dictionary_metadata',\n 'audit_tag',\n 'chat',\n 'autocomplete',\n]);\n\n/** AI credit balance of the organization for the current monthly period. */\nexport const aiCreditBalanceSchema = z.object({\n organizationId: z.string(),\n planType: z.enum(['FREE', 'PREMIUM', 'ENTERPRISE', 'LIFETIME']),\n tokensPerCredit: z.number(),\n monthlyCredits: z.number(),\n usedCredits: z.number(),\n remainingCredits: z.number(),\n periodStart: dateTimeSchema,\n periodEnd: dateTimeSchema,\n usageByFeature: z.array(\n z.object({\n feature: aiCreditFeatureSchema,\n tokens: z.number(),\n credits: z.number(),\n requestCount: z.number(),\n })\n ),\n /** `false` when no monthly credit is granted (self-hosted). */\n hasCreditAllowance: z.boolean(),\n /** Every AI call of the period, own key included, per provider and model. */\n usageByModel: z.array(\n z.object({\n provider: z.optional(z.string()),\n model: z.optional(z.string()),\n isOwnKey: z.boolean(),\n tokens: z.number(),\n requestCount: z.number(),\n })\n ),\n});\n\nconst aiCreditUsageEntrySchema = z.object({\n tokens: z.number(),\n credits: z.number(),\n requestCount: z.number(),\n});\n\n/** Day-by-day AI credit usage of the organization (UTC days). */\nexport const aiCreditDailyUsageSchema = z.object({\n organizationId: z.string(),\n tokensPerCredit: z.number(),\n /** First day of the series, `YYYY-MM-DD`. */\n from: z.string(),\n /** Last day of the series (inclusive), `YYYY-MM-DD`. */\n to: z.string(),\n /** One entry per day, days without usage included. */\n days: z.array(\n z.extend(aiCreditUsageEntrySchema, {\n date: z.string(),\n byFeature: z.array(\n z.extend(aiCreditUsageEntrySchema, { feature: aiCreditFeatureSchema })\n ),\n })\n ),\n});\n\nconst aiOptionsShape = { aiOptions: z.optional(aiOptionsSchema) };\nconst tagsKeysShape = { tagsKeys: z.optional(z.array(z.string())) };\nconst conversationSchema = z.object({\n messages: z.array(chatCompletionRequestMessageSchema),\n discussionId: z.string(),\n});\n\n/** REST contract of the `/api/ai` routes. */\nexport const aiContract = defineRouteGroup({\n prefix: '/api/ai',\n tag: 'AI',\n routes: {\n customQuery: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Run a custom prompt',\n schemas: {\n body: z.looseObject({\n ...aiOptionsShape,\n ...tagsKeysShape,\n /** AI SDK model messages. */\n messages: typedValueSchema<unknown[]>(Array.isArray),\n system: z.optional(z.unknown()),\n applicationContext: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(fileContentResultSchema) },\n },\n }),\n translateJSON: defineRoute({\n method: 'POST',\n path: '/translate/json',\n summary: 'Translate a JSON document into a locale',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n entryFileContent: jsonContentSchema,\n presetOutputContent: jsonContentSchema,\n dictionaryDescription: z.optional(z.string()),\n entryLocale: localeSchema,\n outputLocale: localeSchema,\n mode: z.enum(['complete', 'review']),\n applicationContext: z.optional(z.string()),\n }),\n response: {\n 200: responseDataSchema(\n z.object({ fileContent: jsonContentSchema, ...tokenUsedShape })\n ),\n },\n },\n }),\n auditContentDeclaration: defineRoute({\n method: 'POST',\n path: '/audit/dictionary',\n summary: 'Audit and complete a content declaration file',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n locales: z.array(localeSchema),\n defaultLocale: localeSchema,\n fileContent: z.string(),\n filePath: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(metadataResultSchema) },\n },\n }),\n auditContentDeclarationField: defineRoute({\n method: 'POST',\n path: '/audit/dictionary/field',\n summary: 'Audit a single field of a content declaration',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n locales: z.array(localeSchema),\n fileContent: z.string(),\n filePath: z.optional(z.string()),\n keyPath: z.array(typedValueSchema<KeyPath>()),\n }),\n response: { 200: responseDataSchema(fileContentResultSchema) },\n },\n }),\n auditContentDeclarationMetadata: defineRoute({\n method: 'POST',\n path: '/audit/dictionary/metadata',\n summary: 'Suggest title, description and tags of a dictionary',\n schemas: {\n body: z.object({ ...aiOptionsShape, fileContent: z.string() }),\n response: { 200: responseDataSchema(metadataResultSchema) },\n },\n }),\n auditTag: defineRoute({\n method: 'POST',\n path: '/audit/tag',\n summary: 'Improve the instructions of a tag',\n schemas: {\n body: z.object({ ...aiOptionsShape, tag: tagSchema }),\n response: { 200: responseDataSchema(tagAuditResultSchema) },\n },\n }),\n ask: defineRoute({\n method: 'POST',\n path: '/ask',\n summary: 'Ask the documentation assistant (server-sent events stream)',\n schemas: { body: conversationSchema },\n }),\n chat: defineRoute({\n method: 'POST',\n path: '/chat',\n summary: 'Chat with the dashboard assistant (server-sent events stream)',\n schemas: { body: conversationSchema },\n }),\n autocomplete: defineRoute({\n method: 'POST',\n path: '/autocomplete',\n summary: 'Autocomplete a text being written',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n text: z.string(),\n contextBefore: z.optional(z.string()),\n currentLine: z.optional(z.string()),\n contextAfter: z.optional(z.string()),\n }),\n response: {\n 200: responseDataSchema(z.object({ autocompletion: z.string() })),\n },\n },\n }),\n getDiscussions: defineRoute({\n method: 'GET',\n path: '/discussions',\n summary: 'List AI discussions (own ones, all for admins)',\n schemas: {\n querystring: z.looseObject({\n ...paginationQueryShape,\n includeMessages: z.optional(z.enum(['true', 'false'])),\n ids: z.optional(repeatableQueryValueSchema),\n userId: z.optional(z.string()),\n userIds: z.optional(repeatableQueryValueSchema),\n discussionId: z.optional(z.string()),\n search: z.optional(z.string()),\n isArchived: z.optional(z.enum(['true', 'false'])),\n sortBy: z.optional(z.string()),\n sortOrder: z.optional(z.string()),\n fetchAll: z.optional(z.enum(['true', 'false'])),\n }),\n response: { 200: paginatedResponseSchema(discussionSchema) },\n },\n }),\n getAIStats: defineRoute({\n method: 'GET',\n path: '/stats',\n summary: 'AI token usage of the selected project',\n schemas: {\n response: { 200: responseDataSchema(aiStatsSchema) },\n },\n }),\n getAICredits: defineRoute({\n method: 'GET',\n path: '/credits',\n summary: 'AI credit balance of the selected organization (cloud only)',\n schemas: {\n response: { 200: responseDataSchema(aiCreditBalanceSchema) },\n },\n }),\n getAICreditUsage: defineRoute({\n method: 'GET',\n path: '/credits/usage',\n summary: 'Day-by-day AI credit usage of the selected organization',\n schemas: {\n querystring: z.object({\n /** Number of days to return, ending today (default 30, max 366). */\n days: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(aiCreditDailyUsageSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/ai` group, by name. */\nexport type AIRoutes = (typeof aiContract)['routes'];\n\n/**\n * Chat message as built by clients: `timestamp` may be a `Date` (serialized\n * to an ISO string on the wire) or already a string.\n */\nexport type ChatCompletionRequestMessage = Omit<\n z.output<typeof chatCompletionRequestMessageSchema>,\n 'timestamp'\n> & { timestamp?: Date | string };\nexport type DiscussionAPI = z.output<typeof discussionSchema>;\nexport type AIStats = z.output<typeof aiStatsSchema>;\nexport type AICreditFeature = z.output<typeof aiCreditFeatureSchema>;\nexport type AICreditBalance = z.output<typeof aiCreditBalanceSchema>;\nexport type AICreditDailyUsage = z.output<typeof aiCreditDailyUsageSchema>;\n\nexport type CustomQueryBody = RouteBodyInput<AIRoutes['customQuery']>;\nexport type CustomQueryResult = ResponseData<\n z.output<typeof fileContentResultSchema>\n>;\nexport type TranslateJSONBody = RouteBodyInput<AIRoutes['translateJSON']>;\nexport type TranslateJSONResult = ResponseData<{\n fileContent: Record<string, unknown>;\n tokenUsed: number;\n}>;\nexport type AuditContentDeclarationBody = RouteBodyInput<\n AIRoutes['auditContentDeclaration']\n>;\nexport type AuditContentDeclarationResult = ResponseData<\n z.output<typeof metadataResultSchema>\n>;\nexport type AuditContentDeclarationFieldBody = RouteBodyInput<\n AIRoutes['auditContentDeclarationField']\n>;\nexport type AuditContentDeclarationFieldResult = ResponseData<\n z.output<typeof fileContentResultSchema>\n>;\nexport type AuditContentDeclarationMetadataBody = RouteBodyInput<\n AIRoutes['auditContentDeclarationMetadata']\n>;\nexport type AuditContentDeclarationMetadataResult = ResponseData<\n z.output<typeof metadataResultSchema>\n>;\nexport type AuditTagBody = RouteBodyInput<AIRoutes['auditTag']>;\nexport type AuditTagResultData = z.output<typeof tagAuditResultSchema>;\nexport type AuditTagResult = ResponseData<AuditTagResultData>;\nexport type AskDocQuestionBody = RouteBodyInput<AIRoutes['ask']>;\n/** Final payload of the documentation assistant stream. */\nexport type AskDocQuestionResult = ResponseData<{\n response: string;\n relatedFiles: string[];\n}>;\nexport type ChatBody = RouteBodyInput<AIRoutes['chat']>;\n/** Final payload of the dashboard assistant stream. */\nexport type ChatResult = ResponseData<{\n response: string;\n tokenUsage?: z.output<typeof tokenUsageSchema>;\n aiModel?: string;\n}>;\nexport type AutocompleteBody = RouteBodyInput<AIRoutes['autocomplete']>;\nexport type AutocompleteResponse = ResponseData<{ autocompletion: string }>;\nexport type GetDiscussionsParams = RouteQuerystring<AIRoutes['getDiscussions']>;\nexport type GetDiscussionsResult = PaginatedResponse<DiscussionAPI>;\nexport type GetAIStatsResult = ResponseData<AIStats>;\nexport type GetAICreditsResult = ResponseData<AICreditBalance>;\nexport type GetAICreditUsageParams = RouteQuerystring<\n AIRoutes['getAICreditUsage']\n>;\nexport type GetAICreditUsageResult = ResponseData<AICreditDailyUsage>;\n"],"mappings":"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"}
@@ -26,8 +26,12 @@ const incomingAnalyticsEventSchema = z.looseObject({
26
26
  goal: z.optional(z.string()),
27
27
  value: z.optional(z.number())
28
28
  });
29
- /** Time windows of the audience report. */
29
+ /**
30
+ * Time windows of the audience report. `live` covers the sessions active in the
31
+ * last 30 minutes, bucketed per minute.
32
+ */
30
33
  const audienceRangeSchema = z.enum([
34
+ "live",
31
35
  "1h",
32
36
  "24h",
33
37
  "7d",
@@ -55,6 +59,80 @@ const audienceBreakdownRowSchema = z.object({
55
59
  users: z.number(),
56
60
  views: z.number()
57
61
  });
62
+ /** A session active in the `live` window, placed on the map. */
63
+ const liveVisitorSchema = z.object({
64
+ /** Opaque, non-reversible visitor id (prefix of the hashed session). */
65
+ visitorId: z.string(),
66
+ /** ISO country code, `ZZ` when unknown. */
67
+ country: z.string(),
68
+ /** City reported by the CDN, when available. */
69
+ city: z.optional(z.string()),
70
+ /** City-level latitude (rounded to ~1 km), when available. */
71
+ latitude: z.optional(z.number()),
72
+ /** City-level longitude (rounded to ~1 km), when available. */
73
+ longitude: z.optional(z.number()),
74
+ /** Locale the visitor is browsing in. */
75
+ locale: z.optional(z.string()),
76
+ /** Page of the visitor's latest activity. */
77
+ currentUrl: z.string(),
78
+ /** Pages the visitor was active on during the window. */
79
+ pageCount: z.number(),
80
+ /** Page views during the window. */
81
+ views: z.number(),
82
+ /** ISO date of the visitor's first activity in the window. */
83
+ firstSeenAt: z.string(),
84
+ /** ISO date of the visitor's latest activity. */
85
+ lastSeenAt: z.string(),
86
+ /** Minutes (`YYYY-MM-DDTHH:mm`, UTC) the visitor was active in, oldest first. */
87
+ activeMinutes: z.array(z.string())
88
+ });
89
+ /** One step of a live visitor's journey, oldest first. */
90
+ const liveVisitorFlowStepSchema = z.object({
91
+ url: z.string(),
92
+ locale: z.optional(z.string()),
93
+ /** ISO date the visitor reached the page. */
94
+ firstSeenAt: z.string(),
95
+ /** ISO date of the visitor's latest activity on the page. */
96
+ lastSeenAt: z.string(),
97
+ views: z.number()
98
+ });
99
+ /**
100
+ * Page journey of one live visitor over the `live` window. `visitor` is `null`
101
+ * once the session has left the window (not an error: it simply went quiet).
102
+ */
103
+ const liveVisitorFlowSchema = z.object({
104
+ visitor: z.nullable(liveVisitorSchema),
105
+ steps: z.array(liveVisitorFlowStepSchema)
106
+ });
107
+ /**
108
+ * Pseudo-page a session starts from. Used as the flow's starting page, the
109
+ * next step lists the landing pages.
110
+ */
111
+ const PAGE_FLOW_ENTRANCE = "(entrance)";
112
+ /** One page of a flow step; `url` is `null` for the "other pages" bucket. */
113
+ const pageFlowNodeSchema = z.object({
114
+ url: z.nullable(z.string()),
115
+ /** Average navigations reaching this page at this step. */
116
+ value: z.number(),
117
+ /** Part of `value` that left the site from this page (`null` if unknown). */
118
+ exits: z.nullable(z.number())
119
+ });
120
+ /** Average navigations from a page of one step to a page of the next. */
121
+ const pageFlowLinkSchema = z.object({
122
+ /** Step of the source page; the target is on `fromStep + 1`. */
123
+ fromStep: z.number(),
124
+ fromUrl: z.nullable(z.string()),
125
+ toUrl: z.nullable(z.string()),
126
+ value: z.number()
127
+ });
128
+ /** Averaged navigation flow starting from one page. */
129
+ const pageFlowSchema = z.object({
130
+ startUrl: z.string(),
131
+ range: audienceRangeSchema,
132
+ /** Pages per step, the starting page alone on step 0. */
133
+ steps: z.array(z.array(pageFlowNodeSchema)),
134
+ links: z.array(pageFlowLinkSchema)
135
+ });
58
136
  const audienceStatsSchema = z.object({
59
137
  usersToday: z.number(),
60
138
  usersLast7Days: z.number(),
@@ -66,7 +144,11 @@ const audienceStatsSchema = z.object({
66
144
  series: z.array(audienceSeriesPointSchema),
67
145
  byLocale: z.array(audienceBreakdownRowSchema),
68
146
  byCountry: z.array(audienceBreakdownRowSchema),
69
- byPage: z.array(audienceBreakdownRowSchema)
147
+ byPage: z.array(audienceBreakdownRowSchema),
148
+ /** Active sessions with their location — `live` range only. */
149
+ liveVisitors: z.optional(z.array(liveVisitorSchema)),
150
+ /** First UTC day with collected data (`YYYY-MM-DD`), `null` before any. */
151
+ dataSince: z.nullable(z.string())
70
152
  });
71
153
  const analyticsOverviewRowSchema = z.object({
72
154
  url: z.string(),
@@ -136,6 +218,28 @@ const analyticsContract = defineRouteGroup({
136
218
  response: { 200: responseDataSchema(audienceStatsSchema) }
137
219
  }
138
220
  }),
221
+ getLiveVisitorFlow: defineRoute({
222
+ method: "GET",
223
+ path: "/audience/live/visitors/:visitorId",
224
+ summary: "Page journey of a visitor active in the last 30 minutes",
225
+ schemas: {
226
+ params: z.object({ visitorId: z.string().check(z.regex(/^[a-f0-9]{16}$/)) }),
227
+ response: { 200: responseDataSchema(liveVisitorFlowSchema) }
228
+ }
229
+ }),
230
+ getPageFlow: defineRoute({
231
+ method: "GET",
232
+ path: "/page-flow",
233
+ summary: "Average page-to-page navigation flow from a starting page",
234
+ schemas: {
235
+ querystring: z.object({
236
+ range: z.optional(z.string()),
237
+ /** Starting page pathname; defaults to `/`. */
238
+ startUrl: z.optional(z.string())
239
+ }),
240
+ response: { 200: responseDataSchema(pageFlowSchema) }
241
+ }
242
+ }),
139
243
  getContentStats: defineRoute({
140
244
  method: "GET",
141
245
  path: "/content-stats",
@@ -163,5 +267,5 @@ const analyticsContract = defineRouteGroup({
163
267
  }
164
268
  });
165
269
 
166
- export { analyticsContract, analyticsEventTypeSchema, audienceGranularitySchema, audienceRangeSchema, audienceSeriesPointSchema, audienceStatsSchema, incomingAnalyticsEventSchema };
270
+ export { PAGE_FLOW_ENTRANCE, analyticsContract, analyticsEventTypeSchema, audienceGranularitySchema, audienceRangeSchema, audienceSeriesPointSchema, audienceStatsSchema, incomingAnalyticsEventSchema, liveVisitorFlowSchema, liveVisitorFlowStepSchema, liveVisitorSchema, pageFlowLinkSchema, pageFlowNodeSchema, pageFlowSchema };
167
271
  //# sourceMappingURL=analytics.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.mjs","names":[],"sources":["../../src/analytics.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n} from './defineRoute';\nimport { type ResponseData, responseDataSchema } from './responseData';\n\n/** Kind of analytics event sent by the SDK. */\nexport const analyticsEventTypeSchema = z.enum([\n 'page_view',\n 'content_exposure',\n 'conversion',\n]);\n\n/** One event as sent by the SDK (batched). */\nexport const incomingAnalyticsEventSchema = z.looseObject({\n type: analyticsEventTypeSchema,\n /** Client timestamp (epoch ms). */\n t: z.number(),\n locale: z.string(),\n url: z.string(),\n ref: z.optional(z.string()),\n dictionaryKey: z.optional(z.string()),\n keyPath: z.optional(z.string()),\n nodeType: z.optional(z.string()),\n variant: z.optional(z.string()),\n count: z.optional(z.number()),\n experimentKey: z.optional(z.string()),\n goal: z.optional(z.string()),\n value: z.optional(z.number()),\n});\n\n/** Time windows of the audience report. */\nexport const audienceRangeSchema = z.enum([\n '1h',\n '24h',\n '7d',\n '30d',\n '90d',\n '6mo',\n '1y',\n '3y',\n]);\n\nexport const audienceGranularitySchema = z.enum([\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n]);\n\nexport const audienceSeriesPointSchema = z.object({\n /** ISO bucket start. */\n bucket: z.string(),\n users: z.number(),\n views: z.number(),\n});\n\nconst audienceBreakdownRowSchema = z.object({\n key: z.string(),\n users: z.number(),\n views: z.number(),\n});\n\nexport const audienceStatsSchema = z.object({\n usersToday: z.number(),\n usersLast7Days: z.number(),\n usersInRange: z.number(),\n viewsInRange: z.number(),\n range: audienceRangeSchema,\n rangeHours: z.number(),\n granularity: audienceGranularitySchema,\n series: z.array(audienceSeriesPointSchema),\n byLocale: z.array(audienceBreakdownRowSchema),\n byCountry: z.array(audienceBreakdownRowSchema),\n byPage: z.array(audienceBreakdownRowSchema),\n});\n\nconst analyticsOverviewRowSchema = z.object({\n url: z.string(),\n locale: z.string(),\n views: z.number(),\n});\n\nconst contentStatRowSchema = z.object({\n dictionaryKey: z.string(),\n keyPath: z.string(),\n locale: z.string(),\n exposures: z.number(),\n});\n\nconst experimentResultSchema = z.object({\n experimentKey: z.string(),\n variants: z.array(\n z.object({\n variant: z.string(),\n exposures: z.number(),\n conversions: z.number(),\n conversionRate: z.number(),\n })\n ),\n pValue: z.nullable(z.number()),\n winner: z.nullable(z.string()),\n});\n\nconst pageMetadataSchema = z.object({\n title: z.optional(z.string()),\n description: z.optional(z.string()),\n});\n\n/** REST contract of the `/api/analytics` routes. */\nexport const analyticsContract = defineRouteGroup({\n prefix: '/api/analytics',\n tag: 'Analytics',\n routes: {\n ingestAnalyticsEvents: defineRoute({\n method: 'POST',\n path: '/events',\n summary: 'Ingest SDK events (public browser token, rate limited)',\n schemas: {\n /** Sent as `text/plain` JSON by `navigator.sendBeacon`. */\n body: z.looseObject({\n /** Token from `POST /api/public/token` (`analytics:ingest`). */\n token: z.optional(z.string()),\n /** @deprecated Superseded by `token`; still accepted. */\n clientId: z.optional(z.string()),\n sessionId: z.string(),\n sdkVersion: z.string(),\n events: z.array(incomingAnalyticsEventSchema),\n }),\n response: {\n 200: responseDataSchema(z.object({ accepted: z.number() })),\n },\n },\n }),\n getAnalyticsOverview: defineRoute({\n method: 'GET',\n path: '/overview',\n summary: 'Page views per page and locale',\n schemas: {\n response: {\n 200: responseDataSchema(z.array(analyticsOverviewRowSchema)),\n },\n },\n }),\n getAnalyticsAudience: defineRoute({\n method: 'GET',\n path: '/audience',\n summary: 'Audience report over a time window',\n schemas: {\n querystring: z.object({\n range: z.optional(z.string()),\n /** Legacy: converted to the closest range. */\n days: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(audienceStatsSchema) },\n },\n }),\n getContentStats: defineRoute({\n method: 'GET',\n path: '/content-stats',\n summary: 'Content exposures per dictionary key path and locale',\n schemas: {\n response: { 200: responseDataSchema(z.array(contentStatRowSchema)) },\n },\n }),\n getExperimentResults: defineRoute({\n method: 'GET',\n path: '/experiments/:experimentKey',\n summary: 'A/B test results of an experiment',\n schemas: {\n params: z.object({ experimentKey: z.string().check(z.minLength(1)) }),\n response: { 200: responseDataSchema(experimentResultSchema) },\n },\n }),\n getPageMetadata: defineRoute({\n method: 'GET',\n path: '/page-metadata',\n summary: 'Title and description of a page of the project',\n schemas: {\n querystring: z.object({ url: z.optional(z.string()) }),\n response: { 200: responseDataSchema(pageMetadataSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/analytics` group, by name. */\nexport type AnalyticsRoutes = (typeof analyticsContract)['routes'];\n\nexport type AnalyticsEventType = z.output<typeof analyticsEventTypeSchema>;\nexport type IncomingAnalyticsEvent = z.output<\n typeof incomingAnalyticsEventSchema\n>;\nexport type AudienceRange = z.output<typeof audienceRangeSchema>;\nexport type AudienceGranularity = z.output<typeof audienceGranularitySchema>;\nexport type AudienceSeriesPoint = z.output<typeof audienceSeriesPointSchema>;\nexport type AudienceBreakdownRow = z.output<typeof audienceBreakdownRowSchema>;\nexport type AudienceStats = z.output<typeof audienceStatsSchema>;\nexport type AnalyticsOverviewRow = z.output<typeof analyticsOverviewRowSchema>;\nexport type ContentStatRow = z.output<typeof contentStatRowSchema>;\nexport type ExperimentResult = z.output<typeof experimentResultSchema>;\nexport type PageMetadata = z.output<typeof pageMetadataSchema>;\n\nexport type IngestAnalyticsBody = RouteBodyInput<\n AnalyticsRoutes['ingestAnalyticsEvents']\n>;\nexport type IngestAnalyticsResult = ResponseData<{ accepted: number }>;\nexport type GetAnalyticsOverviewResult = ResponseData<AnalyticsOverviewRow[]>;\nexport type GetContentStatsResult = ResponseData<ContentStatRow[]>;\nexport type GetExperimentResultsResult = ResponseData<ExperimentResult>;\nexport type GetAudienceResult = ResponseData<AudienceStats>;\nexport type GetPageMetadataResult = ResponseData<PageMetadata>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"analytics.mjs","names":[],"sources":["../../src/analytics.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n} from './defineRoute';\nimport { type ResponseData, responseDataSchema } from './responseData';\n\n/** Kind of analytics event sent by the SDK. */\nexport const analyticsEventTypeSchema = z.enum([\n 'page_view',\n 'content_exposure',\n 'conversion',\n]);\n\n/** One event as sent by the SDK (batched). */\nexport const incomingAnalyticsEventSchema = z.looseObject({\n type: analyticsEventTypeSchema,\n /** Client timestamp (epoch ms). */\n t: z.number(),\n locale: z.string(),\n url: z.string(),\n ref: z.optional(z.string()),\n dictionaryKey: z.optional(z.string()),\n keyPath: z.optional(z.string()),\n nodeType: z.optional(z.string()),\n variant: z.optional(z.string()),\n count: z.optional(z.number()),\n experimentKey: z.optional(z.string()),\n goal: z.optional(z.string()),\n value: z.optional(z.number()),\n});\n\n/**\n * Time windows of the audience report. `live` covers the sessions active in the\n * last 30 minutes, bucketed per minute.\n */\nexport const audienceRangeSchema = z.enum([\n 'live',\n '1h',\n '24h',\n '7d',\n '30d',\n '90d',\n '6mo',\n '1y',\n '3y',\n]);\n\nexport const audienceGranularitySchema = z.enum([\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n]);\n\nexport const audienceSeriesPointSchema = z.object({\n /** ISO bucket start. */\n bucket: z.string(),\n users: z.number(),\n views: z.number(),\n});\n\nconst audienceBreakdownRowSchema = z.object({\n key: z.string(),\n users: z.number(),\n views: z.number(),\n});\n\n/** A session active in the `live` window, placed on the map. */\nexport const liveVisitorSchema = z.object({\n /** Opaque, non-reversible visitor id (prefix of the hashed session). */\n visitorId: z.string(),\n /** ISO country code, `ZZ` when unknown. */\n country: z.string(),\n /** City reported by the CDN, when available. */\n city: z.optional(z.string()),\n /** City-level latitude (rounded to ~1 km), when available. */\n latitude: z.optional(z.number()),\n /** City-level longitude (rounded to ~1 km), when available. */\n longitude: z.optional(z.number()),\n /** Locale the visitor is browsing in. */\n locale: z.optional(z.string()),\n /** Page of the visitor's latest activity. */\n currentUrl: z.string(),\n /** Pages the visitor was active on during the window. */\n pageCount: z.number(),\n /** Page views during the window. */\n views: z.number(),\n /** ISO date of the visitor's first activity in the window. */\n firstSeenAt: z.string(),\n /** ISO date of the visitor's latest activity. */\n lastSeenAt: z.string(),\n /** Minutes (`YYYY-MM-DDTHH:mm`, UTC) the visitor was active in, oldest first. */\n activeMinutes: z.array(z.string()),\n});\n\n/** One step of a live visitor's journey, oldest first. */\nexport const liveVisitorFlowStepSchema = z.object({\n url: z.string(),\n locale: z.optional(z.string()),\n /** ISO date the visitor reached the page. */\n firstSeenAt: z.string(),\n /** ISO date of the visitor's latest activity on the page. */\n lastSeenAt: z.string(),\n views: z.number(),\n});\n\n/**\n * Page journey of one live visitor over the `live` window. `visitor` is `null`\n * once the session has left the window (not an error: it simply went quiet).\n */\nexport const liveVisitorFlowSchema = z.object({\n visitor: z.nullable(liveVisitorSchema),\n steps: z.array(liveVisitorFlowStepSchema),\n});\n\n/**\n * Pseudo-page a session starts from. Used as the flow's starting page, the\n * next step lists the landing pages.\n */\nexport const PAGE_FLOW_ENTRANCE = '(entrance)';\n\n/** One page of a flow step; `url` is `null` for the \"other pages\" bucket. */\nexport const pageFlowNodeSchema = z.object({\n url: z.nullable(z.string()),\n /** Average navigations reaching this page at this step. */\n value: z.number(),\n /** Part of `value` that left the site from this page (`null` if unknown). */\n exits: z.nullable(z.number()),\n});\n\n/** Average navigations from a page of one step to a page of the next. */\nexport const pageFlowLinkSchema = z.object({\n /** Step of the source page; the target is on `fromStep + 1`. */\n fromStep: z.number(),\n fromUrl: z.nullable(z.string()),\n toUrl: z.nullable(z.string()),\n value: z.number(),\n});\n\n/** Averaged navigation flow starting from one page. */\nexport const pageFlowSchema = z.object({\n startUrl: z.string(),\n range: audienceRangeSchema,\n /** Pages per step, the starting page alone on step 0. */\n steps: z.array(z.array(pageFlowNodeSchema)),\n links: z.array(pageFlowLinkSchema),\n});\n\nexport const audienceStatsSchema = z.object({\n usersToday: z.number(),\n usersLast7Days: z.number(),\n usersInRange: z.number(),\n viewsInRange: z.number(),\n range: audienceRangeSchema,\n rangeHours: z.number(),\n granularity: audienceGranularitySchema,\n series: z.array(audienceSeriesPointSchema),\n byLocale: z.array(audienceBreakdownRowSchema),\n byCountry: z.array(audienceBreakdownRowSchema),\n byPage: z.array(audienceBreakdownRowSchema),\n /** Active sessions with their location — `live` range only. */\n liveVisitors: z.optional(z.array(liveVisitorSchema)),\n /** First UTC day with collected data (`YYYY-MM-DD`), `null` before any. */\n dataSince: z.nullable(z.string()),\n});\n\nconst analyticsOverviewRowSchema = z.object({\n url: z.string(),\n locale: z.string(),\n views: z.number(),\n});\n\nconst contentStatRowSchema = z.object({\n dictionaryKey: z.string(),\n keyPath: z.string(),\n locale: z.string(),\n exposures: z.number(),\n});\n\nconst experimentResultSchema = z.object({\n experimentKey: z.string(),\n variants: z.array(\n z.object({\n variant: z.string(),\n exposures: z.number(),\n conversions: z.number(),\n conversionRate: z.number(),\n })\n ),\n pValue: z.nullable(z.number()),\n winner: z.nullable(z.string()),\n});\n\nconst pageMetadataSchema = z.object({\n title: z.optional(z.string()),\n description: z.optional(z.string()),\n});\n\n/** REST contract of the `/api/analytics` routes. */\nexport const analyticsContract = defineRouteGroup({\n prefix: '/api/analytics',\n tag: 'Analytics',\n routes: {\n ingestAnalyticsEvents: defineRoute({\n method: 'POST',\n path: '/events',\n summary: 'Ingest SDK events (public browser token, rate limited)',\n schemas: {\n /** Sent as `text/plain` JSON by `navigator.sendBeacon`. */\n body: z.looseObject({\n /** Token from `POST /api/public/token` (`analytics:ingest`). */\n token: z.optional(z.string()),\n /** @deprecated Superseded by `token`; still accepted. */\n clientId: z.optional(z.string()),\n sessionId: z.string(),\n sdkVersion: z.string(),\n events: z.array(incomingAnalyticsEventSchema),\n }),\n response: {\n 200: responseDataSchema(z.object({ accepted: z.number() })),\n },\n },\n }),\n getAnalyticsOverview: defineRoute({\n method: 'GET',\n path: '/overview',\n summary: 'Page views per page and locale',\n schemas: {\n response: {\n 200: responseDataSchema(z.array(analyticsOverviewRowSchema)),\n },\n },\n }),\n getAnalyticsAudience: defineRoute({\n method: 'GET',\n path: '/audience',\n summary: 'Audience report over a time window',\n schemas: {\n querystring: z.object({\n range: z.optional(z.string()),\n /** Legacy: converted to the closest range. */\n days: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(audienceStatsSchema) },\n },\n }),\n getLiveVisitorFlow: defineRoute({\n method: 'GET',\n path: '/audience/live/visitors/:visitorId',\n summary: 'Page journey of a visitor active in the last 30 minutes',\n schemas: {\n params: z.object({\n visitorId: z.string().check(z.regex(/^[a-f0-9]{16}$/)),\n }),\n response: { 200: responseDataSchema(liveVisitorFlowSchema) },\n },\n }),\n getPageFlow: defineRoute({\n method: 'GET',\n path: '/page-flow',\n summary: 'Average page-to-page navigation flow from a starting page',\n schemas: {\n querystring: z.object({\n range: z.optional(z.string()),\n /** Starting page pathname; defaults to `/`. */\n startUrl: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(pageFlowSchema) },\n },\n }),\n getContentStats: defineRoute({\n method: 'GET',\n path: '/content-stats',\n summary: 'Content exposures per dictionary key path and locale',\n schemas: {\n response: { 200: responseDataSchema(z.array(contentStatRowSchema)) },\n },\n }),\n getExperimentResults: defineRoute({\n method: 'GET',\n path: '/experiments/:experimentKey',\n summary: 'A/B test results of an experiment',\n schemas: {\n params: z.object({ experimentKey: z.string().check(z.minLength(1)) }),\n response: { 200: responseDataSchema(experimentResultSchema) },\n },\n }),\n getPageMetadata: defineRoute({\n method: 'GET',\n path: '/page-metadata',\n summary: 'Title and description of a page of the project',\n schemas: {\n querystring: z.object({ url: z.optional(z.string()) }),\n response: { 200: responseDataSchema(pageMetadataSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/analytics` group, by name. */\nexport type AnalyticsRoutes = (typeof analyticsContract)['routes'];\n\nexport type AnalyticsEventType = z.output<typeof analyticsEventTypeSchema>;\nexport type IncomingAnalyticsEvent = z.output<\n typeof incomingAnalyticsEventSchema\n>;\nexport type AudienceRange = z.output<typeof audienceRangeSchema>;\nexport type AudienceGranularity = z.output<typeof audienceGranularitySchema>;\nexport type AudienceSeriesPoint = z.output<typeof audienceSeriesPointSchema>;\nexport type AudienceBreakdownRow = z.output<typeof audienceBreakdownRowSchema>;\nexport type AudienceStats = z.output<typeof audienceStatsSchema>;\nexport type LiveVisitor = z.output<typeof liveVisitorSchema>;\nexport type LiveVisitorFlowStep = z.output<typeof liveVisitorFlowStepSchema>;\nexport type LiveVisitorFlow = z.output<typeof liveVisitorFlowSchema>;\nexport type PageFlowNode = z.output<typeof pageFlowNodeSchema>;\nexport type PageFlowLink = z.output<typeof pageFlowLinkSchema>;\nexport type PageFlow = z.output<typeof pageFlowSchema>;\nexport type AnalyticsOverviewRow = z.output<typeof analyticsOverviewRowSchema>;\nexport type ContentStatRow = z.output<typeof contentStatRowSchema>;\nexport type ExperimentResult = z.output<typeof experimentResultSchema>;\nexport type PageMetadata = z.output<typeof pageMetadataSchema>;\n\nexport type IngestAnalyticsBody = RouteBodyInput<\n AnalyticsRoutes['ingestAnalyticsEvents']\n>;\nexport type IngestAnalyticsResult = ResponseData<{ accepted: number }>;\nexport type GetAnalyticsOverviewResult = ResponseData<AnalyticsOverviewRow[]>;\nexport type GetContentStatsResult = ResponseData<ContentStatRow[]>;\nexport type GetExperimentResultsResult = ResponseData<ExperimentResult>;\nexport type GetAudienceResult = ResponseData<AudienceStats>;\nexport type GetLiveVisitorFlowResult = ResponseData<LiveVisitorFlow>;\nexport type GetPageFlowResult = ResponseData<PageFlow>;\nexport type GetPageMetadataResult = ResponseData<PageMetadata>;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"project.mjs","names":[],"sources":["../../src/project.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { AiConfig, URLType } from '@intlayer/types/config';\nimport { z } from 'zod/mini';\nimport {\n dateTimeSchema,\n objectIdSchema,\n paginationQueryShape,\n repeatableQueryValueSchema,\n typedStringSchema,\n typedValueSchema,\n} from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBody,\n type RouteBodyInput,\n type RouteParams,\n type RouteQuerystring,\n} from './defineRoute';\nimport {\n type PaginatedResponse,\n paginatedResponseSchema,\n type ResponseData,\n responseDataSchema,\n} from './responseData';\n\n/** Locale code (ex: `en`, `fr-CA`). */\nexport const localeSchema = typedStringSchema<Locale>();\n\n/** Project AI settings: the Intlayer AI config plus the masked key state. */\nexport type ProjectConfigAI = Partial<AiConfig> & {\n /** Masked API key (`sk-proj-****abcd`), never the real one. */\n apiKey?: string;\n apiKeyConfigured?: boolean;\n};\n\n/**\n * Project-level overrides of the Intlayer configuration. Loose objects: the\n * CLI pushes whole config sections, unknown keys must reach the service.\n */\nexport const projectConfigurationSchema = z.looseObject({\n internationalization: z.optional(\n z.looseObject({\n locales: z.optional(z.array(localeSchema)),\n defaultLocale: z.optional(localeSchema),\n })\n ),\n editor: z.optional(\n z.looseObject({\n applicationURL: z.optional(typedStringSchema<URLType>()),\n cmsURL: z.optional(typedStringSchema<URLType>()),\n })\n ),\n ai: z.optional(typedValueSchema<ProjectConfigAI>()),\n});\n\n/** Generic build webhook (Vercel, Netlify, custom). */\nexport const webhookSchema = z.looseObject({\n id: z.optional(z.string()),\n name: z.string(),\n url: z.string(),\n enabled: z.optional(z.boolean()),\n /** Optional signature secret. */\n secret: z.optional(z.string()),\n});\n\n/** Build triggers: git provider pipeline + generic webhooks. */\nexport const projectCISchema = z.object({\n autoTriggerBuilds: z.optional(z.boolean()),\n /** Commit CMS edits of `hybrid` dictionaries back to their source file. */\n autoCommitDictionaries: z.optional(z.boolean()),\n webhooks: z.optional(z.array(webhookSchema)),\n});\n\n/** Git provider of a connected repository. */\nexport const repositoryProviderSchema = z.enum([\n 'github',\n 'gitlab',\n 'bitbucket',\n 'codeberg',\n 'gitee',\n]);\n\nconst baseRepositoryShape = {\n owner: z.string(),\n repository: z.string(),\n branch: z.string(),\n url: z.string(),\n configFilePath: z.string(),\n};\n\n/**\n * Git repository connected to a project. The repo-scoped token never leaves\n * the server.\n */\nexport const repositoryConnectionSchema = z.discriminatedUnion('provider', [\n z.looseObject({\n provider: z.literal('github'),\n ...baseRepositoryShape,\n installationId: z.optional(z.number()),\n }),\n z.looseObject({\n provider: z.literal('gitlab'),\n ...baseRepositoryShape,\n projectId: z.optional(z.number()),\n /** Custom GitLab instance URL (ex: https://gitlab.company.com). */\n instanceUrl: z.optional(z.string()),\n }),\n z.looseObject({\n provider: z.literal('bitbucket'),\n ...baseRepositoryShape,\n workspace: z.string(),\n }),\n z.looseObject({ provider: z.literal('codeberg'), ...baseRepositoryShape }),\n z.looseObject({ provider: z.literal('gitee'), ...baseRepositoryShape }),\n]);\n\n/** null = unrestricted, [] = no access, array = allowed ids (null = production). */\nconst allowedEnvironmentIdsSchema = z.nullable(z.array(z.nullable(z.string())));\n/** null = unrestricted, [] = no access, array = allowed locales. */\nconst allowedLocalesSchema = z.nullable(z.array(localeSchema));\n\n/** Project environment (production is injected when none is the default). */\nexport const environmentSchema = z.looseObject({\n id: z.string(),\n name: z.string(),\n isDefault: z.boolean(),\n configuration: z.optional(projectConfigurationSchema),\n createdAt: z.optional(dateTimeSchema),\n updatedAt: z.optional(dateTimeSchema),\n});\n\n/** Granular per-member access, overlaid on the member's role. */\nexport const projectMemberGranularAccessSchema = z.object({\n userId: z.string(),\n allowedEnvironmentIds: allowedEnvironmentIdsSchema,\n allowedLocales: allowedLocalesSchema,\n});\n\n/** Access key (OAuth2 client credentials). Live bearer tokens are never sent. */\nexport const accessKeySchema = z.looseObject({\n id: z.string(),\n name: z.string(),\n clientId: z.string(),\n /** Shown to project members (dashboard copy, CLI login). */\n clientSecret: z.string(),\n grants: z.array(z.string()),\n userId: z.string(),\n expiresAt: z.optional(z.nullable(dateTimeSchema)),\n allowedEnvironmentIds: z.optional(allowedEnvironmentIdsSchema),\n allowedLocales: z.optional(allowedLocalesSchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Project as returned by the API. */\nexport const projectSchema = z.looseObject({\n id: z.string(),\n organizationId: z.string(),\n name: z.string(),\n membersIds: z.array(z.string()),\n adminsIds: z.array(z.string()),\n viewersIds: z.optional(z.array(z.string())),\n memberAccess: z.optional(z.array(projectMemberGranularAccessSchema)),\n creatorId: z.string(),\n configuration: z.optional(projectConfigurationSchema),\n repository: z.optional(z.nullable(repositoryConnectionSchema)),\n webhooks: z.optional(projectCISchema),\n autoFill: z.optional(z.boolean()),\n /** Screenshot of the application URL, generated automatically. */\n imageUrl: z.optional(z.string()),\n environments: z.optional(z.array(environmentSchema)),\n oAuth2Access: z.array(accessKeySchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Translation health of one locale of a project. */\nexport const localeInsightSchema = z.object({\n locale: localeSchema,\n isDefault: z.boolean(),\n translatedKeys: z.number(),\n totalKeys: z.number(),\n missingKeys: z.number(),\n /** Ratio in the `[0, 1]` range. */\n completionRate: z.number(),\n});\n\n/** Project-wide localization insights shown on the dashboard overview. */\nexport const projectInsightsSchema = z.object({\n projectId: z.string(),\n /** Unix epoch (ms) at which the snapshot was computed. */\n generatedAt: z.number(),\n defaultLocale: z.nullable(localeSchema),\n localeCount: z.number(),\n dictionaryCount: z.number(),\n keyCount: z.number(),\n translationUnitCount: z.number(),\n translatedUnitCount: z.number(),\n overallCompletionRate: z.number(),\n fullyTranslatedLocaleCount: z.number(),\n dictionariesWithMissingTranslations: z.number(),\n missingTranslationCount: z.number(),\n localeInsights: z.array(localeInsightSchema),\n recentlyUpdated: z.array(\n z.object({ key: z.string(), updatedAt: z.number() })\n ),\n lastUpdatedAt: z.nullable(z.number()),\n memberCount: z.number(),\n adminCount: z.number(),\n environmentCount: z.number(),\n autoFill: z.boolean(),\n aiConfigured: z.boolean(),\n repositoryProvider: z.nullable(repositoryProviderSchema),\n applicationURL: z.nullable(z.string()),\n});\n\n/** CI configuration file status of the connected repository. */\nexport const ciStatusSchema = z.object({\n exists: z.boolean(),\n content: z.string(),\n path: z.string(),\n fileUrl: z.optional(z.string()),\n allowAutoPush: z.boolean(),\n});\n\nconst projectIdParamsSchema = z.object({ projectId: objectIdSchema });\nconst clientIdBodySchema = z.object({ clientId: z.string() });\n\nconst ciTargetResultSchema = z.object({\n target: z.string(),\n success: z.boolean(),\n message: z.optional(z.string()),\n});\n\n/** REST contract of the `/api/project` routes. */\nexport const projectContract = defineRouteGroup({\n prefix: '/api/project',\n tag: 'Project',\n routes: {\n getProjects: defineRoute({\n method: 'GET',\n path: '/',\n summary: 'List the projects visible to the session',\n schemas: {\n querystring: z.looseObject({\n ...paginationQueryShape,\n ids: z.optional(repeatableQueryValueSchema),\n name: z.optional(z.string()),\n search: z.optional(z.string()),\n organizationId: z.optional(z.string()),\n membersIds: z.optional(repeatableQueryValueSchema),\n sortBy: z.optional(z.string()),\n sortOrder: z.optional(z.string()),\n /** Admin only: list projects of every organization. */\n fetchAll: z.optional(z.enum(['true', 'false'])),\n }),\n response: { 200: paginatedResponseSchema(projectSchema) },\n },\n }),\n getProjectInsights: defineRoute({\n method: 'GET',\n path: '/insights',\n summary: 'Localization insights of the selected project',\n schemas: {\n response: { 200: responseDataSchema(projectInsightsSchema) },\n },\n }),\n addProject: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Create a project in the selected organization',\n schemas: {\n body: z.looseObject({ name: z.string().check(z.minLength(1)) }),\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n updateProject: defineRoute({\n method: 'PUT',\n path: '/',\n summary: 'Update the selected project',\n schemas: {\n /**\n * Allow-list: membership and ownership fields (`adminsIds`,\n * `membersIds`, `viewersIds`, `creatorId`, `memberAccess`,\n * `environments`) are stripped, they only change through their\n * dedicated endpoints and the invariants those enforce.\n */\n body: z.object({\n name: z.optional(z.string().check(z.minLength(1))),\n configuration: z.optional(projectConfigurationSchema),\n autoFill: z.optional(z.boolean()),\n webhooks: z.optional(projectCISchema),\n /** `null` disconnects the repository. */\n repository: z.optional(z.nullable(repositoryConnectionSchema)),\n }),\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n updateProjectMembers: defineRoute({\n method: 'PUT',\n path: '/members',\n summary: 'Replace the members of the selected project',\n schemas: {\n body: z.object({\n membersIds: z.optional(\n z.array(\n z.object({\n userId: objectIdSchema,\n isAdmin: z.optional(z.boolean()),\n })\n )\n ),\n }),\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n pushProjectConfiguration: defineRoute({\n method: 'PUT',\n path: '/configuration',\n summary: 'Push the local Intlayer configuration to the project',\n schemas: {\n body: projectConfigurationSchema,\n response: { 200: responseDataSchema(projectConfigurationSchema) },\n },\n }),\n deleteProject: defineRoute({\n method: 'DELETE',\n path: '/',\n summary: 'Delete the selected project',\n schemas: {\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n selectProject: defineRoute({\n method: 'PUT',\n path: '/:projectId',\n summary: 'Select a project for the current session',\n schemas: {\n params: projectIdParamsSchema,\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n unselectProject: defineRoute({\n method: 'POST',\n path: '/logout',\n summary: 'Unselect the project of the current session',\n schemas: {\n response: { 200: responseDataSchema(z.null()) },\n },\n }),\n addNewAccessKey: defineRoute({\n method: 'POST',\n path: '/access_key',\n summary: 'Create an access key for the selected project',\n schemas: {\n body: z.object({\n name: z.string().check(z.minLength(1)),\n grants: z.array(z.string()),\n /** ISO date-time, parsed to a `Date`; omitted for a key that never expires. */\n expiresAt: z.optional(\n z.pipe(\n z.iso.datetime(),\n z.transform((value) => new Date(value))\n )\n ),\n allowedEnvironmentIds: z.optional(allowedEnvironmentIdsSchema),\n allowedLocales: z.optional(allowedLocalesSchema),\n }),\n response: { 200: responseDataSchema(accessKeySchema) },\n },\n }),\n refreshAccessKey: defineRoute({\n method: 'PATCH',\n path: '/access_key',\n summary: 'Regenerate the secret of an access key',\n schemas: {\n body: clientIdBodySchema,\n response: { 200: responseDataSchema(accessKeySchema) },\n },\n }),\n deleteAccessKey: defineRoute({\n method: 'DELETE',\n path: '/access_key',\n summary: 'Delete an access key',\n schemas: {\n body: clientIdBodySchema,\n response: { 200: responseDataSchema(z.null()) },\n },\n }),\n triggerBuild: defineRoute({\n method: 'POST',\n path: '/build',\n summary: 'Trigger the CI pipelines and webhooks of the project',\n schemas: {\n response: {\n 200: responseDataSchema(\n z.object({ results: z.array(ciTargetResultSchema) })\n ),\n },\n },\n }),\n triggerWebhook: defineRoute({\n method: 'POST',\n path: '/webhook',\n summary: 'Trigger a single project webhook',\n schemas: {\n body: z.object({ webhookIndex: z.int().check(z.gte(0)) }),\n response: { 200: responseDataSchema(ciTargetResultSchema) },\n },\n }),\n getCIConfiguration: defineRoute({\n method: 'GET',\n path: '/ci',\n summary: 'CI configuration status of the connected repository',\n schemas: {\n response: { 200: responseDataSchema(ciStatusSchema) },\n },\n }),\n pushCIConfiguration: defineRoute({\n method: 'POST',\n path: '/ci',\n summary: 'Commit the CI configuration file to the repository',\n schemas: {\n response: {\n 200: responseDataSchema(z.object({ success: z.boolean() })),\n },\n },\n }),\n deleteProjectByIdAdmin: defineRoute({\n method: 'DELETE',\n path: '/:projectId/admin',\n summary: 'Admin only: delete any project',\n schemas: {\n params: projectIdParamsSchema,\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n updateMemberAccess: defineRoute({\n method: 'PUT',\n path: '/member/:userId/access',\n summary: 'Restrict the environments and locales of a project member',\n schemas: {\n params: z.object({ userId: objectIdSchema }),\n body: z.object({\n allowedEnvironmentIds: allowedEnvironmentIdsSchema,\n allowedLocales: allowedLocalesSchema,\n }),\n response: {\n 200: responseDataSchema(projectMemberGranularAccessSchema),\n },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/project` group, by name. */\nexport type ProjectRoutes = (typeof projectContract)['routes'];\n\n// Entity types\nexport type ProjectConfiguration = z.output<typeof projectConfigurationSchema>;\nexport type Webhook = z.output<typeof webhookSchema>;\nexport type ProjectConfigCI = z.output<typeof projectCISchema>;\nexport type RepositoryProvider = z.output<typeof repositoryProviderSchema>;\nexport type RepositoryConnection = z.output<typeof repositoryConnectionSchema>;\nexport type EnvironmentAPI = z.output<typeof environmentSchema>;\nexport type ProjectMemberGranularAccessAPI = z.output<\n typeof projectMemberGranularAccessSchema\n>;\nexport type OAuth2AccessAPI = z.output<typeof accessKeySchema>;\nexport type ProjectAPI = z.output<typeof projectSchema>;\nexport type ProjectInsights = z.output<typeof projectInsightsSchema>;\nexport type CIStatus = z.output<typeof ciStatusSchema>;\n\n// Request / response types\nexport type GetProjectsParams = RouteQuerystring<ProjectRoutes['getProjects']>;\nexport type GetProjectsResult = PaginatedResponse<ProjectAPI>;\nexport type GetProjectInsightsResult = ResponseData<ProjectInsights>;\nexport type AddProjectBody = RouteBodyInput<ProjectRoutes['addProject']>;\nexport type AddProjectResult = ResponseData<ProjectAPI>;\nexport type UpdateProjectBody = RouteBodyInput<ProjectRoutes['updateProject']>;\nexport type UpdateProjectResult = ResponseData<ProjectAPI>;\nexport type UpdateProjectMembersBody = RouteBodyInput<\n ProjectRoutes['updateProjectMembers']\n>;\nexport type UpdateProjectMembersResult = ResponseData<ProjectAPI>;\nexport type PushProjectConfigurationBody = RouteBodyInput<\n ProjectRoutes['pushProjectConfiguration']\n>;\nexport type PushProjectConfigurationResult = ResponseData<ProjectConfiguration>;\nexport type DeleteProjectResult = ResponseData<ProjectAPI>;\nexport type SelectProjectParam = RouteParams<ProjectRoutes['selectProject']>;\nexport type SelectProjectResult = ResponseData<ProjectAPI>;\nexport type UnselectProjectResult = ResponseData<null>;\n/** `expiresAt` also accepts a `Date`: JSON serializes it to an ISO string. */\nexport type AddNewAccessKeyBody = Omit<\n RouteBodyInput<ProjectRoutes['addNewAccessKey']>,\n 'expiresAt'\n> & { expiresAt?: Date | string };\nexport type AddNewAccessKeyResponse = ResponseData<OAuth2AccessAPI>;\nexport type RefreshAccessKeyBody = RouteBody<ProjectRoutes['refreshAccessKey']>;\nexport type RefreshAccessKeyResponse = ResponseData<OAuth2AccessAPI>;\nexport type DeleteAccessKeyBody = RouteBody<ProjectRoutes['deleteAccessKey']>;\nexport type DeleteAccessKeyResponse = ResponseData<null>;\nexport type TriggerBuildResult = ResponseData<{\n results: z.output<typeof ciTargetResultSchema>[];\n}>;\nexport type TriggerWebhookBody = RouteBody<ProjectRoutes['triggerWebhook']>;\nexport type TriggerWebhookResult = ResponseData<\n z.output<typeof ciTargetResultSchema>\n>;\nexport type GetCIConfigurationResult = ResponseData<CIStatus>;\nexport type PushCIConfigurationResult = ResponseData<{ success: boolean }>;\nexport type DeleteProjectByIdAdminResult = ResponseData<ProjectAPI>;\nexport type UpdateMemberAccessParams = RouteParams<\n ProjectRoutes['updateMemberAccess']\n>;\nexport type UpdateMemberAccessBody = RouteBodyInput<\n ProjectRoutes['updateMemberAccess']\n>;\nexport type UpdateMemberAccessResult =\n ResponseData<ProjectMemberGranularAccessAPI>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"project.mjs","names":[],"sources":["../../src/project.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { AiConfig, URLType } from '@intlayer/types/config';\nimport { z } from 'zod/mini';\nimport {\n dateTimeSchema,\n objectIdSchema,\n paginationQueryShape,\n repeatableQueryValueSchema,\n typedStringSchema,\n typedValueSchema,\n} from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBody,\n type RouteBodyInput,\n type RouteParams,\n type RouteQuerystring,\n} from './defineRoute';\nimport {\n type PaginatedResponse,\n paginatedResponseSchema,\n type ResponseData,\n responseDataSchema,\n} from './responseData';\n\n/** Locale code (ex: `en`, `fr-CA`). */\nexport const localeSchema = typedStringSchema<Locale>();\n\n/** Project AI settings: the Intlayer AI config plus the masked key state. */\nexport type ProjectConfigAI = Partial<AiConfig> & {\n /** Masked API key (`sk-proj-****abcd`), never the real one. */\n apiKey?: string;\n apiKeyConfigured?: boolean;\n /**\n * `false` runs AI calls on the plan credits instead of the own key.\n * Missing means enabled.\n */\n isOwnAPIKeyEnabled?: boolean;\n};\n\n/**\n * Project-level overrides of the Intlayer configuration. Loose objects: the\n * CLI pushes whole config sections, unknown keys must reach the service.\n */\nexport const projectConfigurationSchema = z.looseObject({\n internationalization: z.optional(\n z.looseObject({\n locales: z.optional(z.array(localeSchema)),\n defaultLocale: z.optional(localeSchema),\n })\n ),\n editor: z.optional(\n z.looseObject({\n applicationURL: z.optional(typedStringSchema<URLType>()),\n cmsURL: z.optional(typedStringSchema<URLType>()),\n })\n ),\n ai: z.optional(typedValueSchema<ProjectConfigAI>()),\n});\n\n/** Generic build webhook (Vercel, Netlify, custom). */\nexport const webhookSchema = z.looseObject({\n id: z.optional(z.string()),\n name: z.string(),\n url: z.string(),\n enabled: z.optional(z.boolean()),\n /** Optional signature secret. */\n secret: z.optional(z.string()),\n});\n\n/** Build triggers: git provider pipeline + generic webhooks. */\nexport const projectCISchema = z.object({\n autoTriggerBuilds: z.optional(z.boolean()),\n /** Commit CMS edits of `hybrid` dictionaries back to their source file. */\n autoCommitDictionaries: z.optional(z.boolean()),\n webhooks: z.optional(z.array(webhookSchema)),\n});\n\n/** Git provider of a connected repository. */\nexport const repositoryProviderSchema = z.enum([\n 'github',\n 'gitlab',\n 'bitbucket',\n 'codeberg',\n 'gitee',\n]);\n\nconst baseRepositoryShape = {\n owner: z.string(),\n repository: z.string(),\n branch: z.string(),\n url: z.string(),\n configFilePath: z.string(),\n};\n\n/**\n * Git repository connected to a project. The repo-scoped token never leaves\n * the server.\n */\nexport const repositoryConnectionSchema = z.discriminatedUnion('provider', [\n z.looseObject({\n provider: z.literal('github'),\n ...baseRepositoryShape,\n installationId: z.optional(z.number()),\n }),\n z.looseObject({\n provider: z.literal('gitlab'),\n ...baseRepositoryShape,\n projectId: z.optional(z.number()),\n /** Custom GitLab instance URL (ex: https://gitlab.company.com). */\n instanceUrl: z.optional(z.string()),\n }),\n z.looseObject({\n provider: z.literal('bitbucket'),\n ...baseRepositoryShape,\n workspace: z.string(),\n }),\n z.looseObject({ provider: z.literal('codeberg'), ...baseRepositoryShape }),\n z.looseObject({ provider: z.literal('gitee'), ...baseRepositoryShape }),\n]);\n\n/** null = unrestricted, [] = no access, array = allowed ids (null = production). */\nconst allowedEnvironmentIdsSchema = z.nullable(z.array(z.nullable(z.string())));\n/** null = unrestricted, [] = no access, array = allowed locales. */\nconst allowedLocalesSchema = z.nullable(z.array(localeSchema));\n\n/** Project environment (production is injected when none is the default). */\nexport const environmentSchema = z.looseObject({\n id: z.string(),\n name: z.string(),\n isDefault: z.boolean(),\n configuration: z.optional(projectConfigurationSchema),\n createdAt: z.optional(dateTimeSchema),\n updatedAt: z.optional(dateTimeSchema),\n});\n\n/** Granular per-member access, overlaid on the member's role. */\nexport const projectMemberGranularAccessSchema = z.object({\n userId: z.string(),\n allowedEnvironmentIds: allowedEnvironmentIdsSchema,\n allowedLocales: allowedLocalesSchema,\n});\n\n/** Access key (OAuth2 client credentials). Live bearer tokens are never sent. */\nexport const accessKeySchema = z.looseObject({\n id: z.string(),\n name: z.string(),\n clientId: z.string(),\n /** Shown to project members (dashboard copy, CLI login). */\n clientSecret: z.string(),\n grants: z.array(z.string()),\n userId: z.string(),\n expiresAt: z.optional(z.nullable(dateTimeSchema)),\n allowedEnvironmentIds: z.optional(allowedEnvironmentIdsSchema),\n allowedLocales: z.optional(allowedLocalesSchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Project as returned by the API. */\nexport const projectSchema = z.looseObject({\n id: z.string(),\n organizationId: z.string(),\n name: z.string(),\n membersIds: z.array(z.string()),\n adminsIds: z.array(z.string()),\n viewersIds: z.optional(z.array(z.string())),\n memberAccess: z.optional(z.array(projectMemberGranularAccessSchema)),\n creatorId: z.string(),\n configuration: z.optional(projectConfigurationSchema),\n repository: z.optional(z.nullable(repositoryConnectionSchema)),\n webhooks: z.optional(projectCISchema),\n autoFill: z.optional(z.boolean()),\n /** Screenshot of the application URL, generated automatically. */\n imageUrl: z.optional(z.string()),\n environments: z.optional(z.array(environmentSchema)),\n oAuth2Access: z.array(accessKeySchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Translation health of one locale of a project. */\nexport const localeInsightSchema = z.object({\n locale: localeSchema,\n isDefault: z.boolean(),\n translatedKeys: z.number(),\n totalKeys: z.number(),\n missingKeys: z.number(),\n /** Ratio in the `[0, 1]` range. */\n completionRate: z.number(),\n});\n\n/** Project-wide localization insights shown on the dashboard overview. */\nexport const projectInsightsSchema = z.object({\n projectId: z.string(),\n /** Unix epoch (ms) at which the snapshot was computed. */\n generatedAt: z.number(),\n defaultLocale: z.nullable(localeSchema),\n localeCount: z.number(),\n dictionaryCount: z.number(),\n keyCount: z.number(),\n translationUnitCount: z.number(),\n translatedUnitCount: z.number(),\n overallCompletionRate: z.number(),\n fullyTranslatedLocaleCount: z.number(),\n dictionariesWithMissingTranslations: z.number(),\n missingTranslationCount: z.number(),\n localeInsights: z.array(localeInsightSchema),\n recentlyUpdated: z.array(\n z.object({ key: z.string(), updatedAt: z.number() })\n ),\n lastUpdatedAt: z.nullable(z.number()),\n memberCount: z.number(),\n adminCount: z.number(),\n environmentCount: z.number(),\n autoFill: z.boolean(),\n aiConfigured: z.boolean(),\n repositoryProvider: z.nullable(repositoryProviderSchema),\n applicationURL: z.nullable(z.string()),\n});\n\n/** CI configuration file status of the connected repository. */\nexport const ciStatusSchema = z.object({\n exists: z.boolean(),\n content: z.string(),\n path: z.string(),\n fileUrl: z.optional(z.string()),\n allowAutoPush: z.boolean(),\n});\n\nconst projectIdParamsSchema = z.object({ projectId: objectIdSchema });\nconst clientIdBodySchema = z.object({ clientId: z.string() });\n\nconst ciTargetResultSchema = z.object({\n target: z.string(),\n success: z.boolean(),\n message: z.optional(z.string()),\n});\n\n/** REST contract of the `/api/project` routes. */\nexport const projectContract = defineRouteGroup({\n prefix: '/api/project',\n tag: 'Project',\n routes: {\n getProjects: defineRoute({\n method: 'GET',\n path: '/',\n summary: 'List the projects visible to the session',\n schemas: {\n querystring: z.looseObject({\n ...paginationQueryShape,\n ids: z.optional(repeatableQueryValueSchema),\n name: z.optional(z.string()),\n search: z.optional(z.string()),\n organizationId: z.optional(z.string()),\n membersIds: z.optional(repeatableQueryValueSchema),\n sortBy: z.optional(z.string()),\n sortOrder: z.optional(z.string()),\n /** Admin only: list projects of every organization. */\n fetchAll: z.optional(z.enum(['true', 'false'])),\n }),\n response: { 200: paginatedResponseSchema(projectSchema) },\n },\n }),\n getProjectInsights: defineRoute({\n method: 'GET',\n path: '/insights',\n summary: 'Localization insights of the selected project',\n schemas: {\n response: { 200: responseDataSchema(projectInsightsSchema) },\n },\n }),\n addProject: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Create a project in the selected organization',\n schemas: {\n body: z.looseObject({ name: z.string().check(z.minLength(1)) }),\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n updateProject: defineRoute({\n method: 'PUT',\n path: '/',\n summary: 'Update the selected project',\n schemas: {\n /**\n * Allow-list: membership and ownership fields (`adminsIds`,\n * `membersIds`, `viewersIds`, `creatorId`, `memberAccess`,\n * `environments`) are stripped, they only change through their\n * dedicated endpoints and the invariants those enforce.\n */\n body: z.object({\n name: z.optional(z.string().check(z.minLength(1))),\n configuration: z.optional(projectConfigurationSchema),\n autoFill: z.optional(z.boolean()),\n webhooks: z.optional(projectCISchema),\n /** `null` disconnects the repository. */\n repository: z.optional(z.nullable(repositoryConnectionSchema)),\n }),\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n updateProjectMembers: defineRoute({\n method: 'PUT',\n path: '/members',\n summary: 'Replace the members of the selected project',\n schemas: {\n body: z.object({\n membersIds: z.optional(\n z.array(\n z.object({\n userId: objectIdSchema,\n isAdmin: z.optional(z.boolean()),\n })\n )\n ),\n }),\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n pushProjectConfiguration: defineRoute({\n method: 'PUT',\n path: '/configuration',\n summary: 'Push the local Intlayer configuration to the project',\n schemas: {\n body: projectConfigurationSchema,\n response: { 200: responseDataSchema(projectConfigurationSchema) },\n },\n }),\n deleteProject: defineRoute({\n method: 'DELETE',\n path: '/',\n summary: 'Delete the selected project',\n schemas: {\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n selectProject: defineRoute({\n method: 'PUT',\n path: '/:projectId',\n summary: 'Select a project for the current session',\n schemas: {\n params: projectIdParamsSchema,\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n unselectProject: defineRoute({\n method: 'POST',\n path: '/logout',\n summary: 'Unselect the project of the current session',\n schemas: {\n response: { 200: responseDataSchema(z.null()) },\n },\n }),\n addNewAccessKey: defineRoute({\n method: 'POST',\n path: '/access_key',\n summary: 'Create an access key for the selected project',\n schemas: {\n body: z.object({\n name: z.string().check(z.minLength(1)),\n grants: z.array(z.string()),\n /** ISO date-time, parsed to a `Date`; omitted for a key that never expires. */\n expiresAt: z.optional(\n z.pipe(\n z.iso.datetime(),\n z.transform((value) => new Date(value))\n )\n ),\n allowedEnvironmentIds: z.optional(allowedEnvironmentIdsSchema),\n allowedLocales: z.optional(allowedLocalesSchema),\n }),\n response: { 200: responseDataSchema(accessKeySchema) },\n },\n }),\n refreshAccessKey: defineRoute({\n method: 'PATCH',\n path: '/access_key',\n summary: 'Regenerate the secret of an access key',\n schemas: {\n body: clientIdBodySchema,\n response: { 200: responseDataSchema(accessKeySchema) },\n },\n }),\n deleteAccessKey: defineRoute({\n method: 'DELETE',\n path: '/access_key',\n summary: 'Delete an access key',\n schemas: {\n body: clientIdBodySchema,\n response: { 200: responseDataSchema(z.null()) },\n },\n }),\n triggerBuild: defineRoute({\n method: 'POST',\n path: '/build',\n summary: 'Trigger the CI pipelines and webhooks of the project',\n schemas: {\n response: {\n 200: responseDataSchema(\n z.object({ results: z.array(ciTargetResultSchema) })\n ),\n },\n },\n }),\n triggerWebhook: defineRoute({\n method: 'POST',\n path: '/webhook',\n summary: 'Trigger a single project webhook',\n schemas: {\n body: z.object({ webhookIndex: z.int().check(z.gte(0)) }),\n response: { 200: responseDataSchema(ciTargetResultSchema) },\n },\n }),\n getCIConfiguration: defineRoute({\n method: 'GET',\n path: '/ci',\n summary: 'CI configuration status of the connected repository',\n schemas: {\n response: { 200: responseDataSchema(ciStatusSchema) },\n },\n }),\n pushCIConfiguration: defineRoute({\n method: 'POST',\n path: '/ci',\n summary: 'Commit the CI configuration file to the repository',\n schemas: {\n response: {\n 200: responseDataSchema(z.object({ success: z.boolean() })),\n },\n },\n }),\n deleteProjectByIdAdmin: defineRoute({\n method: 'DELETE',\n path: '/:projectId/admin',\n summary: 'Admin only: delete any project',\n schemas: {\n params: projectIdParamsSchema,\n response: { 200: responseDataSchema(projectSchema) },\n },\n }),\n updateMemberAccess: defineRoute({\n method: 'PUT',\n path: '/member/:userId/access',\n summary: 'Restrict the environments and locales of a project member',\n schemas: {\n params: z.object({ userId: objectIdSchema }),\n body: z.object({\n allowedEnvironmentIds: allowedEnvironmentIdsSchema,\n allowedLocales: allowedLocalesSchema,\n }),\n response: {\n 200: responseDataSchema(projectMemberGranularAccessSchema),\n },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/project` group, by name. */\nexport type ProjectRoutes = (typeof projectContract)['routes'];\n\n// Entity types\nexport type ProjectConfiguration = z.output<typeof projectConfigurationSchema>;\nexport type Webhook = z.output<typeof webhookSchema>;\nexport type ProjectConfigCI = z.output<typeof projectCISchema>;\nexport type RepositoryProvider = z.output<typeof repositoryProviderSchema>;\nexport type RepositoryConnection = z.output<typeof repositoryConnectionSchema>;\nexport type EnvironmentAPI = z.output<typeof environmentSchema>;\nexport type ProjectMemberGranularAccessAPI = z.output<\n typeof projectMemberGranularAccessSchema\n>;\nexport type OAuth2AccessAPI = z.output<typeof accessKeySchema>;\nexport type ProjectAPI = z.output<typeof projectSchema>;\nexport type ProjectInsights = z.output<typeof projectInsightsSchema>;\nexport type CIStatus = z.output<typeof ciStatusSchema>;\n\n// Request / response types\nexport type GetProjectsParams = RouteQuerystring<ProjectRoutes['getProjects']>;\nexport type GetProjectsResult = PaginatedResponse<ProjectAPI>;\nexport type GetProjectInsightsResult = ResponseData<ProjectInsights>;\nexport type AddProjectBody = RouteBodyInput<ProjectRoutes['addProject']>;\nexport type AddProjectResult = ResponseData<ProjectAPI>;\nexport type UpdateProjectBody = RouteBodyInput<ProjectRoutes['updateProject']>;\nexport type UpdateProjectResult = ResponseData<ProjectAPI>;\nexport type UpdateProjectMembersBody = RouteBodyInput<\n ProjectRoutes['updateProjectMembers']\n>;\nexport type UpdateProjectMembersResult = ResponseData<ProjectAPI>;\nexport type PushProjectConfigurationBody = RouteBodyInput<\n ProjectRoutes['pushProjectConfiguration']\n>;\nexport type PushProjectConfigurationResult = ResponseData<ProjectConfiguration>;\nexport type DeleteProjectResult = ResponseData<ProjectAPI>;\nexport type SelectProjectParam = RouteParams<ProjectRoutes['selectProject']>;\nexport type SelectProjectResult = ResponseData<ProjectAPI>;\nexport type UnselectProjectResult = ResponseData<null>;\n/** `expiresAt` also accepts a `Date`: JSON serializes it to an ISO string. */\nexport type AddNewAccessKeyBody = Omit<\n RouteBodyInput<ProjectRoutes['addNewAccessKey']>,\n 'expiresAt'\n> & { expiresAt?: Date | string };\nexport type AddNewAccessKeyResponse = ResponseData<OAuth2AccessAPI>;\nexport type RefreshAccessKeyBody = RouteBody<ProjectRoutes['refreshAccessKey']>;\nexport type RefreshAccessKeyResponse = ResponseData<OAuth2AccessAPI>;\nexport type DeleteAccessKeyBody = RouteBody<ProjectRoutes['deleteAccessKey']>;\nexport type DeleteAccessKeyResponse = ResponseData<null>;\nexport type TriggerBuildResult = ResponseData<{\n results: z.output<typeof ciTargetResultSchema>[];\n}>;\nexport type TriggerWebhookBody = RouteBody<ProjectRoutes['triggerWebhook']>;\nexport type TriggerWebhookResult = ResponseData<\n z.output<typeof ciTargetResultSchema>\n>;\nexport type GetCIConfigurationResult = ResponseData<CIStatus>;\nexport type PushCIConfigurationResult = ResponseData<{ success: boolean }>;\nexport type DeleteProjectByIdAdminResult = ResponseData<ProjectAPI>;\nexport type UpdateMemberAccessParams = RouteParams<\n ProjectRoutes['updateMemberAccess']\n>;\nexport type UpdateMemberAccessBody = RouteBodyInput<\n ProjectRoutes['updateMemberAccess']\n>;\nexport type UpdateMemberAccessResult =\n ResponseData<ProjectMemberGranularAccessAPI>;\n"],"mappings":"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"}