@exagone313/dsh-podman 0.2.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/README.zh.md +41 -0
  4. package/cordis.patch.yml +17 -0
  5. package/dist/approval-reasons.d.ts +129 -0
  6. package/dist/approval-reasons.js +253 -0
  7. package/dist/approval-reasons.test.d.ts +1 -0
  8. package/dist/approval-reasons.test.js +115 -0
  9. package/dist/approval.d.ts +29 -0
  10. package/dist/approval.js +412 -0
  11. package/dist/approval.test.d.ts +1 -0
  12. package/dist/approval.test.js +462 -0
  13. package/dist/card-route.d.ts +15 -0
  14. package/dist/card-route.js +478 -0
  15. package/dist/card-route.test.d.ts +1 -0
  16. package/dist/card-route.test.js +181 -0
  17. package/dist/card-test-support.d.ts +15 -0
  18. package/dist/card-test-support.js +160 -0
  19. package/dist/client/ContainerCard.d.ts +6 -0
  20. package/dist/client/ContainerCard.js +79 -0
  21. package/dist/client/card-client.d.ts +6 -0
  22. package/dist/client/card-client.js +47 -0
  23. package/dist/client/card-protocol.d.ts +101 -0
  24. package/dist/client/card-protocol.js +10 -0
  25. package/dist/client/container-card-caches.d.ts +10 -0
  26. package/dist/client/container-card-caches.js +31 -0
  27. package/dist/client/container-card-controller.d.ts +107 -0
  28. package/dist/client/container-card-controller.js +207 -0
  29. package/dist/client/container-card-create-modal.d.ts +24 -0
  30. package/dist/client/container-card-create-modal.js +109 -0
  31. package/dist/client/container-card-directory-styles.d.ts +5 -0
  32. package/dist/client/container-card-directory-styles.js +246 -0
  33. package/dist/client/container-card-directory.d.ts +12 -0
  34. package/dist/client/container-card-directory.js +144 -0
  35. package/dist/client/container-card-editors.d.ts +30 -0
  36. package/dist/client/container-card-editors.js +116 -0
  37. package/dist/client/container-card-images.d.ts +37 -0
  38. package/dist/client/container-card-images.js +35 -0
  39. package/dist/client/container-card-paths.d.ts +20 -0
  40. package/dist/client/container-card-paths.js +88 -0
  41. package/dist/client/container-card-row.d.ts +30 -0
  42. package/dist/client/container-card-row.js +54 -0
  43. package/dist/client/container-card-secrets.d.ts +21 -0
  44. package/dist/client/container-card-secrets.js +71 -0
  45. package/dist/client/container-card-shared.d.ts +55 -0
  46. package/dist/client/container-card-shared.js +152 -0
  47. package/dist/client/container-card-styles.d.ts +21 -0
  48. package/dist/client/container-card-styles.js +143 -0
  49. package/dist/client/container-card-volumes.d.ts +12 -0
  50. package/dist/client/container-card-volumes.js +37 -0
  51. package/dist/client/container-card-workspace.d.ts +31 -0
  52. package/dist/client/container-card-workspace.js +24 -0
  53. package/dist/client/directory-picker.d.ts +12 -0
  54. package/dist/client/directory-picker.js +30 -0
  55. package/dist/client/index.d.ts +5 -0
  56. package/dist/client/index.js +4419 -0
  57. package/dist/client/locales.d.ts +9 -0
  58. package/dist/client/locales.js +370 -0
  59. package/dist/client/read-only-approval.d.ts +8 -0
  60. package/dist/client/read-only-approval.js +63 -0
  61. package/dist/client/slot-contract.d.ts +12 -0
  62. package/dist/client/slot-contract.js +4 -0
  63. package/dist/client/terminal-styles.d.ts +5 -0
  64. package/dist/client/terminal-styles.js +31 -0
  65. package/dist/client/tool-views.d.ts +8 -0
  66. package/dist/client/tool-views.js +241 -0
  67. package/dist/containers.test.d.ts +1 -0
  68. package/dist/containers.test.js +443 -0
  69. package/dist/daemons.test.d.ts +1 -0
  70. package/dist/daemons.test.js +153 -0
  71. package/dist/fs-provider.d.ts +23 -0
  72. package/dist/fs-provider.js +184 -0
  73. package/dist/fs-provider.test.d.ts +1 -0
  74. package/dist/fs-provider.test.js +260 -0
  75. package/dist/generated/version.d.ts +2 -0
  76. package/dist/generated/version.js +6 -0
  77. package/dist/grpc/proto/dshctl/v1/control.proto +133 -0
  78. package/dist/grpc/proto/dshguest/v1/guest.proto +79 -0
  79. package/dist/grpc/runtime-client.d.ts +5 -0
  80. package/dist/grpc/runtime-client.js +43 -0
  81. package/dist/guest-rpc.d.ts +62 -0
  82. package/dist/guest-rpc.js +391 -0
  83. package/dist/images.test.d.ts +1 -0
  84. package/dist/images.test.js +79 -0
  85. package/dist/index.d.ts +22 -0
  86. package/dist/index.js +140 -0
  87. package/dist/misc.test.d.ts +1 -0
  88. package/dist/misc.test.js +141 -0
  89. package/dist/mount-enums.d.ts +22 -0
  90. package/dist/mount-enums.js +81 -0
  91. package/dist/mount-input.d.ts +14 -0
  92. package/dist/mount-input.js +64 -0
  93. package/dist/mounts.test.d.ts +1 -0
  94. package/dist/mounts.test.js +408 -0
  95. package/dist/output-reader.d.ts +34 -0
  96. package/dist/output-reader.js +87 -0
  97. package/dist/paths.test.d.ts +1 -0
  98. package/dist/paths.test.js +74 -0
  99. package/dist/preferences.d.ts +6 -0
  100. package/dist/preferences.js +27 -0
  101. package/dist/project-path.d.ts +6 -0
  102. package/dist/project-path.js +73 -0
  103. package/dist/project-path.test.d.ts +1 -0
  104. package/dist/project-path.test.js +52 -0
  105. package/dist/prompts.d.ts +13 -0
  106. package/dist/prompts.js +149 -0
  107. package/dist/public.d.ts +4 -0
  108. package/dist/public.js +63 -0
  109. package/dist/read-only-shell.d.ts +14 -0
  110. package/dist/read-only-shell.js +150 -0
  111. package/dist/read-only-shell.test.d.ts +1 -0
  112. package/dist/read-only-shell.test.js +127 -0
  113. package/dist/secrets.test.d.ts +1 -0
  114. package/dist/secrets.test.js +181 -0
  115. package/dist/settings-commands.test.d.ts +1 -0
  116. package/dist/settings-commands.test.js +549 -0
  117. package/dist/settings-create.test.d.ts +1 -0
  118. package/dist/settings-create.test.js +394 -0
  119. package/dist/settings-mounts.test.d.ts +1 -0
  120. package/dist/settings-mounts.test.js +467 -0
  121. package/dist/settings-paths.test.d.ts +1 -0
  122. package/dist/settings-paths.test.js +65 -0
  123. package/dist/settings-schema.d.ts +14 -0
  124. package/dist/settings-schema.js +14 -0
  125. package/dist/settings-workspaces.test.d.ts +1 -0
  126. package/dist/settings-workspaces.test.js +265 -0
  127. package/dist/spill-store.d.ts +17 -0
  128. package/dist/spill-store.js +54 -0
  129. package/dist/spill-store.test.d.ts +1 -0
  130. package/dist/spill-store.test.js +59 -0
  131. package/dist/subprocess.d.ts +9 -0
  132. package/dist/subprocess.js +369 -0
  133. package/dist/subprocess.test.d.ts +1 -0
  134. package/dist/subprocess.test.js +234 -0
  135. package/dist/test-support.d.ts +328 -0
  136. package/dist/test-support.js +437 -0
  137. package/dist/tool-defs.d.ts +26 -0
  138. package/dist/tool-defs.js +188 -0
  139. package/dist/tool-handlers.d.ts +2 -0
  140. package/dist/tool-handlers.js +546 -0
  141. package/dist/tool-params.d.ts +803 -0
  142. package/dist/tool-params.js +494 -0
  143. package/dist/tool-schemas.d.ts +2 -0
  144. package/dist/tool-schemas.js +5 -0
  145. package/dist/tool-views.d.ts +2 -0
  146. package/dist/tool-views.js +56 -0
  147. package/dist/views.test.d.ts +1 -0
  148. package/dist/views.test.js +23 -0
  149. package/dist/volumes.test.d.ts +1 -0
  150. package/dist/volumes.test.js +40 -0
  151. package/dist/workspace-binding.d.ts +40 -0
  152. package/dist/workspace-binding.js +275 -0
  153. package/dist/workspace-binding.test.d.ts +1 -0
  154. package/dist/workspace-binding.test.js +337 -0
  155. package/docs/architecture.md +173 -0
  156. package/docs/architecture.zh.md +129 -0
  157. package/docs/configuration.md +160 -0
  158. package/docs/configuration.zh.md +147 -0
  159. package/docs/development.md +142 -0
  160. package/docs/development.zh.md +135 -0
  161. package/docs/install-dsh-and-dsh-podman.md +165 -0
  162. package/docs/install-dsh-and-dsh-podman.zh.md +145 -0
  163. package/docs/usage.md +393 -0
  164. package/docs/usage.zh.md +315 -0
  165. package/package.json +119 -0
