@yugoo-design/dsh-design-studio-dsh 0.1.0-beta.3 → 0.1.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.
Files changed (52) hide show
  1. package/README.md +11 -1
  2. package/lib/client-adapter.d.ts +2 -0
  3. package/lib/client-adapter.js +2 -0
  4. package/lib/index.d.ts +8 -0
  5. package/lib/index.js +141 -60
  6. package/lib/page-client.js +6205 -452
  7. package/lib/page-rpc.d.ts +1 -1
  8. package/lib/page-rpc.js +9 -0
  9. package/lib/typert.remote-client.js +24 -0
  10. package/licenses/bundled-js/@floating-ui/core@1.8.0/LICENSE +20 -0
  11. package/licenses/bundled-js/@floating-ui/dom@1.8.0/LICENSE +20 -0
  12. package/licenses/bundled-js/@floating-ui/react-dom@2.1.9/LICENSE +20 -0
  13. package/licenses/bundled-js/@floating-ui/utils@0.2.12/LICENSE +20 -0
  14. package/licenses/bundled-js/@radix-ui/number@1.1.3/LICENSE +21 -0
  15. package/licenses/bundled-js/@radix-ui/primitive@1.1.7/LICENSE +21 -0
  16. package/licenses/bundled-js/@radix-ui/react-collection@1.1.15/LICENSE +21 -0
  17. package/licenses/bundled-js/@radix-ui/react-compose-refs@1.1.5/LICENSE +21 -0
  18. package/licenses/bundled-js/@radix-ui/react-context@1.2.2/LICENSE +21 -0
  19. package/licenses/bundled-js/@radix-ui/react-direction@1.1.4/LICENSE +21 -0
  20. package/licenses/bundled-js/@radix-ui/react-dismissable-layer@1.1.19/LICENSE +21 -0
  21. package/licenses/bundled-js/@radix-ui/react-focus-guards@1.1.6/LICENSE +21 -0
  22. package/licenses/bundled-js/@radix-ui/react-focus-scope@1.1.16/LICENSE +21 -0
  23. package/licenses/bundled-js/@radix-ui/react-id@1.1.4/LICENSE +21 -0
  24. package/licenses/bundled-js/@radix-ui/react-popper@1.3.7/LICENSE +21 -0
  25. package/licenses/bundled-js/@radix-ui/react-portal@1.1.17/LICENSE +21 -0
  26. package/licenses/bundled-js/@radix-ui/react-presence@1.1.10/LICENSE +21 -0
  27. package/licenses/bundled-js/@radix-ui/react-primitive@2.1.10/LICENSE +21 -0
  28. package/licenses/bundled-js/@radix-ui/react-select@2.3.7/LICENSE +21 -0
  29. package/licenses/bundled-js/@radix-ui/react-slot@1.3.3/LICENSE +21 -0
  30. package/licenses/bundled-js/@radix-ui/react-use-callback-ref@1.1.4/LICENSE +21 -0
  31. package/licenses/bundled-js/@radix-ui/react-use-controllable-state@1.2.6/LICENSE +21 -0
  32. package/licenses/bundled-js/@radix-ui/react-use-effect-event@0.0.5/LICENSE +21 -0
  33. package/licenses/bundled-js/@radix-ui/react-use-layout-effect@1.1.4/LICENSE +21 -0
  34. package/licenses/bundled-js/@radix-ui/react-use-previous@1.1.4/LICENSE +21 -0
  35. package/licenses/bundled-js/@radix-ui/react-use-size@1.1.4/LICENSE +21 -0
  36. package/licenses/bundled-js/@radix-ui/react-visually-hidden@1.2.11/LICENSE +21 -0
  37. package/licenses/bundled-js/aria-hidden@1.2.6/LICENSE +21 -0
  38. package/licenses/bundled-js/get-nonce@1.0.1/LICENSE +21 -0
  39. package/licenses/bundled-js/lucide-react@0.562.0/LICENSE +39 -0
  40. package/licenses/bundled-js/react-remove-scroll-bar@2.3.8/ATTRIBUTION.md +19 -0
  41. package/licenses/bundled-js/react-remove-scroll-bar@2.3.8/UPSTREAM-LICENSE-2.3.7.txt +21 -0
  42. package/licenses/bundled-js/react-remove-scroll@2.7.2/LICENSE +21 -0
  43. package/licenses/bundled-js/react-style-singleton@2.2.3/LICENSE +21 -0
  44. package/licenses/bundled-js/tslib@2.8.1/LICENSE.txt +12 -0
  45. package/licenses/bundled-js/use-callback-ref@1.3.3/LICENSE +21 -0
  46. package/licenses/bundled-js/use-sidecar@1.1.3/LICENSE +21 -0
  47. package/licenses/dsh-distribution.json +2327 -19
  48. package/licenses/first-party/dsh-design-panel/LICENSE +202 -0
  49. package/licenses/first-party/dsh-design-panel/NOTICE +13 -0
  50. package/licenses/first-party/dsh-design-studio-ui/LICENSE +202 -0
  51. package/licenses/first-party/dsh-design-studio-ui/NOTICE +13 -0
  52. package/package.json +16 -10
