mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Simplify Svelte accept orchestration
Unify Svelte component accept and discard around one operation dispatch, source lock, error path, and result emission while preserving their existing CLI contracts. Add direct CLI characterization coverage for both operations.\n\nAI-assisted implementation under pbakaus's scheduled-refactor authorization.
This commit is contained in:
@@ -170,51 +170,35 @@ Output (JSON):
|
||||
}
|
||||
|
||||
if (svelteComponentManifest) {
|
||||
if (isDiscard) {
|
||||
let result;
|
||||
try {
|
||||
result = withSourceLockSync(
|
||||
path.resolve(process.cwd(), svelteComponentManifest.sourceFile),
|
||||
'discard:' + id,
|
||||
() => {
|
||||
removeSvelteComponentSession(id, process.cwd());
|
||||
return { handled: true };
|
||||
},
|
||||
{ waitMs: ACCEPT_LOCK_WAIT_MS },
|
||||
);
|
||||
} catch (err) {
|
||||
result = operationFailure(err);
|
||||
}
|
||||
emitResult({
|
||||
...result,
|
||||
file: svelteComponentManifest.sourceFile,
|
||||
carbonize: false,
|
||||
previewMode: 'svelte-component',
|
||||
componentDir: svelteComponentManifest.componentDir,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = withSourceLockSync(
|
||||
path.resolve(process.cwd(), svelteComponentManifest.sourceFile),
|
||||
'accept:' + id,
|
||||
() => inlineSvelteComponentAccept(
|
||||
const { sourceFile, componentDir } = svelteComponentManifest;
|
||||
const resultContext = {
|
||||
file: sourceFile,
|
||||
...(isDiscard ? { carbonize: false } : { sourceFile }),
|
||||
previewMode: 'svelte-component',
|
||||
componentDir,
|
||||
};
|
||||
const runOperation = isDiscard
|
||||
? () => {
|
||||
removeSvelteComponentSession(id, process.cwd());
|
||||
return { handled: true, ...resultContext };
|
||||
}
|
||||
: () => inlineSvelteComponentAccept(
|
||||
svelteComponentManifest,
|
||||
variantNum,
|
||||
paramValues,
|
||||
process.cwd(),
|
||||
),
|
||||
);
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = withSourceLockSync(
|
||||
path.resolve(process.cwd(), sourceFile),
|
||||
requestedOperation + ':' + id,
|
||||
runOperation,
|
||||
{ waitMs: ACCEPT_LOCK_WAIT_MS },
|
||||
);
|
||||
} catch (err) {
|
||||
result = operationFailure(err, {
|
||||
file: svelteComponentManifest.sourceFile,
|
||||
sourceFile: svelteComponentManifest.sourceFile,
|
||||
previewMode: 'svelte-component',
|
||||
componentDir: svelteComponentManifest.componentDir,
|
||||
});
|
||||
result = operationFailure(err, resultContext);
|
||||
}
|
||||
if (result.carbonize) {
|
||||
result.todo = 'REQUIRED before next poll: carbonize cleanup in ' + result.file + '. See reference/live.md "Required after accept".';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { describe, it, beforeEach, afterEach } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { cpSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync, symlinkSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { join, dirname, resolve } from 'node:path';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import {
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const REPO_NODE_MODULES = join(__dirname, '..', 'node_modules');
|
||||
const ACCEPT = resolve(__dirname, '..', 'skill/scripts/live-accept.mjs');
|
||||
|
||||
const ROUTE_SOURCE = `<script>
|
||||
let stages = [
|
||||
@@ -54,6 +56,14 @@ function write(root, rel, content) {
|
||||
writeFileSync(abs, content);
|
||||
}
|
||||
|
||||
function runAccept(cwd, args) {
|
||||
const output = execFileSync(process.execPath, [ACCEPT, ...args], {
|
||||
cwd,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
return JSON.parse(output.trim());
|
||||
}
|
||||
|
||||
describe('svelte component scaffold + accept pipeline', () => {
|
||||
let tmp;
|
||||
|
||||
@@ -105,6 +115,50 @@ describe('svelte component scaffold + accept pipeline', () => {
|
||||
assert.match(v1, /border-top: 1px solid #333/);
|
||||
});
|
||||
|
||||
it('accepts a Svelte component session through the CLI', () => {
|
||||
const session = scaffold('cliacc1');
|
||||
write(tmp, join(session.componentDir, 'v1.svelte'), `<script>
|
||||
let { stages = [] } = $props();
|
||||
</script>
|
||||
|
||||
<ol class="accepted-board">
|
||||
{#each stages as stage, i}
|
||||
<li class="stage">
|
||||
<span class="label">{stage.label}</span>
|
||||
<p class="detail">{stage.detail}</p>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
|
||||
<style>
|
||||
.accepted-board { display: grid; }
|
||||
</style>
|
||||
`);
|
||||
|
||||
const result = runAccept(tmp, ['--id', 'cliacc1', '--variant', '1']);
|
||||
assert.equal(result.handled, true, result.error);
|
||||
assert.equal(result.file, 'src/routes/+page.svelte');
|
||||
assert.equal(result.previewMode, 'svelte-component');
|
||||
assert.equal(result.componentDir, session.componentDir);
|
||||
assert.match(readFileSync(join(tmp, result.file), 'utf-8'), /class="[^"]*\baccepted-board\b/);
|
||||
assert.equal(findSvelteComponentManifest('cliacc1', tmp), null);
|
||||
});
|
||||
|
||||
it('discards a Svelte component session through the CLI', () => {
|
||||
const session = scaffold('clidisc1');
|
||||
|
||||
const result = runAccept(tmp, ['--id', 'clidisc1', '--discard']);
|
||||
assert.deepEqual(result, {
|
||||
handled: true,
|
||||
file: 'src/routes/+page.svelte',
|
||||
carbonize: false,
|
||||
previewMode: 'svelte-component',
|
||||
componentDir: session.componentDir,
|
||||
});
|
||||
assert.equal(readFileSync(join(tmp, result.file), 'utf-8'), ROUTE_SOURCE);
|
||||
assert.equal(findSvelteComponentManifest('clidisc1', tmp), null);
|
||||
});
|
||||
|
||||
it('falls back to source-preview for markup with component tags', () => {
|
||||
const res = scaffoldSvelteComponentSession({
|
||||
id: 'fallb1',
|
||||
|
||||
Reference in New Issue
Block a user