@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,461 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
DATABASE_ALERT_MESSAGE_MAX_LENGTH,
|
|
4
|
+
DATABASE_ALERT_NAME_MAX_LENGTH,
|
|
5
|
+
DATABASE_HOST_MAX_LENGTH,
|
|
6
|
+
DATABASE_NAME_MAX_LENGTH,
|
|
7
|
+
DATABASE_SECRET_MAX_LENGTH,
|
|
8
|
+
DATABASE_SQL_MAX_LENGTH,
|
|
9
|
+
DATABASE_USER_MAX_LENGTH,
|
|
10
|
+
databaseAccessKindSchema,
|
|
11
|
+
databaseAlertSchema,
|
|
12
|
+
databaseCellSchema,
|
|
13
|
+
databaseCombinatorSchema,
|
|
14
|
+
databaseConditionSchema,
|
|
15
|
+
databaseEngineSchema,
|
|
16
|
+
databaseExecutionSchema,
|
|
17
|
+
databaseExportFormatSchema,
|
|
18
|
+
databaseFilterSchema,
|
|
19
|
+
databaseIdRangeSchema,
|
|
20
|
+
databaseProbeSchema,
|
|
21
|
+
databaseRowsSchema,
|
|
22
|
+
databaseSchema,
|
|
23
|
+
databaseSortSchema,
|
|
24
|
+
databaseSshAuthSchema,
|
|
25
|
+
databaseStructureSchema,
|
|
26
|
+
databaseTableSchema,
|
|
27
|
+
databaseUsageSchema
|
|
28
|
+
} from '../domain/database';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Commandes des bases de données de l'espace.
|
|
32
|
+
*
|
|
33
|
+
* Préfixe unique `database.`, comme `git.` et `project.` — d'où le camelCase
|
|
34
|
+
* derrière le point.
|
|
35
|
+
*
|
|
36
|
+
* ⚠️ Conséquence à connaître : le filet de démarrage (`MUTATION_VERB` dans
|
|
37
|
+
* `src/features/_topics.ts`) cherche un verbe **juste après le point**. Il ne
|
|
38
|
+
* verra donc **aucune** de ces commandes, et un `mutates` oublié ne produira
|
|
39
|
+
* aucun avertissement. Il se relit à la main.
|
|
40
|
+
*
|
|
41
|
+
* ## Rien ne se connecte tout seul
|
|
42
|
+
*
|
|
43
|
+
* Seules `test`, `inspect`, `tableList`, `tableRows` et `alertTest` joignent la
|
|
44
|
+
* base, et toutes sont déclenchées par un geste explicite. `list` et `get`
|
|
45
|
+
* lisent le cache local — ouvrir la feature ne réveille aucun serveur.
|
|
46
|
+
*
|
|
47
|
+
* L'espace visé n'apparaît dans aucune entrée : il voyage sur l'enveloppe WS et
|
|
48
|
+
* le dispatcheur le résout, appartenance vérifiée, avant le handler.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
const databaseId = z.number().int().positive();
|
|
52
|
+
const alertId = z.number().int().positive();
|
|
53
|
+
|
|
54
|
+
/** La partie réglable d'un accès, secret compris (jamais rendu en retour). */
|
|
55
|
+
const accessInput = z.object({
|
|
56
|
+
kind: databaseAccessKindSchema,
|
|
57
|
+
host: z.string().max(DATABASE_HOST_MAX_LENGTH),
|
|
58
|
+
port: z.number().int().min(1).max(65535).nullable(),
|
|
59
|
+
username: z.string().max(DATABASE_USER_MAX_LENGTH),
|
|
60
|
+
auth: databaseSshAuthSchema,
|
|
61
|
+
/**
|
|
62
|
+
* Mot de passe SSH ou clé privée. Absent = on garde celui en place ; une
|
|
63
|
+
* chaîne vide l'efface. Le client ne le reçoit jamais, il ne peut donc pas
|
|
64
|
+
* le renvoyer inchangé — d'où cette convention plutôt qu'un champ obligatoire.
|
|
65
|
+
*/
|
|
66
|
+
secret: z.string().max(DATABASE_SECRET_MAX_LENGTH).optional()
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ------------------------------------------------------------------- bases
|
|
70
|
+
|
|
71
|
+
/** Le nombre de bases de l'espace, pour la tuile de l'accueil. */
|
|
72
|
+
export const databaseCount = {
|
|
73
|
+
command: 'database.count' as const,
|
|
74
|
+
input: z.object({}),
|
|
75
|
+
output: z.object({ count: z.number().int().nonnegative() })
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** Les bases de l'espace, dans l'ordre de l'utilisateur. Lit le cache local. */
|
|
79
|
+
export const databaseList = {
|
|
80
|
+
command: 'database.list' as const,
|
|
81
|
+
input: z.object({}),
|
|
82
|
+
output: z.object({ databases: z.array(databaseSchema) })
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** Une base, avec les projets qui s'en servent et ses alertes. */
|
|
86
|
+
export const databaseGet = {
|
|
87
|
+
command: 'database.get' as const,
|
|
88
|
+
input: z.object({ databaseId }),
|
|
89
|
+
output: z.object({
|
|
90
|
+
database: databaseSchema,
|
|
91
|
+
usage: z.array(databaseUsageSchema),
|
|
92
|
+
alerts: z.array(databaseAlertSchema)
|
|
93
|
+
})
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const databaseAdd = {
|
|
97
|
+
command: 'database.add' as const,
|
|
98
|
+
input: z.object({
|
|
99
|
+
engine: databaseEngineSchema,
|
|
100
|
+
name: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
101
|
+
host: z.string().min(1).max(DATABASE_HOST_MAX_LENGTH),
|
|
102
|
+
port: z.number().int().min(1).max(65535),
|
|
103
|
+
database: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
104
|
+
username: z.string().max(DATABASE_USER_MAX_LENGTH),
|
|
105
|
+
password: z.string().max(DATABASE_SECRET_MAX_LENGTH),
|
|
106
|
+
access: accessInput,
|
|
107
|
+
monitorEnabled: z.boolean(),
|
|
108
|
+
intervalSeconds: z.number().int().min(60).max(86400),
|
|
109
|
+
autoLoadTables: z.boolean()
|
|
110
|
+
}),
|
|
111
|
+
output: z.object({ database: databaseSchema })
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Modifie une base. `password` absent = on garde celui en place ; une chaîne
|
|
116
|
+
* vide l'efface. Même convention que le secret du tunnel, et pour la même
|
|
117
|
+
* raison : un secret rendu au client est un secret qu'on ne peut plus reprendre.
|
|
118
|
+
*/
|
|
119
|
+
export const databaseUpdate = {
|
|
120
|
+
command: 'database.update' as const,
|
|
121
|
+
input: z.object({
|
|
122
|
+
databaseId,
|
|
123
|
+
name: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
124
|
+
host: z.string().min(1).max(DATABASE_HOST_MAX_LENGTH),
|
|
125
|
+
port: z.number().int().min(1).max(65535),
|
|
126
|
+
database: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
127
|
+
username: z.string().max(DATABASE_USER_MAX_LENGTH),
|
|
128
|
+
password: z.string().max(DATABASE_SECRET_MAX_LENGTH).optional(),
|
|
129
|
+
access: accessInput,
|
|
130
|
+
monitorEnabled: z.boolean(),
|
|
131
|
+
intervalSeconds: z.number().int().min(60).max(86400),
|
|
132
|
+
autoLoadTables: z.boolean()
|
|
133
|
+
}),
|
|
134
|
+
output: z.object({ database: databaseSchema })
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Retire une base de l'espace, avec ses alertes et toutes ses liaisons.
|
|
139
|
+
*
|
|
140
|
+
* Les projets liés ne sont **pas** touchés : ils perdent leur base, rien
|
|
141
|
+
* d'autre. Le serveur distant, lui, n'est évidemment jamais atteint.
|
|
142
|
+
*/
|
|
143
|
+
export const databaseRemove = {
|
|
144
|
+
command: 'database.remove' as const,
|
|
145
|
+
input: z.object({ databaseId }),
|
|
146
|
+
output: z.object({ databaseId })
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Range les bases de l'espace : `ids` est la liste **complète** dans son ordre
|
|
151
|
+
* final. Une nouvelle base prend le rang suivant, donc la fin de la liste.
|
|
152
|
+
*/
|
|
153
|
+
export const databaseReorder = {
|
|
154
|
+
command: 'database.reorder' as const,
|
|
155
|
+
input: z.object({ ids: z.array(databaseId).min(1) }),
|
|
156
|
+
output: z.object({ ids: z.array(databaseId) })
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// ------------------------------------------------------- à la demande
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Essaie de joindre la base, maintenant.
|
|
163
|
+
*
|
|
164
|
+
* Ne lève **jamais** sur un échec de connexion : un serveur injoignable est une
|
|
165
|
+
* réponse, pas une erreur de commande. Le message revient dans `error`, déjà
|
|
166
|
+
* traduit, et l'interface le montre sans rien bloquer.
|
|
167
|
+
*/
|
|
168
|
+
export const databaseTest = {
|
|
169
|
+
command: 'database.test' as const,
|
|
170
|
+
input: z.object({ databaseId }),
|
|
171
|
+
output: z.object({ probe: databaseProbeSchema })
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Essaie une connexion **avant** de l'enregistrer.
|
|
176
|
+
*
|
|
177
|
+
* Le formulaire d'ajout décrit une base qui n'existe pas encore : `test` ne peut
|
|
178
|
+
* rien pour lui, il part d'un identifiant. Celui-ci prend les réglages tels
|
|
179
|
+
* qu'ils sont saisis, et n'écrit rien — ni ligne, ni état.
|
|
180
|
+
*
|
|
181
|
+
* `databaseId` sert à la modification : les secrets ne redescendant jamais au
|
|
182
|
+
* client, un champ laissé intact n'a rien à renvoyer, et le serveur reprend
|
|
183
|
+
* alors celui qu'il détient déjà. Sans cela, « Tester » échouerait sur une base
|
|
184
|
+
* qui fonctionne, faute de mot de passe.
|
|
185
|
+
*/
|
|
186
|
+
export const databaseTestDraft = {
|
|
187
|
+
command: 'database.testDraft' as const,
|
|
188
|
+
input: z.object({
|
|
189
|
+
databaseId: databaseId.optional(),
|
|
190
|
+
engine: databaseEngineSchema,
|
|
191
|
+
host: z.string().min(1).max(DATABASE_HOST_MAX_LENGTH),
|
|
192
|
+
port: z.number().int().min(1).max(65535),
|
|
193
|
+
database: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
194
|
+
username: z.string().max(DATABASE_USER_MAX_LENGTH),
|
|
195
|
+
password: z.string().max(DATABASE_SECRET_MAX_LENGTH).optional(),
|
|
196
|
+
access: accessInput
|
|
197
|
+
}),
|
|
198
|
+
output: z.object({ probe: databaseProbeSchema })
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Relève l'inventaire maintenant : version du serveur, taille, nombre de
|
|
203
|
+
* tables, et l'état des alertes. C'est ce que fait le relevé périodique, sur
|
|
204
|
+
* demande explicite — ce qui le rend utile même sur une base au repos.
|
|
205
|
+
*/
|
|
206
|
+
export const databaseInspect = {
|
|
207
|
+
command: 'database.inspect' as const,
|
|
208
|
+
input: z.object({ databaseId }),
|
|
209
|
+
output: z.object({ database: databaseSchema, probe: databaseProbeSchema })
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/** Les tables de la base, lues chez le serveur au moment de la demande. */
|
|
213
|
+
export const databaseTableList = {
|
|
214
|
+
command: 'database.tableList' as const,
|
|
215
|
+
input: z.object({ databaseId }),
|
|
216
|
+
output: z.object({ tables: z.array(databaseTableSchema) })
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Le contenu d'une table, page par page.
|
|
221
|
+
*
|
|
222
|
+
* ## Rien de ce qui vient du client n'entre tel quel dans une requête
|
|
223
|
+
*
|
|
224
|
+
* Un identifiant ne peut pas être un paramètre lié : nom de table, nom de
|
|
225
|
+
* colonne, sens du tri sont donc **confrontés au catalogue réel** avant d'être
|
|
226
|
+
* cités, et un nom qui n'y figure pas n'atteint jamais le moteur. Les valeurs,
|
|
227
|
+
* elles, sont toujours liées ; l'opérateur d'un filtre est choisi dans une
|
|
228
|
+
* énumération fermée. Aucun fragment de SQL ne traverse le contrat.
|
|
229
|
+
*
|
|
230
|
+
* `withStructure` évite un second aller-retour à la sélection d'une table : la
|
|
231
|
+
* structure et la première page arrivent alors dans la **même session**, ce qui
|
|
232
|
+
* compte quand chaque connexion rouvre un tunnel SSH.
|
|
233
|
+
*/
|
|
234
|
+
export const databaseTableRows = {
|
|
235
|
+
command: 'database.tableRows' as const,
|
|
236
|
+
input: z.object({
|
|
237
|
+
databaseId,
|
|
238
|
+
schema: z.string().max(DATABASE_NAME_MAX_LENGTH),
|
|
239
|
+
table: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
240
|
+
offset: z.number().int().nonnegative().max(1_000_000).optional(),
|
|
241
|
+
limit: z.number().int().positive().max(200).optional(),
|
|
242
|
+
filters: z.array(databaseFilterSchema).max(8).optional(),
|
|
243
|
+
combinator: databaseCombinatorSchema.optional(),
|
|
244
|
+
sort: databaseSortSchema.optional(),
|
|
245
|
+
withStructure: z.boolean().optional()
|
|
246
|
+
}),
|
|
247
|
+
output: z.object({ rows: databaseRowsSchema, structure: databaseStructureSchema.optional() })
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
/** La structure seule : colonnes, clé primaire, clés étrangères, index. */
|
|
251
|
+
export const databaseTableStructure = {
|
|
252
|
+
command: 'database.tableStructure' as const,
|
|
253
|
+
input: z.object({
|
|
254
|
+
databaseId,
|
|
255
|
+
schema: z.string().max(DATABASE_NAME_MAX_LENGTH),
|
|
256
|
+
table: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH)
|
|
257
|
+
}),
|
|
258
|
+
output: z.object({ structure: databaseStructureSchema })
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// ------------------------------------------------------- écrire des lignes
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Les trois écritures de l'explorateur.
|
|
265
|
+
*
|
|
266
|
+
* ## Ce que le serveur refuse, et pourquoi
|
|
267
|
+
*
|
|
268
|
+
* Modifier ou supprimer exige une **clé primaire**. Sans elle, aucune condition
|
|
269
|
+
* ne désigne *une* ligne : un `UPDATE` en toucherait plusieurs, un `DELETE` en
|
|
270
|
+
* emporterait autant, et rien ne permettrait de revenir en arrière. Le serveur
|
|
271
|
+
* refuse alors, avec la raison ; l'interface ne propose même pas le geste.
|
|
272
|
+
*
|
|
273
|
+
* ## Ce qui décide en dernier ressort
|
|
274
|
+
*
|
|
275
|
+
* Le compte saisi dans les réglages de la base. DevEye peut demander une
|
|
276
|
+
* écriture ; c'est le serveur distant qui l'accorde ou la refuse. Un compte en
|
|
277
|
+
* lecture seule rend donc tout ceci inoffensif, ce que dit le formulaire.
|
|
278
|
+
*/
|
|
279
|
+
export const databaseRowInsert = {
|
|
280
|
+
command: 'database.rowInsert' as const,
|
|
281
|
+
input: z.object({
|
|
282
|
+
databaseId,
|
|
283
|
+
schema: z.string().max(DATABASE_NAME_MAX_LENGTH),
|
|
284
|
+
table: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
285
|
+
values: z.array(databaseCellSchema).min(1).max(200)
|
|
286
|
+
}),
|
|
287
|
+
output: z.object({ inserted: z.number().int().nonnegative() })
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
export const databaseRowUpdate = {
|
|
291
|
+
command: 'database.rowUpdate' as const,
|
|
292
|
+
input: z.object({
|
|
293
|
+
databaseId,
|
|
294
|
+
schema: z.string().max(DATABASE_NAME_MAX_LENGTH),
|
|
295
|
+
table: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
296
|
+
/** La ligne visée, par ses colonnes de clé primaire. */
|
|
297
|
+
key: z.array(databaseCellSchema).min(1).max(16),
|
|
298
|
+
values: z.array(databaseCellSchema).min(1).max(200)
|
|
299
|
+
}),
|
|
300
|
+
output: z.object({ updated: z.number().int().nonnegative() })
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
export const databaseRowDelete = {
|
|
304
|
+
command: 'database.rowDelete' as const,
|
|
305
|
+
input: z.object({
|
|
306
|
+
databaseId,
|
|
307
|
+
schema: z.string().max(DATABASE_NAME_MAX_LENGTH),
|
|
308
|
+
table: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH),
|
|
309
|
+
/** Une entrée par ligne, chacune par ses colonnes de clé primaire. */
|
|
310
|
+
keys: z.array(z.array(databaseCellSchema).min(1).max(16)).min(1).max(200)
|
|
311
|
+
}),
|
|
312
|
+
output: z.object({ deleted: z.number().int().nonnegative() })
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Une instruction libre, écriture comprise — le terminal.
|
|
317
|
+
*
|
|
318
|
+
* Distincte de `query`, qui refuse tout ce qui n'est pas une lecture parce
|
|
319
|
+
* qu'elle sert à mettre au point une condition d'alerte. Ici l'intention est
|
|
320
|
+
* l'inverse : administrer. Une seule instruction à la fois malgré tout, le
|
|
321
|
+
* point-virgule interne restant refusé — c'est ce qui empêche qu'un copier-coller
|
|
322
|
+
* en exécute trois quand on en visait une.
|
|
323
|
+
*/
|
|
324
|
+
export const databaseExecute = {
|
|
325
|
+
command: 'database.execute' as const,
|
|
326
|
+
input: z.object({ databaseId, sql: z.string().min(1).max(DATABASE_SQL_MAX_LENGTH) }),
|
|
327
|
+
output: z.object({ result: databaseExecutionSchema })
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Exporte une table, ou toute la base.
|
|
332
|
+
*
|
|
333
|
+
* L'export est **complet** : il lit tout ce que la portée désigne, page par
|
|
334
|
+
* page. Le seul plafond qui subsiste est un garde-fou mémoire du serveur, très
|
|
335
|
+
* au-dessus de ce qu'un export normal atteint ; s'il est touché, `truncated` le
|
|
336
|
+
* dit et l'interface le répète. Pour une copie fidèle d'un serveur entier,
|
|
337
|
+
* `mysqldump` et `pg_dump` restent malgré tout les bons outils — eux savent
|
|
338
|
+
* rejouer schéma, index et contraintes.
|
|
339
|
+
*
|
|
340
|
+
* `idRanges` restreint l'export aux lignes dont la **clé primaire** tombe dans
|
|
341
|
+
* l'une des plages. Réservé à une portée d'une seule table : sur toute la base,
|
|
342
|
+
* les clés n'ont ni le même nom ni le même sens d'une table à l'autre.
|
|
343
|
+
*/
|
|
344
|
+
export const databaseExport = {
|
|
345
|
+
command: 'database.export' as const,
|
|
346
|
+
input: z.object({
|
|
347
|
+
databaseId,
|
|
348
|
+
format: databaseExportFormatSchema,
|
|
349
|
+
/** Absents : toute la base. Présents : cette table seule. */
|
|
350
|
+
schema: z.string().max(DATABASE_NAME_MAX_LENGTH).optional(),
|
|
351
|
+
table: z.string().min(1).max(DATABASE_NAME_MAX_LENGTH).optional(),
|
|
352
|
+
/** Plages d'identifiants, bornes comprises. Sans effet sans `table`. */
|
|
353
|
+
idRanges: z.array(databaseIdRangeSchema).max(64).optional()
|
|
354
|
+
}),
|
|
355
|
+
output: z.object({
|
|
356
|
+
filename: z.string(),
|
|
357
|
+
content: z.string(),
|
|
358
|
+
rowCount: z.number().int().nonnegative(),
|
|
359
|
+
tableCount: z.number().int().nonnegative(),
|
|
360
|
+
/** Le plafond a été atteint : ce qui suit manque. */
|
|
361
|
+
truncated: z.boolean()
|
|
362
|
+
})
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// ----------------------------------------------------------------- alertes
|
|
366
|
+
|
|
367
|
+
export const databaseAlertList = {
|
|
368
|
+
command: 'database.alertList' as const,
|
|
369
|
+
input: z.object({ databaseId }),
|
|
370
|
+
output: z.object({ alerts: z.array(databaseAlertSchema) })
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
export const databaseAlertAdd = {
|
|
374
|
+
command: 'database.alertAdd' as const,
|
|
375
|
+
input: z.object({
|
|
376
|
+
databaseId,
|
|
377
|
+
name: z.string().min(1).max(DATABASE_ALERT_NAME_MAX_LENGTH),
|
|
378
|
+
enabled: z.boolean(),
|
|
379
|
+
combinator: databaseCombinatorSchema,
|
|
380
|
+
conditions: z.array(databaseConditionSchema).min(1).max(8),
|
|
381
|
+
message: z.string().min(1).max(DATABASE_ALERT_MESSAGE_MAX_LENGTH)
|
|
382
|
+
}),
|
|
383
|
+
output: z.object({ alert: databaseAlertSchema })
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
export const databaseAlertUpdate = {
|
|
387
|
+
command: 'database.alertUpdate' as const,
|
|
388
|
+
input: z.object({
|
|
389
|
+
alertId,
|
|
390
|
+
name: z.string().min(1).max(DATABASE_ALERT_NAME_MAX_LENGTH),
|
|
391
|
+
enabled: z.boolean(),
|
|
392
|
+
combinator: databaseCombinatorSchema,
|
|
393
|
+
conditions: z.array(databaseConditionSchema).min(1).max(8),
|
|
394
|
+
message: z.string().min(1).max(DATABASE_ALERT_MESSAGE_MAX_LENGTH)
|
|
395
|
+
}),
|
|
396
|
+
output: z.object({ alert: databaseAlertSchema })
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
export const databaseAlertRemove = {
|
|
400
|
+
command: 'database.alertRemove' as const,
|
|
401
|
+
input: z.object({ alertId }),
|
|
402
|
+
output: z.object({ alertId })
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Évalue une alerte tout de suite et rend ce que chaque condition a mesuré,
|
|
407
|
+
* **sans notifier personne**.
|
|
408
|
+
*
|
|
409
|
+
* C'est ce qui rend une condition écrivable : on voit le nombre que rend sa
|
|
410
|
+
* requête avant de choisir un seuil, au lieu d'attendre une notification pour
|
|
411
|
+
* découvrir qu'on s'est trompé de colonne.
|
|
412
|
+
*/
|
|
413
|
+
export const databaseAlertTest = {
|
|
414
|
+
command: 'database.alertTest' as const,
|
|
415
|
+
input: z.object({
|
|
416
|
+
databaseId,
|
|
417
|
+
combinator: databaseCombinatorSchema,
|
|
418
|
+
conditions: z.array(databaseConditionSchema).min(1).max(8)
|
|
419
|
+
}),
|
|
420
|
+
output: z.object({
|
|
421
|
+
firing: z.boolean(),
|
|
422
|
+
values: z.array(z.number().nullable()),
|
|
423
|
+
/** L'erreur de chaque condition, à sa place — `null` si elle a abouti. */
|
|
424
|
+
errors: z.array(z.string().nullable()),
|
|
425
|
+
elapsedMs: z.number().int().nonnegative()
|
|
426
|
+
})
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
/** Une requête libre en lecture seule, pour mettre au point une condition. */
|
|
430
|
+
export const databaseQuery = {
|
|
431
|
+
command: 'database.query' as const,
|
|
432
|
+
input: z.object({ databaseId, sql: z.string().min(1).max(DATABASE_SQL_MAX_LENGTH) }),
|
|
433
|
+
output: z.object({ rows: databaseRowsSchema })
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
export const databaseCommands = [
|
|
437
|
+
databaseCount,
|
|
438
|
+
databaseList,
|
|
439
|
+
databaseGet,
|
|
440
|
+
databaseAdd,
|
|
441
|
+
databaseUpdate,
|
|
442
|
+
databaseRemove,
|
|
443
|
+
databaseReorder,
|
|
444
|
+
databaseTest,
|
|
445
|
+
databaseTestDraft,
|
|
446
|
+
databaseInspect,
|
|
447
|
+
databaseTableList,
|
|
448
|
+
databaseTableRows,
|
|
449
|
+
databaseTableStructure,
|
|
450
|
+
databaseRowInsert,
|
|
451
|
+
databaseRowUpdate,
|
|
452
|
+
databaseRowDelete,
|
|
453
|
+
databaseExecute,
|
|
454
|
+
databaseExport,
|
|
455
|
+
databaseAlertList,
|
|
456
|
+
databaseAlertAdd,
|
|
457
|
+
databaseAlertUpdate,
|
|
458
|
+
databaseAlertRemove,
|
|
459
|
+
databaseAlertTest,
|
|
460
|
+
databaseQuery
|
|
461
|
+
] as const;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
CREDENTIAL_LABEL_MAX_LENGTH,
|
|
4
|
+
CREDENTIAL_SECRET_MAX_LENGTH,
|
|
5
|
+
credentialSchema
|
|
6
|
+
} from '../domain/credential';
|
|
7
|
+
import {
|
|
8
|
+
DEPLOY_DESCRIPTION_MAX_LENGTH,
|
|
9
|
+
DEPLOY_EXTERNAL_ID_MAX_LENGTH,
|
|
10
|
+
DEPLOY_TARGET_NAME_MAX_LENGTH,
|
|
11
|
+
DEPLOY_TITLE_MAX_LENGTH,
|
|
12
|
+
deployCandidateSchema,
|
|
13
|
+
deployHistoryEntrySchema,
|
|
14
|
+
deployTargetKindSchema,
|
|
15
|
+
deployTargetSchema,
|
|
16
|
+
deploymentSchema
|
|
17
|
+
} from '../domain/deploy';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Commandes du déploiement.
|
|
21
|
+
*
|
|
22
|
+
* Feature d'espace de premier rang, sur le modèle de Git : une cible appartient
|
|
23
|
+
* à l'espace, un projet n'y **pointe** (voir `project.deployLink`). Tout est à
|
|
24
|
+
* l'étage ouvert, donc aucune de ces commandes ne demande de session
|
|
25
|
+
* déverrouillée.
|
|
26
|
+
*
|
|
27
|
+
* Les clés d'API Dokploy vivent ici et non plus dans la feature Git, où elles
|
|
28
|
+
* n'avaient atterri que faute de module pour les accueillir : poser la clé qui
|
|
29
|
+
* déploie relève de `deploy`, pas de `git`.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const targetId = z.number().int().positive();
|
|
33
|
+
const credentialId = z.number().int().positive();
|
|
34
|
+
|
|
35
|
+
/** Les cibles de l'espace, dans l'ordre choisi par l'utilisateur. */
|
|
36
|
+
export const deployList = {
|
|
37
|
+
command: 'deploy.list' as const,
|
|
38
|
+
input: z.object({}),
|
|
39
|
+
output: z.object({ targets: z.array(deployTargetSchema) })
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Compte les cibles. Métadonnée en clair pure : la tuile d'accueil affiche
|
|
44
|
+
* toujours un nombre, même session verrouillée.
|
|
45
|
+
*/
|
|
46
|
+
export const deployCount = {
|
|
47
|
+
command: 'deploy.count' as const,
|
|
48
|
+
input: z.object({}),
|
|
49
|
+
output: z.object({ count: z.number().int().nonnegative() })
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Une cible et son historique de déclenchements, du plus récent au plus ancien. */
|
|
53
|
+
export const deployGet = {
|
|
54
|
+
command: 'deploy.get' as const,
|
|
55
|
+
input: z.object({ targetId, limit: z.number().int().positive().max(50).optional() }),
|
|
56
|
+
output: z.object({
|
|
57
|
+
target: deployTargetSchema,
|
|
58
|
+
deployments: z.array(deploymentSchema),
|
|
59
|
+
/** Les projets qui la déploient, pour que la fiche sache où elle sert. */
|
|
60
|
+
projectIds: z.array(z.number().int().positive())
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Déclare une cible. **Idempotente** sur (jeton, identifiant externe) : la même
|
|
66
|
+
* application déclarée deux fois est la même cible, et la seconde déclaration
|
|
67
|
+
* met simplement son intitulé à jour.
|
|
68
|
+
*/
|
|
69
|
+
export const deployAdd = {
|
|
70
|
+
command: 'deploy.add' as const,
|
|
71
|
+
input: z.object({
|
|
72
|
+
credentialId,
|
|
73
|
+
kind: deployTargetKindSchema,
|
|
74
|
+
externalId: z.string().min(1).max(DEPLOY_EXTERNAL_ID_MAX_LENGTH),
|
|
75
|
+
name: z.string().min(1).max(DEPLOY_TARGET_NAME_MAX_LENGTH)
|
|
76
|
+
}),
|
|
77
|
+
output: z.object({ target: deployTargetSchema })
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/** Change le jeton, le type ou l'intitulé d'une cible. */
|
|
81
|
+
export const deployUpdate = {
|
|
82
|
+
command: 'deploy.update' as const,
|
|
83
|
+
input: z.object({
|
|
84
|
+
targetId,
|
|
85
|
+
credentialId: credentialId.nullable(),
|
|
86
|
+
kind: deployTargetKindSchema,
|
|
87
|
+
externalId: z.string().min(1).max(DEPLOY_EXTERNAL_ID_MAX_LENGTH),
|
|
88
|
+
name: z.string().min(1).max(DEPLOY_TARGET_NAME_MAX_LENGTH)
|
|
89
|
+
}),
|
|
90
|
+
output: z.object({ target: deployTargetSchema })
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Supprime une cible, **et son historique avec elle**.
|
|
95
|
+
*
|
|
96
|
+
* L'application chez le fournisseur n'est pas touchée : DevEye ne fait que la
|
|
97
|
+
* pointer. Les projets qui la déployaient perdent leur liaison, rien d'autre.
|
|
98
|
+
*/
|
|
99
|
+
export const deployRemove = {
|
|
100
|
+
command: 'deploy.remove' as const,
|
|
101
|
+
input: z.object({ targetId }),
|
|
102
|
+
output: z.object({ targetId })
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** Range la liste : `targetIds` en est le contenu complet, dans son ordre final. */
|
|
106
|
+
export const deployReorder = {
|
|
107
|
+
command: 'deploy.reorder' as const,
|
|
108
|
+
input: z.object({ targetIds: z.array(targetId).min(1) }),
|
|
109
|
+
output: z.object({ targetIds: z.array(targetId) })
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Les applications proposées par l'instance, pour en choisir une.
|
|
114
|
+
*
|
|
115
|
+
* Seule commande du module qui appelle un service externe en direct : elle sert
|
|
116
|
+
* à remplir un sélecteur, et attendre le prochain tour d'un ordonnanceur pour
|
|
117
|
+
* voir apparaître la liste n'aurait aucun sens.
|
|
118
|
+
*/
|
|
119
|
+
export const deployCandidates = {
|
|
120
|
+
command: 'deploy.candidates' as const,
|
|
121
|
+
input: z.object({ credentialId }),
|
|
122
|
+
output: z.object({ candidates: z.array(deployCandidateSchema) })
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Déclenche un déploiement.
|
|
127
|
+
*
|
|
128
|
+
* Toujours audité en `warn` : c'est la seule action du module qui produise un
|
|
129
|
+
* effet **hors** de DevEye, et savoir qui a poussé quoi en production compte
|
|
130
|
+
* plus que le reste.
|
|
131
|
+
*
|
|
132
|
+
* `projectId` est facultatif et ne sert qu'à la frise du projet : déclenché
|
|
133
|
+
* depuis l'onglet d'un projet, l'événement y est inscrit ; déclenché depuis la
|
|
134
|
+
* feature, il n'appartient à aucun projet en particulier.
|
|
135
|
+
*/
|
|
136
|
+
export const deployTrigger = {
|
|
137
|
+
command: 'deploy.trigger' as const,
|
|
138
|
+
input: z.object({
|
|
139
|
+
targetId,
|
|
140
|
+
title: z.string().max(DEPLOY_TITLE_MAX_LENGTH),
|
|
141
|
+
description: z.string().max(DEPLOY_DESCRIPTION_MAX_LENGTH),
|
|
142
|
+
projectId: z.number().int().positive().optional()
|
|
143
|
+
}),
|
|
144
|
+
output: z.object({ deployment: deploymentSchema })
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* L'historique complet d'une cible, **tel que Dokploy le rend** — pas
|
|
149
|
+
* seulement ce que DevEye a déclenché : un déploiement lancé depuis
|
|
150
|
+
* l'interface de Dokploy ou une CI y apparaît aussi.
|
|
151
|
+
*
|
|
152
|
+
* Distincte de `deployGet`, qui reste le suivi local (léger, toujours
|
|
153
|
+
* disponible sans réseau vers le fournisseur) : celle-ci interroge Dokploy en
|
|
154
|
+
* direct à chaque appel, coûte une requête externe, et n'a donc de sens que
|
|
155
|
+
* là où on la demande explicitement — la fiche d'une cible dans la feature,
|
|
156
|
+
* pas l'onglet d'un projet qui en reliste plusieurs.
|
|
157
|
+
*/
|
|
158
|
+
export const deployHistory = {
|
|
159
|
+
command: 'deploy.history' as const,
|
|
160
|
+
input: z.object({ targetId }),
|
|
161
|
+
output: z.object({ entries: z.array(deployHistoryEntrySchema) })
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Le journal complet d'un déploiement, tel que Dokploy l'a produit.
|
|
166
|
+
*
|
|
167
|
+
* `externalId` vient d'une ligne de `deployHistory` : c'est la seule façon dont
|
|
168
|
+
* le client connaît un déploiement dont DevEye n'a pas forcément la ligne
|
|
169
|
+
* locale. Repose sur un point d'entrée de Dokploy sans procédure tRPC dédiée
|
|
170
|
+
* (voir l'adaptateur `dokploy.ts`) : peut échouer sur une instance qui
|
|
171
|
+
* l'authentifie autrement, ou pas du tout — l'appelant le traite alors comme
|
|
172
|
+
* n'importe quelle autre panne réseau.
|
|
173
|
+
*/
|
|
174
|
+
export const deployLog = {
|
|
175
|
+
command: 'deploy.log' as const,
|
|
176
|
+
input: z.object({ targetId, externalId: z.string().min(1) }),
|
|
177
|
+
output: z.object({ log: z.string() })
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// ------------------------------------------------------------------ jetons
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Les clés d'API Dokploy de l'espace.
|
|
184
|
+
*
|
|
185
|
+
* Quatre commandes jumelles de `git.credential*` : même table, même forme, mais
|
|
186
|
+
* chaque feature n'expose que les jetons de ses fournisseurs et les garde
|
|
187
|
+
* derrière son propre droit. Le secret n'est jamais rendu.
|
|
188
|
+
*/
|
|
189
|
+
export const deployCredentialList = {
|
|
190
|
+
command: 'deploy.credentialList' as const,
|
|
191
|
+
input: z.object({}),
|
|
192
|
+
output: z.object({ credentials: z.array(credentialSchema) })
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** Une instance Dokploy exige son adresse : sans elle, rien n'est adressable. */
|
|
196
|
+
export const deployCredentialAdd = {
|
|
197
|
+
command: 'deploy.credentialAdd' as const,
|
|
198
|
+
input: z.object({
|
|
199
|
+
label: z.string().min(1).max(CREDENTIAL_LABEL_MAX_LENGTH),
|
|
200
|
+
baseUrl: z.string().min(1).max(255),
|
|
201
|
+
secret: z.string().min(1).max(CREDENTIAL_SECRET_MAX_LENGTH)
|
|
202
|
+
}),
|
|
203
|
+
output: z.object({ credential: credentialSchema })
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/** `secret` omis = inchangé : le serveur ne l'a jamais rendu, on ne le réécrit pas. */
|
|
207
|
+
export const deployCredentialUpdate = {
|
|
208
|
+
command: 'deploy.credentialUpdate' as const,
|
|
209
|
+
input: z.object({
|
|
210
|
+
credentialId,
|
|
211
|
+
label: z.string().min(1).max(CREDENTIAL_LABEL_MAX_LENGTH),
|
|
212
|
+
baseUrl: z.string().min(1).max(255),
|
|
213
|
+
secret: z.string().min(1).max(CREDENTIAL_SECRET_MAX_LENGTH).optional()
|
|
214
|
+
}),
|
|
215
|
+
output: z.object({ credential: credentialSchema })
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Retire un jeton. Les cibles qui s'en servaient **restent**, sans jeton
|
|
220
|
+
* (`ON DELETE SET NULL`) : elles cessent d'être déployables et le disent, plutôt
|
|
221
|
+
* que de disparaître avec leur clé.
|
|
222
|
+
*/
|
|
223
|
+
export const deployCredentialRemove = {
|
|
224
|
+
command: 'deploy.credentialRemove' as const,
|
|
225
|
+
input: z.object({ credentialId }),
|
|
226
|
+
output: z.object({ credentialId })
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export const deployCommands = [
|
|
230
|
+
deployList,
|
|
231
|
+
deployCount,
|
|
232
|
+
deployGet,
|
|
233
|
+
deployAdd,
|
|
234
|
+
deployUpdate,
|
|
235
|
+
deployRemove,
|
|
236
|
+
deployReorder,
|
|
237
|
+
deployCandidates,
|
|
238
|
+
deployTrigger,
|
|
239
|
+
deployHistory,
|
|
240
|
+
deployLog,
|
|
241
|
+
deployCredentialList,
|
|
242
|
+
deployCredentialAdd,
|
|
243
|
+
deployCredentialUpdate,
|
|
244
|
+
deployCredentialRemove
|
|
245
|
+
] as const;
|