@deveye/types 0.15.2 → 0.16.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/package.json +6 -6
- package/src/domain/device.ts +4 -29
- package/src/domain/featureRegistry.ts +40 -108
- package/src/domain/home.ts +40 -101
- package/src/domain/live.ts +36 -87
- package/src/domain/metrics.ts +10 -14
- package/src/domain/notifications.ts +39 -110
- package/src/domain/project.ts +3 -162
- package/src/domain/report.ts +46 -95
- package/src/domain/secrecy.ts +3 -5
- package/src/domain/sharing.ts +33 -70
- package/src/domain/syncProtocol.ts +5 -12
- package/src/domain/user.ts +8 -14
- package/src/domain/workspace.ts +0 -3
- package/src/domain/workspaceRole.ts +34 -82
- package/src/features/agent.ts +306 -0
- package/src/features/live.ts +17 -37
- package/src/features/notify.ts +19 -57
- package/src/features/registry.ts +7 -44
- package/src/features/secrecy.ts +4 -9
- package/src/features/sharing.ts +12 -26
- package/src/features/user.ts +6 -11
- package/src/features/workspace.ts +6 -11
- package/src/http/auth.ts +6 -13
- package/src/http/device.ts +13 -17
- package/src/http/status.ts +6 -10
- package/src/index.ts +29 -932
- package/src/protocol/agent.ts +40 -70
- package/src/protocol/envelope.ts +3 -10
- package/src/sdk/client-ambient.d.ts +228 -21
- package/src/sdk/client.ts +277 -17
- package/src/sdk/devb.ts +120 -0
- package/src/sdk/manifest.test.ts +0 -1
- package/src/sdk/manifest.ts +94 -25
- package/src/sdk/providers.ts +310 -5
- package/src/sdk/server.ts +483 -19
- package/src/sdk/testing.test.ts +2 -2
- package/src/sdk/testing.ts +302 -26
- package/src/utils/version.ts +5 -8
- package/src/domain/audience.ts +0 -549
- package/src/domain/backup.ts +0 -355
- package/src/domain/credential.ts +0 -55
- package/src/domain/database.ts +0 -467
- package/src/domain/deploy.ts +0 -231
- package/src/domain/finance.ts +0 -477
- package/src/domain/git.ts +0 -419
- package/src/domain/mail.ts +0 -394
- package/src/domain/note.ts +0 -202
- package/src/domain/password.ts +0 -36
- package/src/domain/projectBoard.ts +0 -130
- package/src/domain/projectChat.ts +0 -46
- package/src/domain/projectHistory.ts +0 -82
- package/src/domain/projectLink.ts +0 -87
- package/src/domain/projectPlan.ts +0 -68
- package/src/domain/sentinel.ts +0 -623
- package/src/domain/uptime.ts +0 -216
- package/src/features/audience.ts +0 -275
- package/src/features/backup.ts +0 -230
- package/src/features/database.ts +0 -461
- package/src/features/deploy.ts +0 -245
- package/src/features/device.ts +0 -292
- package/src/features/deviceFiles.ts +0 -83
- package/src/features/deviceLogs.ts +0 -36
- package/src/features/deviceTerminal.ts +0 -57
- package/src/features/finance.ts +0 -360
- package/src/features/git.ts +0 -368
- package/src/features/mail.ts +0 -374
- package/src/features/metrics.ts +0 -185
- package/src/features/note.ts +0 -189
- package/src/features/password.ts +0 -67
- package/src/features/project.ts +0 -709
- package/src/features/sentinel.ts +0 -233
- package/src/features/uptime.ts +0 -186
package/src/domain/uptime.ts
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Uptime monitoring: user-defined HTTP services the server pings on a schedule,
|
|
5
|
-
* with long-term history, incidents and notifications.
|
|
6
|
-
*
|
|
7
|
-
* Storage split (see `Docs/SECURITY_MODEL.md`): everything the scheduler needs
|
|
8
|
-
* to *plan* a check (cadence, timeout, enabled…) and everything a chart
|
|
9
|
-
* aggregates (status, latency, timestamps) lives in clear columns; what
|
|
10
|
-
* identifies the target — name, URL, expected keyword — and the error strings
|
|
11
|
-
* are encrypted with the **open** tier, since the checker runs in the
|
|
12
|
-
* background, with no session and no password.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
export const UPTIME_NAME_MAX_LENGTH = 80;
|
|
16
|
-
export const UPTIME_URL_MAX_LENGTH = 2048;
|
|
17
|
-
export const UPTIME_KEYWORD_MAX_LENGTH = 200;
|
|
18
|
-
/** Bounds of a service's cadence, in seconds (30 s → 24 h). */
|
|
19
|
-
export const UPTIME_INTERVAL_MIN = 30;
|
|
20
|
-
export const UPTIME_INTERVAL_MAX = 86400;
|
|
21
|
-
/** Bounds of a single request's timeout, in seconds. */
|
|
22
|
-
export const UPTIME_TIMEOUT_MIN = 1;
|
|
23
|
-
export const UPTIME_TIMEOUT_MAX = 120;
|
|
24
|
-
/** Consecutive failures required before a service is declared down. */
|
|
25
|
-
export const UPTIME_THRESHOLD_MAX = 10;
|
|
26
|
-
|
|
27
|
-
/** HTTP verb used for the probe. `POST` sends no body — it only pokes the route. */
|
|
28
|
-
export const uptimeMethodSchema = z.enum(['GET', 'HEAD', 'POST']);
|
|
29
|
-
export type UptimeMethod = z.infer<typeof uptimeMethodSchema>;
|
|
30
|
-
|
|
31
|
-
/** `unknown` = never probed yet (just created, or paused before its first check). */
|
|
32
|
-
export const uptimeStatusSchema = z.enum(['up', 'down', 'unknown']);
|
|
33
|
-
export type UptimeStatus = z.infer<typeof uptimeStatusSchema>;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* How long a service keeps its **raw** per-ping rows. The daily rollup is never
|
|
37
|
-
* pruned, so uptime ratios stay readable years back whatever this is set to.
|
|
38
|
-
* `null` = keep every ping forever (the default).
|
|
39
|
-
*/
|
|
40
|
-
export const uptimeRetentionSchema = z.number().int().positive().max(3650).nullable();
|
|
41
|
-
|
|
42
|
-
/** Window a chart or a ratio is computed over. */
|
|
43
|
-
export const uptimeRangeSchema = z.enum(['24h', '7d', '30d', '90d', '1y', 'all']);
|
|
44
|
-
export type UptimeRange = z.infer<typeof uptimeRangeSchema>;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Bucket size the server picked for a history query: one point per ping (`raw`),
|
|
48
|
-
* per hour, or per day. Chosen from the range so a year-long chart never carries
|
|
49
|
-
* hundreds of thousands of points.
|
|
50
|
-
*/
|
|
51
|
-
export const uptimeResolutionSchema = z.enum(['raw', 'hour', 'day']);
|
|
52
|
-
export type UptimeResolution = z.infer<typeof uptimeResolutionSchema>;
|
|
53
|
-
|
|
54
|
-
/** One monitored service: its configuration, its live state and its ratios. */
|
|
55
|
-
export const uptimeServiceSchema = z.object({
|
|
56
|
-
id: z.number().int().positive(),
|
|
57
|
-
name: z.string(),
|
|
58
|
-
url: z.string(),
|
|
59
|
-
method: uptimeMethodSchema,
|
|
60
|
-
/** Exact status code required, or `null` to accept any 2xx/3xx. */
|
|
61
|
-
expectedStatus: z.number().int().min(100).max(599).nullable(),
|
|
62
|
-
/** Substring the response body must contain, or `null` to skip the check. */
|
|
63
|
-
keyword: z.string().nullable(),
|
|
64
|
-
intervalSeconds: z.number().int().positive(),
|
|
65
|
-
timeoutSeconds: z.number().int().positive(),
|
|
66
|
-
failureThreshold: z.number().int().positive(),
|
|
67
|
-
retentionDays: uptimeRetentionSchema,
|
|
68
|
-
/** Paused services keep their history but are never probed. */
|
|
69
|
-
enabled: z.boolean(),
|
|
70
|
-
/** Rank in the list; only the user's drag & drop changes it. */
|
|
71
|
-
sortOrder: z.number().int().nonnegative(),
|
|
72
|
-
/**
|
|
73
|
-
* Ce service vient d'un **autre espace**, qui le projette ici.
|
|
74
|
-
*
|
|
75
|
-
* Il se lit et se modifie normalement — c'est tout l'objet de la projection
|
|
76
|
-
* — mais l'écran le signale : sans ça, le supprimer depuis l'espace où on le
|
|
77
|
-
* voit donnerait l'impression de retirer une ligne locale, alors qu'on
|
|
78
|
-
* toucherait la donnée d'ailleurs.
|
|
79
|
-
*/
|
|
80
|
-
foreign: z.boolean(),
|
|
81
|
-
|
|
82
|
-
status: uptimeStatusSchema,
|
|
83
|
-
lastCheckedAt: z.number().int().nonnegative().nullable(),
|
|
84
|
-
lastResponseMs: z.number().int().nonnegative().nullable(),
|
|
85
|
-
lastHttpStatus: z.number().int().nullable(),
|
|
86
|
-
/** Why the last probe failed, or `null` when it succeeded. */
|
|
87
|
-
lastError: z.string().nullable(),
|
|
88
|
-
/** Start of the ongoing outage, or `null` while the service is healthy. */
|
|
89
|
-
downSince: z.number().int().nonnegative().nullable(),
|
|
90
|
-
|
|
91
|
-
/** Share of successful pings over the window (0 → 1), `null` without data. */
|
|
92
|
-
ratio24h: z.number().min(0).max(1).nullable(),
|
|
93
|
-
ratio7d: z.number().min(0).max(1).nullable(),
|
|
94
|
-
ratio30d: z.number().min(0).max(1).nullable(),
|
|
95
|
-
/** Mean response time over the last 24 h, in ms. */
|
|
96
|
-
avgMs24h: z.number().int().nonnegative().nullable(),
|
|
97
|
-
|
|
98
|
-
created: z.number().int().nonnegative()
|
|
99
|
-
});
|
|
100
|
-
export type UptimeService = z.infer<typeof uptimeServiceSchema>;
|
|
101
|
-
|
|
102
|
-
/** A single recorded probe — the "journal des pings". */
|
|
103
|
-
export const uptimeCheckSchema = z.object({
|
|
104
|
-
at: z.number().int().nonnegative(),
|
|
105
|
-
up: z.boolean(),
|
|
106
|
-
httpStatus: z.number().int().nullable(),
|
|
107
|
-
responseMs: z.number().int().nonnegative().nullable(),
|
|
108
|
-
error: z.string().nullable()
|
|
109
|
-
});
|
|
110
|
-
export type UptimeCheck = z.infer<typeof uptimeCheckSchema>;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Aggregates over a filtered slice of a service's raw pings — what the measures
|
|
114
|
-
* browser shows above its list, computed over the **whole** selection rather
|
|
115
|
-
* than the loaded page.
|
|
116
|
-
*/
|
|
117
|
-
export const uptimeCheckStatsSchema = z.object({
|
|
118
|
-
count: z.number().int().nonnegative(),
|
|
119
|
-
failures: z.number().int().nonnegative(),
|
|
120
|
-
avgMs: z.number().int().nonnegative().nullable(),
|
|
121
|
-
minMs: z.number().int().nonnegative().nullable(),
|
|
122
|
-
maxMs: z.number().int().nonnegative().nullable(),
|
|
123
|
-
/** Bounds of the selection; `null` when it holds nothing. */
|
|
124
|
-
firstAt: z.number().int().nonnegative().nullable(),
|
|
125
|
-
lastAt: z.number().int().nonnegative().nullable()
|
|
126
|
-
});
|
|
127
|
-
export type UptimeCheckStats = z.infer<typeof uptimeCheckStatsSchema>;
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* One chart point. A `raw` point is a single ping (`checks === 1`); an `hour` or
|
|
131
|
-
* `day` point aggregates every ping of its bucket, which is what keeps a
|
|
132
|
-
* multi-year chart cheap.
|
|
133
|
-
*/
|
|
134
|
-
export const uptimePointSchema = z.object({
|
|
135
|
-
/** Bucket start, epoch seconds. */
|
|
136
|
-
at: z.number().int().nonnegative(),
|
|
137
|
-
checks: z.number().int().positive(),
|
|
138
|
-
upChecks: z.number().int().nonnegative(),
|
|
139
|
-
avgMs: z.number().int().nonnegative().nullable(),
|
|
140
|
-
minMs: z.number().int().nonnegative().nullable(),
|
|
141
|
-
maxMs: z.number().int().nonnegative().nullable()
|
|
142
|
-
});
|
|
143
|
-
export type UptimePoint = z.infer<typeof uptimePointSchema>;
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* A continuous outage. Opened when a service crosses its failure threshold,
|
|
147
|
-
* closed on the first successful probe — so the list reads as a plain incident
|
|
148
|
-
* history, and it survives raw-history pruning.
|
|
149
|
-
*/
|
|
150
|
-
export const uptimeIncidentSchema = z.object({
|
|
151
|
-
id: z.number().int().positive(),
|
|
152
|
-
startedAt: z.number().int().nonnegative(),
|
|
153
|
-
/** `null` while the outage is still ongoing. */
|
|
154
|
-
endedAt: z.number().int().nonnegative().nullable(),
|
|
155
|
-
httpStatus: z.number().int().nullable(),
|
|
156
|
-
error: z.string().nullable()
|
|
157
|
-
});
|
|
158
|
-
export type UptimeIncident = z.infer<typeof uptimeIncidentSchema>;
|
|
159
|
-
|
|
160
|
-
/** Database row shapes (server-only). Mirror the columns exactly. */
|
|
161
|
-
export interface UptimeServiceRow {
|
|
162
|
-
id: number;
|
|
163
|
-
user_id: number;
|
|
164
|
-
workspace_id: number;
|
|
165
|
-
/** Encrypted `{ name, url, keyword }` (open tier). */
|
|
166
|
-
content: string;
|
|
167
|
-
method: UptimeMethod;
|
|
168
|
-
expected_status: number | null;
|
|
169
|
-
interval_seconds: number;
|
|
170
|
-
timeout_seconds: number;
|
|
171
|
-
failure_threshold: number;
|
|
172
|
-
retention_days: number | null;
|
|
173
|
-
enabled: number;
|
|
174
|
-
sort_order: number;
|
|
175
|
-
status: UptimeStatus;
|
|
176
|
-
consecutive_failures: number;
|
|
177
|
-
last_checked_at: number | null;
|
|
178
|
-
last_response_ms: number | null;
|
|
179
|
-
last_http_status: number | null;
|
|
180
|
-
/** Encrypted error string (open tier), or null after a success. */
|
|
181
|
-
last_error: string | null;
|
|
182
|
-
created: number;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export interface UptimeCheckRow {
|
|
186
|
-
id: number;
|
|
187
|
-
service_id: number;
|
|
188
|
-
checked_at: number;
|
|
189
|
-
up: number;
|
|
190
|
-
http_status: number | null;
|
|
191
|
-
response_ms: number | null;
|
|
192
|
-
/** Encrypted error string (open tier). */
|
|
193
|
-
error: string | null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export interface UptimeDayRow {
|
|
197
|
-
service_id: number;
|
|
198
|
-
day: number;
|
|
199
|
-
checks: number;
|
|
200
|
-
up_checks: number;
|
|
201
|
-
total_ms: number;
|
|
202
|
-
ms_samples: number;
|
|
203
|
-
min_ms: number | null;
|
|
204
|
-
max_ms: number | null;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export interface UptimeIncidentRow {
|
|
208
|
-
id: number;
|
|
209
|
-
service_id: number;
|
|
210
|
-
started_at: number;
|
|
211
|
-
ended_at: number | null;
|
|
212
|
-
http_status: number | null;
|
|
213
|
-
/** Encrypted error string (open tier). */
|
|
214
|
-
error: string | null;
|
|
215
|
-
notified: number;
|
|
216
|
-
}
|
package/src/features/audience.ts
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import {
|
|
3
|
-
AUDIENCE_BREAKDOWN_MAX,
|
|
4
|
-
AUDIENCE_FUNNEL_MAX_STEPS,
|
|
5
|
-
AUDIENCE_FUNNEL_NAME_MAX_LENGTH,
|
|
6
|
-
AUDIENCE_MAX_ORIGINS,
|
|
7
|
-
AUDIENCE_ORIGIN_MAX_LENGTH,
|
|
8
|
-
AUDIENCE_RETENTION_MAX_DAYS,
|
|
9
|
-
AUDIENCE_RETENTION_MIN_DAYS,
|
|
10
|
-
AUDIENCE_SITE_DESCRIPTION_MAX_LENGTH,
|
|
11
|
-
AUDIENCE_SITE_NAME_MAX_LENGTH,
|
|
12
|
-
audienceActivitySchema,
|
|
13
|
-
audienceBreakdownItemSchema,
|
|
14
|
-
audienceDimensionSchema,
|
|
15
|
-
audienceFunnelSchema,
|
|
16
|
-
audienceFunnelStepDraftSchema,
|
|
17
|
-
audienceLiveSchema,
|
|
18
|
-
audienceOverviewSchema,
|
|
19
|
-
audiencePlatformSchema,
|
|
20
|
-
audienceRangeSchema,
|
|
21
|
-
audienceVisitorModeSchema,
|
|
22
|
-
audienceSiteSchema,
|
|
23
|
-
audienceUsageSchema
|
|
24
|
-
} from '../domain/audience';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Commandes de l'audience d'un espace.
|
|
28
|
-
*
|
|
29
|
-
* Préfixe unique `audience.`, comme `git.`, `database.` et `project.` — d'où le
|
|
30
|
-
* camelCase derrière le point.
|
|
31
|
-
*
|
|
32
|
-
* ⚠️ Conséquence à connaître : le filet de démarrage (`MUTATION_VERB` dans
|
|
33
|
-
* `src/features/_topics.ts`) cherche un verbe **juste après le point**. Il ne
|
|
34
|
-
* verra donc **aucune** de ces commandes, et un `mutates` oublié ne produira
|
|
35
|
-
* aucun avertissement. Il se relit à la main.
|
|
36
|
-
*
|
|
37
|
-
* ## Ce qui n'est pas ici
|
|
38
|
-
*
|
|
39
|
-
* L'**ingestion** n'est pas une commande. Elle entre par HTTP, sans session,
|
|
40
|
-
* depuis des machines qui ne connaissent pas DevEye — voir `POST /api/t/b`. Ces
|
|
41
|
-
* commandes-ci ne font que *lire* ce qu'elle a écrit, et *déclarer* les sites.
|
|
42
|
-
*
|
|
43
|
-
* L'espace visé n'apparaît dans aucune entrée : il voyage sur l'enveloppe WS et
|
|
44
|
-
* le dispatcheur le résout, appartenance vérifiée, avant le handler.
|
|
45
|
-
*/
|
|
46
|
-
|
|
47
|
-
const siteId = z.number().int().positive();
|
|
48
|
-
|
|
49
|
-
/** Ce qu'on peut régler sur un site — identique à l'ajout et à la modification. */
|
|
50
|
-
const siteBody = {
|
|
51
|
-
name: z.string().min(1).max(AUDIENCE_SITE_NAME_MAX_LENGTH),
|
|
52
|
-
description: z.string().max(AUDIENCE_SITE_DESCRIPTION_MAX_LENGTH),
|
|
53
|
-
platform: audiencePlatformSchema,
|
|
54
|
-
visitorMode: audienceVisitorModeSchema,
|
|
55
|
-
/**
|
|
56
|
-
* Les hôtes autorisés à écrire. Le client envoie des hôtes nus
|
|
57
|
-
* (`exemple.fr`) ou des origines complètes (`https://exemple.fr`) : le
|
|
58
|
-
* serveur normalise, parce que c'est lui qui compare.
|
|
59
|
-
*/
|
|
60
|
-
origins: z.array(z.string().max(AUDIENCE_ORIGIN_MAX_LENGTH)).max(AUDIENCE_MAX_ORIGINS),
|
|
61
|
-
active: z.boolean(),
|
|
62
|
-
retentionDays: z
|
|
63
|
-
.number()
|
|
64
|
-
.int()
|
|
65
|
-
.min(AUDIENCE_RETENTION_MIN_DAYS)
|
|
66
|
-
.max(AUDIENCE_RETENTION_MAX_DAYS)
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// ------------------------------------------------------------------ sites
|
|
70
|
-
|
|
71
|
-
/** Le nombre de sites de l'espace, pour la tuile de l'accueil. */
|
|
72
|
-
export const audienceCount = {
|
|
73
|
-
command: 'audience.count' as const,
|
|
74
|
-
input: z.object({}),
|
|
75
|
-
output: z.object({ count: z.number().int().nonnegative() })
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
/** Les sites de l'espace, dans l'ordre de l'utilisateur. */
|
|
79
|
-
export const audienceList = {
|
|
80
|
-
command: 'audience.list' as const,
|
|
81
|
-
input: z.object({}),
|
|
82
|
-
output: z.object({ sites: z.array(audienceSiteSchema) })
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Un site, avec les projets qui le suivent et l'adresse de sa balise.
|
|
87
|
-
*
|
|
88
|
-
* `ingestOrigin` vient du serveur (`AUDIENCE_ORIGIN`, à défaut `PUBLIC_ORIGIN`)
|
|
89
|
-
* et non de l'origine du navigateur : l'application est derrière le VPN, alors
|
|
90
|
-
* que l'ingestion doit être joignable sans lui — les deux adresses diffèrent
|
|
91
|
-
* donc par construction. La déduire côté client aurait donné une balise juste en
|
|
92
|
-
* développement et fausse en production, ce qui est le pire des deux mondes.
|
|
93
|
-
*/
|
|
94
|
-
export const audienceGet = {
|
|
95
|
-
command: 'audience.get' as const,
|
|
96
|
-
input: z.object({ siteId }),
|
|
97
|
-
output: z.object({
|
|
98
|
-
site: audienceSiteSchema,
|
|
99
|
-
usage: z.array(audienceUsageSchema),
|
|
100
|
-
ingestOrigin: z.string()
|
|
101
|
-
})
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Déclare un site. La clé publique est **engendrée par le serveur** : la laisser
|
|
106
|
-
* choisir permettrait de viser celle d'un site existant d'un autre espace.
|
|
107
|
-
*/
|
|
108
|
-
export const audienceSiteAdd = {
|
|
109
|
-
command: 'audience.siteAdd' as const,
|
|
110
|
-
input: z.object(siteBody),
|
|
111
|
-
output: z.object({ site: audienceSiteSchema })
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export const audienceSiteUpdate = {
|
|
115
|
-
command: 'audience.siteUpdate' as const,
|
|
116
|
-
input: z.object({ siteId, ...siteBody }),
|
|
117
|
-
output: z.object({ site: audienceSiteSchema })
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Supprime un site **et tout son historique**.
|
|
122
|
-
*
|
|
123
|
-
* Contrairement aux projets, rien ne s'archive ici : un site retiré n'a pas de
|
|
124
|
-
* seconde vie, et garder des millions d'événements orphelins pour un objet que
|
|
125
|
-
* plus rien ne nomme ne rendrait service à personne. Les liaisons de projet
|
|
126
|
-
* tombent avec (`CASCADE`), les projets eux-mêmes ne bougent pas.
|
|
127
|
-
*/
|
|
128
|
-
export const audienceSiteRemove = {
|
|
129
|
-
command: 'audience.siteRemove' as const,
|
|
130
|
-
input: z.object({ siteId }),
|
|
131
|
-
output: z.object({ ok: z.literal(true) })
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Renouvelle la clé publique.
|
|
136
|
-
*
|
|
137
|
-
* Le geste utile quand une clé s'est retrouvée là où elle n'aurait pas dû —
|
|
138
|
-
* dépôt public, capture d'écran. L'ancienne cesse d'entrer **immédiatement** ;
|
|
139
|
-
* l'historique déjà collecté, lui, reste : il a été mesuré, il est vrai.
|
|
140
|
-
*/
|
|
141
|
-
export const audienceSiteRotateKey = {
|
|
142
|
-
command: 'audience.siteRotateKey' as const,
|
|
143
|
-
input: z.object({ siteId }),
|
|
144
|
-
output: z.object({ site: audienceSiteSchema })
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
export const audienceReorder = {
|
|
148
|
-
command: 'audience.reorder' as const,
|
|
149
|
-
input: z.object({ siteIds: z.array(siteId).min(1) }),
|
|
150
|
-
output: z.object({ ok: z.literal(true) })
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// ------------------------------------------------------------ statistiques
|
|
154
|
-
|
|
155
|
-
/** Le bandeau, la comparaison à la période précédente, et la courbe. */
|
|
156
|
-
export const audienceOverview = {
|
|
157
|
-
command: 'audience.overview' as const,
|
|
158
|
-
input: z.object({ siteId, range: audienceRangeSchema }),
|
|
159
|
-
output: audienceOverviewSchema
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Un classement sur l'axe demandé.
|
|
164
|
-
*
|
|
165
|
-
* Une commande pour les neuf axes plutôt que neuf commandes : ils rendent tous
|
|
166
|
-
* la même forme, se lisent par la même requête, et l'écran en affiche plusieurs
|
|
167
|
-
* côte à côte. Neuf entrées auraient divergé au premier ajustement.
|
|
168
|
-
*/
|
|
169
|
-
export const audienceBreakdown = {
|
|
170
|
-
command: 'audience.breakdown' as const,
|
|
171
|
-
input: z.object({
|
|
172
|
-
siteId,
|
|
173
|
-
range: audienceRangeSchema,
|
|
174
|
-
dimension: audienceDimensionSchema,
|
|
175
|
-
limit: z.number().int().min(1).max(AUDIENCE_BREAKDOWN_MAX).optional()
|
|
176
|
-
}),
|
|
177
|
-
output: z.object({ items: z.array(audienceBreakdownItemSchema) })
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/** La carte jour × heure, en heure **locale du visiteur**, et les fuseaux. */
|
|
181
|
-
export const audienceActivity = {
|
|
182
|
-
command: 'audience.activity' as const,
|
|
183
|
-
input: z.object({ siteId, range: audienceRangeSchema }),
|
|
184
|
-
output: audienceActivitySchema
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Qui est là en ce moment (cinq dernières minutes).
|
|
189
|
-
*
|
|
190
|
-
* Volontairement séparée de `overview` : elle est minuscule, elle se relit
|
|
191
|
-
* souvent, et la faire voyager avec le bandeau obligerait à recalculer tout
|
|
192
|
-
* l'agrégat pour rafraîchir un compteur.
|
|
193
|
-
*/
|
|
194
|
-
export const audienceLive = {
|
|
195
|
-
command: 'audience.live' as const,
|
|
196
|
-
input: z.object({ siteId }),
|
|
197
|
-
output: audienceLiveSchema
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// ------------------------------------------------------------ entonnoirs
|
|
201
|
-
|
|
202
|
-
const funnelId = z.number().int().positive();
|
|
203
|
-
|
|
204
|
-
/** Les marches, dans l'ordre. Un entonnoir d'une seule marche n'en est pas un. */
|
|
205
|
-
const steps = z.array(audienceFunnelStepDraftSchema).min(2).max(AUDIENCE_FUNNEL_MAX_STEPS);
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Les entonnoirs d'un site, **avec leurs chiffres** sur la fenêtre demandée.
|
|
209
|
-
*
|
|
210
|
-
* Définitions et mesures dans la même réponse : l'écran n'affiche jamais l'une
|
|
211
|
-
* sans l'autre, et les séparer aurait fait deux allers-retours pour dessiner un
|
|
212
|
-
* seul graphique. Les entonnoirs se comptent en unités, pas en milliers.
|
|
213
|
-
*/
|
|
214
|
-
export const audienceFunnelList = {
|
|
215
|
-
command: 'audience.funnelList' as const,
|
|
216
|
-
input: z.object({ siteId, range: audienceRangeSchema }),
|
|
217
|
-
output: z.object({ funnels: z.array(audienceFunnelSchema) })
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Définit un entonnoir à partir de ce que le site a **déjà** émis.
|
|
222
|
-
*
|
|
223
|
-
* C'est tout le découpage : le site pose des signaux nommés, l'entonnoir se
|
|
224
|
-
* compose ici. Mesurer autre chose ne demande donc aucun redéploiement — ni
|
|
225
|
-
* même de prévenir qui que ce soit.
|
|
226
|
-
*/
|
|
227
|
-
export const audienceFunnelAdd = {
|
|
228
|
-
command: 'audience.funnelAdd' as const,
|
|
229
|
-
input: z.object({
|
|
230
|
-
siteId,
|
|
231
|
-
name: z.string().min(1).max(AUDIENCE_FUNNEL_NAME_MAX_LENGTH),
|
|
232
|
-
steps
|
|
233
|
-
}),
|
|
234
|
-
output: z.object({ funnelId })
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
export const audienceFunnelUpdate = {
|
|
238
|
-
command: 'audience.funnelUpdate' as const,
|
|
239
|
-
input: z.object({
|
|
240
|
-
funnelId,
|
|
241
|
-
name: z.string().min(1).max(AUDIENCE_FUNNEL_NAME_MAX_LENGTH),
|
|
242
|
-
steps
|
|
243
|
-
}),
|
|
244
|
-
output: z.object({ ok: z.literal(true) })
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Supprime un entonnoir. **Aucune mesure n'est perdue** : un entonnoir n'est
|
|
249
|
-
* qu'une lecture des événements déjà là, jamais une collecte à part. Le
|
|
250
|
-
* recréer à l'identique rendrait exactement les mêmes chiffres.
|
|
251
|
-
*/
|
|
252
|
-
export const audienceFunnelRemove = {
|
|
253
|
-
command: 'audience.funnelRemove' as const,
|
|
254
|
-
input: z.object({ funnelId }),
|
|
255
|
-
output: z.object({ ok: z.literal(true) })
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
export const audienceCommands = [
|
|
259
|
-
audienceCount,
|
|
260
|
-
audienceList,
|
|
261
|
-
audienceGet,
|
|
262
|
-
audienceSiteAdd,
|
|
263
|
-
audienceSiteUpdate,
|
|
264
|
-
audienceSiteRemove,
|
|
265
|
-
audienceSiteRotateKey,
|
|
266
|
-
audienceReorder,
|
|
267
|
-
audienceOverview,
|
|
268
|
-
audienceBreakdown,
|
|
269
|
-
audienceActivity,
|
|
270
|
-
audienceLive,
|
|
271
|
-
audienceFunnelList,
|
|
272
|
-
audienceFunnelAdd,
|
|
273
|
-
audienceFunnelUpdate,
|
|
274
|
-
audienceFunnelRemove
|
|
275
|
-
] as const;
|