@jinion/core 0.3.0 → 0.4.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/dist/agent/claude/backend.d.ts +4 -0
- package/dist/agent/claude/backend.d.ts.map +1 -1
- package/dist/agent/claude/backend.js.map +1 -1
- package/dist/agent/claude/events.js +1 -1
- package/dist/agent/claude/events.js.map +1 -1
- package/dist/agent/claude/guard.d.ts.map +1 -1
- package/dist/agent/claude/guard.js +2 -1
- package/dist/agent/claude/guard.js.map +1 -1
- package/dist/agent/claude/jinion-tools.d.ts +9 -1
- package/dist/agent/claude/jinion-tools.d.ts.map +1 -1
- package/dist/agent/claude/jinion-tools.js +14 -2
- package/dist/agent/claude/jinion-tools.js.map +1 -1
- package/dist/agent/claude/mcp.d.ts.map +1 -1
- package/dist/agent/claude/mcp.js +21 -1
- package/dist/agent/claude/mcp.js.map +1 -1
- package/dist/agent/claude/options.d.ts +9 -1
- package/dist/agent/claude/options.d.ts.map +1 -1
- package/dist/agent/claude/options.js +5 -3
- package/dist/agent/claude/options.js.map +1 -1
- package/dist/agent/claude/paths.d.ts +0 -3
- package/dist/agent/claude/paths.d.ts.map +1 -1
- package/dist/agent/claude/paths.js +1 -7
- package/dist/agent/claude/paths.js.map +1 -1
- package/dist/agent/claude/permissions.js +1 -1
- package/dist/agent/claude/permissions.js.map +1 -1
- package/dist/agent/claude/prompt.d.ts +2 -1
- package/dist/agent/claude/prompt.d.ts.map +1 -1
- package/dist/agent/claude/prompt.js +10 -5
- package/dist/agent/claude/prompt.js.map +1 -1
- package/dist/agent/claude/review.d.ts +4 -1
- package/dist/agent/claude/review.d.ts.map +1 -1
- package/dist/agent/claude/review.js +5 -2
- package/dist/agent/claude/review.js.map +1 -1
- package/dist/agent/claude/session.d.ts +7 -0
- package/dist/agent/claude/session.d.ts.map +1 -1
- package/dist/agent/claude/session.js +6 -1
- package/dist/agent/claude/session.js.map +1 -1
- package/dist/agent/claude/tool-calls.d.ts.map +1 -1
- package/dist/agent/claude/tool-calls.js +11 -2
- package/dist/agent/claude/tool-calls.js.map +1 -1
- package/dist/agent/codex/backend.d.ts +4 -0
- package/dist/agent/codex/backend.d.ts.map +1 -1
- package/dist/agent/codex/backend.js.map +1 -1
- package/dist/agent/codex/events.d.ts.map +1 -1
- package/dist/agent/codex/events.js +15 -1
- package/dist/agent/codex/events.js.map +1 -1
- package/dist/agent/codex/jinion-tools.d.ts +38 -4
- package/dist/agent/codex/jinion-tools.d.ts.map +1 -1
- package/dist/agent/codex/jinion-tools.js +57 -10
- package/dist/agent/codex/jinion-tools.js.map +1 -1
- package/dist/agent/codex/mcp.d.ts.map +1 -1
- package/dist/agent/codex/mcp.js +4 -0
- package/dist/agent/codex/mcp.js.map +1 -1
- package/dist/agent/codex/rewind.js +1 -47
- package/dist/agent/codex/rewind.js.map +1 -1
- package/dist/agent/codex/session.d.ts +9 -2
- package/dist/agent/codex/session.d.ts.map +1 -1
- package/dist/agent/codex/session.js +21 -7
- package/dist/agent/codex/session.js.map +1 -1
- package/dist/agent/demo/mcp.d.ts +2 -0
- package/dist/agent/demo/mcp.d.ts.map +1 -1
- package/dist/agent/demo/mcp.js +14 -0
- package/dist/agent/demo/mcp.js.map +1 -1
- package/dist/agent/demo/scenarios/pricing-card.d.ts +3 -0
- package/dist/agent/demo/scenarios/pricing-card.d.ts.map +1 -0
- package/dist/agent/demo/scenarios/pricing-card.js +43 -0
- package/dist/agent/demo/scenarios/pricing-card.js.map +1 -0
- package/dist/agent/demo/script.d.ts +6 -0
- package/dist/agent/demo/script.d.ts.map +1 -1
- package/dist/agent/demo/tasks.d.ts +3 -0
- package/dist/agent/demo/tasks.d.ts.map +1 -1
- package/dist/agent/events.d.ts +3 -0
- package/dist/agent/events.d.ts.map +1 -1
- package/dist/agent/events.js +2 -0
- package/dist/agent/events.js.map +1 -1
- package/dist/agent/mcp.d.ts +5 -0
- package/dist/agent/mcp.d.ts.map +1 -1
- package/dist/agent/mcp.js +2 -0
- package/dist/agent/mcp.js.map +1 -1
- package/dist/agent/patches.d.ts +5 -0
- package/dist/agent/patches.d.ts.map +1 -1
- package/dist/agent/patches.js +49 -0
- package/dist/agent/patches.js.map +1 -1
- package/dist/agent/review-tools.d.ts +15 -0
- package/dist/agent/review-tools.d.ts.map +1 -0
- package/dist/agent/review-tools.js +13 -0
- package/dist/agent/review-tools.js.map +1 -0
- package/dist/agent/review.d.ts +18 -6
- package/dist/agent/review.d.ts.map +1 -1
- package/dist/agent/review.js +52 -17
- package/dist/agent/review.js.map +1 -1
- package/dist/api/client.d.ts +15 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +14 -3
- package/dist/api/client.js.map +1 -1
- package/dist/api/connection.d.ts +5 -0
- package/dist/api/connection.d.ts.map +1 -1
- package/dist/api/connection.js +6 -0
- package/dist/api/connection.js.map +1 -1
- package/dist/api/fields.d.ts +3 -1
- package/dist/api/fields.d.ts.map +1 -1
- package/dist/api/fields.js +3 -2
- package/dist/api/fields.js.map +1 -1
- package/dist/api/json-schema.d.ts +592 -89
- package/dist/api/json-schema.d.ts.map +1 -1
- package/dist/api/json-schema.js +2 -1
- package/dist/api/json-schema.js.map +1 -1
- package/dist/api/methods/accounts.d.ts.map +1 -1
- package/dist/api/methods/accounts.js +1 -2
- package/dist/api/methods/accounts.js.map +1 -1
- package/dist/api/methods/app.d.ts.map +1 -1
- package/dist/api/methods/app.js +9 -5
- package/dist/api/methods/app.js.map +1 -1
- package/dist/api/methods/files.d.ts +3 -1
- package/dist/api/methods/files.d.ts.map +1 -1
- package/dist/api/methods/files.js +75 -2
- package/dist/api/methods/files.js.map +1 -1
- package/dist/api/methods/git.d.ts.map +1 -1
- package/dist/api/methods/git.js +54 -6
- package/dist/api/methods/git.js.map +1 -1
- package/dist/api/methods/lsp.d.ts +7 -0
- package/dist/api/methods/lsp.d.ts.map +1 -0
- package/dist/api/methods/lsp.js +68 -0
- package/dist/api/methods/lsp.js.map +1 -0
- package/dist/api/methods/preview.d.ts +4 -1
- package/dist/api/methods/preview.d.ts.map +1 -1
- package/dist/api/methods/preview.js +19 -3
- package/dist/api/methods/preview.js.map +1 -1
- package/dist/api/methods/terminals.d.ts.map +1 -1
- package/dist/api/methods/terminals.js +7 -1
- package/dist/api/methods/terminals.js.map +1 -1
- package/dist/api/protocol.d.ts +762 -7
- package/dist/api/protocol.d.ts.map +1 -1
- package/dist/api/protocol.js +126 -8
- package/dist/api/protocol.js.map +1 -1
- package/dist/api/schemas.d.ts +7 -0
- package/dist/api/schemas.d.ts.map +1 -1
- package/dist/api/schemas.js +4 -0
- package/dist/api/schemas.js.map +1 -1
- package/dist/api/screen.d.ts +2 -0
- package/dist/api/screen.d.ts.map +1 -1
- package/dist/api/screen.js +3 -0
- package/dist/api/screen.js.map +1 -1
- package/dist/api/server.d.ts +2 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +13 -0
- package/dist/api/server.js.map +1 -1
- package/dist/commands/builtin.d.ts.map +1 -1
- package/dist/commands/builtin.js +2 -0
- package/dist/commands/builtin.js.map +1 -1
- package/dist/commands/conversation.d.ts.map +1 -1
- package/dist/commands/conversation.js +2 -0
- package/dist/commands/conversation.js.map +1 -1
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +1 -0
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/notifications.d.ts.map +1 -1
- package/dist/commands/notifications.js +5 -3
- package/dist/commands/notifications.js.map +1 -1
- package/dist/commands/registry.d.ts +3 -0
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +14 -0
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/skill.d.ts +5 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +30 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/views.d.ts.map +1 -1
- package/dist/commands/views.js +5 -1
- package/dist/commands/views.js.map +1 -1
- package/dist/controllers/accounts.d.ts +5 -2
- package/dist/controllers/accounts.d.ts.map +1 -1
- package/dist/controllers/accounts.js +11 -8
- package/dist/controllers/accounts.js.map +1 -1
- package/dist/controllers/context.d.ts +2 -0
- package/dist/controllers/context.d.ts.map +1 -1
- package/dist/controllers/context.js.map +1 -1
- package/dist/controllers/feedback.d.ts +1 -1
- package/dist/controllers/feedback.d.ts.map +1 -1
- package/dist/controllers/feedback.js +4 -1
- package/dist/controllers/feedback.js.map +1 -1
- package/dist/controllers/input.d.ts.map +1 -1
- package/dist/controllers/input.js +2 -0
- package/dist/controllers/input.js.map +1 -1
- package/dist/controllers/jinion.d.ts +7 -0
- package/dist/controllers/jinion.d.ts.map +1 -1
- package/dist/controllers/jinion.js +7 -0
- package/dist/controllers/jinion.js.map +1 -1
- package/dist/controllers/mcp.d.ts +7 -2
- package/dist/controllers/mcp.d.ts.map +1 -1
- package/dist/controllers/mcp.js +23 -7
- package/dist/controllers/mcp.js.map +1 -1
- package/dist/controllers/session.d.ts.map +1 -1
- package/dist/controllers/session.js +4 -0
- package/dist/controllers/session.js.map +1 -1
- package/dist/conversation/activity.d.ts +5 -0
- package/dist/conversation/activity.d.ts.map +1 -0
- package/dist/conversation/activity.js +41 -0
- package/dist/conversation/activity.js.map +1 -0
- package/dist/conversation/apply-event.d.ts.map +1 -1
- package/dist/conversation/apply-event.js +2 -1
- package/dist/conversation/apply-event.js.map +1 -1
- package/dist/conversation/edits.d.ts +5 -0
- package/dist/conversation/edits.d.ts.map +1 -1
- package/dist/conversation/edits.js +10 -0
- package/dist/conversation/edits.js.map +1 -1
- package/dist/conversation/reducer.d.ts +9 -0
- package/dist/conversation/reducer.d.ts.map +1 -1
- package/dist/design/guides.d.ts +78 -5
- package/dist/design/guides.d.ts.map +1 -1
- package/dist/design/guides.js +78 -5
- package/dist/design/guides.js.map +1 -1
- package/dist/design/prompt.d.ts +1 -1
- package/dist/design/prompt.d.ts.map +1 -1
- package/dist/design/prompt.js +2 -2
- package/dist/design/prompt.js.map +1 -1
- package/dist/design/tools.d.ts +2 -0
- package/dist/design/tools.d.ts.map +1 -1
- package/dist/design/tools.js +6 -2
- package/dist/design/tools.js.map +1 -1
- package/dist/directions/directions.d.ts +42 -0
- package/dist/directions/directions.d.ts.map +1 -0
- package/dist/directions/directions.js +120 -0
- package/dist/directions/directions.js.map +1 -0
- package/dist/directions/store.d.ts +34 -0
- package/dist/directions/store.d.ts.map +1 -0
- package/dist/directions/store.js +61 -0
- package/dist/directions/store.js.map +1 -0
- package/dist/directions/tools.d.ts +29 -0
- package/dist/directions/tools.d.ts.map +1 -0
- package/dist/directions/tools.js +57 -0
- package/dist/directions/tools.js.map +1 -0
- package/dist/directions/viewer.d.ts +6 -0
- package/dist/directions/viewer.d.ts.map +1 -0
- package/dist/directions/viewer.js +266 -0
- package/dist/directions/viewer.js.map +1 -0
- package/dist/files/names.d.ts +6 -0
- package/dist/files/names.d.ts.map +1 -0
- package/dist/files/names.js +18 -0
- package/dist/files/names.js.map +1 -0
- package/dist/files/operations.d.ts +54 -0
- package/dist/files/operations.d.ts.map +1 -0
- package/dist/files/operations.js +173 -0
- package/dist/files/operations.js.map +1 -0
- package/dist/files/search.d.ts +11 -0
- package/dist/files/search.d.ts.map +1 -0
- package/dist/files/search.js +112 -0
- package/dist/files/search.js.map +1 -0
- package/dist/files/trash.d.ts +11 -0
- package/dist/files/trash.d.ts.map +1 -0
- package/dist/files/trash.js +64 -0
- package/dist/files/trash.js.map +1 -0
- package/dist/files/types.d.ts +112 -0
- package/dist/files/types.d.ts.map +1 -0
- package/dist/files/types.js +47 -0
- package/dist/files/types.js.map +1 -0
- package/dist/files/watch.d.ts +26 -0
- package/dist/files/watch.d.ts.map +1 -0
- package/dist/files/watch.js +107 -0
- package/dist/files/watch.js.map +1 -0
- package/dist/git/blame.d.ts +10 -0
- package/dist/git/blame.d.ts.map +1 -0
- package/dist/git/blame.js +91 -0
- package/dist/git/blame.js.map +1 -0
- package/dist/git/repos.d.ts +5 -0
- package/dist/git/repos.d.ts.map +1 -1
- package/dist/git/repos.js +13 -0
- package/dist/git/repos.js.map +1 -1
- package/dist/git/staging.d.ts +10 -1
- package/dist/git/staging.d.ts.map +1 -1
- package/dist/git/staging.js +21 -0
- package/dist/git/staging.js.map +1 -1
- package/dist/git/types.d.ts +48 -0
- package/dist/git/types.d.ts.map +1 -1
- package/dist/git/types.js +25 -0
- package/dist/git/types.js.map +1 -1
- package/dist/host.d.ts +2 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +8 -1
- package/dist/host.js.map +1 -1
- package/dist/lib/glob.d.ts +6 -0
- package/dist/lib/glob.d.ts.map +1 -0
- package/dist/lib/glob.js +49 -0
- package/dist/lib/glob.js.map +1 -0
- package/dist/lib/paths.d.ts +3 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +9 -1
- package/dist/lib/paths.js.map +1 -1
- package/dist/look/tools.d.ts +7 -1
- package/dist/look/tools.d.ts.map +1 -1
- package/dist/look/tools.js +19 -4
- package/dist/look/tools.js.map +1 -1
- package/dist/lsp/code-intelligence.d.ts +87 -0
- package/dist/lsp/code-intelligence.d.ts.map +1 -0
- package/dist/lsp/code-intelligence.js +343 -0
- package/dist/lsp/code-intelligence.js.map +1 -0
- package/dist/lsp/edits.d.ts +4 -0
- package/dist/lsp/edits.d.ts.map +1 -0
- package/dist/lsp/edits.js +14 -0
- package/dist/lsp/edits.js.map +1 -0
- package/dist/lsp/project-check.d.ts +8 -0
- package/dist/lsp/project-check.d.ts.map +1 -0
- package/dist/lsp/project-check.js +71 -0
- package/dist/lsp/project-check.js.map +1 -0
- package/dist/lsp/results.d.ts +95 -0
- package/dist/lsp/results.d.ts.map +1 -0
- package/dist/lsp/results.js +116 -0
- package/dist/lsp/results.js.map +1 -0
- package/dist/lsp/server.d.ts +22 -0
- package/dist/lsp/server.d.ts.map +1 -0
- package/dist/lsp/server.js +123 -0
- package/dist/lsp/server.js.map +1 -0
- package/dist/lsp/servers.d.ts +21 -0
- package/dist/lsp/servers.d.ts.map +1 -0
- package/dist/lsp/servers.js +57 -0
- package/dist/lsp/servers.js.map +1 -0
- package/dist/lsp/transport.d.ts +9 -0
- package/dist/lsp/transport.d.ts.map +1 -0
- package/dist/lsp/transport.js +64 -0
- package/dist/lsp/transport.js.map +1 -0
- package/dist/lsp/types.d.ts +262 -0
- package/dist/lsp/types.d.ts.map +1 -0
- package/dist/lsp/types.js +64 -0
- package/dist/lsp/types.js.map +1 -0
- package/dist/map/prompt.d.ts.map +1 -1
- package/dist/map/prompt.js +2 -1
- package/dist/map/prompt.js.map +1 -1
- package/dist/map/review.d.ts +29 -9
- package/dist/map/review.d.ts.map +1 -1
- package/dist/map/review.js +105 -25
- package/dist/map/review.js.map +1 -1
- package/dist/mcp/login.d.ts +2 -0
- package/dist/mcp/login.d.ts.map +1 -1
- package/dist/mcp/login.js +5 -0
- package/dist/mcp/login.js.map +1 -1
- package/dist/preview/pages.d.ts +17 -0
- package/dist/preview/pages.d.ts.map +1 -0
- package/dist/preview/pages.js +92 -0
- package/dist/preview/pages.js.map +1 -0
- package/dist/preview/previews.d.ts +22 -0
- package/dist/preview/previews.d.ts.map +1 -0
- package/dist/preview/previews.js +28 -0
- package/dist/preview/previews.js.map +1 -0
- package/dist/preview/prompt.d.ts +3 -0
- package/dist/preview/prompt.d.ts.map +1 -0
- package/dist/preview/prompt.js +5 -0
- package/dist/preview/prompt.js.map +1 -0
- package/dist/preview/tools.d.ts +21 -0
- package/dist/preview/tools.d.ts.map +1 -0
- package/dist/preview/tools.js +34 -0
- package/dist/preview/tools.js.map +1 -0
- package/dist/preview/types.d.ts +7 -0
- package/dist/preview/types.d.ts.map +1 -1
- package/dist/preview/types.js +2 -0
- package/dist/preview/types.js.map +1 -1
- package/dist/prompt/files.d.ts +4 -1
- package/dist/prompt/files.d.ts.map +1 -1
- package/dist/prompt/files.js +23 -8
- package/dist/prompt/files.js.map +1 -1
- package/dist/skills/tools.d.ts +26 -0
- package/dist/skills/tools.d.ts.map +1 -0
- package/dist/skills/tools.js +34 -0
- package/dist/skills/tools.js.map +1 -0
- package/dist/state/session.d.ts +4 -0
- package/dist/state/session.d.ts.map +1 -1
- package/dist/state/session.js +1 -0
- package/dist/state/session.js.map +1 -1
- package/package.json +3 -1
- package/schema/api.json +3016 -45
- package/vendor/darwin-arm64/build.json +62 -0
- package/vendor/darwin-arm64/ffmpeg +0 -0
- package/vendor/darwin-arm64/ffprobe +0 -0
- package/vendor/darwin-arm64/licenses/README.md +13 -0
- package/vendor/darwin-arm64/licenses/ffmpeg-LGPL-2.1.txt +502 -0
- package/vendor/darwin-arm64/licenses/whisper.cpp-MIT.txt +21 -0
- package/vendor/darwin-arm64/voices.bin +0 -0
- package/vendor/darwin-arm64/whisper-cli +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The viewer the core serves, as drawn in @jinion/ui's playground (`pages/directions`): one page that reads the rounds
|
|
3
|
+
* from beside it. The core draws no React, so it is written out here, with @jinion/ui's tokens by the same names.
|
|
4
|
+
*/
|
|
5
|
+
export function viewerPage(project) {
|
|
6
|
+
return `<!doctype html>
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="utf-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
11
|
+
<title>Directions</title>
|
|
12
|
+
<style>${STYLE}</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<nav id="rounds"><h1><span class="strong">Directions</span><span class="faint">${escapeHtml(project)}</span></h1></nav>
|
|
16
|
+
<main><div class="sheet" id="sheet"></div></main>
|
|
17
|
+
<script>${SCRIPT}</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>`;
|
|
20
|
+
}
|
|
21
|
+
function escapeHtml(text) {
|
|
22
|
+
return text.replace(/[&<>"']/g, (character) => `&#${character.charCodeAt(0)};`);
|
|
23
|
+
}
|
|
24
|
+
const STYLE = `
|
|
25
|
+
:root {
|
|
26
|
+
--background: #ffffff;
|
|
27
|
+
--raised: #f4f5f8;
|
|
28
|
+
--floating: #ffffff;
|
|
29
|
+
--ink: #12162a;
|
|
30
|
+
--muted: #5c6275;
|
|
31
|
+
--faint: #989dae;
|
|
32
|
+
--edge: rgb(18 22 42 / 0.1);
|
|
33
|
+
--shade: rgb(18 22 42 / 0.045);
|
|
34
|
+
--selected: rgb(18 22 42 / 0.07);
|
|
35
|
+
--primary: #181e33;
|
|
36
|
+
--on-primary: #ffffff;
|
|
37
|
+
--float-shadow: 0 6px 24px -8px rgb(0 0 0 / 0.14), 0 0 0 0.5px rgb(0 0 0 / 0.1);
|
|
38
|
+
--sheet-shadow: 0 0 0 1px rgb(0 0 0 / 0.05), 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
39
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
|
|
40
|
+
--font-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
|
|
41
|
+
color-scheme: light;
|
|
42
|
+
}
|
|
43
|
+
* { box-sizing: border-box; }
|
|
44
|
+
html, body { height: 100%; margin: 0; }
|
|
45
|
+
body { display: flex; background: var(--raised); color: var(--ink); font: 13px/20px var(--font-sans); -webkit-font-smoothing: antialiased; }
|
|
46
|
+
button { font: inherit; color: inherit; border: 0; background: none; padding: 0; cursor: default; text-align: left; transition: background-color 100ms ease-out, color 100ms ease-out; }
|
|
47
|
+
button:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
|
|
48
|
+
.strong { font-weight: 600; }
|
|
49
|
+
.faint { color: var(--faint); }
|
|
50
|
+
.small { font-size: 12px; line-height: 16px; }
|
|
51
|
+
.truncate { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
52
|
+
nav { display: flex; flex-direction: column; gap: 1px; width: 224px; flex-shrink: 0; padding: 12px; overflow-y: auto; }
|
|
53
|
+
nav h1 { display: flex; align-items: baseline; gap: 8px; margin: 0; padding: 4px 10px 12px; font-size: inherit; font-weight: 400; min-width: 0; }
|
|
54
|
+
.round { display: flex; flex-direction: column; min-width: 0; border-radius: 8px; padding: 6px 10px; color: var(--muted); }
|
|
55
|
+
.round:hover { color: var(--ink); }
|
|
56
|
+
.round[aria-current="true"] { background: var(--shade); color: var(--ink); }
|
|
57
|
+
main { flex: 1; min-width: 0; padding: 12px 12px 12px 0; }
|
|
58
|
+
.sidebar-closed nav { display: none; }
|
|
59
|
+
.sidebar-closed main { padding-left: 12px; }
|
|
60
|
+
.sheet { position: relative; height: 100%; overflow: hidden; border-radius: 12px; background: var(--background); box-shadow: var(--sheet-shadow); }
|
|
61
|
+
iframe { display: block; width: 100%; height: 100%; border: 0; }
|
|
62
|
+
.dock { position: absolute; inset: auto 16px 16px; display: flex; justify-content: center; pointer-events: none; }
|
|
63
|
+
.switcher { display: flex; align-items: center; gap: 4px; max-width: 100%; min-width: 0; padding: 4px; border-radius: 16px; background: var(--floating); box-shadow: var(--float-shadow); pointer-events: auto; user-select: none; }
|
|
64
|
+
.options { display: flex; gap: 4px; min-width: 0; overflow-x: auto; }
|
|
65
|
+
.option { display: flex; flex-direction: column; gap: 2px; width: 208px; min-width: 144px; flex-shrink: 1; border-radius: 12px; padding: 8px 12px; }
|
|
66
|
+
.option:hover { background: var(--shade); }
|
|
67
|
+
.option[aria-pressed="true"] { background: var(--selected); }
|
|
68
|
+
.option-head { display: flex; align-items: center; gap: 6px; }
|
|
69
|
+
.option-name { font-weight: 500; color: var(--ink); }
|
|
70
|
+
.option-number { margin-left: auto; font: 12px/20px var(--font-mono); color: var(--faint); }
|
|
71
|
+
.idea { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font-size: 12px; line-height: 16px; color: var(--muted); }
|
|
72
|
+
.check { width: 14px; height: 14px; flex-shrink: 0; color: var(--muted); }
|
|
73
|
+
.act { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; padding: 0 8px; }
|
|
74
|
+
.button { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; border-radius: 8px; font-weight: 500; white-space: nowrap; }
|
|
75
|
+
.button .check { width: 16px; height: 16px; color: inherit; }
|
|
76
|
+
.primary { background: var(--primary); color: var(--on-primary); }
|
|
77
|
+
.primary:hover { background: color-mix(in srgb, var(--primary) 90%, transparent); }
|
|
78
|
+
.outline { background: var(--background); box-shadow: 0 0 0 1px var(--edge), 0 1px 2px 0 rgb(0 0 0 / 0.05); }
|
|
79
|
+
.button:disabled { opacity: 0.4; }
|
|
80
|
+
.said { max-width: 208px; text-align: right; }
|
|
81
|
+
.empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; height: 100%; padding: 0 24px; text-align: center; }
|
|
82
|
+
.empty p { margin: 0; }
|
|
83
|
+
.empty .title { font-weight: 500; }
|
|
84
|
+
.empty .text { max-width: 320px; color: var(--muted); text-wrap: pretty; }
|
|
85
|
+
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }
|
|
86
|
+
`;
|
|
87
|
+
const SCRIPT = `
|
|
88
|
+
const CHECK = '<svg class="check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>';
|
|
89
|
+
const nav = document.getElementById('rounds');
|
|
90
|
+
const sheet = document.getElementById('sheet');
|
|
91
|
+
let rounds = [];
|
|
92
|
+
let loaded = false;
|
|
93
|
+
const params = new URLSearchParams(location.search);
|
|
94
|
+
let roundId = params.get('round');
|
|
95
|
+
// The direction the address asks for, by its number in the round, as the agent opens each one to look at it.
|
|
96
|
+
const asked = Number(params.get('direction') ?? 1) - 1;
|
|
97
|
+
let shown = 0;
|
|
98
|
+
let said = '';
|
|
99
|
+
|
|
100
|
+
function element(tag, className, text) {
|
|
101
|
+
const made = document.createElement(tag);
|
|
102
|
+
if (className) made.className = className;
|
|
103
|
+
if (text !== undefined) made.textContent = text;
|
|
104
|
+
return made;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function current() {
|
|
108
|
+
return rounds.find((round) => round.id === roundId);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function when(at) {
|
|
112
|
+
const date = new Date(at);
|
|
113
|
+
const time = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
114
|
+
const days = Math.round((new Date().setHours(0, 0, 0, 0) - new Date(at).setHours(0, 0, 0, 0)) / 86400000);
|
|
115
|
+
if (days === 0) return 'Today, ' + time;
|
|
116
|
+
if (days === 1) return 'Yesterday, ' + time;
|
|
117
|
+
return date.toLocaleDateString([], { day: 'numeric', month: 'long' });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function open(id, index = 0) {
|
|
121
|
+
roundId = id;
|
|
122
|
+
show(index);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function show(index) {
|
|
126
|
+
const round = current();
|
|
127
|
+
shown = round && index >= 0 && index < round.directions.length ? index : 0;
|
|
128
|
+
said = '';
|
|
129
|
+
const url = new URL(location.href);
|
|
130
|
+
if (roundId) url.searchParams.set('round', roundId);
|
|
131
|
+
url.searchParams.set('direction', String(shown + 1));
|
|
132
|
+
history.replaceState(null, '', url);
|
|
133
|
+
render();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function renderRounds() {
|
|
137
|
+
nav.querySelectorAll('.round').forEach((row) => row.remove());
|
|
138
|
+
for (const round of rounds) {
|
|
139
|
+
const row = element('button', 'round');
|
|
140
|
+
row.type = 'button';
|
|
141
|
+
row.setAttribute('aria-current', String(round.id === roundId));
|
|
142
|
+
row.append(element('span', 'truncate', round.title));
|
|
143
|
+
const status = round.picked ? 'Picked ' + round.picked : round.directions.length + ' to pick from';
|
|
144
|
+
row.append(element('span', 'truncate small faint', status + ' · ' + when(round.at)));
|
|
145
|
+
row.onclick = () => open(round.id);
|
|
146
|
+
nav.append(row);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function renderSheet() {
|
|
151
|
+
const round = current();
|
|
152
|
+
if (!round) {
|
|
153
|
+
sheet.replaceChildren(empty());
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
document.title = round.title + ' · Directions';
|
|
157
|
+
const direction = round.directions[shown];
|
|
158
|
+
const src = 'rounds/' + round.id + '/' + (shown + 1);
|
|
159
|
+
let frame = sheet.querySelector('iframe');
|
|
160
|
+
if (!frame) frame = element('iframe');
|
|
161
|
+
if (frame.getAttribute('src') !== src) {
|
|
162
|
+
frame.setAttribute('src', src);
|
|
163
|
+
frame.title = direction.name;
|
|
164
|
+
}
|
|
165
|
+
// The page holds no secret of the viewer's, and runs on an origin of its own besides.
|
|
166
|
+
frame.setAttribute('sandbox', 'allow-scripts allow-forms allow-popups');
|
|
167
|
+
sheet.replaceChildren(frame, dock(round));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function dock(round) {
|
|
171
|
+
const options = element('div', 'options');
|
|
172
|
+
round.directions.forEach((direction, index) => {
|
|
173
|
+
const option = element('button', 'option');
|
|
174
|
+
option.type = 'button';
|
|
175
|
+
option.title = direction.idea;
|
|
176
|
+
option.setAttribute('aria-pressed', String(index === shown));
|
|
177
|
+
const head = element('span', 'option-head');
|
|
178
|
+
head.append(element('span', 'option-name', direction.name));
|
|
179
|
+
if (direction.name === round.picked) head.insertAdjacentHTML('beforeend', CHECK);
|
|
180
|
+
head.append(element('span', 'option-number', String(index + 1)));
|
|
181
|
+
option.append(head, element('span', 'idea', direction.idea));
|
|
182
|
+
option.onclick = () => show(index);
|
|
183
|
+
options.append(option);
|
|
184
|
+
});
|
|
185
|
+
const act = element('div', 'act');
|
|
186
|
+
const name = round.directions[shown].name;
|
|
187
|
+
const button = element('button', 'button');
|
|
188
|
+
button.type = 'button';
|
|
189
|
+
if (name === round.picked) {
|
|
190
|
+
button.className = 'button outline';
|
|
191
|
+
button.disabled = true;
|
|
192
|
+
button.innerHTML = CHECK;
|
|
193
|
+
button.append('Picked');
|
|
194
|
+
} else {
|
|
195
|
+
button.className = 'button primary';
|
|
196
|
+
button.textContent = round.picked ? 'Pick ' + name + ' instead' : 'Pick ' + name;
|
|
197
|
+
button.onclick = () => pick(round, name);
|
|
198
|
+
}
|
|
199
|
+
act.append(button);
|
|
200
|
+
if (said) act.append(element('span', 'said small faint', said));
|
|
201
|
+
const switcher = element('div', 'switcher');
|
|
202
|
+
switcher.append(options, act);
|
|
203
|
+
const wrapper = element('div', 'dock');
|
|
204
|
+
wrapper.append(switcher);
|
|
205
|
+
return wrapper;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function empty(title = 'No directions yet', text = 'When Jinion offers you directions for this project, each round shows here to compare and pick from.') {
|
|
209
|
+
const box = element('div', 'empty');
|
|
210
|
+
box.append(element('p', 'title', title), element('p', 'text', text));
|
|
211
|
+
return box;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function pick(round, name) {
|
|
215
|
+
try {
|
|
216
|
+
const response = await fetch('rounds/' + round.id + '/pick', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ direction: name }) });
|
|
217
|
+
if (!response.ok) throw new Error(String(response.status));
|
|
218
|
+
const answer = await response.json();
|
|
219
|
+
rounds = rounds.map((each) => (each.id === answer.round.id ? answer.round : each));
|
|
220
|
+
said = answer.sent ? '' : "Saved. Its conversation isn't open, so tell Jinion there.";
|
|
221
|
+
} catch {
|
|
222
|
+
said = "Jinion couldn't be reached. Is it still running?";
|
|
223
|
+
}
|
|
224
|
+
render();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function render() {
|
|
228
|
+
document.body.classList.toggle('sidebar-closed', location.hash === '#sidebar-closed');
|
|
229
|
+
renderRounds();
|
|
230
|
+
renderSheet();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function load() {
|
|
234
|
+
try {
|
|
235
|
+
const known = new Set(rounds.map((round) => round.id));
|
|
236
|
+
const response = await fetch('rounds');
|
|
237
|
+
if (!response.ok) throw new Error(String(response.status));
|
|
238
|
+
const fresh = await response.json();
|
|
239
|
+
const first = !loaded;
|
|
240
|
+
loaded = true;
|
|
241
|
+
rounds = fresh;
|
|
242
|
+
const added = fresh.find((round) => !known.has(round.id));
|
|
243
|
+
// A round shown while the viewer is open comes up by itself.
|
|
244
|
+
if (!first && added) return open(added.id);
|
|
245
|
+
if (!current()) roundId = rounds[0] ? rounds[0].id : null;
|
|
246
|
+
if (first) return roundId ? open(roundId, asked) : render();
|
|
247
|
+
renderRounds();
|
|
248
|
+
} catch {
|
|
249
|
+
if (rounds.length === 0) sheet.replaceChildren(empty("Jinion isn't running", 'The directions show while Jinion runs. Start it again, then reload this page.'));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
addEventListener('hashchange', render);
|
|
254
|
+
addEventListener('keydown', (event) => {
|
|
255
|
+
const round = current();
|
|
256
|
+
if (!round || event.metaKey || event.ctrlKey || event.altKey) return;
|
|
257
|
+
const count = round.directions.length;
|
|
258
|
+
const number = Number(event.key);
|
|
259
|
+
if (event.key === 'ArrowRight') show((shown + 1) % count);
|
|
260
|
+
else if (event.key === 'ArrowLeft') show((shown - 1 + count) % count);
|
|
261
|
+
else if (number >= 1 && number <= count) show(number - 1);
|
|
262
|
+
});
|
|
263
|
+
load();
|
|
264
|
+
setInterval(load, 2000);
|
|
265
|
+
`;
|
|
266
|
+
//# sourceMappingURL=viewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewer.js","sourceRoot":"","sources":["../../src/directions/viewer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO;;;;;;SAMA,KAAK;;;iFAGmE,UAAU,CAAC,OAAO,CAAC;;UAE1F,MAAM;;QAER,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Db,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkLd,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The first name free in `folder`, as the Finder names a copy: with a word, `box copy.tsx`, then `box copy 2.tsx`;
|
|
3
|
+
* without one, `box.tsx` itself, then `box 2.tsx`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function freeName(folder: string, name: string, word: string): Promise<string>;
|
|
6
|
+
//# sourceMappingURL=names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../src/files/names.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAexE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { lstat } from 'node:fs/promises';
|
|
2
|
+
import { extname, join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* The first name free in `folder`, as the Finder names a copy: with a word, `box copy.tsx`, then `box copy 2.tsx`;
|
|
5
|
+
* without one, `box.tsx` itself, then `box 2.tsx`.
|
|
6
|
+
*/
|
|
7
|
+
export async function freeName(folder, name, word) {
|
|
8
|
+
const extension = extname(name);
|
|
9
|
+
const stem = name.slice(0, name.length - extension.length);
|
|
10
|
+
for (let count = 1;; count++) {
|
|
11
|
+
const suffix = [word, count > 1 ? String(count) : ''].filter(Boolean).join(' ');
|
|
12
|
+
const candidate = suffix ? `${stem} ${suffix}${extension}` : name;
|
|
13
|
+
const taken = await lstat(join(folder, candidate)).then(() => true, () => false);
|
|
14
|
+
if (!taken)
|
|
15
|
+
return candidate;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/files/names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAY,EAAE,IAAY;IACvE,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAE3D,KAAK,IAAI,KAAK,GAAG,CAAC,GAAI,KAAK,EAAE,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChF,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAElE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CACrD,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;QAEF,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;IAC/B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { FileCreated, FilesCopied, FilesMoved, FilesRestored, Trashed } from './types.js';
|
|
2
|
+
/** Why an operation was refused, for the API to tell as its own error. */
|
|
3
|
+
export declare class FileProblem extends Error {
|
|
4
|
+
readonly kind: 'missing' | 'taken' | 'invalid';
|
|
5
|
+
readonly path?: string | undefined;
|
|
6
|
+
constructor(kind: 'missing' | 'taken' | 'invalid', message: string, path?: string | undefined);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* What can change which files a folder holds: each keeps to the folder, by real paths, so neither `..` nor a link
|
|
10
|
+
* leads out of it, and a name already taken is refused unless `replace` says to move what holds it to the Trash.
|
|
11
|
+
*/
|
|
12
|
+
export declare class FolderFiles {
|
|
13
|
+
private readonly root;
|
|
14
|
+
private constructor();
|
|
15
|
+
static of(folder: string): Promise<FolderFiles>;
|
|
16
|
+
/** A file, empty or with `content`, or a folder; the folders it is in are made as needed. */
|
|
17
|
+
create(path: string, { folder, content, replace }: {
|
|
18
|
+
folder?: boolean;
|
|
19
|
+
content?: Buffer;
|
|
20
|
+
replace?: boolean;
|
|
21
|
+
}): Promise<FileCreated>;
|
|
22
|
+
/** Gives a file or folder another name where it is. */
|
|
23
|
+
rename(path: string, name: string, replace?: boolean): Promise<FilesMoved>;
|
|
24
|
+
/**
|
|
25
|
+
* Moves files and folders into a folder of the session's, each keeping its name; with `keepBoth`, one whose name is
|
|
26
|
+
* taken there takes the next free one, as the Finder's Keep Both names it, `box 2.tsx`.
|
|
27
|
+
*/
|
|
28
|
+
move(paths: string[], into: string, replace?: boolean, keepBoth?: boolean): Promise<FilesMoved>;
|
|
29
|
+
/**
|
|
30
|
+
* Copies files and folders into a folder of the session's: ones of the folder by their paths in it, others, as files
|
|
31
|
+
* dropped from the Finder, by their whole paths. Copied into the folder it is in, a copy takes a name of its own, as
|
|
32
|
+
* one whose name is taken does with `keepBoth`.
|
|
33
|
+
*/
|
|
34
|
+
copy(paths: string[], into: string, replace?: boolean, keepBoth?: boolean): Promise<FilesCopied>;
|
|
35
|
+
/** Moves files and folders to the Trash. */
|
|
36
|
+
delete(paths: string[]): Promise<{
|
|
37
|
+
path: string;
|
|
38
|
+
trash: string;
|
|
39
|
+
}[]>;
|
|
40
|
+
/** Puts back what `delete` or a replace sent to the Trash, at the path it had. */
|
|
41
|
+
restore(items: Trashed[], replace?: boolean): Promise<FilesRestored>;
|
|
42
|
+
/** A folder of the session's by its path there, `''` for the folder itself, as a whole path. */
|
|
43
|
+
folderAt(path: string): Promise<string>;
|
|
44
|
+
private relocate;
|
|
45
|
+
private notInto;
|
|
46
|
+
/** What holds `target`, to the Trash when `replace` says so. */
|
|
47
|
+
private clear;
|
|
48
|
+
private existing;
|
|
49
|
+
private outside;
|
|
50
|
+
/** Where something new goes: under the deepest folder of its path that is there, which has to be in the folder. */
|
|
51
|
+
private target;
|
|
52
|
+
private named;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/files/operations.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAS,OAAO,EAAE,MAAM,YAAY,CAAC;AAEtG,0EAA0E;AAC1E,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS;IAE9C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;IAHxB,YACW,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,EAC9C,OAAO,EAAE,MAAM,EACN,IAAI,CAAC,EAAE,MAAM,YAAA,EAGvB;CACF;AAED;;;GAGG;AACH,qBAAa,WAAW;IACF,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAzC,OAAO,eAA8C;IAErD,OAAa,EAAE,CAAC,MAAM,EAAE,MAAM,wBAE7B;IAED,6FAA6F;IACvF,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAc,EAAE,OAAO,EAAE,OAAe,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAUxJ;IAED,uDAAuD;IACjD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ7E;IAED;;;OAGG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAQhG;IAED;;;;OAIG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBjG;IAED,4CAA4C;IACtC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE;;;SAO3B;IAED,kFAAkF;IAC5E,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAcvE;IAED,gGAAgG;IAC1F,QAAQ,CAAC,IAAI,EAAE,MAAM,mBAO1B;YAEa,QAAQ;IAiBtB,OAAO,CAAC,OAAO;IAIf,gEAAgE;YAClD,KAAK;YAQL,QAAQ;YAUR,OAAO;IAMrB,mHAAmH;YACrG,MAAM;IAcpB,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { cp, lstat, mkdir, realpath, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { within } from '../lib/paths.js';
|
|
4
|
+
import { freeName } from './names.js';
|
|
5
|
+
import { fromTrash, moveAcross, restorable, toTrash } from './trash.js';
|
|
6
|
+
/** Why an operation was refused, for the API to tell as its own error. */
|
|
7
|
+
export class FileProblem extends Error {
|
|
8
|
+
kind;
|
|
9
|
+
path;
|
|
10
|
+
constructor(kind, message, path) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.kind = kind;
|
|
13
|
+
this.path = path;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* What can change which files a folder holds: each keeps to the folder, by real paths, so neither `..` nor a link
|
|
18
|
+
* leads out of it, and a name already taken is refused unless `replace` says to move what holds it to the Trash.
|
|
19
|
+
*/
|
|
20
|
+
export class FolderFiles {
|
|
21
|
+
root;
|
|
22
|
+
constructor(root) {
|
|
23
|
+
this.root = root;
|
|
24
|
+
}
|
|
25
|
+
static async of(folder) {
|
|
26
|
+
return new FolderFiles(await realpath(folder));
|
|
27
|
+
}
|
|
28
|
+
/** A file, empty or with `content`, or a folder; the folders it is in are made as needed. */
|
|
29
|
+
async create(path, { folder = false, content, replace = false }) {
|
|
30
|
+
const target = await this.target(path);
|
|
31
|
+
const replaced = await this.clear(target, replace);
|
|
32
|
+
await mkdir(dirname(target), { recursive: true });
|
|
33
|
+
if (folder)
|
|
34
|
+
await mkdir(target);
|
|
35
|
+
else
|
|
36
|
+
await writeFile(target, content ?? '', { flag: 'wx' });
|
|
37
|
+
return { path: this.named(target), replaced };
|
|
38
|
+
}
|
|
39
|
+
/** Gives a file or folder another name where it is. */
|
|
40
|
+
async rename(path, name, replace = false) {
|
|
41
|
+
if (!name || name === '.' || name === '..' || name.includes('/') || name.includes(sep)) {
|
|
42
|
+
throw new FileProblem('invalid', `“${name}” can't be a file's name.`);
|
|
43
|
+
}
|
|
44
|
+
const source = await this.existing(path);
|
|
45
|
+
return this.relocate([[source, join(dirname(source), name)]], replace);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Moves files and folders into a folder of the session's, each keeping its name; with `keepBoth`, one whose name is
|
|
49
|
+
* taken there takes the next free one, as the Finder's Keep Both names it, `box 2.tsx`.
|
|
50
|
+
*/
|
|
51
|
+
async move(paths, into, replace = false, keepBoth = false) {
|
|
52
|
+
const folder = await this.folderAt(into);
|
|
53
|
+
const sources = await Promise.all(paths.map((path) => this.existing(path)));
|
|
54
|
+
const pairs = [];
|
|
55
|
+
for (const source of sources)
|
|
56
|
+
pairs.push([source, join(folder, keepBoth && dirname(source) !== folder ? await freeName(folder, basename(source), '') : basename(source))]);
|
|
57
|
+
return this.relocate(pairs, replace);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Copies files and folders into a folder of the session's: ones of the folder by their paths in it, others, as files
|
|
61
|
+
* dropped from the Finder, by their whole paths. Copied into the folder it is in, a copy takes a name of its own, as
|
|
62
|
+
* one whose name is taken does with `keepBoth`.
|
|
63
|
+
*/
|
|
64
|
+
async copy(paths, into, replace = false, keepBoth = false) {
|
|
65
|
+
const folder = await this.folderAt(into);
|
|
66
|
+
const copied = [];
|
|
67
|
+
const replaced = [];
|
|
68
|
+
for (const path of paths) {
|
|
69
|
+
const source = isAbsolute(path) && within(path, this.root) === undefined ? await this.outside(path) : await this.existing(path);
|
|
70
|
+
const own = dirname(source) === folder;
|
|
71
|
+
const name = own ? await freeName(folder, basename(source), 'copy') : keepBoth ? await freeName(folder, basename(source), '') : basename(source);
|
|
72
|
+
const target = join(folder, name);
|
|
73
|
+
this.notInto(source, target);
|
|
74
|
+
replaced.push(...(await this.clear(target, replace)));
|
|
75
|
+
await cp(source, target, { recursive: true, verbatimSymlinks: true, errorOnExist: true, force: false });
|
|
76
|
+
copied.push({ from: within(source, this.root) === undefined ? source : this.named(source), to: this.named(target) });
|
|
77
|
+
}
|
|
78
|
+
return { copied, replaced };
|
|
79
|
+
}
|
|
80
|
+
/** Moves files and folders to the Trash. */
|
|
81
|
+
async delete(paths) {
|
|
82
|
+
const sources = await Promise.all(paths.map((path) => this.existing(path)));
|
|
83
|
+
const trashed = [];
|
|
84
|
+
for (const source of sources)
|
|
85
|
+
trashed.push({ path: this.named(source), trash: await toTrash(source) });
|
|
86
|
+
return trashed;
|
|
87
|
+
}
|
|
88
|
+
/** Puts back what `delete` or a replace sent to the Trash, at the path it had. */
|
|
89
|
+
async restore(items, replace = false) {
|
|
90
|
+
const restored = [];
|
|
91
|
+
const replaced = [];
|
|
92
|
+
for (const { path, trash } of items) {
|
|
93
|
+
const target = await this.target(path);
|
|
94
|
+
if (!(await restorable(trash)))
|
|
95
|
+
throw new FileProblem('missing', `${path} isn't in the Trash any more.`, path);
|
|
96
|
+
replaced.push(...(await this.clear(target, replace)));
|
|
97
|
+
await fromTrash(trash, target);
|
|
98
|
+
restored.push(this.named(target));
|
|
99
|
+
}
|
|
100
|
+
return { restored, replaced };
|
|
101
|
+
}
|
|
102
|
+
/** A folder of the session's by its path there, `''` for the folder itself, as a whole path. */
|
|
103
|
+
async folderAt(path) {
|
|
104
|
+
const folder = path === '' || path === '.' ? this.root : await this.existing(path).then((each) => realpath(each));
|
|
105
|
+
const info = await lstat(folder);
|
|
106
|
+
if (!info.isDirectory() || within(folder, this.root) === undefined)
|
|
107
|
+
throw new FileProblem('missing', `${path} isn't a folder in this session's folder.`, path);
|
|
108
|
+
return folder;
|
|
109
|
+
}
|
|
110
|
+
async relocate(pairs, replace) {
|
|
111
|
+
const moved = [];
|
|
112
|
+
const replaced = [];
|
|
113
|
+
for (const [source, target] of pairs) {
|
|
114
|
+
if (source === target)
|
|
115
|
+
continue;
|
|
116
|
+
this.notInto(source, target);
|
|
117
|
+
// A name that differs only in case is the same file on a disk that ignores case, which is no clash.
|
|
118
|
+
if (!(await sameFile(source, target)))
|
|
119
|
+
replaced.push(...(await this.clear(target, replace)));
|
|
120
|
+
await moveAcross(source, target);
|
|
121
|
+
moved.push({ from: this.named(source), to: this.named(target) });
|
|
122
|
+
}
|
|
123
|
+
return { moved, replaced };
|
|
124
|
+
}
|
|
125
|
+
notInto(source, target) {
|
|
126
|
+
if (target.startsWith(`${source}${sep}`))
|
|
127
|
+
throw new FileProblem('invalid', `${this.named(source)} can't go into itself.`, this.named(source));
|
|
128
|
+
}
|
|
129
|
+
/** What holds `target`, to the Trash when `replace` says so. */
|
|
130
|
+
async clear(target, replace) {
|
|
131
|
+
if (!(await lstat(target).catch(() => undefined)))
|
|
132
|
+
return [];
|
|
133
|
+
if (!replace)
|
|
134
|
+
throw new FileProblem('taken', `${this.named(target)} is already there.`, this.named(target));
|
|
135
|
+
return [{ path: this.named(target), trash: await toTrash(target) }];
|
|
136
|
+
}
|
|
137
|
+
// A path that is there, its last part not followed, so a link is moved itself rather than what it points at.
|
|
138
|
+
async existing(path) {
|
|
139
|
+
const absolute = resolve(this.root, path);
|
|
140
|
+
const parent = within(absolute, this.root) === undefined ? undefined : await realpath(dirname(absolute)).catch(() => undefined);
|
|
141
|
+
const file = parent && join(parent, basename(absolute));
|
|
142
|
+
const there = file && file !== this.root && within(file, this.root) !== undefined && (await lstat(file).catch(() => undefined));
|
|
143
|
+
if (!file || !there)
|
|
144
|
+
throw new FileProblem('missing', `${path} isn't in this session's folder.`, path);
|
|
145
|
+
return file;
|
|
146
|
+
}
|
|
147
|
+
async outside(path) {
|
|
148
|
+
if (!(await lstat(path).catch(() => undefined)))
|
|
149
|
+
throw new FileProblem('missing', `${path} isn't there.`, path);
|
|
150
|
+
return path;
|
|
151
|
+
}
|
|
152
|
+
/** Where something new goes: under the deepest folder of its path that is there, which has to be in the folder. */
|
|
153
|
+
async target(path) {
|
|
154
|
+
const absolute = resolve(this.root, path);
|
|
155
|
+
if (within(absolute, this.root) === undefined || absolute === this.root)
|
|
156
|
+
throw new FileProblem('missing', `${path} isn't in this session's folder.`, path);
|
|
157
|
+
let base = dirname(absolute);
|
|
158
|
+
while (!(await lstat(base).catch(() => undefined)))
|
|
159
|
+
base = dirname(base);
|
|
160
|
+
const real = await realpath(base);
|
|
161
|
+
if (within(real, this.root) === undefined)
|
|
162
|
+
throw new FileProblem('missing', `${path} isn't in this session's folder.`, path);
|
|
163
|
+
return join(real, relative(base, absolute));
|
|
164
|
+
}
|
|
165
|
+
named(file) {
|
|
166
|
+
return relative(this.root, file);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function sameFile(one, other) {
|
|
170
|
+
const [a, b] = await Promise.all([lstat(one), lstat(other).catch(() => undefined)]);
|
|
171
|
+
return b !== undefined && a.dev === b.dev && a.ino === b.ino;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/files/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Replaced, SearchQuery, SearchResults } from './types.js';
|
|
2
|
+
/** What `query` asks for as a regular expression; throws one that isn't valid. */
|
|
3
|
+
export declare function patternOf({ query, caseSensitive, wholeWord, regex }: SearchQuery): RegExp;
|
|
4
|
+
/** Every line of the folder's files the query finds, file by file in the order git lists them, up to a limit. */
|
|
5
|
+
export declare function searchFiles(folder: string, search: SearchQuery): Promise<SearchResults>;
|
|
6
|
+
/**
|
|
7
|
+
* Replaces what the query finds with `replacement` in the folder's files, or in `paths` of them only, and writes those
|
|
8
|
+
* it changed. In a regular expression `$1` and the like stand for what it caught; otherwise the text goes in as it is.
|
|
9
|
+
*/
|
|
10
|
+
export declare function replaceInFiles(folder: string, search: SearchQuery, replacement: string, paths?: string[]): Promise<Replaced>;
|
|
11
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/files/search.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAe,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AASpF,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,UAIhF;AAED,iHAAiH;AACjH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAqB7F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsBlI"}
|