@parlor/scaffold 0.0.0-stage → 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.
- package/LICENSE +21 -0
- package/README.md +11 -2
- package/dist/add/addon.d.ts +101 -0
- package/dist/add/addon.d.ts.map +1 -0
- package/dist/add/addon.js +6 -0
- package/dist/add/addon.js.map +1 -0
- package/dist/add/plan.d.ts +72 -0
- package/dist/add/plan.d.ts.map +1 -0
- package/dist/add/plan.js +237 -0
- package/dist/add/plan.js.map +1 -0
- package/dist/add/run.d.ts +92 -0
- package/dist/add/run.d.ts.map +1 -0
- package/dist/add/run.js +167 -0
- package/dist/add/run.js.map +1 -0
- package/dist/add/transaction.d.ts +67 -0
- package/dist/add/transaction.d.ts.map +1 -0
- package/dist/add/transaction.js +181 -0
- package/dist/add/transaction.js.map +1 -0
- package/dist/addons/agent.d.ts +61 -0
- package/dist/addons/agent.d.ts.map +1 -0
- package/dist/addons/agent.js +50 -0
- package/dist/addons/agent.js.map +1 -0
- package/dist/addons/auth.d.ts +106 -0
- package/dist/addons/auth.d.ts.map +1 -0
- package/dist/addons/auth.js +93 -0
- package/dist/addons/auth.js.map +1 -0
- package/dist/addons/index.d.ts +165 -0
- package/dist/addons/index.d.ts.map +1 -0
- package/dist/addons/index.js +8 -0
- package/dist/addons/index.js.map +1 -0
- package/dist/catalog.d.ts +3 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +23 -0
- package/dist/catalog.js.map +1 -0
- package/dist/create.d.ts +45 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +162 -0
- package/dist/create.js.map +1 -0
- package/dist/docs.d.ts +12 -0
- package/dist/docs.d.ts.map +1 -0
- package/dist/docs.js +66 -0
- package/dist/docs.js.map +1 -0
- package/dist/edit/inspect.d.ts +15 -0
- package/dist/edit/inspect.d.ts.map +1 -0
- package/dist/edit/inspect.js +73 -0
- package/dist/edit/inspect.js.map +1 -0
- package/dist/edit/ops.d.ts +92 -0
- package/dist/edit/ops.d.ts.map +1 -0
- package/dist/edit/ops.js +516 -0
- package/dist/edit/ops.js.map +1 -0
- package/dist/edit/source.d.ts +24 -0
- package/dist/edit/source.d.ts.map +1 -0
- package/dist/edit/source.js +36 -0
- package/dist/edit/source.js.map +1 -0
- package/dist/edit/syntax.d.ts +34 -0
- package/dist/edit/syntax.d.ts.map +1 -0
- package/dist/edit/syntax.js +114 -0
- package/dist/edit/syntax.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +5 -0
- package/dist/errors.js.map +1 -0
- package/dist/files.d.ts +15 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +65 -0
- package/dist/files.js.map +1 -0
- package/dist/fixtures.d.ts +28 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +66 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/git.d.ts +22 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +56 -0
- package/dist/git.js.map +1 -0
- package/dist/identity.d.ts +9 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +23 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/package-manager.d.ts +49 -0
- package/dist/package-manager.d.ts.map +1 -0
- package/dist/package-manager.js +118 -0
- package/dist/package-manager.js.map +1 -0
- package/dist/version.d.ts +6 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +9 -0
- package/dist/version.js.map +1 -0
- package/package.json +46 -3
- package/templates/auth/auth.ts +20 -0
- package/templates/auth/schema/auth.ts +1 -0
- package/templates/auth/src/auth/client.ts +3 -0
- package/templates/auth/src/auth/sign-in-gate.tsx +17 -0
- package/templates/auth/src/auth/sign-out-button.tsx +17 -0
- package/templates/auth/src/routes/link.tsx +92 -0
- package/templates/auth/src/routes/sign-in.tsx +117 -0
- package/templates/default/_gitignore +7 -0
- package/templates/default/actions/index.ts +58 -0
- package/templates/default/actions/todos.spec.ts +38 -0
- package/templates/default/index.html +13 -0
- package/templates/default/migrations/0000_init.sql +9 -0
- package/templates/default/migrations/meta/0000_snapshot.json +87 -0
- package/templates/default/migrations/meta/_journal.json +13 -0
- package/templates/default/package.json +44 -0
- package/templates/default/parlor.config.ts +12 -0
- package/templates/default/schema/index.ts +1 -0
- package/templates/default/schema/todos.ts +13 -0
- package/templates/default/server.ts +13 -0
- package/templates/default/src/agent/agent-button.tsx +120 -0
- package/templates/default/src/agent/agent-sidebar.tsx +821 -0
- package/templates/default/src/agent/agent.css +5 -0
- package/templates/default/src/agent/confirmation-card.tsx +42 -0
- package/templates/default/src/agent/sidebar-view.ts +36 -0
- package/templates/default/src/agent/views.ts +9 -0
- package/templates/default/src/app.css +1 -0
- package/templates/default/src/header-actions.tsx +9 -0
- package/templates/default/src/main.tsx +24 -0
- package/templates/default/src/parlor.d.ts +9 -0
- package/templates/default/src/routeTree.gen.ts +59 -0
- package/templates/default/src/routes/__root.tsx +28 -0
- package/templates/default/src/routes/index.tsx +136 -0
- package/templates/default/tsconfig.json +8 -0
- package/templates/default/vitest.config.ts +5 -0
package/dist/docs.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AppIdentity } from "./identity.js";
|
|
2
|
+
import { type PackageManager } from "./package-manager.js";
|
|
3
|
+
export interface ProjectDocsInput {
|
|
4
|
+
readonly identity: AppIdentity;
|
|
5
|
+
readonly packageManager: PackageManager;
|
|
6
|
+
readonly version: string;
|
|
7
|
+
}
|
|
8
|
+
/** Rendered per package manager, so every command in it runs as written. */
|
|
9
|
+
export declare function renderReadme({ identity, packageManager }: ProjectDocsInput): string;
|
|
10
|
+
/** Facts a coding agent cannot infer from the files, plus where the full docs are. */
|
|
11
|
+
export declare function renderAgentsMd({ packageManager, version }: ProjectDocsInput): string;
|
|
12
|
+
//# sourceMappingURL=docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,gBAAgB,GAAG,MAAM,CAmCnF;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,gBAAgB,GAAG,MAAM,CAwBpF"}
|
package/dist/docs.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { commandsFor } from "./package-manager.js";
|
|
2
|
+
import { DOCS_URL } from "./version.js";
|
|
3
|
+
/** Rendered per package manager, so every command in it runs as written. */
|
|
4
|
+
export function renderReadme({ identity, packageManager }) {
|
|
5
|
+
const pm = commandsFor(packageManager);
|
|
6
|
+
return `# ${identity.appName}
|
|
7
|
+
|
|
8
|
+
A [Parlor](${DOCS_URL}) app. Everything the UI does goes through actions, so your coding agent
|
|
9
|
+
can do it too: from the sidebar, over MCP, or over HTTP.
|
|
10
|
+
|
|
11
|
+
## Develop
|
|
12
|
+
|
|
13
|
+
\`\`\`sh
|
|
14
|
+
${pm.run("dev")}
|
|
15
|
+
\`\`\`
|
|
16
|
+
|
|
17
|
+
Open http://localhost:5173 and press **Agent** to chat with the coding agent on this computer
|
|
18
|
+
(Claude Code or Codex). Ask it to add a todo.
|
|
19
|
+
|
|
20
|
+
| Command | What it does |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| \`${pm.run("dev")}\` | App, API and agent host with hot reload |
|
|
23
|
+
| \`${pm.run("typecheck")}\` | Regenerate the route tree, then \`tsc\` |
|
|
24
|
+
| \`${pm.run("test")}\` | Vitest |
|
|
25
|
+
| \`${pm.run("db:generate")}\` | A SQL migration from \`schema/\` |
|
|
26
|
+
| \`${pm.run("build")}\` | Production build in \`.parlor/\` |
|
|
27
|
+
| \`${pm.exec("parlor", ["add", "auth"])}\` | Sign-in, so each user sees only their own data |
|
|
28
|
+
| \`${pm.exec("parlor", ["dev", "--target", "mac"])}\` | The same app as a macOS window |
|
|
29
|
+
|
|
30
|
+
## Layout
|
|
31
|
+
|
|
32
|
+
- \`actions/\`: every piece of business logic, as \`defineAction\`. The UI, agents, HTTP and MCP all call these.
|
|
33
|
+
- \`schema/\`: the Drizzle tables; \`migrations/\` is generated from them.
|
|
34
|
+
- \`src/routes/\`: pages. \`src/agent/\`: the agent sidebar, yours to change.
|
|
35
|
+
- \`parlor.config.ts\`: app name, id, ports, and Vite options under \`vite\`.
|
|
36
|
+
|
|
37
|
+
Learn more at ${DOCS_URL}/getting-started/.
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
/** Facts a coding agent cannot infer from the files, plus where the full docs are. */
|
|
41
|
+
export function renderAgentsMd({ packageManager, version }) {
|
|
42
|
+
const pm = commandsFor(packageManager);
|
|
43
|
+
return `# AGENTS.md
|
|
44
|
+
|
|
45
|
+
This is a Parlor ${version} app. Parlor changes faster than your training data: read
|
|
46
|
+
${DOCS_URL}/llms.txt (every page, as Markdown) before changing how the app is wired.
|
|
47
|
+
|
|
48
|
+
## Rules
|
|
49
|
+
|
|
50
|
+
- Business logic lives only in \`actions/\` as \`defineAction\`. The UI calls actions with
|
|
51
|
+
\`useActionQuery\` and \`useActionMutation\` from \`@parlor/client/react\`, never \`fetch\`.
|
|
52
|
+
- Every table has a \`scope\` column and every action filters by \`ctx.scope\`.
|
|
53
|
+
- An action that changes data declares \`writes\`; one that reads declares \`reads\`. That is how
|
|
54
|
+
pages refresh when an agent changes something.
|
|
55
|
+
- After changing \`schema/\`, run \`${pm.run("db:generate")}\` and commit the migration.
|
|
56
|
+
- \`.parlor/\` is generated. Never edit it. There is no \`vite.config.ts\`: Vite options go in the
|
|
57
|
+
\`vite\` field of \`parlor.config.ts\`.
|
|
58
|
+
- Add features with \`${pm.exec("parlor", ["add", "<auth|agent>"])}\` instead of wiring them by hand.
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
- \`${pm.run("dev")}\`: runs until stopped; the app is on http://localhost:5173.
|
|
63
|
+
- \`${pm.run("typecheck")}\` and \`${pm.run("test")}\` must pass before you finish.
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=docs.js.map
|
package/dist/docs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAuB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAQxC,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAoB;IACzE,MAAM,EAAE,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IACvC,OAAO,KAAK,QAAQ,CAAC,OAAO;;aAEjB,QAAQ;;;;;;EAMnB,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;;;;;;;;MAQT,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;MACb,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC;MACnB,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;MACd,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC;MACrB,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;MACf,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;MAClC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;;;;;;;;;gBASnC,QAAQ;CACvB,CAAC;AACF,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,cAAc,CAAC,EAAE,cAAc,EAAE,OAAO,EAAoB;IAC1E,MAAM,EAAE,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IACvC,OAAO;;mBAEU,OAAO;EACxB,QAAQ;;;;;;;;;sCAS4B,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC;;;wBAGnC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;;;;MAI5D,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;MACb,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;CAClD,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type SourceFile } from "./source.js";
|
|
2
|
+
export type Presence = "installed" | "absent" | "unknown";
|
|
3
|
+
/**
|
|
4
|
+
* What the app's server entry passes to `createServer`, read from its syntax without running
|
|
5
|
+
* it. `unknown` when the shape hides it (options built elsewhere, spreads, a plugins variable),
|
|
6
|
+
* so every reader picks the behavior that is safe when it cannot tell.
|
|
7
|
+
*/
|
|
8
|
+
export interface ServerShape {
|
|
9
|
+
readonly auth: Presence;
|
|
10
|
+
readonly chat: Presence;
|
|
11
|
+
}
|
|
12
|
+
export declare const UNKNOWN_SERVER: ServerShape;
|
|
13
|
+
export declare function inspectServer(file: SourceFile): ServerShape;
|
|
14
|
+
export declare function inspectServerEntry(rootDir: string, entry: string): Promise<ServerShape>;
|
|
15
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/edit/inspect.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAU3D,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB;AAED,eAAO,MAAM,cAAc,EAAE,WAAkD,CAAC;AA8ChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAa3D;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,CAAC,CAQtB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseSource } from "./source.js";
|
|
4
|
+
import { findCall, importedName, objectArgument, propertyOf, valueOf, } from "./syntax.js";
|
|
5
|
+
export const UNKNOWN_SERVER = { auth: "unknown", chat: "unknown" };
|
|
6
|
+
const SERVER = { callee: "createServer", from: "@parlor/server" };
|
|
7
|
+
const CHAT = { callee: "chat", from: "@parlor/chat/server" };
|
|
8
|
+
/** A call, or a module-scope `const` bound once to a call; anything conditional is unknown. */
|
|
9
|
+
function authPresence(file, value) {
|
|
10
|
+
if (value.type === "Identifier" && value.name === "undefined")
|
|
11
|
+
return "absent";
|
|
12
|
+
const unwrapped = value.type === "AwaitExpression" ? value.argument : value;
|
|
13
|
+
if (unwrapped.type === "CallExpression" || unwrapped.type === "NewExpression") {
|
|
14
|
+
return "installed";
|
|
15
|
+
}
|
|
16
|
+
if (value.type !== "Identifier")
|
|
17
|
+
return "unknown";
|
|
18
|
+
const declarators = file.ast.program.body.flatMap((statement) => {
|
|
19
|
+
const declaration = statement.type === "ExportNamedDeclaration" ? statement.declaration : statement;
|
|
20
|
+
return declaration?.type === "VariableDeclaration" && declaration.kind === "const"
|
|
21
|
+
? declaration.declarations.filter((declarator) => declarator.id.type === "Identifier" && declarator.id.name === value.name)
|
|
22
|
+
: [];
|
|
23
|
+
});
|
|
24
|
+
const init = declarators.length === 1 ? declarators[0]?.init : undefined;
|
|
25
|
+
const call = init?.type === "AwaitExpression" ? init.argument : init;
|
|
26
|
+
return call?.type === "CallExpression" || call?.type === "NewExpression"
|
|
27
|
+
? "installed"
|
|
28
|
+
: "unknown";
|
|
29
|
+
}
|
|
30
|
+
function chatPresence(file, plugins) {
|
|
31
|
+
if (plugins.type !== "ArrayExpression")
|
|
32
|
+
return "unknown";
|
|
33
|
+
if (plugins.elements.some((element) => element?.type === "SpreadElement"))
|
|
34
|
+
return "unknown";
|
|
35
|
+
const local = importedName(file, CHAT.callee, CHAT.from);
|
|
36
|
+
if (!local)
|
|
37
|
+
return "absent";
|
|
38
|
+
return plugins.elements.some((element) => element?.type === "CallExpression" &&
|
|
39
|
+
element.callee.type === "Identifier" &&
|
|
40
|
+
element.callee.name === local)
|
|
41
|
+
? "installed"
|
|
42
|
+
: "absent";
|
|
43
|
+
}
|
|
44
|
+
export function inspectServer(file) {
|
|
45
|
+
const call = findCall(file, SERVER);
|
|
46
|
+
if (!call.ok)
|
|
47
|
+
return UNKNOWN_SERVER;
|
|
48
|
+
const argument = objectArgument(file, SERVER, call.value);
|
|
49
|
+
if (!argument.ok)
|
|
50
|
+
return UNKNOWN_SERVER;
|
|
51
|
+
if (argument.value.kind === "none")
|
|
52
|
+
return { auth: "absent", chat: "absent" };
|
|
53
|
+
const auth = propertyOf(file, argument.value.node, "auth");
|
|
54
|
+
const plugins = propertyOf(file, argument.value.node, "plugins");
|
|
55
|
+
if (!auth.ok || !plugins.ok)
|
|
56
|
+
return UNKNOWN_SERVER;
|
|
57
|
+
return {
|
|
58
|
+
auth: auth.value ? authPresence(file, valueOf(auth.value)) : "absent",
|
|
59
|
+
chat: plugins.value ? chatPresence(file, valueOf(plugins.value)) : "absent",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export async function inspectServerEntry(rootDir, entry) {
|
|
63
|
+
const text = await readFile(join(rootDir, entry), "utf8").catch(() => undefined);
|
|
64
|
+
if (text === undefined)
|
|
65
|
+
return UNKNOWN_SERVER;
|
|
66
|
+
try {
|
|
67
|
+
return inspectServer(parseSource(entry, text));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return UNKNOWN_SERVER;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=inspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/edit/inspect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type SourceFile, type Splice } from "./source.js";
|
|
2
|
+
import { type CallSite } from "./syntax.js";
|
|
3
|
+
export type { CallSite } from "./syntax.js";
|
|
4
|
+
/**
|
|
5
|
+
* The closed set of code edits. Each one knows how to tell that it is already done, how to
|
|
6
|
+
* make it, and when it is unsafe. Add a kind here, with its tests, instead of editing text
|
|
7
|
+
* anywhere else.
|
|
8
|
+
*/
|
|
9
|
+
export type Op =
|
|
10
|
+
/** Joins an existing value import from `from`, else a new line where oxfmt's sorted imports put it. */
|
|
11
|
+
{
|
|
12
|
+
readonly kind: "import";
|
|
13
|
+
readonly names: readonly string[];
|
|
14
|
+
readonly from: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "export-all";
|
|
17
|
+
readonly from: string;
|
|
18
|
+
}
|
|
19
|
+
/** Present when an element starts with the same identifier: `chat()` is present when `chat(...)` is. */
|
|
20
|
+
| {
|
|
21
|
+
readonly kind: "append-element";
|
|
22
|
+
readonly call: CallSite;
|
|
23
|
+
readonly path: readonly [string, ...string[]];
|
|
24
|
+
readonly element: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* `$name` in `value` is replaced with the source text of the sibling property `name`, so
|
|
28
|
+
* `createAuth($database)` follows whatever the app passes.
|
|
29
|
+
*/
|
|
30
|
+
| {
|
|
31
|
+
readonly kind: "set-property";
|
|
32
|
+
readonly call: CallSite;
|
|
33
|
+
readonly path: readonly [string, ...string[]];
|
|
34
|
+
readonly value: string;
|
|
35
|
+
/** `unsafe` for add-ons, which never overwrite; `replace` for create's own template. */
|
|
36
|
+
readonly onConflict: "unsafe" | "replace";
|
|
37
|
+
} | {
|
|
38
|
+
readonly kind: "wrap-property";
|
|
39
|
+
readonly call: CallSite;
|
|
40
|
+
readonly path: readonly [string, ...string[]];
|
|
41
|
+
readonly wrapper: string;
|
|
42
|
+
} | {
|
|
43
|
+
readonly kind: "jsx-attribute";
|
|
44
|
+
readonly element: string;
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly value: string;
|
|
47
|
+
}
|
|
48
|
+
/** The component must return exactly one JSX element or fragment. */
|
|
49
|
+
| {
|
|
50
|
+
readonly kind: "jsx-child";
|
|
51
|
+
readonly component: string;
|
|
52
|
+
readonly element: string;
|
|
53
|
+
};
|
|
54
|
+
export type OpOutcome = {
|
|
55
|
+
readonly status: "done";
|
|
56
|
+
} | {
|
|
57
|
+
readonly status: "edit";
|
|
58
|
+
readonly splices: readonly Splice[];
|
|
59
|
+
} | {
|
|
60
|
+
readonly status: "unsafe";
|
|
61
|
+
readonly reason: string;
|
|
62
|
+
};
|
|
63
|
+
export declare function evaluateOp(file: SourceFile, op: Op): OpOutcome;
|
|
64
|
+
/** One short line for the printed plan, such as "auth: createAuth(database)"; none for an import. */
|
|
65
|
+
export declare function opSummary(file: SourceFile, op: Op): string | undefined;
|
|
66
|
+
/** The code to write by hand for `op`; a `$name` stands for the sibling the app passes. */
|
|
67
|
+
export declare function manualCode(op: Op): string;
|
|
68
|
+
export declare function indentLines(text: string, indent: string): string;
|
|
69
|
+
/** The change to make by hand when `op` is unsafe. */
|
|
70
|
+
export declare function manualChange(file: string, op: Op): string;
|
|
71
|
+
export type EditOutcome = {
|
|
72
|
+
readonly status: "done";
|
|
73
|
+
} | {
|
|
74
|
+
readonly status: "edit";
|
|
75
|
+
readonly text: string;
|
|
76
|
+
} | {
|
|
77
|
+
readonly status: "unsafe";
|
|
78
|
+
readonly unsafe: readonly UnsafeOp[];
|
|
79
|
+
};
|
|
80
|
+
export interface UnsafeOp {
|
|
81
|
+
readonly op: Op;
|
|
82
|
+
readonly reason: string;
|
|
83
|
+
}
|
|
84
|
+
export declare const UNCONFIRMED = "could not confirm the edit";
|
|
85
|
+
/**
|
|
86
|
+
* Applies `ops` in order, reparsing after each one, then proves the result: it must still
|
|
87
|
+
* parse and every op must now evaluate to `done`. A failed proof is `unsafe`, so a bug in an op
|
|
88
|
+
* can cost a manual step but never a broken or half-edited file, and a second run is a no-op
|
|
89
|
+
* by construction. Collects every unsafe op instead of stopping at the first.
|
|
90
|
+
*/
|
|
91
|
+
export declare function editSource(file: SourceFile, ops: readonly Op[]): EditOutcome;
|
|
92
|
+
//# sourceMappingURL=ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../src/edit/ops.ts"],"names":[],"mappings":"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"}
|