package/README.md CHANGED
@@ -9,7 +9,7 @@ explicit `kitSources` mode remains available with its strict startup validation.
9
9
 
10
10
  `dsh-design-studio-dsh` is the DSH-only adapter around the host-neutral read-only Studio application and shared `StudioWorkspace`. It owns the session-free `studioManagement` Typert Remote, a root-scoped Settings launcher, and the plugin-owned `/design-studio/` full-page route. It does not change the Agent loop, Design Project selection, Design Files, or G/R/A services, and it persists nothing: Studio 1.0 has no durable record, no working copies, and no mutation endpoint.
11
11
 
12
- The Remote exposes exactly four read methods: `workspace`, `readKitWorkspace` (exact `name@version` pin required; a diverging response identity diagnoses), `readBundleWorkspace`, and `readBundleFile`. The catalog snapshot projects `ctx.design.listKits()`. Bundle source reads run through `ctx.fs`: the `kitSources` config lists installed content packages (`packageName`, resolved like the Design Core kit-loader) or absolute directories (`root`); every path resolves through the filesystem capability and must stay canonically contained in a configured root, so traversal and symlink escapes never read outside the authored trees and non-UTF-8 content diagnoses as binary. Invalid or ambiguous configuration — a missing root, a root without `mindset.md`, a relative path, a duplicate root, or one Kit/Bundle name declared by two roots — fails loud at startup. Without `kitSources` the catalog stays readable and Bundle reads diagnose `studio.source_not_configured`. Disposal rejects new work and drains admitted calls.
12
+ The Remote exposes exactly six read methods: `workspace`, `readKitWorkspace` (exact `name@version` pin required; a diverging response identity diagnoses), `readKitFiles` and `readKitFile` (the same exact Kit pin), `readBundleWorkspace`, and `readBundleFile`. Kit file inspection includes `kit.yaml`, `mindset.md` and other authored files beneath the selected Kit root, excluding `.git` and `node_modules`; the text viewer accepts regular UTF-8 files up to 1 MiB, with bounded tree traversal. Missing sources, forbidden paths, binary content and oversized files diagnose rather than falling back to another version. The catalog snapshot projects `ctx.design.listKits()`. Bundle source reads run through `ctx.fs`: the `kitSources` config lists installed content packages (`packageName`, resolved like the Design Core kit-loader) or absolute directories (`root`); every path resolves through the filesystem capability and must stay canonically contained in a configured root, so traversal and symlink escapes never read outside the authored trees and non-UTF-8 content diagnoses as binary. Invalid or ambiguous configuration — a missing root, a root without `mindset.md`, a relative path, a duplicate root, or one Kit/Bundle name declared by two roots — fails loud at startup. Without `kitSources` the catalog stays readable and Bundle reads diagnose `studio.source_not_configured`. Disposal rejects new work and drains admitted calls.
13
13
 
