@aprovan/patchwork 0.1.0 → 0.1.1

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.
Files changed (71) hide show
  1. package/.github/workflows/publish.yml +1 -1
  2. package/.vscode/launch.json +19 -0
  3. package/README.md +24 -0
  4. package/apps/chat/package.json +4 -4
  5. package/apps/chat/vite.config.ts +8 -8
  6. package/docs/specs/directory-sync.md +822 -0
  7. package/docs/specs/patchwork-vscode.md +625 -0
  8. package/package.json +2 -2
  9. package/packages/compiler/package.json +3 -2
  10. package/packages/compiler/src/index.ts +13 -14
  11. package/packages/compiler/src/vfs/backends/http.ts +139 -0
  12. package/packages/compiler/src/vfs/backends/indexeddb.ts +185 -24
  13. package/packages/compiler/src/vfs/backends/memory.ts +166 -0
  14. package/packages/compiler/src/vfs/core/index.ts +26 -0
  15. package/packages/compiler/src/vfs/core/types.ts +93 -0
  16. package/packages/compiler/src/vfs/core/utils.ts +42 -0
  17. package/packages/compiler/src/vfs/core/virtual-fs.ts +120 -0
  18. package/packages/compiler/src/vfs/index.ts +37 -5
  19. package/packages/compiler/src/vfs/project.ts +16 -16
  20. package/packages/compiler/src/vfs/store.ts +183 -19
  21. package/packages/compiler/src/vfs/sync/differ.ts +47 -0
  22. package/packages/compiler/src/vfs/sync/engine.ts +398 -0
  23. package/packages/compiler/src/vfs/sync/index.ts +3 -0
  24. package/packages/compiler/src/vfs/sync/resolver.ts +46 -0
  25. package/packages/compiler/src/vfs/types.ts +1 -8
  26. package/packages/compiler/tsup.config.ts +5 -5
  27. package/packages/editor/package.json +1 -1
  28. package/packages/editor/src/components/CodeBlockExtension.tsx +1 -1
  29. package/packages/editor/src/components/CodePreview.tsx +59 -1
  30. package/packages/editor/src/components/edit/CodeBlockView.tsx +72 -0
  31. package/packages/editor/src/components/edit/EditModal.tsx +169 -28
  32. package/packages/editor/src/components/edit/FileTree.tsx +67 -13
  33. package/packages/editor/src/components/edit/MediaPreview.tsx +106 -0
  34. package/packages/editor/src/components/edit/SaveConfirmDialog.tsx +60 -0
  35. package/packages/editor/src/components/edit/fileTypes.ts +125 -0
  36. package/packages/editor/src/components/edit/index.ts +4 -0
  37. package/packages/editor/src/components/edit/types.ts +3 -0
  38. package/packages/editor/src/components/edit/useEditSession.ts +22 -4
  39. package/packages/editor/src/index.ts +17 -0
  40. package/packages/editor/src/lib/diff.ts +2 -1
  41. package/packages/editor/src/lib/vfs.ts +28 -10
  42. package/packages/editor/tsup.config.ts +10 -5
  43. package/packages/stitchery/package.json +5 -3
  44. package/packages/stitchery/src/server/index.ts +57 -57
  45. package/packages/stitchery/src/server/vfs-routes.ts +246 -56
  46. package/packages/stitchery/tsup.config.ts +5 -5
  47. package/packages/utcp/package.json +3 -2
  48. package/packages/utcp/tsconfig.json +6 -2
  49. package/packages/utcp/tsup.config.ts +6 -6
  50. package/packages/vscode/README.md +31 -0
  51. package/packages/vscode/media/outline.png +0 -0
  52. package/packages/vscode/media/outline.svg +70 -0
  53. package/packages/vscode/media/patchwork.png +0 -0
  54. package/packages/vscode/media/patchwork.svg +72 -0
  55. package/packages/vscode/node_modules/.bin/jiti +17 -0
  56. package/packages/vscode/node_modules/.bin/tsc +17 -0
  57. package/packages/vscode/node_modules/.bin/tsserver +17 -0
  58. package/packages/vscode/node_modules/.bin/tsup +17 -0
  59. package/packages/vscode/node_modules/.bin/tsup-node +17 -0
  60. package/packages/vscode/node_modules/.bin/tsx +17 -0
  61. package/packages/vscode/package.json +136 -0
  62. package/packages/vscode/src/extension.ts +612 -0
  63. package/packages/vscode/src/providers/PatchworkFileSystemProvider.ts +205 -0
  64. package/packages/vscode/src/providers/PatchworkTreeProvider.ts +177 -0
  65. package/packages/vscode/src/providers/PreviewPanelProvider.ts +536 -0
  66. package/packages/vscode/src/services/EditService.ts +24 -0
  67. package/packages/vscode/src/services/EmbeddedStitchery.ts +82 -0
  68. package/packages/vscode/tsconfig.json +13 -0
  69. package/packages/vscode/tsup.config.ts +11 -0
  70. package/packages/compiler/src/vfs/backends/local-fs.ts +0 -41
  71. package/packages/compiler/src/vfs/backends/s3.ts +0 -60
