Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/commands/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@ import { MANIFEST_FILE, collectManifestVariables, loadTemplateManifest, type Tem

export type TemplateIndexEntry = {
code: string; version: string; name: string; tagline?: string; category?: string
requiredVarCount?: number; deployCount?: number
maintainer?: string; totalProjects?: number; successRate?: number | null
}

// One aligned row per template; numeric columns right-aligned. Plain padded columns, as the rest
// of the CLI (storage list, compute check-domain) — no table library.
export function templateListLines(templates: TemplateIndexEntry[]): string[] {
if (!templates.length) return ['(no templates published yet)']
const head = ['CODE', 'VERSION', 'CATEGORY', 'VARS', 'DEPLOYS', 'NAME']
const head = ['CODE', 'VERSION', 'CATEGORY', 'PROJECTS', 'SUCCESS', 'NAME']
const numeric = [false, false, false, true, true, false]
const rows = templates.map((t) => [
t.code, t.version ?? '', t.category ?? '-',
String(t.requiredVarCount ?? 0), String(t.deployCount ?? 0),
String(t.totalProjects ?? 0),
// null = nothing has concluded yet; the platform never sends 0 for that.
t.successRate == null ? '-' : `${t.successRate}%`,
t.tagline ? `${t.name} — ${t.tagline}` : (t.name ?? ''),
])
const widths = head.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i]!.length)))
Expand Down Expand Up @@ -161,11 +163,11 @@ export async function resolveVariables(vars: TemplateVar[], given: Record<string
}

// The platform's machine-readable "you forgot these" answer to the POST (error=missing_variables,
// missing: [{name, key, description}] with a missingVariables alias) — turned back into promptable
// variables. null = some other error, not ours to interpret.
// missing: [{name, key, description}]) — turned back into promptable variables. null = some other
// error, not ours to interpret.
export function missingVariablesFrom(body: any): TemplateVar[] | null {
if ((body?.error ?? body?.code) !== 'missing_variables') return null
const list = body?.missing ?? body?.missingVariables ?? []
const list = body?.missing ?? []
if (!Array.isArray(list)) return []
return list.map((v: any) => ({ name: String(v.name ?? v.key ?? v), required: true, description: v.description }))
}
Expand Down
14 changes: 7 additions & 7 deletions test/template.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,12 @@ describe('collectManifestVariables', () => {
describe('templateListLines', () => {
it('renders an aligned table with numeric columns right-aligned', () => {
const lines = templateListLines([
{ code: 'plausible', version: '2.1.1', name: 'Plausible', tagline: 'web analytics', category: 'analytics', requiredVarCount: 1, deployCount: 120 },
{ code: 'n8n', version: '1.64.0', name: 'n8n', category: 'automation', requiredVarCount: 0, deployCount: 7 },
{ code: 'plausible', version: '2.1.1', name: 'Plausible', tagline: 'web analytics', category: 'analytics', totalProjects: 120, successRate: 79 },
{ code: 'n8n', version: '1.64.0', name: 'n8n', category: 'automation', totalProjects: 7, successRate: null },
])
expect(lines[0]).toMatch(/^CODE\s+VERSION\s+CATEGORY\s+VARS\s+DEPLOYS\s+NAME$/)
expect(lines[1]).toBe('plausible 2.1.1 analytics 1 120 Plausible — web analytics')
expect(lines[2]).toBe('n8n 1.64.0 automation 0 7 n8n')
expect(lines[0]).toMatch(/^CODE\s+VERSION\s+CATEGORY\s+PROJECTS\s+SUCCESS\s+NAME$/)
expect(lines[1]).toBe('plausible 2.1.1 analytics 120 79% Plausible — web analytics')
expect(lines[2]).toBe('n8n 1.64.0 automation 7 - n8n')
})
it('says so when the registry is empty', () => {
expect(templateListLines([])).toEqual(['(no templates published yet)'])
Expand Down Expand Up @@ -324,10 +324,10 @@ describe('resolveVariables', () => {
})

describe('missingVariablesFrom', () => {
it('extracts the platform missing_variables payload (and its alias key)', () => {
it('extracts the platform missing_variables payload', () => {
expect(missingVariablesFrom({ error: 'missing_variables', missing: [{ name: 'A', key: 'A', description: 'a' }] }))
.toEqual([{ name: 'A', required: true, description: 'a' }])
expect(missingVariablesFrom({ error: 'missing_variables', missingVariables: [{ name: 'B', key: 'B' }] }))
expect(missingVariablesFrom({ error: 'missing_variables', missing: [{ name: 'B', key: 'B' }] }))
.toEqual([{ name: 'B', required: true, description: undefined }])
})
it('leaves other errors alone', () => {
Expand Down
Loading