@@ -0,0 +1,394 @@
1
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
2
+ //
3
+ // SPDX-License-Identifier: MIT
4
+ import { test } from "node:test";
5
+ import { strict as assert } from "node:assert";
6
+ import { fakeScope, fakeContext, baseValue } from "./card-test-support.js";
7
+ import { installCardCommandDriver } from "./card-test-support.js";
8
+ test("create command sends PATH additions", async () => {
9
+ const scope = fakeScope(baseValue());
10
+ const calls = [];
11
+ const resolver = {
12
+ getConfig: () => ({}),
13
+ setConfig: () => { },
14
+ async control(method, request) {
15
+ calls.push([method, request]);
16
+ if (method === "listContainers")
17
+ return { containers: [] };
18
+ if (method === "listImages")
19
+ return { images: [] };
20
+ if (method === "listWorkspaces")
21
+ return { workspaces: [] };
22
+ return {};
23
+ },
24
+ };
25
+ await installCardCommandDriver(fakeContext(scope), resolver);
26
+ await scope.update({
27
+ command: {
28
+ op: "create",
29
+ workspace: "w1",
30
+ projectName: "w1",
31
+ image: "img1",
32
+ at: 1,
33
+ mounts: [],
34
+ paths: ["/opt/bin"],
35
+ env: {},
36
+ container: "",
37
+ secretEnvMap: {},
38
+ mount: null,
39
+ },
40
+ });
41
+ await new Promise((resolve) => setImmediate(resolve));
42
+ const createCall = calls.find(([method]) => method === "createWorkspace");
43
+ assert.deepEqual(createCall?.[1], {
44
+ workspaceSlug: "w1",
45
+ projectName: "w1",
46
+ imageId: "img1",
47
+ paths: ["/opt/bin"],
48
+ });
49
+ const calls2 = [];
50
+ const resolver2 = {
51
+ getConfig: () => ({}),
52
+ setConfig: () => { },
53
+ async control(method, request) {
54
+ calls2.push([method, request]);
55
+ if (method === "listContainers")
56
+ return { containers: [] };
57
+ if (method === "listImages")
58
+ return { images: [] };
59
+ if (method === "listWorkspaces")
60
+ return { workspaces: [] };
61
+ return {};
62
+ },
63
+ };
64
+ const scope2 = fakeScope(baseValue());
65
+ await installCardCommandDriver(fakeContext(scope2), resolver2);
66
+ await scope2.update({
67
+ command: {
68
+ op: "create",
69
+ workspace: "w1",
70
+ container: "dev",
71
+ image: "img1",
72
+ at: 2,
73
+ mounts: [],
74
+ paths: ["/opt/bin", "/usr/local/bin"],
75
+ env: {},
76
+ secretEnvMap: {},
77
+ mount: null,
78
+ },
79
+ });
80
+ await new Promise((resolve) => setImmediate(resolve));
81
+ const startCall = calls2.find(([method]) => method === "startContainer");
82
+ assert.deepEqual(startCall?.[1], {
83
+ workspaceSlug: "w1",
84
+ imageId: "img1",
85
+ container: "dev",
86
+ paths: ["/opt/bin", "/usr/local/bin"],
87
+ });
88
+ });
89
+ test("volume_create command drives createVolume with the name", async () => {
90
+ const scope = fakeScope(baseValue());
91
+ const calls = [];
92
+ const resolver = {
93
+ getConfig: () => ({}),
94
+ setConfig: () => { },
95
+ async control(method, request) {
96
+ calls.push([method, request]);
97
+ if (method === "listContainers")
98
+ return { containers: [] };
99
+ if (method === "listImages")
100
+ return { images: [] };
101
+ if (method === "listWorkspaces")
102
+ return { workspaces: [] };
103
+ if (method === "listVolumes")
104
+ return { volumes: [] };
105
+ return {};
106
+ },
107
+ };
108
+ await installCardCommandDriver(fakeContext(scope), resolver);
109
+ await scope.update({
110
+ command: { op: "volume_create", workspace: "data", image: "", at: 3 },
111
+ });
112
+ await new Promise((resolve) => setImmediate(resolve));
113
+ const createCall = calls.find(([method]) => method === "createVolume");
114
+ assert.deepEqual(createCall?.[1], { name: "data" });
115
+ assert.equal(scope.value.command, null);
116
+ });
117
+ test("secret_create command drives createSecret with the name", async () => {
118
+ const scope = fakeScope(baseValue());
119
+ const calls = [];
120
+ const resolver = {
121
+ getConfig: () => ({}),
122
+ setConfig: () => { },
123
+ async control(method, request) {
124
+ calls.push([method, request]);
125
+ if (method === "listContainers")
126
+ return { containers: [] };
127
+ if (method === "listImages")
128
+ return { images: [] };
129
+ if (method === "listWorkspaces")
130
+ return { workspaces: [] };
131
+ if (method === "listVolumes")
132
+ return { volumes: [] };
133
+ if (method === "listSecrets")
134
+ return { secrets: [] };
135
+ return {};
136
+ },
137
+ };
138
+ await installCardCommandDriver(fakeContext(scope), resolver);
139
+ await scope.update({
140
+ command: { op: "secret_create", workspace: "db-pass", image: "", at: 6, mounts: [], value: "" },
141
+ });
142
+ await new Promise((resolve) => setImmediate(resolve));
143
+ const createCall = calls.find(([method]) => method === "createSecret");
144
+ assert.deepEqual(createCall?.[1], { name: "db-pass" });
145
+ assert.equal(scope.value.command, null);
146
+ });
147
+ test("secret_create command drives createSecret with length when provided", async () => {
148
+ const scope = fakeScope(baseValue());
149
+ const calls = [];
150
+ const resolver = {
151
+ getConfig: () => ({}),
152
+ setConfig: () => { },
153
+ async control(method, request) {
154
+ calls.push([method, request]);
155
+ if (method === "listContainers")
156
+ return { containers: [] };
157
+ if (method === "listImages")
158
+ return { images: [] };
159
+ if (method === "listWorkspaces")
160
+ return { workspaces: [] };
161
+ if (method === "listVolumes")
162
+ return { volumes: [] };
163
+ if (method === "listSecrets")
164
+ return { secrets: [] };
165
+ return {};
166
+ },
167
+ };
168
+ await installCardCommandDriver(fakeContext(scope), resolver);
169
+ await scope.update({
170
+ command: { op: "secret_create", workspace: "s", image: "", at: 11, length: 48 },
171
+ });
172
+ await new Promise((resolve) => setImmediate(resolve));
173
+ const createCall = calls.find(([method]) => method === "createSecret");
174
+ assert.deepEqual(createCall?.[1], { name: "s", length: 48 });
175
+ assert.equal(scope.value.command, null);
176
+ });
177
+ test("secret_create command drives createSecret without length when omitted", async () => {
178
+ const scope = fakeScope(baseValue());
179
+ const calls = [];
180
+ const resolver = {
181
+ getConfig: () => ({}),
182
+ setConfig: () => { },
183
+ async control(method, request) {
184
+ calls.push([method, request]);
185
+ if (method === "listContainers")
186
+ return { containers: [] };
187
+ if (method === "listImages")
188
+ return { images: [] };
189
+ if (method === "listWorkspaces")
190
+ return { workspaces: [] };
191
+ if (method === "listVolumes")
192
+ return { volumes: [] };
193
+ if (method === "listSecrets")
194
+ return { secrets: [] };
195
+ return {};
196
+ },
197
+ };
198
+ await installCardCommandDriver(fakeContext(scope), resolver);
199
+ await scope.update({
200
+ command: { op: "secret_create", workspace: "s", image: "", at: 12 },
201
+ });
202
+ await new Promise((resolve) => setImmediate(resolve));
203
+ const createCall = calls.find(([method]) => method === "createSecret");
204
+ assert.deepEqual(createCall?.[1], { name: "s" });
205
+ assert.equal(scope.value.command, null);
206
+ });
207
+ test("secret_create command drives createSecret with charset when provided", async () => {
208
+ const scope = fakeScope(baseValue());
209
+ const calls = [];
210
+ const resolver = {
211
+ getConfig: () => ({}),
212
+ setConfig: () => { },
213
+ async control(method, request) {
214
+ calls.push([method, request]);
215
+ if (method === "listContainers")
216
+ return { containers: [] };
217
+ if (method === "listImages")
218
+ return { images: [] };
219
+ if (method === "listWorkspaces")
220
+ return { workspaces: [] };
221
+ if (method === "listVolumes")
222
+ return { volumes: [] };
223
+ if (method === "listSecrets")
224
+ return { secrets: [] };
225
+ return {};
226
+ },
227
+ };
228
+ await installCardCommandDriver(fakeContext(scope), resolver);
229
+ await scope.update({
230
+ command: { op: "secret_create", workspace: "tok", length: 48, charset: "hex" },
231
+ });
232
+ await new Promise((resolve) => setImmediate(resolve));
233
+ const createCall = calls.find(([method]) => method === "createSecret");
234
+ assert.deepEqual(createCall?.[1], { name: "tok", length: 48, charset: "hex" });
235
+ assert.equal(scope.value.command, null);
236
+ });
237
+ test("recreate command drives recreateContainer with env", async () => {
238
+ const scope = fakeScope(baseValue());
239
+ const calls = [];
240
+ const resolver = {
241
+ getConfig: () => ({}),
242
+ setConfig: () => { },
243
+ async control(method, request) {
244
+ calls.push([method, request]);
245
+ if (method === "listContainers")
246
+ return { containers: [] };
247
+ if (method === "listImages")
248
+ return { images: [] };
249
+ if (method === "listWorkspaces")
250
+ return { workspaces: [] };
251
+ return {};
252
+ },
253
+ };
254
+ await installCardCommandDriver(fakeContext(scope), resolver);
255
+ await scope.update({
256
+ command: {
257
+ op: "recreate",
258
+ workspace: "w1",
259
+ image: "img2",
260
+ at: 15,
261
+ env: { A: "1" },
262
+ },
263
+ });
264
+ await new Promise((resolve) => setImmediate(resolve));
265
+ const recreateCall = calls.find(([method]) => method === "recreateContainer");
266
+ assert.deepEqual(recreateCall?.[1], {
267
+ workspaceSlug: "w1",
268
+ imageId: "img2",
269
+ env: { A: "1" },
270
+ });
271
+ assert.equal(scope.value.command, null);
272
+ });
273
+ test("create command with a container name routes to startContainer", async () => {
274
+ const scope = fakeScope(baseValue());
275
+ const calls = [];
276
+ const resolver = {
277
+ getConfig: () => ({}),
278
+ setConfig: () => { },
279
+ async control(method, request) {
280
+ calls.push([method, request]);
281
+ if (method === "listContainers")
282
+ return { containers: [] };
283
+ if (method === "listImages")
284
+ return { images: [] };
285
+ if (method === "listWorkspaces")
286
+ return { workspaces: [] };
287
+ return {};
288
+ },
289
+ };
290
+ await installCardCommandDriver(fakeContext(scope), resolver);
291
+ await scope.update({
292
+ command: {
293
+ op: "create",
294
+ workspace: "w1",
295
+ container: "dev",
296
+ image: "img1",
297
+ at: 1,
298
+ mounts: [],
299
+ env: {},
300
+ secretEnvMap: {},
301
+ mount: null,
302
+ },
303
+ });
304
+ await new Promise((resolve) => setImmediate(resolve));
305
+ const startCall = calls.find(([method]) => method === "startContainer");
306
+ assert.deepEqual(startCall?.[1], {
307
+ workspaceSlug: "w1",
308
+ imageId: "img1",
309
+ container: "dev",
310
+ });
311
+ assert.equal(calls.some(([method]) => method === "createWorkspace"), false, "a create command with a container name must not create a workspace");
312
+ assert.equal(scope.value.command, null);
313
+ });
314
+ test("create command sends secret env", async () => {
315
+ const scope = fakeScope(baseValue());
316
+ const calls = [];
317
+ const resolver = {
318
+ getConfig: () => ({}),
319
+ setConfig: () => { },
320
+ async control(method, request) {
321
+ calls.push([method, request]);
322
+ if (method === "listContainers")
323
+ return { containers: [] };
324
+ if (method === "listImages")
325
+ return { images: [] };
326
+ if (method === "listWorkspaces")
327
+ return { workspaces: [] };
328
+ return {};
329
+ },
330
+ };
331
+ await installCardCommandDriver(fakeContext(scope), resolver);
332
+ await scope.update({
333
+ command: {
334
+ op: "create",
335
+ workspace: "w1",
336
+ projectName: "w1",
337
+ image: "img1",
338
+ at: 1,
339
+ mounts: [],
340
+ env: {},
341
+ container: "",
342
+ secretEnvMap: { VALKEY_PASSWORD: "valkey-tls" },
343
+ mount: null,
344
+ },
345
+ });
346
+ await new Promise((resolve) => setImmediate(resolve));
347
+ const createCall = calls.find(([method]) => method === "createWorkspace");
348
+ assert.deepEqual(createCall?.[1], {
349
+ workspaceSlug: "w1",
350
+ projectName: "w1",
351
+ imageId: "img1",
352
+ secretEnv: { VALKEY_PASSWORD: "valkey-tls" },
353
+ });
354
+ assert.equal(scope.value.command, null);
355
+ const calls2 = [];
356
+ const resolver2 = {
357
+ getConfig: () => ({}),
358
+ setConfig: () => { },
359
+ async control(method, request) {
360
+ calls2.push([method, request]);
361
+ if (method === "listContainers")
362
+ return { containers: [] };
363
+ if (method === "listImages")
364
+ return { images: [] };
365
+ if (method === "listWorkspaces")
366
+ return { workspaces: [] };
367
+ return {};
368
+ },
369
+ };
370
+ const scope2 = fakeScope(baseValue());
371
+ await installCardCommandDriver(fakeContext(scope2), resolver2);
372
+ await scope2.update({
373
+ command: {
374
+ op: "create",
375
+ workspace: "w1",
376
+ projectName: "w1",
377
+ image: "img1",
378
+ at: 2,
379
+ mounts: [],
380
+ env: {},
381
+ container: "",
382
+ secretEnvMap: {},
383
+ mount: null,
384
+ },
385
+ });
386
+ await new Promise((resolve) => setImmediate(resolve));
387
+ const createCall2 = calls2.find(([method]) => method === "createWorkspace");
388
+ assert.deepEqual(createCall2?.[1], {
389
+ workspaceSlug: "w1",
390
+ projectName: "w1",
391
+ imageId: "img1",
392
+ });
393
+ assert.equal(scope2.value.command, null);
394
+ });
@@ -0,0 +1 @@
1
+ export {};