14
14
  Strict codecs follow the current Typert `create(): TypertSchema` factory contract.
15
15
  The existing Zod validators supply that parser capability; both Host registration
@@ -26,3 +26,13 @@ dependencies or remaining static/dynamic module imports. Its page-route test als
26
26
  checks the emitted JavaScript with the shared loader analyzer and exercises real
27
27
  bundler rejection cases. These checks establish browser module closure; rendered
28
28
  Host interaction remains a separate integration check.
29
+
30
+ Only the standalone browser page injects `PanelSelect` and
31
+ `PANEL_SELECT_MENU_CSS` from the isolated public `dsh-design-panel/select` into
32
+ Studio's optional neutral choice-control port. This is a shared control and popup
33
+ style, not the broad provider API or Panel/DSL workspace renderer. The server,
34
+ Settings launcher and transports retain their existing dependency boundary.
35
+ The menu snapshots Studio's semantic
36
+ tokens and fonts; inside an open native dialog it stays within that dialog's top
37
+ layer, otherwise it uses the owning document body. These source changes do not
38
+ establish installed Web/Desktop interaction acceptance.
@@ -32,6 +32,8 @@ type DshRemoteResult<T> = {
32
32
  interface DshStudioRemote {
33
33
  workspace(query: string): Promise<DshRemoteResult<Awaited<ReturnType<StudioManagementClient['workspace']>>>>;
34
34
  readKitWorkspace(name: string, version: string): Promise<DshRemoteResult<Awaited<ReturnType<StudioManagementClient['readKitWorkspace']>>>>;
35
+ readKitFiles(name: string, version: string): Promise<DshRemoteResult<Awaited<ReturnType<NonNullable<StudioManagementClient['readKitFiles']>>>>>;
36
+ readKitFile(name: string, version: string, path: string): Promise<DshRemoteResult<Awaited<ReturnType<NonNullable<StudioManagementClient['readKitFile']>>>>>;
35
37
  readBundleWorkspace(name: string, version?: string): Promise<DshRemoteResult<Awaited<ReturnType<StudioManagementClient['readBundleWorkspace']>>>>;
36
38
  readBundleFile(name: string, path: string, version?: string): Promise<DshRemoteResult<Awaited<ReturnType<StudioManagementClient['readBundleFile']>>>>;
37
39
  }
@@ -45,6 +45,8 @@ function createDshStudioClient(remote) {
45
45
  })
46
46
  });
47
47
  },
48
+ readKitFiles: (input) => unwrap("readKitFiles", remote.readKitFiles(input.name, input.version)),
49
+ readKitFile: (input) => unwrap("readKitFile", remote.readKitFile(input.name, input.version, input.path)),
48
50
  readBundleWorkspace: (name, version) => unwrap("readBundleWorkspace", remote.readBundleWorkspace(name, version)),
49
51
  readBundleFile: (input) => unwrap("readBundleFile", remote.readBundleFile(input.name, input.path, input.version))
50
52
  });
