feat(v1.1.3-modules): dashboard kind dropdown + scripts-list and detail badges
- `Script` type gains `kind: 'endpoint' | 'module'`. `CreateScriptInput` + `UpdateScriptInput` carry an optional `kind` field. - App page's script-create form grows a kind dropdown next to Name + Description. Selecting "module" surfaces a hint that modules cannot bind to routes / triggers. - Scripts list renders a small badge after the version: blue "endpoint" or purple "module". - Script detail page renders the same badge next to the H1. `npm run check` passes (0 errors, 0 warnings). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,8 @@ export interface ScriptSandbox {
|
|||||||
max_expr_depth?: number;
|
max_expr_depth?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ScriptKind = 'endpoint' | 'module';
|
||||||
|
|
||||||
export interface Script {
|
export interface Script {
|
||||||
id: string;
|
id: string;
|
||||||
app_id: string;
|
app_id: string;
|
||||||
@@ -28,6 +30,8 @@ export interface Script {
|
|||||||
description: string | null;
|
description: string | null;
|
||||||
version: number;
|
version: number;
|
||||||
source: string;
|
source: string;
|
||||||
|
/** v1.1.3 — 'endpoint' (default) handles routes/triggers; 'module' is imported by other scripts. */
|
||||||
|
kind: ScriptKind;
|
||||||
timeout_seconds: number;
|
timeout_seconds: number;
|
||||||
memory_limit_mb: number;
|
memory_limit_mb: number;
|
||||||
sandbox: ScriptSandbox;
|
sandbox: ScriptSandbox;
|
||||||
@@ -173,6 +177,8 @@ export interface CreateScriptInput {
|
|||||||
name: string;
|
name: string;
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
source: string;
|
source: string;
|
||||||
|
/** Defaults to 'endpoint' server-side if omitted. v1.1.3. */
|
||||||
|
kind?: ScriptKind;
|
||||||
timeout_seconds?: number;
|
timeout_seconds?: number;
|
||||||
memory_limit_mb?: number;
|
memory_limit_mb?: number;
|
||||||
}
|
}
|
||||||
@@ -184,6 +190,8 @@ export interface UpdateScriptInput {
|
|||||||
timeout_seconds?: number;
|
timeout_seconds?: number;
|
||||||
memory_limit_mb?: number;
|
memory_limit_mb?: number;
|
||||||
sandbox?: ScriptSandbox;
|
sandbox?: ScriptSandbox;
|
||||||
|
/** v1.1.3 — endpoint→module rejected if routes/triggers reference the script. */
|
||||||
|
kind?: ScriptKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeadLetterRow {
|
export interface DeadLetterRow {
|
||||||
|
|||||||
@@ -63,6 +63,10 @@
|
|||||||
let createScriptName = $state('');
|
let createScriptName = $state('');
|
||||||
let createScriptDescription = $state('');
|
let createScriptDescription = $state('');
|
||||||
let createScriptSource = $state(SAMPLE_SOURCE);
|
let createScriptSource = $state(SAMPLE_SOURCE);
|
||||||
|
// v1.1.3: endpoint (default — handles routes/triggers) vs module
|
||||||
|
// (library imported by other scripts). Modules cannot be bound to
|
||||||
|
// routes or used as trigger targets.
|
||||||
|
let createScriptKind = $state<'endpoint' | 'module'>('endpoint');
|
||||||
let creatingScript = $state(false);
|
let creatingScript = $state(false);
|
||||||
let createScriptError = $state<string | null>(null);
|
let createScriptError = $state<string | null>(null);
|
||||||
|
|
||||||
@@ -201,12 +205,14 @@
|
|||||||
app_id: app.id,
|
app_id: app.id,
|
||||||
name: createScriptName.trim(),
|
name: createScriptName.trim(),
|
||||||
description: createScriptDescription.trim() || null,
|
description: createScriptDescription.trim() || null,
|
||||||
source: createScriptSource
|
source: createScriptSource,
|
||||||
|
kind: createScriptKind
|
||||||
});
|
});
|
||||||
showCreateScript = false;
|
showCreateScript = false;
|
||||||
createScriptName = '';
|
createScriptName = '';
|
||||||
createScriptDescription = '';
|
createScriptDescription = '';
|
||||||
createScriptSource = SAMPLE_SOURCE;
|
createScriptSource = SAMPLE_SOURCE;
|
||||||
|
createScriptKind = 'endpoint';
|
||||||
await loadScripts(app.id);
|
await loadScripts(app.id);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
createScriptError = e instanceof Error ? e.message : String(e);
|
createScriptError = e instanceof Error ? e.message : String(e);
|
||||||
@@ -473,6 +479,13 @@
|
|||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<input bind:value={createScriptName} required placeholder="echo" />
|
<input bind:value={createScriptName} required placeholder="echo" />
|
||||||
</label>
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Kind</span>
|
||||||
|
<select bind:value={createScriptKind}>
|
||||||
|
<option value="endpoint">Endpoint (handles HTTP / triggers)</option>
|
||||||
|
<option value="module">Module (imported by other scripts)</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span>Description</span>
|
<span>Description</span>
|
||||||
<input bind:value={createScriptDescription} placeholder="optional" />
|
<input bind:value={createScriptDescription} placeholder="optional" />
|
||||||
@@ -482,6 +495,13 @@
|
|||||||
<span>Source (Rhai)</span>
|
<span>Source (Rhai)</span>
|
||||||
<CodeEditor bind:value={createScriptSource} language="rhai" minHeight="14rem" />
|
<CodeEditor bind:value={createScriptSource} language="rhai" minHeight="14rem" />
|
||||||
</label>
|
</label>
|
||||||
|
{#if createScriptKind === 'module'}
|
||||||
|
<p class="muted small">
|
||||||
|
Modules expose <code>fn</code> and <code>const</code> declarations to other
|
||||||
|
scripts via <code>import "name" as alias;</code>. They cannot be bound to
|
||||||
|
routes or used as trigger targets.
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
{#if createScriptError}
|
{#if createScriptError}
|
||||||
<div class="error">{createScriptError}</div>
|
<div class="error">{createScriptError}</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -503,6 +523,11 @@
|
|||||||
<div class="primary">
|
<div class="primary">
|
||||||
<strong>{script.name}</strong>
|
<strong>{script.name}</strong>
|
||||||
<span class="muted">v{script.version}</span>
|
<span class="muted">v{script.version}</span>
|
||||||
|
{#if script.kind === 'module'}
|
||||||
|
<span class="kind-badge kind-module" title="Library imported by other scripts">module</span>
|
||||||
|
{:else}
|
||||||
|
<span class="kind-badge kind-endpoint" title="Handles HTTP routes and trigger events">endpoint</span>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="secondary muted">{script.description ?? '—'}</div>
|
<div class="secondary muted">{script.description ?? '—'}</div>
|
||||||
</a>
|
</a>
|
||||||
@@ -1154,4 +1179,30 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kind-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 0.45rem;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kind-endpoint {
|
||||||
|
background: #1e3a5f;
|
||||||
|
color: #93c5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kind-module {
|
||||||
|
background: #3f2e7d;
|
||||||
|
color: #c4b5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -433,7 +433,14 @@
|
|||||||
<code>{script.name}</code>
|
<code>{script.name}</code>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<h1>{script.name}</h1>
|
<h1>
|
||||||
|
{script.name}
|
||||||
|
{#if script.kind === 'module'}
|
||||||
|
<span class="kind-badge kind-module" title="Library imported by other scripts">module</span>
|
||||||
|
{:else}
|
||||||
|
<span class="kind-badge kind-endpoint" title="Handles HTTP routes and trigger events">endpoint</span>
|
||||||
|
{/if}
|
||||||
|
</h1>
|
||||||
<p class="muted">
|
<p class="muted">
|
||||||
v{script.version} · timeout {script.timeout_seconds}s · {script.description ?? 'no description'}
|
v{script.version} · timeout {script.timeout_seconds}s · {script.description ?? 'no description'}
|
||||||
</p>
|
</p>
|
||||||
@@ -1323,4 +1330,27 @@
|
|||||||
margin: 0.25rem 0 0 4rem;
|
margin: 0.25rem 0 0 4rem;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kind-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 0.45rem;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.65rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
line-height: 1.5;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kind-endpoint {
|
||||||
|
background: #1e3a5f;
|
||||||
|
color: #93c5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kind-module {
|
||||||
|
background: #3f2e7d;
|
||||||
|
color: #c4b5fd;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user