sh3-core 0.3.0 → 0.3.1

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.
@@ -24,6 +24,7 @@
24
24
  const layout = $derived(inspectActiveLayout());
25
25
  const regShards = $derived(Array.from(registeredShards.values()));
26
26
  const actShards = $derived(Array.from(activeShards.keys()));
27
+
27
28
  </script>
28
29
 
29
30
  <div class="diagnostic">
@@ -68,6 +69,7 @@
68
69
  {/each}
69
70
  </ul>
70
71
  </section>
72
+
71
73
  </div>
72
74
 
73
75
  <style>
@@ -0,0 +1,99 @@
1
+ <script lang="ts">
2
+ /*
3
+ * Diagnostic routes view — lists all server API routes.
4
+ *
5
+ * Fetches the route table from GET /api/routes. GET routes render
6
+ * as clickable links for quick testing of parameterless endpoints.
7
+ */
8
+
9
+ interface ApiRoute { method: string; path: string; }
10
+ let routes: ApiRoute[] = $state([]);
11
+ let error: string | null = $state(null);
12
+
13
+ async function fetchRoutes() {
14
+ try {
15
+ const res = await fetch('/api/routes');
16
+ if (!res.ok) { error = `${res.status}`; return; }
17
+ routes = await res.json();
18
+ error = null;
19
+ } catch {
20
+ error = 'unavailable';
21
+ }
22
+ }
23
+
24
+ fetchRoutes();
25
+ </script>
26
+
27
+ <div class="diagnostic">
28
+ <h2>API Routes</h2>
29
+
30
+ {#if error}
31
+ <p class="muted">Server not reachable or route introspection unavailable ({error}).</p>
32
+ {:else}
33
+ <p class="muted">{routes.length} unique routes</p>
34
+ <ul>
35
+ {#each routes as route}
36
+ <li>
37
+ <span class="method" class:get={route.method === 'GET'}>{route.method}</span>
38
+ {#if route.method === 'GET'}
39
+ <a href={route.path} target="_blank" rel="noopener">{route.path}</a>
40
+ {:else}
41
+ <span class="path">{route.path}</span>
42
+ {/if}
43
+ </li>
44
+ {/each}
45
+ </ul>
46
+ {/if}
47
+ </div>
48
+
49
+ <style>
50
+ .diagnostic {
51
+ position: absolute;
52
+ inset: 0;
53
+ padding: 12px 16px;
54
+ overflow: auto;
55
+ background: var(--shell-bg);
56
+ color: var(--shell-fg);
57
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
58
+ font-size: 12px;
59
+ }
60
+ h2 {
61
+ margin: 0 0 12px;
62
+ color: var(--shell-accent);
63
+ font-size: 14px;
64
+ }
65
+ .muted {
66
+ color: var(--shell-fg-muted);
67
+ margin: 0 0 8px;
68
+ }
69
+ ul {
70
+ margin: 0;
71
+ padding: 0;
72
+ list-style: none;
73
+ }
74
+ li {
75
+ margin: 0;
76
+ padding: 2px 0;
77
+ display: flex;
78
+ align-items: baseline;
79
+ gap: 8px;
80
+ }
81
+ .method {
82
+ min-width: 6ch;
83
+ color: var(--shell-fg-muted);
84
+ flex-shrink: 0;
85
+ }
86
+ .method.get {
87
+ color: var(--shell-accent);
88
+ }
89
+ a {
90
+ color: var(--shell-accent);
91
+ text-decoration: none;
92
+ }
93
+ a:hover {
94
+ text-decoration: underline;
95
+ }
96
+ .path {
97
+ color: var(--shell-fg);
98
+ }
99
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const DiagnosticRoutes: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type DiagnosticRoutes = ReturnType<typeof DiagnosticRoutes>;
3
+ export default DiagnosticRoutes;
@@ -19,6 +19,7 @@ export const diagnosticApp = {
19
19
  activeTab: 0,
20
20
  tabs: [
21
21
  { slotId: 'diagnostic.main', viewId: 'diagnostic:panel', label: 'Diagnostic' },
22
+ { slotId: 'diagnostic.routes', viewId: 'diagnostic:routes', label: 'API Routes' },
22
23
  ],
23
24
  },
24
25
  };
@@ -25,6 +25,7 @@
25
25
  */
26
26
  import { mount, unmount } from 'svelte';
27
27
  import DiagnosticPanel from './DiagnosticPanel.svelte';
28
+ import DiagnosticRoutes from './DiagnosticRoutes.svelte';
28
29
  import DiagnosticPromptModal from './DiagnosticPromptModal.svelte';
29
30
  import { shell, getActiveApp, spliceIntoActiveLayout, inspectActiveLayout, } from '../api';
30
31
  export const diagnosticShard = {
@@ -32,7 +33,10 @@ export const diagnosticShard = {
32
33
  id: 'diagnostic',
33
34
  label: 'Diagnostic',
34
35
  version: '0.1.0',
35
- views: [{ id: 'diagnostic:panel', label: 'Diagnostic' }],
36
+ views: [
37
+ { id: 'diagnostic:panel', label: 'Diagnostic' },
38
+ { id: 'diagnostic:routes', label: 'API Routes' },
39
+ ],
36
40
  },
37
41
  activate(ctx) {
38
42
  const factory = {
@@ -46,6 +50,17 @@ export const diagnosticShard = {
46
50
  },
47
51
  };
48
52
  ctx.registerView('diagnostic:panel', factory);
53
+ const routesFactory = {
54
+ mount(container, _context) {
55
+ const instance = mount(DiagnosticRoutes, { target: container });
56
+ return {
57
+ unmount() {
58
+ unmount(instance);
59
+ },
60
+ };
61
+ },
62
+ };
63
+ ctx.registerView('diagnostic:routes', routesFactory);
49
64
  },
50
65
  autostart(ctx) {
51
66
  const state = ctx.state({
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * A server shard is the optional backend counterpart to a client shard.
5
5
  * It runs in Node inside sh3-server and declares routes that are mounted
6
- * under `/s/<shard-id>/`. Server shards have full Node access — filesystem,
6
+ * under `/api/<shard-id>/`. Server shards have full Node access — filesystem,
7
7
  * child_process, network, etc. — and are trusted by the admin who installed
8
8
  * them.
9
9
  *
@@ -39,8 +39,8 @@ export interface ServerShard {
39
39
  id: string;
40
40
  /**
41
41
  * Called once at mount time. Register Hono routes on the provided router.
42
- * Routes are relative to `/s/<shard-id>/` — e.g. `router.get('/data', ...)`
43
- * becomes `GET /s/<shard-id>/data`.
42
+ * Routes are relative to `/api/<shard-id>/` — e.g. `router.get('/data', ...)`
43
+ * becomes `GET /api/<shard-id>/data`.
44
44
  *
45
45
  * May be async if the shard needs to initialise resources before serving.
46
46
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * A server shard is the optional backend counterpart to a client shard.
5
5
  * It runs in Node inside sh3-server and declares routes that are mounted
6
- * under `/s/<shard-id>/`. Server shards have full Node access — filesystem,
6
+ * under `/api/<shard-id>/`. Server shards have full Node access — filesystem,
7
7
  * child_process, network, etc. — and are trusted by the admin who installed
8
8
  * them.
9
9
  *
@@ -98,7 +98,7 @@ export interface ShardManifest {
98
98
  /**
99
99
  * Optional filename of a server-side bundle for this shard. When present,
100
100
  * sh3-server loads the bundle at boot and mounts its routes at
101
- * `/s/<shard-id>/`. The server bundle runs in Node with full access.
101
+ * `/api/<shard-id>/`. The server bundle runs in Node with full access.
102
102
  * Only relevant for shards installed via the package store; framework-
103
103
  * shipped shards do not use this field.
104
104
  */
@@ -97,7 +97,7 @@
97
97
  <section class="shell-home-section">
98
98
  <h2 class="shell-home-section-title">Admin Mode</h2>
99
99
  <p class="shell-home-elevate-hint">
100
- Enter an API key to access admin apps like the Package Store.
100
+ Elevate Permissions
101
101
  </p>
102
102
  <form class="shell-home-elevate-form" onsubmit={(e) => { e.preventDefault(); handleElevate(); }}>
103
103
  <input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh3-core",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"