package/lib/index.d.ts CHANGED
@@ -51,6 +51,7 @@ declare class DshStudioManagementService extends TypertRemoteService {
51
51
  private readonly config;
52
52
  private management?;
53
53
  private bundles?;
54
+ private readonly configuredKitRoots;
54
55
  private accepting;
55
56
  private readonly inFlight;
56
57
  /**
@@ -67,6 +68,13 @@ declare class DshStudioManagementService extends TypertRemoteService {
67
68
  workspace(query: string): Promise<StudioWorkspaceView>;
68
69
  /** Read one exact installed Kit version's workspace and verify the returned identity matches. */
69
70
  readKitWorkspace(name: string, version: string): Promise<StudioKitWorkspaceResult>;
71
+ /** List all authored files of one exact installed Kit, including kit.yaml. */
72
+ readKitFiles(name: string, version: string): Promise<readonly string[]>;
73
+ /** Read one root-confined Kit file as bounded UTF-8 text. */
74
+ readKitFile(name: string, version: string, path: string): Promise<{
75
+ readonly content: string;
76
+ }>;
77
+ private kitFiles;
70
78
  /** Read one Bundle's read-only source workspace. */
71
79
  readBundleWorkspace(name: string, version?: string): Promise<StudioBundleWorkspaceResult>;
72
80
  /** Read one complete Bundle file byte-exactly as UTF-8 text. */
package/lib/index.js CHANGED
@@ -1,8 +1,104 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { Service } from "@deepseek-ai/cordis";
3
- import { dirname, isAbsolute, join, resolve } from "node:path";
4
3
  import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
4
+ import { DesignKitVersion } from "@yugoo-design/dsh-design-core";
5
5
  import { StudioBinaryContentError, StudioBundleSourceService, StudioManagementService, loadStudioKit, snapshotKit } from "@yugoo-design/dsh-design-studio";
6
+ import { dirname, isAbsolute, join, resolve } from "node:path";
7
+ //#region src/kit-files.ts
8
+ /** Installed source reads share the same DSH filesystem containment boundary. */
9
+ const MAX_TEXT_BYTES = 1048576;
10
+ const excludedDirectory = (name) => /^(?:\.git|node_modules)$/iu.test(name);
11
+ /** A code survives the Remote gateway while the message remains useful in the viewer. */
12
+ function kitFileError(code, message) {
13
+ return Object.assign(/* @__PURE__ */ new Error(`${code}: ${message}`), { code });
14
+ }
15
+ /** One read's installed resource root is the complete filesystem boundary, not its catalog id. */
16
+ async function openInstalledSourceFiles(fs, root, kind = "Bundle") {
17
+ if (!isAbsolute(root)) throw new Error(`design studio dsh: installed ${kind} resource root must be absolute`);
18
+ const base = await fs.resolve(root);
19
+ if ((await fs.stat(base))?.type !== "directory") throw new Error(`design studio dsh: installed ${kind} resource root is not a directory`);
20
+ const target = async (path) => {
21
+ const resolved = await fs.resolve(path);
22
+ if (!fs.contains(base, resolved)) {
23
+ if (kind === "Kit") throw kitFileError("kit_file.path_forbidden", "Path escapes installed Kit resource root.");
24
+ throw new Error(`design studio dsh: path escapes installed ${kind} resource root`);
25
+ }
26
+ return resolved;
27
+ };
28
+ const code = (error) => typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
29
+ return {
30
+ async readFile(path) {
31
+ if (typeof path !== "string" || /[\\:\u0000-\u001f\u007f]/u.test(path) || path.split("/").some((part) => !part || part === "." || part === ".." || excludedDirectory(part))) throw kitFileError("kit_file.path_forbidden", "Invalid Kit file path.");
32
+ try {
33
+ const resolved = await target(join(root, path));
34
+ const info = await fs.stat(resolved);
35
+ if (info?.type !== "file") throw kitFileError("kit_file.missing", "Kit file not found or not a regular file.");
36
+ if ((info.size ?? 0) > MAX_TEXT_BYTES) throw kitFileError("kit_file.too_large", "This file exceeds the 1 MiB text viewer limit.");
37
+ const bytes = await fs.readBytes(resolved, void 0, MAX_TEXT_BYTES);
38
+ let content;
39
+ try {
40
+ content = new TextDecoder("utf-8", {
41
+ fatal: true,
42
+ ignoreBOM: true
43
+ }).decode(bytes);
44
+ } catch {
45
+ throw kitFileError("kit_file.binary", "Kit file is binary or invalid UTF-8 text.");
46
+ }
47
+ if (content.includes("\0")) throw kitFileError("kit_file.binary", "Kit file is binary, not UTF-8 text.");
48
+ return { content };
49
+ } catch (error) {
50
+ if (code(error) === "FS_TOO_LARGE") throw kitFileError("kit_file.too_large", "This file exceeds the 1 MiB text viewer limit.");
51
+ if (code(error) === "FS_NOT_FOUND") throw kitFileError("kit_file.missing", "Kit file not found.");
52
+ if (code(error) === "FS_NOT_TEXT") throw kitFileError("kit_file.binary", "Kit file is binary or invalid UTF-8 text.");
53
+ throw error;
54
+ }
55
+ },
56
+ listKitRoots: async () => [],
57
+ async readText(path) {
58
+ try {
59
+ return await fs.readText(await target(path));
60
+ } catch (error) {
61
+ if (code(error) === "FS_NOT_FOUND") return void 0;
62
+ if (code(error) === "FS_NOT_TEXT") throw new StudioBinaryContentError(path);
63
+ throw error;
64
+ }
65
+ },
66
+ async listDir(path) {
67
+ try {
68
+ return (await fs.listDir(await target(path))).map((entry) => entry.name);
69
+ } catch (error) {
70
+ if (code(error) === "FS_NOT_FOUND" || code(error) === "FS_NOT_DIRECTORY") return [];
71
+ throw error;
72
+ }
73
+ },
74
+ async isDirectory(path) {
75
+ try {
76
+ return (await fs.stat(await target(path)))?.type === "directory";
77
+ } catch (error) {
78
+ if (code(error) === "FS_NOT_FOUND") return false;
79
+ throw error;
80
+ }
81
+ },
82
+ async listFiles(path) {
83
+ const files = [];
84
+ let visited = 0;
85
+ const walk = async (directory, prefix, depth) => {
86
+ if (depth > 32) throw new Error(`design studio dsh: ${kind} file tree exceeds depth limit`);
87
+ for (const entry of await fs.listDir(directory)) {
88
+ if (++visited > 2e4) throw new Error(`design studio dsh: ${kind} file tree exceeds entry limit`);
89
+ if (kind === "Kit" && excludedDirectory(entry.name)) continue;
90
+ if (!fs.contains(base, entry.target)) continue;
91
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
92
+ if (entry.type === "directory") await walk(entry.target, relative, depth + 1);
93
+ else if (entry.type === "file") files.push(relative);
94
+ }
95
+ };
96
+ await walk(await target(path), "", 0);
97
+ return files.sort();
98
+ }
99
+ };
100
+ }
101
+ //#endregion
6
102
  //#region src/kit-sources.ts
7
103
  /** Read-only Kit source access over the DSH host filesystem capability. */
8
104
  /**
@@ -132,6 +228,7 @@ var DshStudioManagementService = class extends TypertRemoteService {
132
228
  config;
133
229
  management;
134
230
  bundles;
231
+ configuredKitRoots = /* @__PURE__ */ new Map();
135
232
  accepting = true;
136
233
  inFlight = /* @__PURE__ */ new Set();
137
234
  /**
@@ -150,6 +247,7 @@ var DshStudioManagementService = class extends TypertRemoteService {
150
247
  await Promise.allSettled([...this.inFlight]);
151
248
  this.management = void 0;
152
249
  this.bundles = void 0;
250
+ this.configuredKitRoots.clear();
153
251
  }, "design-studio-dsh.readonly");
154
252
  const catalog = Object.freeze({ snapshot: async () => Object.freeze({
155
253
  kits: Object.freeze(this.host.design.listKits().map(snapshotKit).sort((left, right) => left.name.localeCompare(right.name) || left.version.localeCompare(right.version))),
@@ -159,9 +257,9 @@ var DshStudioManagementService = class extends TypertRemoteService {
159
257
  const configs = this.config.kitSources ?? [];
160
258
  if (configs.length === 0) return;
161
259
  const roots = configs.map((entry) => resolveKitSourceRoot(entry, this.ctx.baseUrl));
162
- this.bundles = await this.openBundleService(this.host.design.listKits(), roots);
260
+ this.bundles = await this.openBundleService(this.host.design.listKits(), roots, true);
163
261
  }
164
- async openBundleService(kits, roots) {
262
+ async openBundleService(kits, roots, recordKitRoots = false) {
165
263
  const catalog = { snapshot: async () => ({ kits: kits.map(snapshotKit) }) };
166
264
  const source = await openDshStudioBundleSource(this.host.fs, roots);
167
265
  const kitNames = /* @__PURE__ */ new Map();
@@ -176,6 +274,7 @@ var DshStudioManagementService = class extends TypertRemoteService {
176
274
  const previousKit = kitNames.get(kit.name);
177
275
  if (previousKit !== void 0) throw new Error(`design studio dsh: Kit ${JSON.stringify(kit.name)} is declared by two kitSources roots: ${JSON.stringify(previousKit)} and ${JSON.stringify(root)}`);
178
276
  kitNames.set(kit.name, root);
277
+ if (recordKitRoots) this.configuredKitRoots.set(`${kit.name}\0${kit.version}`, root);
179
278
  for (const skill of kit.skills) {
180
279
  const previousBundle = bundleNames.get(skill.name);
181
280
  if (previousBundle !== void 0) throw new Error(`design studio dsh: Bundle ${JSON.stringify(skill.name)} is declared by two kitSources roots: ${JSON.stringify(previousBundle)} and ${JSON.stringify(root)}`);
@@ -213,7 +312,7 @@ var DshStudioManagementService = class extends TypertRemoteService {
213
312
  if (!selected) return void 0;
214
313
  const root = this.host.design.resolveBundleRoot(pin) ?? selected.definition.resourceRoot;
215
314
  if (!root) return void 0;
216
- files = await openInstalledBundleFiles(this.host.fs, root);
315
+ files = await openInstalledSourceFiles(this.host.fs, root);
217
316
  return root;
218
317
  },
219
318
  readText: (path) => requireFiles().readText(path),
@@ -245,6 +344,42 @@ var DshStudioManagementService = class extends TypertRemoteService {
245
344
  return result;
246
345
  });
247
346
  }
347
+ /** List all authored files of one exact installed Kit, including kit.yaml. */
348
+ readKitFiles(name, version) {
349
+ return this.run(async () => {
350
+ const { root, files } = await this.kitFiles(name, version);
351
+ return files.listFiles(root);
352
+ });
353
+ }
354
+ /** Read one root-confined Kit file as bounded UTF-8 text. */
355
+ readKitFile(name, version, path) {
356
+ return this.run(async () => (await this.kitFiles(name, version)).files.readFile(path));
357
+ }
358
+ async kitFiles(name, version) {
359
+ if (typeof name !== "string" || !name || typeof version !== "string" || !version) throw kitFileError("workspace.version_missing", "An exact Kit name and version are required.");
360
+ let exactVersion;
361
+ try {
362
+ exactVersion = DesignKitVersion(version);
363
+ } catch {
364
+ throw kitFileError("workspace.version_missing", "An exact Kit major.minor version is required.");
365
+ }
366
+ const kit = typeof this.host.design.resolveKit === "function" ? this.host.design.resolveKit({
367
+ kit: name,
368
+ version: exactVersion
369
+ }) : this.host.design.listKits().find((candidate) => candidate.name === name && candidate.version === version);
370
+ if (!kit || kit.name !== name || kit.version !== version) throw kitFileError("workspace.version_missing", `Kit ${JSON.stringify(name)}@${JSON.stringify(version)} is not installed.`);
371
+ const configured = this.configuredKitRoots.get(`${name}\0${version}`);
372
+ const root = this.config.followInstalledSources ? kit.sourceRoot ?? configured : configured;
373
+ if (!root) throw kitFileError("studio.source_not_configured", `No source root is configured for Kit ${JSON.stringify(name)}@${JSON.stringify(version)}.`);
374
+ try {
375
+ return {
376
+ root,
377
+ files: await openInstalledSourceFiles(this.host.fs, root, "Kit")
378
+ };
379
+ } catch (error) {
380
+ throw kitFileError("studio.source_unavailable", `Kit source is unavailable; the process may retain last-good content: ${String(error)}`);
381
+ }
382
+ }
248
383
  /** Read one Bundle's read-only source workspace. */
249
384
  readBundleWorkspace(name, version) {
250
385
  return this.run(async () => {
@@ -289,62 +424,6 @@ var DshStudioManagementService = class extends TypertRemoteService {
289
424
  return result;
290
425
  }
291
426
  };
292
- /** One read's installed resource root is the complete filesystem boundary, not its catalog id. */
293
- async function openInstalledBundleFiles(fs, root) {
294
- if (!isAbsolute(root)) throw new Error("design studio dsh: installed Bundle resource root must be absolute");
295
- const base = await fs.resolve(root);
296
- if ((await fs.stat(base))?.type !== "directory") throw new Error("design studio dsh: installed Bundle resource root is not a directory");
297
- const target = async (path) => {
298
- const resolved = await fs.resolve(path);
299
- if (!fs.contains(base, resolved)) throw new Error("design studio dsh: path escapes installed Bundle resource root");
300
- return resolved;
301
- };
302
- const code = (error) => typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
303
- return {
304
- listKitRoots: async () => [],
305
- async readText(path) {
306
- try {
307
- return await fs.readText(await target(path));
308
- } catch (error) {
309
- if (code(error) === "FS_NOT_FOUND") return void 0;
310
- if (code(error) === "FS_NOT_TEXT") throw new StudioBinaryContentError(path);
311
- throw error;
312
- }
313
- },
314
- async listDir(path) {
315
- try {
316
- return (await fs.listDir(await target(path))).map((entry) => entry.name);
317
- } catch (error) {
318
- if (code(error) === "FS_NOT_FOUND" || code(error) === "FS_NOT_DIRECTORY") return [];
319
- throw error;
320
- }
321
- },
322
- async isDirectory(path) {
323
- try {
324
- return (await fs.stat(await target(path)))?.type === "directory";
325
- } catch (error) {
326
- if (code(error) === "FS_NOT_FOUND") return false;
327
- throw error;
328
- }
329
- },
330
- async listFiles(path) {
331
- const files = [];
332
- let visited = 0;
333
- const walk = async (directory, prefix, depth) => {
334
- if (depth > 32) throw new Error("design studio dsh: Bundle file tree exceeds depth limit");
335
- for (const entry of await fs.listDir(directory)) {
336
- if (++visited > 2e4) throw new Error("design studio dsh: Bundle file tree exceeds entry limit");
337
- if (!fs.contains(base, entry.target)) continue;
338
- const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
339
- if (entry.type === "directory") await walk(entry.target, relative, depth + 1);
340
- else if (entry.type === "file") files.push(relative);
341
- }
342
- };
343
- await walk(await target(path), "", 0);
344
- return files.sort();
345
- }
346
- };
347
- }
348
427
  function sourceNotConfigured(name) {
349
428
  return Object.freeze({ diagnostics: Object.freeze([Object.freeze({
350
429
  code: "studio.source_not_configured",
@@ -372,6 +451,8 @@ function markRemote(name, method) {
372
451
  }
373
452
  markRemote("workspace", DshStudioManagementService.prototype.workspace);
374
453
  markRemote("readKitWorkspace", DshStudioManagementService.prototype.readKitWorkspace);
454
+ markRemote("readKitFiles", DshStudioManagementService.prototype.readKitFiles);
455
+ markRemote("readKitFile", DshStudioManagementService.prototype.readKitFile);
375
456
  markRemote("readBundleWorkspace", DshStudioManagementService.prototype.readBundleWorkspace);
376
457
  markRemote("readBundleFile", DshStudioManagementService.prototype.readBundleFile);
377
458
  //#endregion