@deveye/types 0.15.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/LICENSE +21 -0
- package/README.md +23 -0
- package/package.json +68 -0
- package/src/domain/audience.ts +549 -0
- package/src/domain/backup.ts +355 -0
- package/src/domain/credential.ts +55 -0
- package/src/domain/database.ts +467 -0
- package/src/domain/deploy.ts +231 -0
- package/src/domain/device.ts +172 -0
- package/src/domain/deviceFiles.ts +84 -0
- package/src/domain/deviceLogs.ts +82 -0
- package/src/domain/featureRegistry.ts +392 -0
- package/src/domain/finance.ts +477 -0
- package/src/domain/git.ts +419 -0
- package/src/domain/home.ts +314 -0
- package/src/domain/live.ts +272 -0
- package/src/domain/logs.ts +117 -0
- package/src/domain/mail.ts +394 -0
- package/src/domain/metrics.ts +127 -0
- package/src/domain/note.ts +202 -0
- package/src/domain/notifications.ts +268 -0
- package/src/domain/packages.ts +35 -0
- package/src/domain/password.ts +36 -0
- package/src/domain/presence.ts +21 -0
- package/src/domain/project.ts +168 -0
- package/src/domain/projectBoard.ts +130 -0
- package/src/domain/projectChat.ts +46 -0
- package/src/domain/projectHistory.ts +82 -0
- package/src/domain/projectLink.ts +87 -0
- package/src/domain/projectPlan.ts +68 -0
- package/src/domain/report.ts +492 -0
- package/src/domain/role.ts +8 -0
- package/src/domain/secrecy.ts +66 -0
- package/src/domain/sentinel.ts +623 -0
- package/src/domain/sharing.ts +186 -0
- package/src/domain/syncProtocol.ts +116 -0
- package/src/domain/twoFactor.ts +40 -0
- package/src/domain/uptime.ts +216 -0
- package/src/domain/user.ts +141 -0
- package/src/domain/workspace.ts +56 -0
- package/src/domain/workspaceRole.ts +251 -0
- package/src/features/admin.ts +112 -0
- package/src/features/audience.ts +275 -0
- package/src/features/backup.ts +230 -0
- package/src/features/database.ts +461 -0
- package/src/features/deploy.ts +245 -0
- package/src/features/device.ts +292 -0
- package/src/features/deviceFiles.ts +83 -0
- package/src/features/deviceLogs.ts +36 -0
- package/src/features/deviceTerminal.ts +57 -0
- package/src/features/finance.ts +360 -0
- package/src/features/git.ts +368 -0
- package/src/features/home.ts +32 -0
- package/src/features/live.ts +113 -0
- package/src/features/logs.ts +86 -0
- package/src/features/mail.ts +374 -0
- package/src/features/metrics.ts +185 -0
- package/src/features/note.ts +189 -0
- package/src/features/notify.ts +164 -0
- package/src/features/password.ts +67 -0
- package/src/features/project.ts +709 -0
- package/src/features/registry.ts +103 -0
- package/src/features/secrecy.ts +120 -0
- package/src/features/sentinel.ts +233 -0
- package/src/features/sharing.ts +79 -0
- package/src/features/twoFactor.ts +47 -0
- package/src/features/uptime.ts +186 -0
- package/src/features/user.ts +91 -0
- package/src/features/workspace.ts +200 -0
- package/src/http/auth.ts +94 -0
- package/src/http/device.ts +222 -0
- package/src/http/status.ts +45 -0
- package/src/index.ts +1700 -0
- package/src/protocol/agent.ts +1171 -0
- package/src/protocol/envelope.ts +46 -0
- package/src/protocol/error.ts +27 -0
- package/src/protocol/result.ts +17 -0
- package/src/protocol/version.ts +6 -0
- package/src/sdk/client-ambient.d.ts +238 -0
- package/src/sdk/client.ts +66 -0
- package/src/sdk/ids.ts +25 -0
- package/src/sdk/index.ts +11 -0
- package/src/sdk/manifest.ts +326 -0
- package/src/sdk/providers.ts +48 -0
- package/src/sdk/server.ts +378 -0
- package/src/sdk/testing.ts +179 -0
- package/src/utils/version.ts +28 -0
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
PROJECT_VERSION_MAX_LENGTH,
|
|
4
|
+
projectDraftSchema,
|
|
5
|
+
projectSchema,
|
|
6
|
+
projectSecurityTierSchema,
|
|
7
|
+
projectStatusSchema,
|
|
8
|
+
projectSummarySchema,
|
|
9
|
+
projectVersionSourceSchema
|
|
10
|
+
} from '../domain/project';
|
|
11
|
+
import {
|
|
12
|
+
PROJECT_COLUMN_NAME_MAX_LENGTH,
|
|
13
|
+
projectCardDraftSchema,
|
|
14
|
+
projectCardSchema,
|
|
15
|
+
projectColumnSchema
|
|
16
|
+
} from '../domain/projectBoard';
|
|
17
|
+
import {
|
|
18
|
+
PROJECT_MESSAGE_MAX_LENGTH,
|
|
19
|
+
PROJECT_MESSAGE_PAGE_SIZE,
|
|
20
|
+
projectMessageSchema
|
|
21
|
+
} from '../domain/projectChat';
|
|
22
|
+
import {
|
|
23
|
+
projectCardDepSchema,
|
|
24
|
+
projectMilestoneDraftSchema,
|
|
25
|
+
projectMilestoneSchema
|
|
26
|
+
} from '../domain/projectPlan';
|
|
27
|
+
import { PROJECT_EVENT_PAGE_SIZE, projectEventSchema } from '../domain/projectHistory';
|
|
28
|
+
import { myTaskSchema, projectLinkCountsSchema } from '../domain/projectLink';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Commandes des projets.
|
|
32
|
+
*
|
|
33
|
+
* L'espace visé n'apparaît dans aucune entrée : il voyage sur l'enveloppe WS
|
|
34
|
+
* (voir `protocol/envelope`) et le dispatcheur le résout, appartenance vérifiée,
|
|
35
|
+
* avant que le handler ne s'exécute.
|
|
36
|
+
*
|
|
37
|
+
* ⚠️ Toutes les commandes partagent le préfixe `project.`, qui porte le sujet
|
|
38
|
+
* live `projects` (`src/features/_topics.ts`). Le contrôle de démarrage qui
|
|
39
|
+
* attrape un `mutates` oublié cherche un verbe **juste après le point**
|
|
40
|
+
* (`note.add`) : avec des noms en camelCase il ne voit rien ici. `mutates` est
|
|
41
|
+
* donc à relire à la main sur chaque écriture ajoutée à ce fichier.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
const projectId = z.number().int().positive();
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Le portefeuille : tous les projets actifs de l'espace, avec leurs compteurs.
|
|
48
|
+
*
|
|
49
|
+
* Jamais verrouillée. Un projet `guarded` dont la session ne peut pas lire le
|
|
50
|
+
* corps revient **masqué** (`masked: true`) plutôt qu'absent : la liste doit
|
|
51
|
+
* dire ce qui existe même verrouillée. `archived: true` bascule sur l'ensemble
|
|
52
|
+
* disjoint des projets archivés.
|
|
53
|
+
*/
|
|
54
|
+
export const projectList = {
|
|
55
|
+
command: 'project.list' as const,
|
|
56
|
+
input: z.object({ archived: z.boolean().optional() }),
|
|
57
|
+
output: z.object({ projects: z.array(projectSummarySchema) })
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Compte les projets **actifs**. Métadonnée en clair pure : aucune ligne n'est
|
|
62
|
+
* déchiffrée, la tuile d'accueil affiche donc toujours un nombre, même session
|
|
63
|
+
* verrouillée.
|
|
64
|
+
*/
|
|
65
|
+
export const projectCount = {
|
|
66
|
+
command: 'project.count' as const,
|
|
67
|
+
input: z.object({}),
|
|
68
|
+
output: z.object({ count: z.number().int().nonnegative() })
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Un projet en entier. Sur un projet `guarded`, la session doit être
|
|
73
|
+
* déverrouillée : sinon le serveur répond `locked` et le client ouvre l'invite
|
|
74
|
+
* habituelle avant de rejouer l'appel.
|
|
75
|
+
*/
|
|
76
|
+
export const projectGet = {
|
|
77
|
+
command: 'project.get' as const,
|
|
78
|
+
input: z.object({ projectId }),
|
|
79
|
+
output: z.object({ project: projectSchema })
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Crée un projet. `securityTier` est figé à la création et ne se change ensuite
|
|
84
|
+
* que par {@link projectSetSecurityTier}, qui re-chiffre tout l'arbre.
|
|
85
|
+
*/
|
|
86
|
+
export const projectAdd = {
|
|
87
|
+
command: 'project.add' as const,
|
|
88
|
+
input: z.object({
|
|
89
|
+
project: projectDraftSchema,
|
|
90
|
+
securityTier: projectSecurityTierSchema
|
|
91
|
+
}),
|
|
92
|
+
output: z.object({ project: projectSchema })
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Modifie le profil d'un projet. Ne touche ni au tier ni à la source de version
|
|
97
|
+
* — deux bascules qui ont des effets de bord, et donc leurs propres commandes.
|
|
98
|
+
*/
|
|
99
|
+
export const projectUpdate = {
|
|
100
|
+
command: 'project.update' as const,
|
|
101
|
+
input: z.object({ projectId, project: projectDraftSchema }),
|
|
102
|
+
output: z.object({ project: projectSchema })
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Pose la version affichée, et d'où elle vient.
|
|
107
|
+
*
|
|
108
|
+
* `github_release` exige un dépôt lié et un projet `open` (un projet `guarded`
|
|
109
|
+
* ne se synchronise pas) ; `version` est alors ignorée et recalculée par le
|
|
110
|
+
* service de fond. En `manual`, la valeur passée fait foi.
|
|
111
|
+
*/
|
|
112
|
+
export const projectSetVersion = {
|
|
113
|
+
command: 'project.setVersion' as const,
|
|
114
|
+
input: z.object({
|
|
115
|
+
projectId,
|
|
116
|
+
source: projectVersionSourceSchema,
|
|
117
|
+
version: z.string().max(PROJECT_VERSION_MAX_LENGTH)
|
|
118
|
+
}),
|
|
119
|
+
output: z.object({ project: projectSchema })
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const projectSetStatus = {
|
|
123
|
+
command: 'project.setStatus' as const,
|
|
124
|
+
input: z.object({ projectId, status: projectStatusSchema }),
|
|
125
|
+
output: z.object({ project: projectSchema })
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Bascule l'étage de chiffrement, et **re-chiffre tout l'arbre du projet**
|
|
130
|
+
* (cartes, messages, jalons, événements, cache git) sous la nouvelle clé, dans
|
|
131
|
+
* la foulée. Exige une session déverrouillée dans les deux sens : on ne
|
|
132
|
+
* re-chiffre pas ce qu'on ne peut pas lire.
|
|
133
|
+
*
|
|
134
|
+
* Passer en `guarded` **désactive les intégrations** du projet (synchronisation
|
|
135
|
+
* git, déploiement) : elles ont besoin de lire sans session.
|
|
136
|
+
*/
|
|
137
|
+
export const projectSetSecurityTier = {
|
|
138
|
+
command: 'project.setSecurityTier' as const,
|
|
139
|
+
input: z.object({ projectId, securityTier: projectSecurityTierSchema }),
|
|
140
|
+
output: z.object({ project: projectSchema })
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Archive un projet : il quitte le portefeuille sans que rien ne soit détruit.
|
|
145
|
+
* C'est ce que « supprimer » fait dans l'interface — il n'existe volontairement
|
|
146
|
+
* aucune commande de suppression dans ce module.
|
|
147
|
+
*/
|
|
148
|
+
export const projectArchive = {
|
|
149
|
+
command: 'project.archive' as const,
|
|
150
|
+
input: z.object({ projectId }),
|
|
151
|
+
output: z.object({ projectId })
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const projectRestore = {
|
|
155
|
+
command: 'project.restore' as const,
|
|
156
|
+
input: z.object({ projectId }),
|
|
157
|
+
output: z.object({ projectId })
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Ordonne le portefeuille : `projectIds` en est le contenu **complet**, dans son
|
|
162
|
+
* ordre final (indice le plus bas en premier). Ne touche jamais au corps
|
|
163
|
+
* chiffré, donc fonctionne aussi sur des projets masqués.
|
|
164
|
+
*/
|
|
165
|
+
export const projectReorder = {
|
|
166
|
+
command: 'project.reorder' as const,
|
|
167
|
+
input: z.object({ projectIds: z.array(projectId).min(1) }),
|
|
168
|
+
output: z.object({ projectIds: z.array(projectId) })
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// ------------------------------------------------------------------ tableau
|
|
172
|
+
|
|
173
|
+
const columnId = z.number().int().positive();
|
|
174
|
+
const cardId = z.number().int().positive();
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Le tableau complet d'un projet : ses colonnes et ses cartes vivantes.
|
|
178
|
+
*
|
|
179
|
+
* Un seul aller-retour plutôt qu'un par colonne — le client ne tient aucun cache
|
|
180
|
+
* normalisé, il re-sollicite, et un tableau entier tient largement dans une
|
|
181
|
+
* trame. Sur un projet confidentiel, exige une session déverrouillée : les
|
|
182
|
+
* titres des cartes sont chiffrés au même étage que le projet.
|
|
183
|
+
*
|
|
184
|
+
* `archived: true` renvoie à la place les cartes archivées, sans les colonnes —
|
|
185
|
+
* c'est l'ensemble disjoint, lu par la page d'historique.
|
|
186
|
+
*/
|
|
187
|
+
export const projectBoard = {
|
|
188
|
+
command: 'project.board' as const,
|
|
189
|
+
input: z.object({ projectId, archived: z.boolean().optional() }),
|
|
190
|
+
output: z.object({
|
|
191
|
+
columns: z.array(projectColumnSchema),
|
|
192
|
+
cards: z.array(projectCardSchema)
|
|
193
|
+
})
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const projectColumnAdd = {
|
|
197
|
+
command: 'project.columnAdd' as const,
|
|
198
|
+
input: z.object({ projectId, name: z.string().min(1).max(PROJECT_COLUMN_NAME_MAX_LENGTH) }),
|
|
199
|
+
output: z.object({ column: projectColumnSchema })
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export const projectColumnUpdate = {
|
|
203
|
+
command: 'project.columnUpdate' as const,
|
|
204
|
+
input: z.object({
|
|
205
|
+
columnId,
|
|
206
|
+
name: z.string().min(1).max(PROJECT_COLUMN_NAME_MAX_LENGTH),
|
|
207
|
+
countsAsDone: z.boolean(),
|
|
208
|
+
wipLimit: z.number().int().positive().nullable()
|
|
209
|
+
}),
|
|
210
|
+
output: z.object({ column: projectColumnSchema })
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Supprime une colonne — la seule suppression du module, et elle est bornée :
|
|
215
|
+
* refusée (`conflict`) tant que la colonne porte la moindre carte, archivée
|
|
216
|
+
* comprise. La contrainte SQL est en CASCADE ; sans cette garde, retirer une
|
|
217
|
+
* colonne détruirait silencieusement des cartes que rien ne permet de
|
|
218
|
+
* supprimer par ailleurs.
|
|
219
|
+
*/
|
|
220
|
+
export const projectColumnRemove = {
|
|
221
|
+
command: 'project.columnRemove' as const,
|
|
222
|
+
input: z.object({ columnId }),
|
|
223
|
+
output: z.object({ columnId })
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export const projectColumnReorder = {
|
|
227
|
+
command: 'project.columnReorder' as const,
|
|
228
|
+
input: z.object({ projectId, columnIds: z.array(columnId).min(1) }),
|
|
229
|
+
output: z.object({ columnIds: z.array(columnId) })
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export const projectCardAdd = {
|
|
233
|
+
command: 'project.cardAdd' as const,
|
|
234
|
+
input: z.object({ projectId, columnId, card: projectCardDraftSchema }),
|
|
235
|
+
output: z.object({ card: projectCardSchema })
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const projectCardUpdate = {
|
|
239
|
+
command: 'project.cardUpdate' as const,
|
|
240
|
+
input: z.object({ cardId, card: projectCardDraftSchema }),
|
|
241
|
+
output: z.object({ card: projectCardSchema })
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Range une colonne : `cardIds` en est le contenu **complet** dans son ordre
|
|
246
|
+
* final, et chaque carte listée est versée dans `columnId` au passage. Une
|
|
247
|
+
* seule commande couvre donc le tri interne et le passage d'une colonne à
|
|
248
|
+
* l'autre — c'est le motif de `note.reorder`.
|
|
249
|
+
*
|
|
250
|
+
* Ne touche jamais au corps chiffré : un glisser-déposer fonctionne donc sans
|
|
251
|
+
* déverrouiller quoi que ce soit.
|
|
252
|
+
*/
|
|
253
|
+
export const projectCardMove = {
|
|
254
|
+
command: 'project.cardMove' as const,
|
|
255
|
+
input: z.object({ columnId, cardIds: z.array(cardId) }),
|
|
256
|
+
output: z.object({ columnId, cardIds: z.array(cardId) })
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Archive une carte : elle quitte le tableau sans que rien ne soit détruit.
|
|
261
|
+
* C'est ce que « supprimer » fait dans l'interface — il n'existe volontairement
|
|
262
|
+
* aucune commande de suppression de carte.
|
|
263
|
+
*/
|
|
264
|
+
export const projectCardArchive = {
|
|
265
|
+
command: 'project.cardArchive' as const,
|
|
266
|
+
input: z.object({ cardId }),
|
|
267
|
+
output: z.object({ cardId })
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export const projectCardRestore = {
|
|
271
|
+
command: 'project.cardRestore' as const,
|
|
272
|
+
input: z.object({ cardId }),
|
|
273
|
+
output: z.object({ cardId })
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
// ------------------------------------------------------------ planification
|
|
277
|
+
|
|
278
|
+
const milestoneId = z.number().int().positive();
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Ce que le tableau ne dit pas : les jalons du projet et le graphe des
|
|
282
|
+
* dépendances entre ses cartes.
|
|
283
|
+
*
|
|
284
|
+
* Volontairement **séparé de `project.board`** : la frise se compose des cartes
|
|
285
|
+
* (que le tableau a déjà chargées) et de ce complément. Les fusionner ferait
|
|
286
|
+
* payer les dépendances à chaque ouverture du kanban, qui n'en a que faire.
|
|
287
|
+
*/
|
|
288
|
+
export const projectPlan = {
|
|
289
|
+
command: 'project.plan' as const,
|
|
290
|
+
input: z.object({ projectId }),
|
|
291
|
+
output: z.object({
|
|
292
|
+
milestones: z.array(projectMilestoneSchema),
|
|
293
|
+
deps: z.array(projectCardDepSchema)
|
|
294
|
+
})
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
export const projectMilestoneAdd = {
|
|
298
|
+
command: 'project.milestoneAdd' as const,
|
|
299
|
+
input: z.object({ projectId, milestone: projectMilestoneDraftSchema }),
|
|
300
|
+
output: z.object({ milestone: projectMilestoneSchema })
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
export const projectMilestoneUpdate = {
|
|
304
|
+
command: 'project.milestoneUpdate' as const,
|
|
305
|
+
input: z.object({ milestoneId, milestone: projectMilestoneDraftSchema }),
|
|
306
|
+
output: z.object({ milestone: projectMilestoneSchema })
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
/** Marque un jalon atteint (ou revient dessus). */
|
|
310
|
+
export const projectMilestoneSetReached = {
|
|
311
|
+
command: 'project.milestoneSetReached' as const,
|
|
312
|
+
input: z.object({ milestoneId, reached: z.boolean() }),
|
|
313
|
+
output: z.object({ milestone: projectMilestoneSchema })
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Retire un jalon. Ses cartes ne sont pas touchées — elles se retrouvent
|
|
318
|
+
* simplement sans jalon (`ON DELETE SET NULL`). Un jalon n'est pas un « bloc » :
|
|
319
|
+
* il ne porte aucun travail, seulement une date, donc le retirer ne perd rien.
|
|
320
|
+
*/
|
|
321
|
+
export const projectMilestoneRemove = {
|
|
322
|
+
command: 'project.milestoneRemove' as const,
|
|
323
|
+
input: z.object({ milestoneId }),
|
|
324
|
+
output: z.object({ milestoneId })
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
/** Rattache une carte à un jalon, ou l'en détache (`null`). */
|
|
328
|
+
export const projectCardSetMilestone = {
|
|
329
|
+
command: 'project.cardSetMilestone' as const,
|
|
330
|
+
input: z.object({ cardId, milestoneId: milestoneId.nullable() }),
|
|
331
|
+
output: z.object({ cardId, milestoneId: milestoneId.nullable() })
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Déclare que `cardId` est bloquée par `blockedByCardId`.
|
|
336
|
+
*
|
|
337
|
+
* Refusée (`validation`) si elle fermerait un cycle : une carte ne peut pas
|
|
338
|
+
* dépendre d'elle-même, fût-ce par un chemin de dix arêtes. Le contrôle est
|
|
339
|
+
* fait côté serveur, là où le graphe complet est connu.
|
|
340
|
+
*/
|
|
341
|
+
export const projectDepAdd = {
|
|
342
|
+
command: 'project.depAdd' as const,
|
|
343
|
+
input: projectCardDepSchema,
|
|
344
|
+
output: z.object({ dep: projectCardDepSchema })
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
export const projectDepRemove = {
|
|
348
|
+
command: 'project.depRemove' as const,
|
|
349
|
+
input: projectCardDepSchema,
|
|
350
|
+
output: projectCardDepSchema
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// ----------------------------------------------------------------- git
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* La liaison du projet vers un dépôt de l'espace.
|
|
357
|
+
*
|
|
358
|
+
* Trois commandes seulement : **le dépôt n'appartient pas au projet.** Il vit
|
|
359
|
+
* dans la feature Git (`features/git.ts`), qui porte son cache, sa
|
|
360
|
+
* synchronisation et ses jetons. Ce qui suit ne fait que poser et retirer un
|
|
361
|
+
* pointeur — d'où le fait que tout y soit un `repoId` et rien d'autre.
|
|
362
|
+
*/
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Les dépôts liés au projet, dans l'ordre de la feature Git.
|
|
366
|
+
*
|
|
367
|
+
* **Plusieurs**, et c'est le cas normal : un projet réel se compose souvent d'un
|
|
368
|
+
* client, d'un serveur et de contrats partagés, chacun dans son dépôt.
|
|
369
|
+
*/
|
|
370
|
+
export const projectRepoList = {
|
|
371
|
+
command: 'project.repoList' as const,
|
|
372
|
+
input: z.object({ projectId }),
|
|
373
|
+
output: z.object({ repoIds: z.array(z.number().int().positive()) })
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Ajoute un dépôt existant au projet. **Idempotente** : le relier deux fois
|
|
378
|
+
* n'est pas une erreur, c'est le même fait déclaré deux fois. Rend la liste
|
|
379
|
+
* complète, pour que l'appelant n'ait pas à la recomposer.
|
|
380
|
+
*
|
|
381
|
+
* Refusé sur un projet confidentiel : la synchronisation tourne sans session, et
|
|
382
|
+
* rattacher un projet gardé à une entité d'espace en clair révélerait par la
|
|
383
|
+
* bande ce qu'il contient. Le dire ici évite un réglage sans effet.
|
|
384
|
+
*/
|
|
385
|
+
export const projectRepoLink = {
|
|
386
|
+
command: 'project.repoLink' as const,
|
|
387
|
+
input: z.object({ projectId, repoId: z.number().int().positive() }),
|
|
388
|
+
output: z.object({ repoIds: z.array(z.number().int().positive()) })
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Retire une liaison.
|
|
393
|
+
*
|
|
394
|
+
* **Le dépôt et son cache survivent** : ils appartiennent à l'espace, et
|
|
395
|
+
* d'autres projets peuvent s'en servir. C'est le pointeur qui part, rien d'autre.
|
|
396
|
+
*/
|
|
397
|
+
export const projectRepoUnlink = {
|
|
398
|
+
command: 'project.repoUnlink' as const,
|
|
399
|
+
input: z.object({ projectId, repoId: z.number().int().positive() }),
|
|
400
|
+
output: z.object({ repoIds: z.array(z.number().int().positive()) })
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// ------------------------------------------------------------- transverse
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Toutes mes tâches, tous projets de l'espace confondus.
|
|
407
|
+
*
|
|
408
|
+
* Une seule requête, rendue possible par le fait qu'`assignee_user_id` est en
|
|
409
|
+
* clair. Les cartes d'un projet confidentiel verrouillé reviennent masquées
|
|
410
|
+
* plutôt qu'absentes : une liste de tâches incomplète serait pire qu'une liste
|
|
411
|
+
* qui dit ce qu'elle ne peut pas lire.
|
|
412
|
+
*/
|
|
413
|
+
export const projectMyTasks = {
|
|
414
|
+
command: 'project.myTasks' as const,
|
|
415
|
+
input: z.object({}),
|
|
416
|
+
output: z.object({ tasks: z.array(myTaskSchema) })
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Combien d'éléments chaque intégration du projet a à montrer.
|
|
421
|
+
*
|
|
422
|
+
* Une seule commande pour les quatre, parce qu'elle sert une seule décision :
|
|
423
|
+
* quels onglets la fiche du projet doit ouvrir. Les demander une par une ferait
|
|
424
|
+
* quatre allers-retours pour dessiner une barre d'onglets, et la ferait
|
|
425
|
+
* apparaître par morceaux.
|
|
426
|
+
*
|
|
427
|
+
* Ne déchiffre rien et ne demande aucune session : ce sont des liaisons en
|
|
428
|
+
* clair. Un projet confidentiel n'en a aucune par construction (voir
|
|
429
|
+
* {@link projectRepoLink}), et répond donc quatre zéros.
|
|
430
|
+
*/
|
|
431
|
+
export const projectLinkCounts = {
|
|
432
|
+
command: 'project.linkCounts' as const,
|
|
433
|
+
input: z.object({ projectId }),
|
|
434
|
+
output: z.object({ counts: projectLinkCountsSchema })
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Les services surveillés rattachés au projet, dans l'ordre d'Uptime.
|
|
439
|
+
*
|
|
440
|
+
* Ne rend que des identifiants : les nommer supposerait de lire Uptime au nom
|
|
441
|
+
* de l'appelant, alors que ce droit-là s'y vérifie déjà. Le client résout les
|
|
442
|
+
* noms et les états par `uptime.list`, et affiche des identifiants nus si son
|
|
443
|
+
* rôle ne lui ouvre pas cette feature — plutôt que de faire disparaître des
|
|
444
|
+
* liaisons qui existent.
|
|
445
|
+
*/
|
|
446
|
+
export const projectUptimeList = {
|
|
447
|
+
command: 'project.uptimeList' as const,
|
|
448
|
+
input: z.object({ projectId }),
|
|
449
|
+
output: z.object({ serviceIds: z.array(z.number().int().positive()) })
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Rattache un service surveillé au projet. **Idempotente** : rattacher deux
|
|
454
|
+
* fois le même service n'est pas une erreur, c'est le même fait déclaré deux
|
|
455
|
+
* fois. Rend la liste complète, pour que l'appelant n'ait pas à la recomposer.
|
|
456
|
+
*/
|
|
457
|
+
export const projectUptimeLink = {
|
|
458
|
+
command: 'project.uptimeLink' as const,
|
|
459
|
+
input: z.object({ projectId, serviceId: z.number().int().positive() }),
|
|
460
|
+
output: z.object({ serviceIds: z.array(z.number().int().positive()) })
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
/** Retire la liaison. Le service, lui, n'est pas touché. */
|
|
464
|
+
export const projectUptimeUnlink = {
|
|
465
|
+
command: 'project.uptimeUnlink' as const,
|
|
466
|
+
input: z.object({ projectId, serviceId: z.number().int().positive() }),
|
|
467
|
+
output: z.object({ serviceIds: z.array(z.number().int().positive()) })
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Les bases de données rattachées au projet, dans l'ordre de la feature Bases.
|
|
472
|
+
*
|
|
473
|
+
* Ne rend que des identifiants, pour la même raison que
|
|
474
|
+
* {@link projectUptimeList} : les nommer supposerait de lire la feature Bases au
|
|
475
|
+
* nom de l'appelant, alors que ce droit s'y vérifie déjà.
|
|
476
|
+
*/
|
|
477
|
+
export const projectDatabaseList = {
|
|
478
|
+
command: 'project.databaseList' as const,
|
|
479
|
+
input: z.object({ projectId }),
|
|
480
|
+
output: z.object({ databaseIds: z.array(z.number().int().positive()) })
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Rattache une base au projet. **Idempotente**, et refusée sur un projet
|
|
485
|
+
* confidentiel : la liaison est une ligne en clair, et la base vit à l'étage
|
|
486
|
+
* ouvert — exactement comme pour un dépôt git.
|
|
487
|
+
*/
|
|
488
|
+
export const projectDatabaseLink = {
|
|
489
|
+
command: 'project.databaseLink' as const,
|
|
490
|
+
input: z.object({ projectId, databaseId: z.number().int().positive() }),
|
|
491
|
+
output: z.object({ databaseIds: z.array(z.number().int().positive()) })
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
/** Retire la liaison. La base, elle, n'est pas touchée. */
|
|
495
|
+
export const projectDatabaseUnlink = {
|
|
496
|
+
command: 'project.databaseUnlink' as const,
|
|
497
|
+
input: z.object({ projectId, databaseId: z.number().int().positive() }),
|
|
498
|
+
output: z.object({ databaseIds: z.array(z.number().int().positive()) })
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Les sites suivis rattachés au projet, dans l'ordre de la feature Audience.
|
|
503
|
+
*
|
|
504
|
+
* Ne rend que des identifiants, pour la même raison que
|
|
505
|
+
* {@link projectDatabaseList} : les nommer supposerait de lire la feature
|
|
506
|
+
* Audience au nom de l'appelant, alors que ce droit s'y vérifie déjà.
|
|
507
|
+
*/
|
|
508
|
+
export const projectAudienceList = {
|
|
509
|
+
command: 'project.audienceList' as const,
|
|
510
|
+
input: z.object({ projectId }),
|
|
511
|
+
output: z.object({ siteIds: z.array(z.number().int().positive()) })
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Rattache un site au projet. **Idempotente**, et refusée sur un projet
|
|
516
|
+
* confidentiel : la liaison est une ligne en clair, et le site vit à l'étage
|
|
517
|
+
* ouvert — exactement comme un dépôt git ou une base.
|
|
518
|
+
*/
|
|
519
|
+
export const projectAudienceLink = {
|
|
520
|
+
command: 'project.audienceLink' as const,
|
|
521
|
+
input: z.object({ projectId, siteId: z.number().int().positive() }),
|
|
522
|
+
output: z.object({ siteIds: z.array(z.number().int().positive()) })
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
/** Retire la liaison. Le site, lui, n'est pas touché. */
|
|
526
|
+
export const projectAudienceUnlink = {
|
|
527
|
+
command: 'project.audienceUnlink' as const,
|
|
528
|
+
input: z.object({ projectId, siteId: z.number().int().positive() }),
|
|
529
|
+
output: z.object({ siteIds: z.array(z.number().int().positive()) })
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
// ---------------------------------------------------------- déploiement
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* La liaison du projet vers les cibles de déploiement de l'espace.
|
|
536
|
+
*
|
|
537
|
+
* Trois commandes, exactement comme pour un dépôt : **la cible n'appartient pas
|
|
538
|
+
* au projet.** Elle vit dans la feature Déploiement, avec son jeton, son
|
|
539
|
+
* historique et son suivi d'état, et plusieurs projets peuvent viser la même —
|
|
540
|
+
* le cas normal quand un client et un serveur partent dans la même pile compose.
|
|
541
|
+
* Ce qui suit ne fait que poser et retirer un pointeur.
|
|
542
|
+
*
|
|
543
|
+
* Déclencher ne se fait pas ici : c'est `deploy.trigger`, qui accepte un
|
|
544
|
+
* `projectId` facultatif pour inscrire le fait dans la frise du projet.
|
|
545
|
+
*/
|
|
546
|
+
export const projectDeployList = {
|
|
547
|
+
command: 'project.deployList' as const,
|
|
548
|
+
input: z.object({ projectId }),
|
|
549
|
+
output: z.object({ targetIds: z.array(z.number().int().positive()) })
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Rattache une cible au projet. **Idempotente**, et refusée sur un projet
|
|
554
|
+
* confidentiel : la liaison est une ligne en clair, la cible vit à l'étage
|
|
555
|
+
* ouvert et son suivi tourne sans session — exactement comme pour un dépôt.
|
|
556
|
+
*/
|
|
557
|
+
export const projectDeployLink = {
|
|
558
|
+
command: 'project.deployLink' as const,
|
|
559
|
+
input: z.object({ projectId, targetId: z.number().int().positive() }),
|
|
560
|
+
output: z.object({ targetIds: z.array(z.number().int().positive()) })
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
/** Retire la liaison. La cible, son historique et les autres projets survivent. */
|
|
564
|
+
export const projectDeployUnlink = {
|
|
565
|
+
command: 'project.deployUnlink' as const,
|
|
566
|
+
input: z.object({ projectId, targetId: z.number().int().positive() }),
|
|
567
|
+
output: z.object({ targetIds: z.array(z.number().int().positive()) })
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
// -------------------------------------------------------------- historique
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* La frise verticale d'un projet, du plus récent au plus ancien.
|
|
574
|
+
*
|
|
575
|
+
* Même pagination par curseur remontant que la discussion : `before` demande la
|
|
576
|
+
* page qui précède un événement donné. Sans lui, on obtient le haut de la frise.
|
|
577
|
+
*/
|
|
578
|
+
export const projectEventList = {
|
|
579
|
+
command: 'project.eventList' as const,
|
|
580
|
+
input: z.object({
|
|
581
|
+
projectId,
|
|
582
|
+
before: z.number().int().positive().optional(),
|
|
583
|
+
limit: z.number().int().positive().max(PROJECT_EVENT_PAGE_SIZE).optional()
|
|
584
|
+
}),
|
|
585
|
+
output: z.object({
|
|
586
|
+
events: z.array(projectEventSchema),
|
|
587
|
+
hasMore: z.boolean()
|
|
588
|
+
})
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
// -------------------------------------------------------------- discussion
|
|
592
|
+
|
|
593
|
+
const messageId = z.number().int().positive();
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Le fil d'une carte, du plus ancien au plus récent.
|
|
597
|
+
*
|
|
598
|
+
* Pagination par **curseur remontant** : `before` demande la page qui précède
|
|
599
|
+
* un message donné, ce qui est le seul ordre qui tienne dans un fil où l'on
|
|
600
|
+
* écrit par le bas. Sans `before`, on obtient la fin du fil — ce qu'on veut à
|
|
601
|
+
* l'ouverture.
|
|
602
|
+
*/
|
|
603
|
+
export const projectMessageList = {
|
|
604
|
+
command: 'project.messageList' as const,
|
|
605
|
+
input: z.object({
|
|
606
|
+
cardId,
|
|
607
|
+
before: messageId.optional(),
|
|
608
|
+
limit: z.number().int().positive().max(PROJECT_MESSAGE_PAGE_SIZE).optional()
|
|
609
|
+
}),
|
|
610
|
+
output: z.object({
|
|
611
|
+
messages: z.array(projectMessageSchema),
|
|
612
|
+
/** Reste-t-il des messages plus anciens à charger ? */
|
|
613
|
+
hasMore: z.boolean()
|
|
614
|
+
})
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Poste un message. Les `mentions` sont des identifiants de **membres de
|
|
619
|
+
* l'espace** ; le serveur refuse tout autre. Elles voyagent à part du texte
|
|
620
|
+
* plutôt que d'être ré-extraites côté serveur : celui-ci ne lit pas le texte
|
|
621
|
+
* pour le comprendre, seulement pour le stocker chiffré.
|
|
622
|
+
*/
|
|
623
|
+
export const projectMessageSend = {
|
|
624
|
+
command: 'project.messageSend' as const,
|
|
625
|
+
input: z.object({
|
|
626
|
+
cardId,
|
|
627
|
+
text: z.string().min(1).max(PROJECT_MESSAGE_MAX_LENGTH),
|
|
628
|
+
mentions: z.array(z.number().int().positive()).max(32)
|
|
629
|
+
}),
|
|
630
|
+
output: z.object({ message: projectMessageSchema })
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
/** Retouche son propre message. Un autre auteur est refusé (`forbidden`). */
|
|
634
|
+
export const projectMessageEdit = {
|
|
635
|
+
command: 'project.messageEdit' as const,
|
|
636
|
+
input: z.object({
|
|
637
|
+
messageId,
|
|
638
|
+
text: z.string().min(1).max(PROJECT_MESSAGE_MAX_LENGTH),
|
|
639
|
+
mentions: z.array(z.number().int().positive()).max(32)
|
|
640
|
+
}),
|
|
641
|
+
output: z.object({ message: projectMessageSchema })
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Pose le point d'eau haute de lecture de l'appelant sur une carte : tout
|
|
646
|
+
* message d'identifiant inférieur ou égal cesse d'être compté comme non lu.
|
|
647
|
+
*
|
|
648
|
+
* N'est **pas** une mutation diffusée : une lecture est personnelle, l'annoncer
|
|
649
|
+
* à l'espace ferait re-solliciter tout le monde pour rien.
|
|
650
|
+
*/
|
|
651
|
+
export const projectMarkRead = {
|
|
652
|
+
command: 'project.markRead' as const,
|
|
653
|
+
input: z.object({ cardId, lastMessageId: messageId }),
|
|
654
|
+
output: z.object({ cardId, lastMessageId: messageId })
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
export const projectCommands = [
|
|
658
|
+
projectList,
|
|
659
|
+
projectCount,
|
|
660
|
+
projectGet,
|
|
661
|
+
projectAdd,
|
|
662
|
+
projectUpdate,
|
|
663
|
+
projectSetVersion,
|
|
664
|
+
projectSetStatus,
|
|
665
|
+
projectSetSecurityTier,
|
|
666
|
+
projectArchive,
|
|
667
|
+
projectRestore,
|
|
668
|
+
projectReorder,
|
|
669
|
+
projectBoard,
|
|
670
|
+
projectColumnAdd,
|
|
671
|
+
projectColumnUpdate,
|
|
672
|
+
projectColumnRemove,
|
|
673
|
+
projectColumnReorder,
|
|
674
|
+
projectCardAdd,
|
|
675
|
+
projectCardUpdate,
|
|
676
|
+
projectCardMove,
|
|
677
|
+
projectCardArchive,
|
|
678
|
+
projectCardRestore,
|
|
679
|
+
projectMessageList,
|
|
680
|
+
projectMessageSend,
|
|
681
|
+
projectMessageEdit,
|
|
682
|
+
projectMarkRead,
|
|
683
|
+
projectPlan,
|
|
684
|
+
projectMilestoneAdd,
|
|
685
|
+
projectMilestoneUpdate,
|
|
686
|
+
projectMilestoneSetReached,
|
|
687
|
+
projectMilestoneRemove,
|
|
688
|
+
projectCardSetMilestone,
|
|
689
|
+
projectDepAdd,
|
|
690
|
+
projectDepRemove,
|
|
691
|
+
projectEventList,
|
|
692
|
+
projectRepoList,
|
|
693
|
+
projectRepoLink,
|
|
694
|
+
projectRepoUnlink,
|
|
695
|
+
projectDeployList,
|
|
696
|
+
projectDeployLink,
|
|
697
|
+
projectDeployUnlink,
|
|
698
|
+
projectMyTasks,
|
|
699
|
+
projectLinkCounts,
|
|
700
|
+
projectUptimeList,
|
|
701
|
+
projectUptimeLink,
|
|
702
|
+
projectUptimeUnlink,
|
|
703
|
+
projectDatabaseList,
|
|
704
|
+
projectDatabaseLink,
|
|
705
|
+
projectDatabaseUnlink,
|
|
706
|
+
projectAudienceList,
|
|
707
|
+
projectAudienceLink,
|
|
708
|
+
projectAudienceUnlink
|
|
709
|
+
] as const;
|