@@ -5,9 +5,11 @@ import {
5
5
  readdir,
6
6
  stat,
7
7
  mkdir,
8
- } from 'node:fs/promises';
9
- import { join, relative, dirname } from 'node:path';
10
- import type { IncomingMessage, ServerResponse } from 'node:http';
8
+ rm,
9
+ } from "node:fs/promises";
10
+ import { watch } from "node:fs";
11
+ import { dirname, resolve, sep } from "node:path";
12
+ import type { IncomingMessage, ServerResponse } from "node:http";
11
13
 
12
14
  export interface VFSContext {
13
15
  rootDir: string;
@@ -15,27 +17,57 @@ export interface VFSContext {
15
17
  log: (...args: unknown[]) => void;
16
18
  }
17
19
 
18
- async function listFilesRecursive(dir: string): Promise<string[]> {
20
+ function normalizeRelPath(path: string): string {
21
+ const decoded = decodeURIComponent(path).replace(/\\/g, "/");
22
+ return decoded.replace(/^\/+|\/+$/g, "");
23
+ }
24
+
25
+ function resolvePath(rootDir: string, relPath: string): string {
26
+ const root = resolve(rootDir);
27
+ const full = resolve(root, relPath);
28
+ if (full !== root && !full.startsWith(`${root}${sep}`)) {
29
+ throw new Error("Invalid path");
30
+ }
31
+ return full;
32
+ }
33
+
34
+ function joinRelPath(base: string, name: string): string {
35
+ return base ? `${base}/${name}` : name;
36
+ }
37
+
38
+ async function listAllFiles(
39
+ rootDir: string,
40
+ relPath: string,
41
+ ): Promise<string[]> {
42
+ const targetPath = resolvePath(rootDir, relPath);
43
+ let entries: Awaited<ReturnType<typeof readdir>> = [];
19
44
  try {
20
- const entries = await readdir(dir, { withFileTypes: true });
21
- const files: string[] = [];
22
- for (const entry of entries) {
23
- const full = join(dir, entry.name);
24
- if (entry.isDirectory()) {
25
- files.push(...(await listFilesRecursive(full)));
26
- } else {
27
- files.push(full);
28
- }
29
- }
30
- return files;
45
+ entries = await readdir(targetPath, { withFileTypes: true });
31
46
  } catch {
32
47
  return [];
33
48
  }
49
+
50
+ const results: string[] = [];
51
+ for (const entry of entries) {
52
+ const entryRelPath = joinRelPath(relPath, entry.name);
53
+ if (entry.isDirectory()) {
54
+ results.push(...(await listAllFiles(rootDir, entryRelPath)));
55
+ } else {
56
+ results.push(entryRelPath);
57
+ }
58
+ }
59
+
60
+ return results.sort((a, b) => a.localeCompare(b));
34
61
  }
35
62
 
36
63
  async function ensureDir(filePath: string): Promise<void> {
37
- const dir = dirname(filePath);
38
- await mkdir(dir, { recursive: true });
64
+ await mkdir(dirname(filePath), { recursive: true });
65
+ }
66
+
67
+ function sendJson(res: ServerResponse, status: number, body: unknown): void {
68
+ res.setHeader("Content-Type", "application/json");
69
+ res.writeHead(status);
70
+ res.end(JSON.stringify(body));
39
71
  }
40
72
 
41
73
  export function handleVFS(
@@ -43,81 +75,239 @@ export function handleVFS(
43
75
  res: ServerResponse,
44
76
  ctx: VFSContext,
45
77
  ): boolean {
46
- const url = req.url || '/';
47
- const method = req.method || 'GET';
78
+ const url = req.url || "/";
79
+ const method = req.method || "GET";
48
80
 
49
- if (!url.startsWith('/vfs')) return false;
81
+ if (!url.startsWith("/vfs")) return false;
50
82
 
51
83
  // Handle config endpoint
52
- if (url === '/vfs/config' && method === 'GET') {
53
- res.setHeader('Content-Type', 'application/json');
84
+ if (url === "/vfs/config" && method === "GET") {
85
+ res.setHeader("Content-Type", "application/json");
54
86
  res.writeHead(200);
55
87
  res.end(JSON.stringify({ usePaths: ctx.usePaths }));
56
88
  return true;
57
89
  }
58
90
 
59
91
  const handleRequest = async () => {
60
- const path = url.slice(4).split('?')[0] || '';
61
- const query = new URL(url, 'http://localhost').searchParams;
62
-
63
- if (path === '' || path === '/') {
64
- if (method === 'GET') {
65
- const prefix = query.get('prefix') || '';
66
- const files = await listFilesRecursive(join(ctx.rootDir, prefix));
67
- const relativePaths = files.map((f) => relative(ctx.rootDir, f));
68
- res.setHeader('Content-Type', 'application/json');
69
- res.writeHead(200);
70
- res.end(JSON.stringify(relativePaths));
92
+ const urlObj = new URL(url, "http://localhost");
93
+ const query = urlObj.searchParams;
94
+ const rawPath = urlObj.pathname.slice(4);
95
+ const relPath = normalizeRelPath(rawPath);
96
+
97
+ if (query.has("watch")) {
98
+ if (method !== "GET") {
99
+ res.writeHead(405);
100
+ res.end("Method not allowed");
71
101
  return;
72
102
  }
103
+
104
+ const watchPath = normalizeRelPath(query.get("watch") || "");
105
+ const fullWatchPath = resolvePath(ctx.rootDir, watchPath);
106
+ let watchStats;
107
+ try {
108
+ watchStats = await stat(fullWatchPath);
109
+ } catch {
110
+ res.writeHead(404);
111
+ res.end("Not found");
112
+ return;
113
+ }
114
+
115
+ res.setHeader("Content-Type", "text/event-stream");
116
+ res.setHeader("Cache-Control", "no-cache");
117
+ res.setHeader("Connection", "keep-alive");
118
+ res.writeHead(200);
119
+
120
+ const watcher = watch(
121
+ fullWatchPath,
122
+ { recursive: watchStats.isDirectory() },
123
+ async (eventType, filename) => {
124
+ const eventPath = normalizeRelPath(
125
+ [watchPath, filename ? filename.toString() : ""]
126
+ .filter(Boolean)
127
+ .join("/"),
128
+ );
129
+ const fullEventPath = resolvePath(ctx.rootDir, eventPath);
130
+
131
+ let type: "create" | "update" | "delete" = "update";
132
+ if (eventType === "rename") {
133
+ try {
134
+ await stat(fullEventPath);
135
+ type = "create";
136
+ } catch {
137
+ type = "delete";
138
+ }
139
+ }
140
+
141
+ res.write("event: change\n");
142
+ res.write(
143
+ `data: ${JSON.stringify({
144
+ type,
145
+ path: eventPath,
146
+ mtime: new Date().toISOString(),
147
+ })}\n\n`,
148
+ );
149
+ },
150
+ );
151
+
152
+ req.on("close", () => watcher.close());
153
+ return;
73
154
  }
74
155
 
75
- const filePath = join(ctx.rootDir, path.slice(1));
156
+ if (method === "HEAD" && !relPath) {
157
+ res.writeHead(200);
158
+ res.end();
159
+ return;
160
+ }
161
+
162
+ if (method === "GET" && !relPath && !query.toString()) {
163
+ const files = await listAllFiles(ctx.rootDir, "");
164
+ sendJson(res, 200, files);
165
+ return;
166
+ }
167
+
168
+ if (!relPath && method !== "GET" && method !== "HEAD") {
169
+ res.writeHead(400);
170
+ res.end("Invalid path");
171
+ return;
172
+ }
173
+
174
+ const targetPath = resolvePath(ctx.rootDir, relPath);
175
+
176
+ if (method === "GET" && query.get("stat") === "true") {
177
+ try {
178
+ const stats = await stat(targetPath);
179
+ sendJson(res, 200, {
180
+ size: stats.size,
181
+ mtime: stats.mtime.toISOString(),
182
+ isFile: stats.isFile(),
183
+ isDirectory: stats.isDirectory(),
184
+ });
185
+ } catch {
186
+ res.writeHead(404);
187
+ res.end("Not found");
188
+ }
189
+ return;
190
+ }
191
+
192
+ if (method === "GET" && query.get("readdir") === "true") {
193
+ try {
194
+ const entries = await readdir(targetPath, { withFileTypes: true });
195
+ const mapped = entries
196
+ .map((entry) => ({
197
+ name: entry.name,
198
+ isDirectory: entry.isDirectory(),
199
+ }))
200
+ .sort((a, b) => a.name.localeCompare(b.name));
201
+ sendJson(res, 200, mapped);
202
+ } catch (err) {
203
+ const code = (err as NodeJS.ErrnoException).code;
204
+ if (code === "ENOTDIR") {
205
+ res.writeHead(409);
206
+ res.end("Not a directory");
207
+ return;
208
+ }
209
+ res.writeHead(404);
210
+ res.end("Not found");
211
+ }
212
+ return;
213
+ }
214
+
215
+ if (method === "POST" && query.get("mkdir") === "true") {
216
+ const recursive = query.get("recursive") === "true";
217
+ try {
218
+ await mkdir(targetPath, { recursive });
219
+ res.writeHead(200);
220
+ res.end("ok");
221
+ } catch {
222
+ res.writeHead(500);
223
+ res.end("Mkdir failed");
224
+ }
225
+ return;
226
+ }
76
227
 
77
228
  switch (method) {
78
- case 'GET': {
229
+ case "GET": {
79
230
  try {
80
- const content = await readFile(filePath, 'utf-8');
81
- res.setHeader('Content-Type', 'text/plain');
231
+ const content = await readFile(targetPath, "utf-8");
232
+ res.setHeader("Content-Type", "text/plain");
82
233
  res.writeHead(200);
83
234
  res.end(content);
84
235
  } catch {
85
236
  res.writeHead(404);
86
- res.end('Not found');
237
+ res.end("Not found");
87
238
  }
88
239
  return;
89
240
  }
90
- case 'PUT': {
91
- let body = '';
92
- req.on('data', (chunk) => (body += chunk));
93
- req.on('end', async () => {
241
+ case "PUT": {
242
+ let body = "";
243
+ req.on("data", (chunk) => (body += chunk));
244
+ req.on("end", async () => {
94
245
  try {
95
- await ensureDir(filePath);
96
- await writeFile(filePath, body, 'utf-8');
246
+ await ensureDir(targetPath);
247
+ await writeFile(targetPath, body, "utf-8");
97
248
  res.writeHead(200);
98
- res.end('ok');
249
+ res.end("ok");
99
250
  } catch (err) {
100
- ctx.log('VFS PUT error:', err);
251
+ ctx.log("VFS PUT error:", err);
101
252
  res.writeHead(500);
102
- res.end('Write failed');
253
+ res.end("Write failed");
103
254
  }
104
255
  });
105
256
  return;
106
257
  }
107
- case 'DELETE': {
258
+ case "DELETE": {
259
+ const recursive = query.get("recursive") === "true";
260
+ let stats;
261
+ try {
262
+ stats = await stat(targetPath);
263
+ } catch {
264
+ res.writeHead(404);
265
+ res.end("Not found");
266
+ return;
267
+ }
268
+
269
+ if (stats.isDirectory()) {
270
+ if (!recursive) {
271
+ try {
272
+ const entries = await readdir(targetPath);
273
+ if (entries.length > 0) {
274
+ res.writeHead(409);
275
+ res.end("Directory not empty");
276
+ return;
277
+ }
278
+ await rm(targetPath, { recursive: false });
279
+ res.writeHead(200);
280
+ res.end("ok");
281
+ } catch {
282
+ res.writeHead(500);
283
+ res.end("Delete failed");
284
+ }
285
+ return;
286
+ }
287
+ try {
288
+ await rm(targetPath, { recursive: true });
289
+ res.writeHead(200);
290
+ res.end("ok");
291
+ } catch {
292
+ res.writeHead(500);
293
+ res.end("Delete failed");
294
+ }
295
+ return;
296
+ }
297
+
108
298
  try {
109
- await unlink(filePath);
299
+ await unlink(targetPath);
110
300
  res.writeHead(200);
111
- res.end('ok');
301
+ res.end("ok");
112
302
  } catch {
113
303
  res.writeHead(404);
114
- res.end('Not found');
304
+ res.end("Not found");
115
305
  }
116
306
  return;
117
307
  }
118
- case 'HEAD': {
308
+ case "HEAD": {
119
309
  try {
120
- await stat(filePath);
310
+ await stat(targetPath);
121
311
  res.writeHead(200);
122
312
  res.end();
123
313
  } catch {
@@ -128,14 +318,14 @@ export function handleVFS(
128
318
  }
129
319
  default:
130
320
  res.writeHead(405);
131
- res.end('Method not allowed');
321
+ res.end("Method not allowed");
132
322
  }
133
323
  };
134
324
 
135
325
  handleRequest().catch((err) => {
136
- ctx.log('VFS error:', err);
326
+ ctx.log("VFS error:", err);
137
327
  res.writeHead(500);
138
- res.end('Internal error');
328
+ res.end("Internal error");
139
329
  });
140
330
 
141
331
  return true;
@@ -1,12 +1,12 @@
1
- import { defineConfig } from 'tsup';
1
+ import { defineConfig } from "tsup";
2
2
 
3
3
  export default defineConfig({
4
4
  entry: {
5
- index: 'src/index.ts',
6
- cli: 'src/cli.ts',
7
- 'server/index': 'src/server/index.ts',
5
+ index: "src/index.ts",
6
+ cli: "src/cli.ts",
7
+ "server/index": "src/server/index.ts",
8
8
  },
9
- format: ['esm'],
9
+ format: ["esm", "cjs"],
10
10
  dts: true,
11
11
  clean: true,
12
12
  sourcemap: true,
@@ -3,12 +3,13 @@
3
3
  "version": "0.1.0",
4
4
  "description": "UTCP backend integration for Patchwork",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
6
+ "main": "./dist/index.cjs",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
12
13
  }
13
14
  },
14
15
  "scripts": {
@@ -2,7 +2,11 @@
2
2
  "extends": "../../tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "./dist",
5
- "rootDir": "./src"
5
+ "rootDir": "..",
6
+ "baseUrl": ".",
7
+ "paths": {
8
+ "@aprovan/patchwork": ["../patchwork/src/index.ts"]
9
+ }
6
10
  },
7
- "include": ["src/**/*"]
11
+ "include": ["src/**/*", "../patchwork/src/**/*"]
8
12
  }
@@ -1,12 +1,12 @@
1
- import { defineConfig } from 'tsup';
1
+ import { defineConfig } from "tsup";
2
2
 
3
3
  export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['esm'],
4
+ entry: ["src/index.ts"],
5
+ format: ["esm", "cjs"],
6
6
  dts: true,
7
7
  clean: true,
8
8
  sourcemap: true,
9
- target: 'node20',
10
- outDir: 'dist',
11
- external: ['@aprovan/patchwork'],
9
+ target: "node20",
10
+ outDir: "dist",
11
+ external: ["@aprovan/patchwork"],
12
12
  });
@@ -0,0 +1,31 @@
1
+ # Patchwork VS Code Extension
2
+
3
+ Patchwork Viewer is a VS Code extension for opening Patchwork projects, previewing widgets, and syncing edits back to disk.
4
+
5
+ ## Commands
6
+
7
+ - `Patchwork: Open Project` (`patchwork.openProject`)
8
+ - `Patchwork: Export Project` (`patchwork.exportProject`)
9
+ - `Patchwork: Show Preview` (`patchwork.showPreview`)
10
+ - `Patchwork: Edit with AI` (`patchwork.editWithAI`)
11
+ - `Patchwork: Show Edit History` (`patchwork.showEditHistory`)
12
+ - `Patchwork: Test Copilot Proxy` (`patchwork.testConnection`)
13
+
14
+ ## Settings
15
+
16
+ - `patchwork.copilotProxyUrl`: Base URL for the Copilot proxy server.
17
+ - `patchwork.mcpServers`: MCP server configs (name, command, args).
18
+ - `patchwork.utcpConfig`: UTCP configuration for service registration.
19
+
20
+ ## Keybindings
21
+
22
+ - `Cmd+Shift+Alt+P`: Show Patchwork Preview
23
+ - `Cmd+Shift+Alt+E`: Edit with AI (selected code)
24
+ - `Cmd+Shift+Alt+H`: Show Edit History
25
+
26
+ ## Development
27
+
28
+ ```bash
29
+ pnpm --filter @aprovan/patchwork-vscode build
30
+ pnpm --filter @aprovan/patchwork-vscode dev
31
+ ```
@@ -0,0 +1,70 @@
1
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2
+ width="100%" viewBox="0 0 336 336" enable-background="new 0 0 336 336" xml:space="preserve">
3
+ <path fill="#000000" opacity="1.000000" stroke="none"
4
+ d="
5
+ M152.000000,337.000000
6
+ C101.333344,337.000000 51.166683,337.000000 1.000020,337.000000
7
+ C1.000013,225.000031 1.000013,113.000061 1.000007,1.000065
8
+ C112.999947,1.000044 224.999893,1.000044 336.999878,1.000022
9
+ C336.999939,112.999931 336.999939,224.999863 336.999969,336.999878
10
+ C275.500000,337.000000 214.000000,337.000000 152.000000,337.000000
11
+ M93.196281,166.261337
12
+ C100.770424,174.654449 109.507950,180.155777 121.377304,181.074783
13
+ C144.430206,182.859695 164.816849,162.887146 162.995041,138.852432
14
+ C161.425385,118.144455 141.941452,98.219574 115.832298,103.695320
15
+ C86.953171,109.752014 75.672241,143.447800 93.196281,166.261337
16
+ M213.624863,163.442642
17
+ C222.153275,163.231750 231.186264,157.583130 233.468781,150.947678
18
+ C237.582123,138.989868 233.959045,124.391647 217.375061,121.223755
19
+ C207.997711,119.432487 195.747040,126.108696 193.148285,134.999390
20
+ C189.314651,148.114777 198.639481,161.612564 213.624863,163.442642
21
+ M156.886856,213.755325
22
+ C153.925049,213.940735 150.963226,214.126129 147.855179,214.320694
23
+ C147.855179,220.513016 147.855179,226.567719 147.855179,232.605728
24
+ C179.550980,233.856476 210.824387,208.428116 216.870972,188.608521
25
+ C212.298660,187.360626 207.653397,186.333801 203.190536,184.782257
26
+ C200.610748,183.885361 199.528000,184.444382 198.027328,186.681854
27
+ C188.309372,201.171295 175.006470,210.375549 156.886856,213.755325
28
+ z"/>
29
+ <path fill="#F5F7FD" opacity="1.000000" stroke="none"
30
+ d="
31
+ M92.949310,166.000244
32
+ C75.672241,143.447800 86.953171,109.752014 115.832298,103.695320
33
+ C141.941452,98.219574 161.425385,118.144455 162.995041,138.852432
34
+ C164.816849,162.887146 144.430206,182.859695 121.377304,181.074783
35
+ C109.507950,180.155777 100.770424,174.654449 92.949310,166.000244
36
+ M121.725945,121.729195
37
+ C119.649338,122.159027 117.372192,122.179886 115.528221,123.084129
38
+ C102.119904,129.659180 97.660942,148.377686 112.702919,159.308014
39
+ C119.427475,164.194412 130.724854,163.348480 137.073151,157.873138
40
+ C145.445633,150.651962 146.667221,139.959183 142.131287,132.396027
41
+ C137.722137,125.044228 131.650635,120.708099 121.725945,121.729195
42
+ z"/>
43
+ <path fill="#F8F9FD" opacity="1.000000" stroke="none"
44
+ d="
45
+ M213.210052,163.440598
46
+ C198.639481,161.612564 189.314651,148.114777 193.148285,134.999390
47
+ C195.747040,126.108696 207.997711,119.432487 217.375061,121.223755
48
+ C233.959045,124.391647 237.582123,138.989868 233.468781,150.947678
49
+ C231.186264,157.583130 222.153275,163.231750 213.210052,163.440598
50
+ z"/>
51
+ <path fill="#F5F7FD" opacity="1.000000" stroke="none"
52
+ d="
53
+ M157.244431,213.504639
54
+ C175.006470,210.375549 188.309372,201.171295 198.027328,186.681854
55
+ C199.528000,184.444382 200.610748,183.885361 203.190536,184.782257
56
+ C207.653397,186.333801 212.298660,187.360626 216.870972,188.608521
57
+ C210.824387,208.428116 179.550980,233.856476 147.855179,232.605728
58
+ C147.855179,226.567719 147.855179,220.513016 147.855179,214.320694
59
+ C150.963226,214.126129 153.925049,213.940735 157.244431,213.504639
60
+ z"/>
61
+ <path fill="#000000" opacity="1.000000" stroke="none"
62
+ d="
63
+ M122.181000,121.777527
64
+ C131.650635,120.708099 137.722137,125.044228 142.131287,132.396027
65
+ C146.667221,139.959183 145.445633,150.651962 137.073151,157.873138
66
+ C130.724854,163.348480 119.427475,164.194412 112.702919,159.308014
67
+ C97.660942,148.377686 102.119904,129.659180 115.528221,123.084129
68
+ C117.372192,122.179886 119.649338,122.159027 122.181000,121.777527
69
+ z"/>
70
+ </svg>
@@ -0,0 +1,72 @@
1
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2
+ width="100%" viewBox="0 0 336 336" enable-background="new 0 0 336 336" xml:space="preserve">
3
+ <path fill="#3059D4" opacity="1.000000" stroke="none"
4
+ d="
5
+ M152.000000,337.000000
6
+ C101.333344,337.000000 51.166683,337.000000 1.000020,337.000000
7
+ C1.000013,225.000031 1.000013,113.000061 1.000007,1.000065
8
+ C112.999947,1.000044 224.999893,1.000044 336.999878,1.000022
9
+ C336.999939,112.999931 336.999939,224.999863 336.999969,336.999878
10
+ C275.500000,337.000000 214.000000,337.000000 152.000000,337.000000
11
+ M93.980904,117.485725
12
+ C80.263412,134.303772 82.603081,158.166016 99.314697,171.884918
13
+ C116.440109,185.943497 140.148102,183.292328 154.846756,165.675034
14
+ C167.992661,149.918793 164.827667,125.333229 147.840790,111.252892
15
+ C132.319046,98.386986 107.835983,100.991982 93.980904,117.485725
16
+ M216.172760,162.929596
17
+ C225.867188,161.315903 232.070618,155.787811 234.469101,146.253860
18
+ C236.407928,138.547150 232.923737,129.540771 225.935318,124.815331
19
+ C218.682510,119.911118 210.934479,119.673912 203.324478,124.015686
20
+ C195.283951,128.603104 191.404617,138.386856 193.794647,147.201721
21
+ C196.453827,157.009277 204.468170,162.884003 216.172760,162.929596
22
+ M170.393631,210.076569
23
+ C163.046021,211.875854 155.698410,213.675140 148.243820,215.500626
24
+ C148.243820,220.751282 148.243820,226.350037 148.243820,231.927643
25
+ C175.580719,233.511520 207.048187,212.813141 216.859344,188.926392
26
+ C212.378143,187.653473 207.904816,186.470901 203.492065,185.094116
27
+ C201.091522,184.345123 199.652283,184.835846 198.223221,187.081223
28
+ C191.601929,197.484787 182.403381,204.927856 170.393631,210.076569
29
+ z"/>
30
+ <path fill="#FDFDFE" opacity="1.000000" stroke="none"
31
+ d="
32
+ M94.207321,117.210541
33
+ C107.835983,100.991982 132.319046,98.386986 147.840790,111.252892
34
+ C164.827667,125.333229 167.992661,149.918793 154.846756,165.675034
35
+ C140.148102,183.292328 116.440109,185.943497 99.314697,171.884918
36
+ C82.603081,158.166016 80.263412,134.303772 94.207321,117.210541
37
+ M138.505569,157.023026
38
+ C144.863892,150.363983 146.846893,142.669434 143.255798,134.082870
39
+ C139.871994,125.991959 133.549652,121.403931 124.724533,121.127022
40
+ C115.942032,120.851448 109.399979,124.904480 105.311424,132.739258
41
+ C100.931969,141.131470 103.009468,151.494095 110.277122,157.689835
42
+ C118.796677,164.952850 128.281952,164.887268 138.505569,157.023026
43
+ z"/>
44
+ <path fill="#FCFDFE" opacity="1.000000" stroke="none"
45
+ d="
46
+ M215.737030,162.948135
47
+ C204.468170,162.884003 196.453827,157.009277 193.794647,147.201721
48
+ C191.404617,138.386856 195.283951,128.603104 203.324478,124.015686
49
+ C210.934479,119.673912 218.682510,119.911118 225.935318,124.815331
50
+ C232.923737,129.540771 236.407928,138.547150 234.469101,146.253860
51
+ C232.070618,155.787811 225.867188,161.315903 215.737030,162.948135
52
+ z"/>
53
+ <path fill="#FCFDFE" opacity="1.000000" stroke="none"
54
+ d="
55
+ M170.767456,209.972427
56
+ C182.403381,204.927856 191.601929,197.484787 198.223221,187.081223
57
+ C199.652283,184.835846 201.091522,184.345123 203.492065,185.094116
58
+ C207.904816,186.470901 212.378143,187.653473 216.859344,188.926392
59
+ C207.048187,212.813141 175.580719,233.511520 148.243820,231.927643
60
+ C148.243820,226.350037 148.243820,220.751282 148.243820,215.500626
61
+ C155.698410,213.675140 163.046021,211.875854 170.767456,209.972427
62
+ z"/>
63
+ <path fill="#335BD5" opacity="1.000000" stroke="none"
64
+ d="
65
+ M138.231918,157.260757
66
+ C128.281952,164.887268 118.796677,164.952850 110.277122,157.689835
67
+ C103.009468,151.494095 100.931969,141.131470 105.311424,132.739258
68
+ C109.399979,124.904480 115.942032,120.851448 124.724533,121.127022
69
+ C133.549652,121.403931 139.871994,125.991959 143.255798,134.082870
70
+ C146.846893,142.669434 144.863892,150.363983 138.231918,157.260757
71
+ z"/>
72
+ </svg>
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/patchwork/patchwork/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/jiti@1.21.7/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/patchwork/patchwork/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/jiti@1.21.7/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/jiti.js" "$@"
15
+ else
16
+ exec node "$basedir/../../../../node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/jiti.js" "$@"
17
+ fi
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/patchwork/patchwork/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/patchwork/patchwork/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/patchwork/patchwork/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
15
+ else
16
+ exec node "$basedir/../typescript/bin/tsc" "$@"
17
+ fi