@symbiosis-lab/moss-api 0.3.0 → 0.5.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/index.d.mts +164 -47
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +225 -51
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -21,17 +21,20 @@ interface PluginManifest {
|
|
|
21
21
|
type PluginCategory = "generator" | "deployer" | "syndicator" | "enhancer" | "processor";
|
|
22
22
|
//#endregion
|
|
23
23
|
//#region src/types/context.d.ts
|
|
24
|
+
|
|
24
25
|
/**
|
|
25
26
|
* Base context shared by all hooks
|
|
27
|
+
*
|
|
28
|
+
* Contains only business data - no paths.
|
|
29
|
+
* Use readFile(), writeFile() for project files.
|
|
30
|
+
* Use readPluginFile(), writePluginFile() for plugin storage.
|
|
26
31
|
*/
|
|
27
32
|
interface BaseContext {
|
|
28
|
-
project_path: string;
|
|
29
|
-
moss_dir: string;
|
|
30
33
|
project_info: ProjectInfo;
|
|
31
34
|
config: Record<string, unknown>;
|
|
32
35
|
}
|
|
33
36
|
/**
|
|
34
|
-
* Context for before_build hook
|
|
37
|
+
* Context for before_build hook (process capability)
|
|
35
38
|
*/
|
|
36
39
|
interface BeforeBuildContext extends BaseContext {}
|
|
37
40
|
/**
|
|
@@ -44,14 +47,12 @@ interface OnBuildContext extends BaseContext {
|
|
|
44
47
|
* Context for on_deploy hook (deployer plugins)
|
|
45
48
|
*/
|
|
46
49
|
interface OnDeployContext extends BaseContext {
|
|
47
|
-
output_dir: string;
|
|
48
50
|
site_files: string[];
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
53
|
* Context for after_deploy hook (syndicator plugins)
|
|
52
54
|
*/
|
|
53
55
|
interface AfterDeployContext extends BaseContext {
|
|
54
|
-
output_dir: string;
|
|
55
56
|
site_files: string[];
|
|
56
57
|
articles: ArticleInfo[];
|
|
57
58
|
deployment?: DeploymentInfo;
|
|
@@ -218,70 +219,170 @@ declare function closeBrowser(): Promise<void>;
|
|
|
218
219
|
/**
|
|
219
220
|
* File system operations for Moss plugins
|
|
220
221
|
*
|
|
221
|
-
* These functions
|
|
222
|
-
*
|
|
222
|
+
* These functions provide access to project files (user content).
|
|
223
|
+
* Project path is auto-detected from the runtime context.
|
|
224
|
+
*
|
|
225
|
+
* For plugin's private storage, use the plugin-storage API instead.
|
|
223
226
|
*/
|
|
224
227
|
/**
|
|
225
228
|
* Read a file from the project directory
|
|
226
229
|
*
|
|
227
|
-
*
|
|
230
|
+
* Project path is auto-detected from the runtime context.
|
|
231
|
+
*
|
|
228
232
|
* @param relativePath - Path relative to the project root
|
|
229
233
|
* @returns File contents as a string
|
|
230
|
-
* @throws Error if file cannot be read
|
|
234
|
+
* @throws Error if file cannot be read or called outside a hook
|
|
231
235
|
*
|
|
232
236
|
* @example
|
|
233
237
|
* ```typescript
|
|
234
|
-
*
|
|
238
|
+
* // Read an article
|
|
239
|
+
* const content = await readFile("article/hello-world.md");
|
|
240
|
+
*
|
|
241
|
+
* // Read package.json
|
|
242
|
+
* const pkg = JSON.parse(await readFile("package.json"));
|
|
235
243
|
* ```
|
|
236
244
|
*/
|
|
237
|
-
declare function readFile(
|
|
245
|
+
declare function readFile(relativePath: string): Promise<string>;
|
|
238
246
|
/**
|
|
239
247
|
* Write content to a file in the project directory
|
|
240
248
|
*
|
|
241
249
|
* Creates parent directories if they don't exist.
|
|
250
|
+
* Project path is auto-detected from the runtime context.
|
|
242
251
|
*
|
|
243
|
-
* @param projectPath - Absolute path to the project directory
|
|
244
252
|
* @param relativePath - Path relative to the project root
|
|
245
253
|
* @param content - Content to write to the file
|
|
246
|
-
* @throws Error if file cannot be written
|
|
254
|
+
* @throws Error if file cannot be written or called outside a hook
|
|
247
255
|
*
|
|
248
256
|
* @example
|
|
249
257
|
* ```typescript
|
|
250
|
-
*
|
|
258
|
+
* // Write a generated article
|
|
259
|
+
* await writeFile("article/new-post.md", "# Hello World\n\nContent here.");
|
|
260
|
+
*
|
|
261
|
+
* // Write index page
|
|
262
|
+
* await writeFile("index.md", markdownContent);
|
|
251
263
|
* ```
|
|
252
264
|
*/
|
|
253
|
-
declare function writeFile(
|
|
265
|
+
declare function writeFile(relativePath: string, content: string): Promise<void>;
|
|
254
266
|
/**
|
|
255
|
-
* List all files in
|
|
267
|
+
* List all files in the project directory
|
|
256
268
|
*
|
|
257
269
|
* Returns file paths relative to the project root.
|
|
270
|
+
* Project path is auto-detected from the runtime context.
|
|
258
271
|
*
|
|
259
|
-
* @param projectPath - Absolute path to the project directory
|
|
260
272
|
* @returns Array of relative file paths
|
|
261
|
-
* @throws Error if directory cannot be listed
|
|
273
|
+
* @throws Error if directory cannot be listed or called outside a hook
|
|
262
274
|
*
|
|
263
275
|
* @example
|
|
264
276
|
* ```typescript
|
|
265
|
-
* const files = await listFiles(
|
|
266
|
-
* // ["
|
|
277
|
+
* const files = await listFiles();
|
|
278
|
+
* // ["index.md", "article/hello.md", "assets/logo.png"]
|
|
279
|
+
*
|
|
280
|
+
* const mdFiles = files.filter(f => f.endsWith(".md"));
|
|
267
281
|
* ```
|
|
268
282
|
*/
|
|
269
|
-
declare function listFiles(
|
|
283
|
+
declare function listFiles(): Promise<string[]>;
|
|
270
284
|
/**
|
|
271
285
|
* Check if a file exists in the project directory
|
|
272
286
|
*
|
|
273
|
-
*
|
|
287
|
+
* Project path is auto-detected from the runtime context.
|
|
288
|
+
*
|
|
274
289
|
* @param relativePath - Path relative to the project root
|
|
275
290
|
* @returns true if file exists, false otherwise
|
|
291
|
+
* @throws Error if called outside a hook
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript
|
|
295
|
+
* if (await fileExists("index.md")) {
|
|
296
|
+
* const content = await readFile("index.md");
|
|
297
|
+
* }
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
declare function fileExists(relativePath: string): Promise<boolean>;
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/utils/plugin-storage.d.ts
|
|
303
|
+
/**
|
|
304
|
+
* Plugin storage API for Moss plugins
|
|
305
|
+
*
|
|
306
|
+
* Provides access to a plugin's private storage directory at:
|
|
307
|
+
* .moss/plugins/{plugin-name}/
|
|
308
|
+
*
|
|
309
|
+
* Plugin identity is auto-detected from the runtime context -
|
|
310
|
+
* plugins never need to know their own name or path.
|
|
311
|
+
*
|
|
312
|
+
* Config is just a file: readPluginFile("config.json")
|
|
313
|
+
*/
|
|
314
|
+
/**
|
|
315
|
+
* Read a file from the plugin's private storage directory
|
|
316
|
+
*
|
|
317
|
+
* Storage path: .moss/plugins/{plugin-name}/{relativePath}
|
|
318
|
+
*
|
|
319
|
+
* @param relativePath - Path relative to the plugin's storage directory
|
|
320
|
+
* @returns File contents as a string
|
|
321
|
+
* @throws Error if file cannot be read or called outside a hook
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* // Read plugin config
|
|
326
|
+
* const configJson = await readPluginFile("config.json");
|
|
327
|
+
* const config = JSON.parse(configJson);
|
|
328
|
+
*
|
|
329
|
+
* // Read cached data
|
|
330
|
+
* const cached = await readPluginFile("cache/articles.json");
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
declare function readPluginFile(relativePath: string): Promise<string>;
|
|
334
|
+
/**
|
|
335
|
+
* Write a file to the plugin's private storage directory
|
|
336
|
+
*
|
|
337
|
+
* Creates parent directories if they don't exist.
|
|
338
|
+
* Storage path: .moss/plugins/{plugin-name}/{relativePath}
|
|
339
|
+
*
|
|
340
|
+
* @param relativePath - Path relative to the plugin's storage directory
|
|
341
|
+
* @param content - Content to write to the file
|
|
342
|
+
* @throws Error if file cannot be written or called outside a hook
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* // Save plugin config
|
|
347
|
+
* await writePluginFile("config.json", JSON.stringify(config, null, 2));
|
|
348
|
+
*
|
|
349
|
+
* // Cache data
|
|
350
|
+
* await writePluginFile("cache/articles.json", JSON.stringify(articles));
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
declare function writePluginFile(relativePath: string, content: string): Promise<void>;
|
|
354
|
+
/**
|
|
355
|
+
* List all files in the plugin's private storage directory
|
|
356
|
+
*
|
|
357
|
+
* Returns file paths relative to the plugin's storage directory.
|
|
358
|
+
*
|
|
359
|
+
* @returns Array of relative file paths
|
|
360
|
+
* @throws Error if directory cannot be listed or called outside a hook
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```typescript
|
|
364
|
+
* const files = await listPluginFiles();
|
|
365
|
+
* // ["config.json", "cache/articles.json", "cache/images.json"]
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
declare function listPluginFiles(): Promise<string[]>;
|
|
369
|
+
/**
|
|
370
|
+
* Check if a file exists in the plugin's private storage directory
|
|
371
|
+
*
|
|
372
|
+
* @param relativePath - Path relative to the plugin's storage directory
|
|
373
|
+
* @returns true if file exists, false otherwise
|
|
374
|
+
* @throws Error if called outside a hook
|
|
276
375
|
*
|
|
277
376
|
* @example
|
|
278
377
|
* ```typescript
|
|
279
|
-
* if (await
|
|
280
|
-
*
|
|
378
|
+
* if (await pluginFileExists("config.json")) {
|
|
379
|
+
* const config = JSON.parse(await readPluginFile("config.json"));
|
|
380
|
+
* } else {
|
|
381
|
+
* // Use default config
|
|
281
382
|
* }
|
|
282
383
|
* ```
|
|
283
384
|
*/
|
|
284
|
-
declare function
|
|
385
|
+
declare function pluginFileExists(relativePath: string): Promise<boolean>;
|
|
285
386
|
//#endregion
|
|
286
387
|
//#region src/utils/http.d.ts
|
|
287
388
|
/**
|
|
@@ -289,6 +390,8 @@ declare function fileExists(projectPath: string, relativePath: string): Promise<
|
|
|
289
390
|
*
|
|
290
391
|
* These functions provide HTTP capabilities that bypass browser CORS
|
|
291
392
|
* restrictions by using Rust's HTTP client under the hood.
|
|
393
|
+
*
|
|
394
|
+
* Project path for downloads is auto-detected from the runtime context.
|
|
292
395
|
*/
|
|
293
396
|
/**
|
|
294
397
|
* Options for HTTP fetch requests
|
|
@@ -358,18 +461,18 @@ declare function fetchUrl(url: string, options?: FetchOptions): Promise<FetchRes
|
|
|
358
461
|
* the binary data through JavaScript. The filename is derived from
|
|
359
462
|
* the URL, and file extension is inferred from Content-Type if needed.
|
|
360
463
|
*
|
|
464
|
+
* Project path is auto-detected from the runtime context.
|
|
465
|
+
*
|
|
361
466
|
* @param url - URL to download
|
|
362
|
-
* @param projectPath - Absolute path to the project directory
|
|
363
467
|
* @param targetDir - Target directory within project (e.g., "assets")
|
|
364
468
|
* @param options - Optional download configuration
|
|
365
469
|
* @returns Download result with actual path where file was saved
|
|
366
|
-
* @throws Error if download or write fails
|
|
470
|
+
* @throws Error if download or write fails, or called outside a hook
|
|
367
471
|
*
|
|
368
472
|
* @example
|
|
369
473
|
* ```typescript
|
|
370
474
|
* const result = await downloadAsset(
|
|
371
475
|
* "https://example.com/image",
|
|
372
|
-
* "/path/to/project",
|
|
373
476
|
* "assets"
|
|
374
477
|
* );
|
|
375
478
|
* if (result.ok) {
|
|
@@ -377,7 +480,7 @@ declare function fetchUrl(url: string, options?: FetchOptions): Promise<FetchRes
|
|
|
377
480
|
* }
|
|
378
481
|
* ```
|
|
379
482
|
*/
|
|
380
|
-
declare function downloadAsset(url: string,
|
|
483
|
+
declare function downloadAsset(url: string, targetDir: string, options?: DownloadOptions): Promise<DownloadResult>;
|
|
381
484
|
//#endregion
|
|
382
485
|
//#region src/utils/binary.d.ts
|
|
383
486
|
/**
|
|
@@ -385,6 +488,9 @@ declare function downloadAsset(url: string, projectPath: string, targetDir: stri
|
|
|
385
488
|
*
|
|
386
489
|
* Allows plugins to execute external binaries (git, npm, etc.)
|
|
387
490
|
* in a controlled environment.
|
|
491
|
+
*
|
|
492
|
+
* Working directory is auto-detected from the runtime context
|
|
493
|
+
* (always the project root).
|
|
388
494
|
*/
|
|
389
495
|
/**
|
|
390
496
|
* Options for executing a binary
|
|
@@ -394,8 +500,6 @@ interface ExecuteOptions {
|
|
|
394
500
|
binaryPath: string;
|
|
395
501
|
/** Arguments to pass to the binary */
|
|
396
502
|
args: string[];
|
|
397
|
-
/** Working directory for execution */
|
|
398
|
-
workingDir: string;
|
|
399
503
|
/** Timeout in milliseconds (default: 60000) */
|
|
400
504
|
timeoutMs?: number;
|
|
401
505
|
/** Additional environment variables */
|
|
@@ -417,9 +521,12 @@ interface ExecuteResult {
|
|
|
417
521
|
/**
|
|
418
522
|
* Execute an external binary
|
|
419
523
|
*
|
|
420
|
-
*
|
|
524
|
+
* Working directory is auto-detected from the runtime context
|
|
525
|
+
* (always the project root).
|
|
526
|
+
*
|
|
527
|
+
* @param options - Execution options including binary path and args
|
|
421
528
|
* @returns Execution result with stdout, stderr, and exit code
|
|
422
|
-
* @throws Error if binary cannot be executed
|
|
529
|
+
* @throws Error if binary cannot be executed or called outside a hook
|
|
423
530
|
*
|
|
424
531
|
* @example
|
|
425
532
|
* ```typescript
|
|
@@ -427,7 +534,6 @@ interface ExecuteResult {
|
|
|
427
534
|
* const result = await executeBinary({
|
|
428
535
|
* binaryPath: "git",
|
|
429
536
|
* args: ["status"],
|
|
430
|
-
* workingDir: "/path/to/repo",
|
|
431
537
|
* });
|
|
432
538
|
*
|
|
433
539
|
* if (result.success) {
|
|
@@ -443,7 +549,6 @@ interface ExecuteResult {
|
|
|
443
549
|
* const result = await executeBinary({
|
|
444
550
|
* binaryPath: "npm",
|
|
445
551
|
* args: ["install"],
|
|
446
|
-
* workingDir: "/path/to/project",
|
|
447
552
|
* timeoutMs: 120000,
|
|
448
553
|
* env: { NODE_ENV: "production" },
|
|
449
554
|
* });
|
|
@@ -457,6 +562,9 @@ declare function executeBinary(options: ExecuteOptions): Promise<ExecuteResult>;
|
|
|
457
562
|
*
|
|
458
563
|
* Allows plugins to store and retrieve authentication cookies
|
|
459
564
|
* for external services (e.g., Matters.town, GitHub).
|
|
565
|
+
*
|
|
566
|
+
* Cookies are automatically scoped to the plugin's registered domain
|
|
567
|
+
* (defined in manifest.json) - plugins cannot access other plugins' cookies.
|
|
460
568
|
*/
|
|
461
569
|
/**
|
|
462
570
|
* A cookie stored for plugin authentication
|
|
@@ -472,37 +580,46 @@ interface Cookie {
|
|
|
472
580
|
path?: string;
|
|
473
581
|
}
|
|
474
582
|
/**
|
|
475
|
-
* Get stored cookies for
|
|
583
|
+
* Get stored cookies for the current plugin.
|
|
584
|
+
*
|
|
585
|
+
* The plugin's identity is automatically detected from the runtime context.
|
|
586
|
+
* Cookies are filtered by the domain declared in the plugin's manifest.json.
|
|
476
587
|
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
* @returns Array of
|
|
588
|
+
* **Must be called from within a plugin hook** (process, generate, deploy, syndicate).
|
|
589
|
+
*
|
|
590
|
+
* @returns Array of cookies for the plugin's registered domain
|
|
591
|
+
* @throws Error if called outside of a plugin hook execution
|
|
480
592
|
*
|
|
481
593
|
* @example
|
|
482
594
|
* ```typescript
|
|
483
|
-
*
|
|
595
|
+
* // Inside a hook function:
|
|
596
|
+
* const cookies = await getPluginCookie();
|
|
484
597
|
* const token = cookies.find(c => c.name === "__access_token");
|
|
485
598
|
* if (token) {
|
|
486
599
|
* // Use token for authenticated requests
|
|
487
600
|
* }
|
|
488
601
|
* ```
|
|
489
602
|
*/
|
|
490
|
-
declare function getPluginCookie(
|
|
603
|
+
declare function getPluginCookie(): Promise<Cookie[]>;
|
|
491
604
|
/**
|
|
492
|
-
* Store cookies for
|
|
605
|
+
* Store cookies for the current plugin.
|
|
606
|
+
*
|
|
607
|
+
* The plugin's identity is automatically detected from the runtime context.
|
|
608
|
+
*
|
|
609
|
+
* **Must be called from within a plugin hook** (process, generate, deploy, syndicate).
|
|
493
610
|
*
|
|
494
|
-
* @param pluginName - Name of the plugin
|
|
495
|
-
* @param projectPath - Absolute path to the project directory
|
|
496
611
|
* @param cookies - Array of cookies to store
|
|
612
|
+
* @throws Error if called outside of a plugin hook execution
|
|
497
613
|
*
|
|
498
614
|
* @example
|
|
499
615
|
* ```typescript
|
|
500
|
-
*
|
|
616
|
+
* // Inside a hook function:
|
|
617
|
+
* await setPluginCookie([
|
|
501
618
|
* { name: "session", value: "abc123" }
|
|
502
619
|
* ]);
|
|
503
620
|
* ```
|
|
504
621
|
*/
|
|
505
|
-
declare function setPluginCookie(
|
|
622
|
+
declare function setPluginCookie(cookies: Cookie[]): Promise<void>;
|
|
506
623
|
//#endregion
|
|
507
|
-
export { AfterDeployContext, ArticleInfo, BaseContext, BeforeBuildContext, CompleteMessage, Cookie, DeploymentInfo, DownloadOptions, DownloadResult, ErrorMessage, ExecuteOptions, ExecuteResult, FetchOptions, FetchResult, HookResult, LogMessage, OnBuildContext, OnDeployContext, PluginCategory, PluginManifest, PluginMessage, ProgressMessage, ProjectInfo, SourceFiles, TauriCore, closeBrowser, downloadAsset, error, executeBinary, fetchUrl, fileExists, getMessageContext, getPluginCookie, getTauriCore, isTauriAvailable, listFiles, log, openBrowser, readFile, reportComplete, reportError, reportProgress, sendMessage, setMessageContext, setPluginCookie, warn, writeFile };
|
|
624
|
+
export { AfterDeployContext, ArticleInfo, BaseContext, BeforeBuildContext, CompleteMessage, Cookie, DeploymentInfo, DownloadOptions, DownloadResult, ErrorMessage, ExecuteOptions, ExecuteResult, FetchOptions, FetchResult, HookResult, LogMessage, OnBuildContext, OnDeployContext, PluginCategory, PluginManifest, PluginMessage, ProgressMessage, ProjectInfo, SourceFiles, TauriCore, closeBrowser, downloadAsset, error, executeBinary, fetchUrl, fileExists, getMessageContext, getPluginCookie, getTauriCore, isTauriAvailable, listFiles, listPluginFiles, log, openBrowser, pluginFileExists, readFile, readPluginFile, reportComplete, reportError, reportProgress, sendMessage, setMessageContext, setPluginCookie, warn, writeFile, writePluginFile };
|
|
508
625
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/plugin.ts","../src/types/context.ts","../src/types/hooks.ts","../src/types/messages.ts","../src/utils/tauri.ts","../src/utils/messaging.ts","../src/utils/logger.ts","../src/utils/browser.ts","../src/utils/filesystem.ts","../src/utils/http.ts","../src/utils/binary.ts","../src/utils/cookies.ts"],"sourcesContent":[],"mappings":";;AAIA;AAOA;AAWY,UAlBK,WAAA,CAkBS;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/plugin.ts","../src/types/context.ts","../src/types/hooks.ts","../src/types/messages.ts","../src/utils/tauri.ts","../src/utils/messaging.ts","../src/utils/logger.ts","../src/utils/browser.ts","../src/utils/filesystem.ts","../src/utils/plugin-storage.ts","../src/utils/http.ts","../src/utils/binary.ts","../src/utils/cookies.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -145,30 +145,57 @@ async function closeBrowser() {
|
|
|
145
145
|
await getTauriCore().invoke("close_plugin_browser", {});
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/utils/context.ts
|
|
150
|
+
/**
|
|
151
|
+
* Get the internal plugin context
|
|
152
|
+
*
|
|
153
|
+
* This is used internally by moss-api utilities to resolve paths
|
|
154
|
+
* and plugin identity. Plugins should not call this directly.
|
|
155
|
+
*
|
|
156
|
+
* @returns The current plugin execution context
|
|
157
|
+
* @throws Error if called outside of a plugin hook execution
|
|
158
|
+
*
|
|
159
|
+
* @internal
|
|
160
|
+
*/
|
|
161
|
+
function getInternalContext() {
|
|
162
|
+
const context = window.__MOSS_INTERNAL_CONTEXT__;
|
|
163
|
+
if (!context) throw new Error("This function must be called from within a plugin hook. Ensure you're calling this from process(), generate(), deploy(), or syndicate().");
|
|
164
|
+
return context;
|
|
165
|
+
}
|
|
166
|
+
|
|
148
167
|
//#endregion
|
|
149
168
|
//#region src/utils/filesystem.ts
|
|
150
169
|
/**
|
|
151
170
|
* File system operations for Moss plugins
|
|
152
171
|
*
|
|
153
|
-
* These functions
|
|
154
|
-
*
|
|
172
|
+
* These functions provide access to project files (user content).
|
|
173
|
+
* Project path is auto-detected from the runtime context.
|
|
174
|
+
*
|
|
175
|
+
* For plugin's private storage, use the plugin-storage API instead.
|
|
155
176
|
*/
|
|
156
177
|
/**
|
|
157
178
|
* Read a file from the project directory
|
|
158
179
|
*
|
|
159
|
-
*
|
|
180
|
+
* Project path is auto-detected from the runtime context.
|
|
181
|
+
*
|
|
160
182
|
* @param relativePath - Path relative to the project root
|
|
161
183
|
* @returns File contents as a string
|
|
162
|
-
* @throws Error if file cannot be read
|
|
184
|
+
* @throws Error if file cannot be read or called outside a hook
|
|
163
185
|
*
|
|
164
186
|
* @example
|
|
165
187
|
* ```typescript
|
|
166
|
-
*
|
|
188
|
+
* // Read an article
|
|
189
|
+
* const content = await readFile("article/hello-world.md");
|
|
190
|
+
*
|
|
191
|
+
* // Read package.json
|
|
192
|
+
* const pkg = JSON.parse(await readFile("package.json"));
|
|
167
193
|
* ```
|
|
168
194
|
*/
|
|
169
|
-
async function readFile(
|
|
195
|
+
async function readFile(relativePath) {
|
|
196
|
+
const ctx = getInternalContext();
|
|
170
197
|
return getTauriCore().invoke("read_project_file", {
|
|
171
|
-
projectPath,
|
|
198
|
+
projectPath: ctx.project_path,
|
|
172
199
|
relativePath
|
|
173
200
|
});
|
|
174
201
|
}
|
|
@@ -176,65 +203,190 @@ async function readFile(projectPath, relativePath) {
|
|
|
176
203
|
* Write content to a file in the project directory
|
|
177
204
|
*
|
|
178
205
|
* Creates parent directories if they don't exist.
|
|
206
|
+
* Project path is auto-detected from the runtime context.
|
|
179
207
|
*
|
|
180
|
-
* @param projectPath - Absolute path to the project directory
|
|
181
208
|
* @param relativePath - Path relative to the project root
|
|
182
209
|
* @param content - Content to write to the file
|
|
183
|
-
* @throws Error if file cannot be written
|
|
210
|
+
* @throws Error if file cannot be written or called outside a hook
|
|
184
211
|
*
|
|
185
212
|
* @example
|
|
186
213
|
* ```typescript
|
|
187
|
-
*
|
|
214
|
+
* // Write a generated article
|
|
215
|
+
* await writeFile("article/new-post.md", "# Hello World\n\nContent here.");
|
|
216
|
+
*
|
|
217
|
+
* // Write index page
|
|
218
|
+
* await writeFile("index.md", markdownContent);
|
|
188
219
|
* ```
|
|
189
220
|
*/
|
|
190
|
-
async function writeFile(
|
|
221
|
+
async function writeFile(relativePath, content) {
|
|
222
|
+
const ctx = getInternalContext();
|
|
191
223
|
await getTauriCore().invoke("write_project_file", {
|
|
192
|
-
projectPath,
|
|
224
|
+
projectPath: ctx.project_path,
|
|
193
225
|
relativePath,
|
|
194
226
|
data: content
|
|
195
227
|
});
|
|
196
228
|
}
|
|
197
229
|
/**
|
|
198
|
-
* List all files in
|
|
230
|
+
* List all files in the project directory
|
|
199
231
|
*
|
|
200
232
|
* Returns file paths relative to the project root.
|
|
233
|
+
* Project path is auto-detected from the runtime context.
|
|
201
234
|
*
|
|
202
|
-
* @param projectPath - Absolute path to the project directory
|
|
203
235
|
* @returns Array of relative file paths
|
|
204
|
-
* @throws Error if directory cannot be listed
|
|
236
|
+
* @throws Error if directory cannot be listed or called outside a hook
|
|
205
237
|
*
|
|
206
238
|
* @example
|
|
207
239
|
* ```typescript
|
|
208
|
-
* const files = await listFiles(
|
|
209
|
-
* // ["
|
|
240
|
+
* const files = await listFiles();
|
|
241
|
+
* // ["index.md", "article/hello.md", "assets/logo.png"]
|
|
242
|
+
*
|
|
243
|
+
* const mdFiles = files.filter(f => f.endsWith(".md"));
|
|
210
244
|
* ```
|
|
211
245
|
*/
|
|
212
|
-
async function listFiles(
|
|
213
|
-
|
|
246
|
+
async function listFiles() {
|
|
247
|
+
const ctx = getInternalContext();
|
|
248
|
+
return getTauriCore().invoke("list_project_files", { projectPath: ctx.project_path });
|
|
214
249
|
}
|
|
215
250
|
/**
|
|
216
251
|
* Check if a file exists in the project directory
|
|
217
252
|
*
|
|
218
|
-
*
|
|
253
|
+
* Project path is auto-detected from the runtime context.
|
|
254
|
+
*
|
|
219
255
|
* @param relativePath - Path relative to the project root
|
|
220
256
|
* @returns true if file exists, false otherwise
|
|
257
|
+
* @throws Error if called outside a hook
|
|
221
258
|
*
|
|
222
259
|
* @example
|
|
223
260
|
* ```typescript
|
|
224
|
-
* if (await fileExists("
|
|
225
|
-
*
|
|
261
|
+
* if (await fileExists("index.md")) {
|
|
262
|
+
* const content = await readFile("index.md");
|
|
226
263
|
* }
|
|
227
264
|
* ```
|
|
228
265
|
*/
|
|
229
|
-
async function fileExists(
|
|
266
|
+
async function fileExists(relativePath) {
|
|
267
|
+
getInternalContext();
|
|
230
268
|
try {
|
|
231
|
-
await readFile(
|
|
269
|
+
await readFile(relativePath);
|
|
232
270
|
return true;
|
|
233
271
|
} catch {
|
|
234
272
|
return false;
|
|
235
273
|
}
|
|
236
274
|
}
|
|
237
275
|
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/utils/plugin-storage.ts
|
|
278
|
+
/**
|
|
279
|
+
* Plugin storage API for Moss plugins
|
|
280
|
+
*
|
|
281
|
+
* Provides access to a plugin's private storage directory at:
|
|
282
|
+
* .moss/plugins/{plugin-name}/
|
|
283
|
+
*
|
|
284
|
+
* Plugin identity is auto-detected from the runtime context -
|
|
285
|
+
* plugins never need to know their own name or path.
|
|
286
|
+
*
|
|
287
|
+
* Config is just a file: readPluginFile("config.json")
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* Read a file from the plugin's private storage directory
|
|
291
|
+
*
|
|
292
|
+
* Storage path: .moss/plugins/{plugin-name}/{relativePath}
|
|
293
|
+
*
|
|
294
|
+
* @param relativePath - Path relative to the plugin's storage directory
|
|
295
|
+
* @returns File contents as a string
|
|
296
|
+
* @throws Error if file cannot be read or called outside a hook
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```typescript
|
|
300
|
+
* // Read plugin config
|
|
301
|
+
* const configJson = await readPluginFile("config.json");
|
|
302
|
+
* const config = JSON.parse(configJson);
|
|
303
|
+
*
|
|
304
|
+
* // Read cached data
|
|
305
|
+
* const cached = await readPluginFile("cache/articles.json");
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
async function readPluginFile(relativePath) {
|
|
309
|
+
const ctx = getInternalContext();
|
|
310
|
+
return getTauriCore().invoke("read_plugin_file", {
|
|
311
|
+
pluginName: ctx.plugin_name,
|
|
312
|
+
projectPath: ctx.project_path,
|
|
313
|
+
relativePath
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Write a file to the plugin's private storage directory
|
|
318
|
+
*
|
|
319
|
+
* Creates parent directories if they don't exist.
|
|
320
|
+
* Storage path: .moss/plugins/{plugin-name}/{relativePath}
|
|
321
|
+
*
|
|
322
|
+
* @param relativePath - Path relative to the plugin's storage directory
|
|
323
|
+
* @param content - Content to write to the file
|
|
324
|
+
* @throws Error if file cannot be written or called outside a hook
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```typescript
|
|
328
|
+
* // Save plugin config
|
|
329
|
+
* await writePluginFile("config.json", JSON.stringify(config, null, 2));
|
|
330
|
+
*
|
|
331
|
+
* // Cache data
|
|
332
|
+
* await writePluginFile("cache/articles.json", JSON.stringify(articles));
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
async function writePluginFile(relativePath, content) {
|
|
336
|
+
const ctx = getInternalContext();
|
|
337
|
+
await getTauriCore().invoke("write_plugin_file", {
|
|
338
|
+
pluginName: ctx.plugin_name,
|
|
339
|
+
projectPath: ctx.project_path,
|
|
340
|
+
relativePath,
|
|
341
|
+
content
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* List all files in the plugin's private storage directory
|
|
346
|
+
*
|
|
347
|
+
* Returns file paths relative to the plugin's storage directory.
|
|
348
|
+
*
|
|
349
|
+
* @returns Array of relative file paths
|
|
350
|
+
* @throws Error if directory cannot be listed or called outside a hook
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```typescript
|
|
354
|
+
* const files = await listPluginFiles();
|
|
355
|
+
* // ["config.json", "cache/articles.json", "cache/images.json"]
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
async function listPluginFiles() {
|
|
359
|
+
const ctx = getInternalContext();
|
|
360
|
+
return getTauriCore().invoke("list_plugin_files", {
|
|
361
|
+
pluginName: ctx.plugin_name,
|
|
362
|
+
projectPath: ctx.project_path
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Check if a file exists in the plugin's private storage directory
|
|
367
|
+
*
|
|
368
|
+
* @param relativePath - Path relative to the plugin's storage directory
|
|
369
|
+
* @returns true if file exists, false otherwise
|
|
370
|
+
* @throws Error if called outside a hook
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```typescript
|
|
374
|
+
* if (await pluginFileExists("config.json")) {
|
|
375
|
+
* const config = JSON.parse(await readPluginFile("config.json"));
|
|
376
|
+
* } else {
|
|
377
|
+
* // Use default config
|
|
378
|
+
* }
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
async function pluginFileExists(relativePath) {
|
|
382
|
+
const ctx = getInternalContext();
|
|
383
|
+
return getTauriCore().invoke("plugin_file_exists", {
|
|
384
|
+
pluginName: ctx.plugin_name,
|
|
385
|
+
projectPath: ctx.project_path,
|
|
386
|
+
relativePath
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
238
390
|
//#endregion
|
|
239
391
|
//#region src/utils/http.ts
|
|
240
392
|
/**
|
|
@@ -242,6 +394,8 @@ async function fileExists(projectPath, relativePath) {
|
|
|
242
394
|
*
|
|
243
395
|
* These functions provide HTTP capabilities that bypass browser CORS
|
|
244
396
|
* restrictions by using Rust's HTTP client under the hood.
|
|
397
|
+
*
|
|
398
|
+
* Project path for downloads is auto-detected from the runtime context.
|
|
245
399
|
*/
|
|
246
400
|
/**
|
|
247
401
|
* Fetch a URL using Rust's HTTP client (bypasses CORS)
|
|
@@ -285,18 +439,18 @@ async function fetchUrl(url, options = {}) {
|
|
|
285
439
|
* the binary data through JavaScript. The filename is derived from
|
|
286
440
|
* the URL, and file extension is inferred from Content-Type if needed.
|
|
287
441
|
*
|
|
442
|
+
* Project path is auto-detected from the runtime context.
|
|
443
|
+
*
|
|
288
444
|
* @param url - URL to download
|
|
289
|
-
* @param projectPath - Absolute path to the project directory
|
|
290
445
|
* @param targetDir - Target directory within project (e.g., "assets")
|
|
291
446
|
* @param options - Optional download configuration
|
|
292
447
|
* @returns Download result with actual path where file was saved
|
|
293
|
-
* @throws Error if download or write fails
|
|
448
|
+
* @throws Error if download or write fails, or called outside a hook
|
|
294
449
|
*
|
|
295
450
|
* @example
|
|
296
451
|
* ```typescript
|
|
297
452
|
* const result = await downloadAsset(
|
|
298
453
|
* "https://example.com/image",
|
|
299
|
-
* "/path/to/project",
|
|
300
454
|
* "assets"
|
|
301
455
|
* );
|
|
302
456
|
* if (result.ok) {
|
|
@@ -304,11 +458,12 @@ async function fetchUrl(url, options = {}) {
|
|
|
304
458
|
* }
|
|
305
459
|
* ```
|
|
306
460
|
*/
|
|
307
|
-
async function downloadAsset(url,
|
|
461
|
+
async function downloadAsset(url, targetDir, options = {}) {
|
|
462
|
+
const ctx = getInternalContext();
|
|
308
463
|
const { timeoutMs = 3e4 } = options;
|
|
309
464
|
const result = await getTauriCore().invoke("download_asset", {
|
|
310
465
|
url,
|
|
311
|
-
projectPath,
|
|
466
|
+
projectPath: ctx.project_path,
|
|
312
467
|
targetDir,
|
|
313
468
|
timeoutMs
|
|
314
469
|
});
|
|
@@ -328,13 +483,19 @@ async function downloadAsset(url, projectPath, targetDir, options = {}) {
|
|
|
328
483
|
*
|
|
329
484
|
* Allows plugins to execute external binaries (git, npm, etc.)
|
|
330
485
|
* in a controlled environment.
|
|
486
|
+
*
|
|
487
|
+
* Working directory is auto-detected from the runtime context
|
|
488
|
+
* (always the project root).
|
|
331
489
|
*/
|
|
332
490
|
/**
|
|
333
491
|
* Execute an external binary
|
|
334
492
|
*
|
|
335
|
-
*
|
|
493
|
+
* Working directory is auto-detected from the runtime context
|
|
494
|
+
* (always the project root).
|
|
495
|
+
*
|
|
496
|
+
* @param options - Execution options including binary path and args
|
|
336
497
|
* @returns Execution result with stdout, stderr, and exit code
|
|
337
|
-
* @throws Error if binary cannot be executed
|
|
498
|
+
* @throws Error if binary cannot be executed or called outside a hook
|
|
338
499
|
*
|
|
339
500
|
* @example
|
|
340
501
|
* ```typescript
|
|
@@ -342,7 +503,6 @@ async function downloadAsset(url, projectPath, targetDir, options = {}) {
|
|
|
342
503
|
* const result = await executeBinary({
|
|
343
504
|
* binaryPath: "git",
|
|
344
505
|
* args: ["status"],
|
|
345
|
-
* workingDir: "/path/to/repo",
|
|
346
506
|
* });
|
|
347
507
|
*
|
|
348
508
|
* if (result.success) {
|
|
@@ -358,18 +518,18 @@ async function downloadAsset(url, projectPath, targetDir, options = {}) {
|
|
|
358
518
|
* const result = await executeBinary({
|
|
359
519
|
* binaryPath: "npm",
|
|
360
520
|
* args: ["install"],
|
|
361
|
-
* workingDir: "/path/to/project",
|
|
362
521
|
* timeoutMs: 120000,
|
|
363
522
|
* env: { NODE_ENV: "production" },
|
|
364
523
|
* });
|
|
365
524
|
* ```
|
|
366
525
|
*/
|
|
367
526
|
async function executeBinary(options) {
|
|
368
|
-
const
|
|
527
|
+
const ctx = getInternalContext();
|
|
528
|
+
const { binaryPath, args, timeoutMs = 6e4, env } = options;
|
|
369
529
|
const result = await getTauriCore().invoke("execute_binary", {
|
|
370
530
|
binaryPath,
|
|
371
531
|
args,
|
|
372
|
-
workingDir,
|
|
532
|
+
workingDir: ctx.project_path,
|
|
373
533
|
timeoutMs,
|
|
374
534
|
env
|
|
375
535
|
});
|
|
@@ -388,51 +548,65 @@ async function executeBinary(options) {
|
|
|
388
548
|
*
|
|
389
549
|
* Allows plugins to store and retrieve authentication cookies
|
|
390
550
|
* for external services (e.g., Matters.town, GitHub).
|
|
551
|
+
*
|
|
552
|
+
* Cookies are automatically scoped to the plugin's registered domain
|
|
553
|
+
* (defined in manifest.json) - plugins cannot access other plugins' cookies.
|
|
391
554
|
*/
|
|
392
555
|
/**
|
|
393
|
-
* Get stored cookies for
|
|
556
|
+
* Get stored cookies for the current plugin.
|
|
557
|
+
*
|
|
558
|
+
* The plugin's identity is automatically detected from the runtime context.
|
|
559
|
+
* Cookies are filtered by the domain declared in the plugin's manifest.json.
|
|
560
|
+
*
|
|
561
|
+
* **Must be called from within a plugin hook** (process, generate, deploy, syndicate).
|
|
394
562
|
*
|
|
395
|
-
* @
|
|
396
|
-
* @
|
|
397
|
-
* @returns Array of stored cookies
|
|
563
|
+
* @returns Array of cookies for the plugin's registered domain
|
|
564
|
+
* @throws Error if called outside of a plugin hook execution
|
|
398
565
|
*
|
|
399
566
|
* @example
|
|
400
567
|
* ```typescript
|
|
401
|
-
*
|
|
568
|
+
* // Inside a hook function:
|
|
569
|
+
* const cookies = await getPluginCookie();
|
|
402
570
|
* const token = cookies.find(c => c.name === "__access_token");
|
|
403
571
|
* if (token) {
|
|
404
572
|
* // Use token for authenticated requests
|
|
405
573
|
* }
|
|
406
574
|
* ```
|
|
407
575
|
*/
|
|
408
|
-
async function getPluginCookie(
|
|
576
|
+
async function getPluginCookie() {
|
|
577
|
+
const ctx = getInternalContext();
|
|
409
578
|
return getTauriCore().invoke("get_plugin_cookie", {
|
|
410
|
-
pluginName,
|
|
411
|
-
projectPath
|
|
579
|
+
pluginName: ctx.plugin_name,
|
|
580
|
+
projectPath: ctx.project_path
|
|
412
581
|
});
|
|
413
582
|
}
|
|
414
583
|
/**
|
|
415
|
-
* Store cookies for
|
|
584
|
+
* Store cookies for the current plugin.
|
|
585
|
+
*
|
|
586
|
+
* The plugin's identity is automatically detected from the runtime context.
|
|
587
|
+
*
|
|
588
|
+
* **Must be called from within a plugin hook** (process, generate, deploy, syndicate).
|
|
416
589
|
*
|
|
417
|
-
* @param pluginName - Name of the plugin
|
|
418
|
-
* @param projectPath - Absolute path to the project directory
|
|
419
590
|
* @param cookies - Array of cookies to store
|
|
591
|
+
* @throws Error if called outside of a plugin hook execution
|
|
420
592
|
*
|
|
421
593
|
* @example
|
|
422
594
|
* ```typescript
|
|
423
|
-
*
|
|
595
|
+
* // Inside a hook function:
|
|
596
|
+
* await setPluginCookie([
|
|
424
597
|
* { name: "session", value: "abc123" }
|
|
425
598
|
* ]);
|
|
426
599
|
* ```
|
|
427
600
|
*/
|
|
428
|
-
async function setPluginCookie(
|
|
601
|
+
async function setPluginCookie(cookies) {
|
|
602
|
+
const ctx = getInternalContext();
|
|
429
603
|
await getTauriCore().invoke("set_plugin_cookie", {
|
|
430
|
-
pluginName,
|
|
431
|
-
projectPath,
|
|
604
|
+
pluginName: ctx.plugin_name,
|
|
605
|
+
projectPath: ctx.project_path,
|
|
432
606
|
cookies
|
|
433
607
|
});
|
|
434
608
|
}
|
|
435
609
|
|
|
436
610
|
//#endregion
|
|
437
|
-
export { closeBrowser, downloadAsset, error, executeBinary, fetchUrl, fileExists, getMessageContext, getPluginCookie, getTauriCore, isTauriAvailable, listFiles, log, openBrowser, readFile, reportComplete, reportError, reportProgress, sendMessage, setMessageContext, setPluginCookie, warn, writeFile };
|
|
611
|
+
export { closeBrowser, downloadAsset, error, executeBinary, fetchUrl, fileExists, getMessageContext, getPluginCookie, getTauriCore, isTauriAvailable, listFiles, listPluginFiles, log, openBrowser, pluginFileExists, readFile, readPluginFile, reportComplete, reportError, reportProgress, sendMessage, setMessageContext, setPluginCookie, warn, writeFile, writePluginFile };
|
|
438
612
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/tauri.ts","../src/utils/messaging.ts","../src/utils/logger.ts","../src/utils/browser.ts","../src/utils/filesystem.ts","../src/utils/http.ts","../src/utils/binary.ts","../src/utils/cookies.ts"],"sourcesContent":["/**\n * Tauri core utilities for plugin communication\n */\n\nexport interface TauriCore {\n invoke: <T>(cmd: string, args?: Record<string, unknown>) => Promise<T>;\n}\n\ninterface TauriWindow {\n __TAURI__?: {\n core: TauriCore;\n };\n}\n\n/**\n * Get the Tauri core API\n *\n * @deprecated Use higher-level APIs instead:\n * - File operations: `readFile`, `writeFile`, `listFiles`, `fileExists`\n * - HTTP: `fetchUrl`, `downloadAsset`\n * - Binary execution: `executeBinary`\n * - Cookies: `getPluginCookie`, `setPluginCookie`\n *\n * @throws Error if Tauri is not available\n */\nexport function getTauriCore(): TauriCore {\n const w = window as unknown as TauriWindow;\n if (!w.__TAURI__?.core) {\n throw new Error(\"Tauri core not available\");\n }\n return w.__TAURI__.core;\n}\n\n/**\n * Check if Tauri is available\n */\nexport function isTauriAvailable(): boolean {\n const w = window as unknown as TauriWindow;\n return !!w.__TAURI__?.core;\n}\n","/**\n * Plugin messaging utilities for communicating with Moss\n */\n\nimport type { PluginMessage } from \"../types/messages\";\nimport { getTauriCore, isTauriAvailable } from \"./tauri\";\n\nlet currentPluginName = \"\";\nlet currentHookName = \"\";\n\n/**\n * Set the message context for subsequent messages\n * This is typically called automatically by the plugin runtime\n */\nexport function setMessageContext(pluginName: string, hookName: string): void {\n currentPluginName = pluginName;\n currentHookName = hookName;\n}\n\n/**\n * Get the current message context\n */\nexport function getMessageContext(): { pluginName: string; hookName: string } {\n return { pluginName: currentPluginName, hookName: currentHookName };\n}\n\n/**\n * Send a message to Moss\n * Silently fails if Tauri is unavailable (useful for testing)\n */\nexport async function sendMessage(message: PluginMessage): Promise<void> {\n if (!isTauriAvailable()) {\n return;\n }\n\n try {\n await getTauriCore().invoke(\"plugin_message\", {\n pluginName: currentPluginName,\n hookName: currentHookName,\n message,\n });\n } catch {\n // Silently fail - logging would be recursive\n }\n}\n\n/**\n * Report progress to Moss\n */\nexport async function reportProgress(\n phase: string,\n current: number,\n total: number,\n message?: string\n): Promise<void> {\n await sendMessage({ type: \"progress\", phase, current, total, message });\n}\n\n/**\n * Report an error to Moss\n */\nexport async function reportError(\n error: string,\n context?: string,\n fatal = false\n): Promise<void> {\n await sendMessage({ type: \"error\", error, context, fatal });\n}\n\n/**\n * Report completion to Moss\n */\nexport async function reportComplete(result: unknown): Promise<void> {\n await sendMessage({ type: \"complete\", result });\n}\n","/**\n * Logging utilities for plugins\n */\n\nimport { sendMessage } from \"./messaging\";\n\n/**\n * Log an informational message\n */\nexport async function log(message: string): Promise<void> {\n await sendMessage({ type: \"log\", level: \"log\", message });\n}\n\n/**\n * Log a warning message\n */\nexport async function warn(message: string): Promise<void> {\n await sendMessage({ type: \"log\", level: \"warn\", message });\n}\n\n/**\n * Log an error message\n */\nexport async function error(message: string): Promise<void> {\n await sendMessage({ type: \"log\", level: \"error\", message });\n}\n","/**\n * Browser utilities for plugins\n * Abstracts Tauri browser commands to decouple plugins from internal APIs\n */\n\nimport { getTauriCore } from \"./tauri\";\n\n/**\n * Open a URL in the plugin browser window\n */\nexport async function openBrowser(url: string): Promise<void> {\n await getTauriCore().invoke(\"open_plugin_browser\", { url });\n}\n\n/**\n * Close the plugin browser window\n */\nexport async function closeBrowser(): Promise<void> {\n await getTauriCore().invoke(\"close_plugin_browser\", {});\n}\n","/**\n * File system operations for Moss plugins\n *\n * These functions abstract away the underlying Tauri commands,\n * providing a clean API for plugins to read/write project files.\n */\n\nimport { getTauriCore } from \"./tauri\";\n\n/**\n * Read a file from the project directory\n *\n * @param projectPath - Absolute path to the project directory\n * @param relativePath - Path relative to the project root\n * @returns File contents as a string\n * @throws Error if file cannot be read\n *\n * @example\n * ```typescript\n * const content = await readFile(\"/path/to/project\", \"src/index.ts\");\n * ```\n */\nexport async function readFile(\n projectPath: string,\n relativePath: string\n): Promise<string> {\n return getTauriCore().invoke<string>(\"read_project_file\", {\n projectPath,\n relativePath,\n });\n}\n\n/**\n * Write content to a file in the project directory\n *\n * Creates parent directories if they don't exist.\n *\n * @param projectPath - Absolute path to the project directory\n * @param relativePath - Path relative to the project root\n * @param content - Content to write to the file\n * @throws Error if file cannot be written\n *\n * @example\n * ```typescript\n * await writeFile(\"/path/to/project\", \"output/result.md\", \"# Hello World\");\n * ```\n */\nexport async function writeFile(\n projectPath: string,\n relativePath: string,\n content: string\n): Promise<void> {\n await getTauriCore().invoke(\"write_project_file\", {\n projectPath,\n relativePath,\n data: content,\n });\n}\n\n/**\n * List all files in a project directory\n *\n * Returns file paths relative to the project root.\n *\n * @param projectPath - Absolute path to the project directory\n * @returns Array of relative file paths\n * @throws Error if directory cannot be listed\n *\n * @example\n * ```typescript\n * const files = await listFiles(\"/path/to/project\");\n * // [\"src/index.ts\", \"package.json\", \"README.md\"]\n * ```\n */\nexport async function listFiles(projectPath: string): Promise<string[]> {\n return getTauriCore().invoke<string[]>(\"list_project_files\", {\n projectPath,\n });\n}\n\n/**\n * Check if a file exists in the project directory\n *\n * @param projectPath - Absolute path to the project directory\n * @param relativePath - Path relative to the project root\n * @returns true if file exists, false otherwise\n *\n * @example\n * ```typescript\n * if (await fileExists(\"/path/to/project\", \"config.json\")) {\n * // load config\n * }\n * ```\n */\nexport async function fileExists(\n projectPath: string,\n relativePath: string\n): Promise<boolean> {\n try {\n await readFile(projectPath, relativePath);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * HTTP operations for Moss plugins\n *\n * These functions provide HTTP capabilities that bypass browser CORS\n * restrictions by using Rust's HTTP client under the hood.\n */\n\nimport { getTauriCore } from \"./tauri\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Options for HTTP fetch requests\n */\nexport interface FetchOptions {\n /** Timeout in milliseconds (default: 30000) */\n timeoutMs?: number;\n}\n\n/**\n * Result from an HTTP fetch operation\n */\nexport interface FetchResult {\n /** HTTP status code */\n status: number;\n /** Whether the request was successful (2xx status) */\n ok: boolean;\n /** Content-Type header from response */\n contentType: string | null;\n /** Response body as Uint8Array */\n body: Uint8Array;\n /** Get response body as text */\n text(): string;\n}\n\n/**\n * Options for asset download\n */\nexport interface DownloadOptions {\n /** Timeout in milliseconds (default: 30000) */\n timeoutMs?: number;\n}\n\n/**\n * Result from an asset download operation\n */\nexport interface DownloadResult {\n /** HTTP status code */\n status: number;\n /** Whether the request was successful (2xx status) */\n ok: boolean;\n /** Content-Type header from response */\n contentType: string | null;\n /** Number of bytes written to disk */\n bytesWritten: number;\n /** Actual path where file was saved (relative to project) */\n actualPath: string;\n}\n\n// ============================================================================\n// Internal Types (Tauri response shapes)\n// ============================================================================\n\ninterface TauriFetchResult {\n status: number;\n ok: boolean;\n body_base64: string;\n content_type: string | null;\n}\n\ninterface TauriDownloadResult {\n status: number;\n ok: boolean;\n content_type: string | null;\n bytes_written: number;\n actual_path: string;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Fetch a URL using Rust's HTTP client (bypasses CORS)\n *\n * @param url - URL to fetch\n * @param options - Optional fetch configuration\n * @returns Fetch result with status, body, and helpers\n * @throws Error if network request fails\n *\n * @example\n * ```typescript\n * const result = await fetchUrl(\"https://api.example.com/data\");\n * if (result.ok) {\n * const data = JSON.parse(result.text());\n * }\n * ```\n */\nexport async function fetchUrl(\n url: string,\n options: FetchOptions = {}\n): Promise<FetchResult> {\n const { timeoutMs = 30000 } = options;\n\n const result = await getTauriCore().invoke<TauriFetchResult>(\"fetch_url\", {\n url,\n timeoutMs,\n });\n\n // Decode base64 body to Uint8Array\n const binaryString = atob(result.body_base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n\n return {\n status: result.status,\n ok: result.ok,\n contentType: result.content_type,\n body: bytes,\n text(): string {\n return new TextDecoder().decode(bytes);\n },\n };\n}\n\n/**\n * Download a URL and save directly to disk\n *\n * Downloads the file and writes it directly to disk without passing\n * the binary data through JavaScript. The filename is derived from\n * the URL, and file extension is inferred from Content-Type if needed.\n *\n * @param url - URL to download\n * @param projectPath - Absolute path to the project directory\n * @param targetDir - Target directory within project (e.g., \"assets\")\n * @param options - Optional download configuration\n * @returns Download result with actual path where file was saved\n * @throws Error if download or write fails\n *\n * @example\n * ```typescript\n * const result = await downloadAsset(\n * \"https://example.com/image\",\n * \"/path/to/project\",\n * \"assets\"\n * );\n * if (result.ok) {\n * console.log(`Saved to ${result.actualPath}`); // e.g., \"assets/image.png\"\n * }\n * ```\n */\nexport async function downloadAsset(\n url: string,\n projectPath: string,\n targetDir: string,\n options: DownloadOptions = {}\n): Promise<DownloadResult> {\n const { timeoutMs = 30000 } = options;\n\n const result = await getTauriCore().invoke<TauriDownloadResult>(\n \"download_asset\",\n {\n url,\n projectPath,\n targetDir,\n timeoutMs,\n }\n );\n\n return {\n status: result.status,\n ok: result.ok,\n contentType: result.content_type,\n bytesWritten: result.bytes_written,\n actualPath: result.actual_path,\n };\n}\n","/**\n * Binary execution for Moss plugins\n *\n * Allows plugins to execute external binaries (git, npm, etc.)\n * in a controlled environment.\n */\n\nimport { getTauriCore } from \"./tauri\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Options for executing a binary\n */\nexport interface ExecuteOptions {\n /** Path to the binary (can be just the name if in PATH) */\n binaryPath: string;\n /** Arguments to pass to the binary */\n args: string[];\n /** Working directory for execution */\n workingDir: string;\n /** Timeout in milliseconds (default: 60000) */\n timeoutMs?: number;\n /** Additional environment variables */\n env?: Record<string, string>;\n}\n\n/**\n * Result from binary execution\n */\nexport interface ExecuteResult {\n /** Whether the command succeeded (exit code 0) */\n success: boolean;\n /** Exit code from the process */\n exitCode: number;\n /** Standard output from the process */\n stdout: string;\n /** Standard error output from the process */\n stderr: string;\n}\n\n// ============================================================================\n// Internal Types (Tauri response shape)\n// ============================================================================\n\ninterface TauriBinaryResult {\n success: boolean;\n exit_code: number;\n stdout: string;\n stderr: string;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Execute an external binary\n *\n * @param options - Execution options including binary path, args, and working directory\n * @returns Execution result with stdout, stderr, and exit code\n * @throws Error if binary cannot be executed\n *\n * @example\n * ```typescript\n * // Run git status\n * const result = await executeBinary({\n * binaryPath: \"git\",\n * args: [\"status\"],\n * workingDir: \"/path/to/repo\",\n * });\n *\n * if (result.success) {\n * console.log(result.stdout);\n * } else {\n * console.error(result.stderr);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Run npm install with timeout\n * const result = await executeBinary({\n * binaryPath: \"npm\",\n * args: [\"install\"],\n * workingDir: \"/path/to/project\",\n * timeoutMs: 120000,\n * env: { NODE_ENV: \"production\" },\n * });\n * ```\n */\nexport async function executeBinary(\n options: ExecuteOptions\n): Promise<ExecuteResult> {\n const { binaryPath, args, workingDir, timeoutMs = 60000, env } = options;\n\n const result = await getTauriCore().invoke<TauriBinaryResult>(\n \"execute_binary\",\n {\n binaryPath,\n args,\n workingDir,\n timeoutMs,\n env,\n }\n );\n\n return {\n success: result.success,\n exitCode: result.exit_code,\n stdout: result.stdout,\n stderr: result.stderr,\n };\n}\n","/**\n * Cookie management for Moss plugins\n *\n * Allows plugins to store and retrieve authentication cookies\n * for external services (e.g., Matters.town, GitHub).\n */\n\nimport { getTauriCore } from \"./tauri\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A cookie stored for plugin authentication\n */\nexport interface Cookie {\n /** Cookie name */\n name: string;\n /** Cookie value */\n value: string;\n /** Optional domain for the cookie */\n domain?: string;\n /** Optional path for the cookie */\n path?: string;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Get stored cookies for a plugin\n *\n * @param pluginName - Name of the plugin\n * @param projectPath - Absolute path to the project directory\n * @returns Array of stored cookies\n *\n * @example\n * ```typescript\n * const cookies = await getPluginCookie(\"matters-syndicator\", \"/path/to/project\");\n * const token = cookies.find(c => c.name === \"__access_token\");\n * if (token) {\n * // Use token for authenticated requests\n * }\n * ```\n */\nexport async function getPluginCookie(\n pluginName: string,\n projectPath: string\n): Promise<Cookie[]> {\n return getTauriCore().invoke<Cookie[]>(\"get_plugin_cookie\", {\n pluginName,\n projectPath,\n });\n}\n\n/**\n * Store cookies for a plugin\n *\n * @param pluginName - Name of the plugin\n * @param projectPath - Absolute path to the project directory\n * @param cookies - Array of cookies to store\n *\n * @example\n * ```typescript\n * await setPluginCookie(\"my-plugin\", \"/path/to/project\", [\n * { name: \"session\", value: \"abc123\" }\n * ]);\n * ```\n */\nexport async function setPluginCookie(\n pluginName: string,\n projectPath: string,\n cookies: Cookie[]\n): Promise<void> {\n await getTauriCore().invoke(\"set_plugin_cookie\", {\n pluginName,\n projectPath,\n cookies,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/tauri.ts","../src/utils/messaging.ts","../src/utils/logger.ts","../src/utils/browser.ts","../src/utils/context.ts","../src/utils/filesystem.ts","../src/utils/plugin-storage.ts","../src/utils/http.ts","../src/utils/binary.ts","../src/utils/cookies.ts"],"sourcesContent":["/**\n * Tauri core utilities for plugin communication\n */\n\nexport interface TauriCore {\n invoke: <T>(cmd: string, args?: Record<string, unknown>) => Promise<T>;\n}\n\ninterface TauriWindow {\n __TAURI__?: {\n core: TauriCore;\n };\n}\n\n/**\n * Get the Tauri core API\n *\n * @deprecated Use higher-level APIs instead:\n * - File operations: `readFile`, `writeFile`, `listFiles`, `fileExists`\n * - HTTP: `fetchUrl`, `downloadAsset`\n * - Binary execution: `executeBinary`\n * - Cookies: `getPluginCookie`, `setPluginCookie`\n *\n * @throws Error if Tauri is not available\n */\nexport function getTauriCore(): TauriCore {\n const w = window as unknown as TauriWindow;\n if (!w.__TAURI__?.core) {\n throw new Error(\"Tauri core not available\");\n }\n return w.__TAURI__.core;\n}\n\n/**\n * Check if Tauri is available\n */\nexport function isTauriAvailable(): boolean {\n const w = window as unknown as TauriWindow;\n return !!w.__TAURI__?.core;\n}\n","/**\n * Plugin messaging utilities for communicating with Moss\n */\n\nimport type { PluginMessage } from \"../types/messages\";\nimport { getTauriCore, isTauriAvailable } from \"./tauri\";\n\nlet currentPluginName = \"\";\nlet currentHookName = \"\";\n\n/**\n * Set the message context for subsequent messages\n * This is typically called automatically by the plugin runtime\n */\nexport function setMessageContext(pluginName: string, hookName: string): void {\n currentPluginName = pluginName;\n currentHookName = hookName;\n}\n\n/**\n * Get the current message context\n */\nexport function getMessageContext(): { pluginName: string; hookName: string } {\n return { pluginName: currentPluginName, hookName: currentHookName };\n}\n\n/**\n * Send a message to Moss\n * Silently fails if Tauri is unavailable (useful for testing)\n */\nexport async function sendMessage(message: PluginMessage): Promise<void> {\n if (!isTauriAvailable()) {\n return;\n }\n\n try {\n await getTauriCore().invoke(\"plugin_message\", {\n pluginName: currentPluginName,\n hookName: currentHookName,\n message,\n });\n } catch {\n // Silently fail - logging would be recursive\n }\n}\n\n/**\n * Report progress to Moss\n */\nexport async function reportProgress(\n phase: string,\n current: number,\n total: number,\n message?: string\n): Promise<void> {\n await sendMessage({ type: \"progress\", phase, current, total, message });\n}\n\n/**\n * Report an error to Moss\n */\nexport async function reportError(\n error: string,\n context?: string,\n fatal = false\n): Promise<void> {\n await sendMessage({ type: \"error\", error, context, fatal });\n}\n\n/**\n * Report completion to Moss\n */\nexport async function reportComplete(result: unknown): Promise<void> {\n await sendMessage({ type: \"complete\", result });\n}\n","/**\n * Logging utilities for plugins\n */\n\nimport { sendMessage } from \"./messaging\";\n\n/**\n * Log an informational message\n */\nexport async function log(message: string): Promise<void> {\n await sendMessage({ type: \"log\", level: \"log\", message });\n}\n\n/**\n * Log a warning message\n */\nexport async function warn(message: string): Promise<void> {\n await sendMessage({ type: \"log\", level: \"warn\", message });\n}\n\n/**\n * Log an error message\n */\nexport async function error(message: string): Promise<void> {\n await sendMessage({ type: \"log\", level: \"error\", message });\n}\n","/**\n * Browser utilities for plugins\n * Abstracts Tauri browser commands to decouple plugins from internal APIs\n */\n\nimport { getTauriCore } from \"./tauri\";\n\n/**\n * Open a URL in the plugin browser window\n */\nexport async function openBrowser(url: string): Promise<void> {\n await getTauriCore().invoke(\"open_plugin_browser\", { url });\n}\n\n/**\n * Close the plugin browser window\n */\nexport async function closeBrowser(): Promise<void> {\n await getTauriCore().invoke(\"close_plugin_browser\", {});\n}\n","/**\n * Internal context utilities for Moss plugins\n *\n * This module provides access to the plugin execution context that is\n * set by the plugin runtime before each hook execution.\n *\n * INTERNAL USE ONLY - not exported to plugins.\n * Plugins should use the higher-level APIs (readFile, writeFile, etc.)\n * which use this context internally.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Internal plugin execution context\n *\n * Set by the plugin runtime (window.__MOSS_INTERNAL_CONTEXT__)\n * before each hook execution. Cleared after hook completes.\n */\nexport interface InternalPluginContext {\n /** Plugin name from manifest */\n plugin_name: string;\n /** Absolute path to the project directory */\n project_path: string;\n /** Absolute path to the .moss directory */\n moss_dir: string;\n}\n\n/**\n * Window interface with internal context\n */\ninterface ContextWindow {\n __MOSS_INTERNAL_CONTEXT__?: InternalPluginContext;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Get the internal plugin context\n *\n * This is used internally by moss-api utilities to resolve paths\n * and plugin identity. Plugins should not call this directly.\n *\n * @returns The current plugin execution context\n * @throws Error if called outside of a plugin hook execution\n *\n * @internal\n */\nexport function getInternalContext(): InternalPluginContext {\n const context = (window as unknown as ContextWindow).__MOSS_INTERNAL_CONTEXT__;\n\n if (!context) {\n throw new Error(\n \"This function must be called from within a plugin hook. \" +\n \"Ensure you're calling this from process(), generate(), deploy(), or syndicate().\"\n );\n }\n\n return context;\n}\n\n/**\n * Check if we're currently inside a plugin hook execution\n *\n * @returns true if inside a hook, false otherwise\n *\n * @internal\n */\nexport function hasContext(): boolean {\n const context = (window as unknown as ContextWindow).__MOSS_INTERNAL_CONTEXT__;\n return context !== undefined;\n}\n","/**\n * File system operations for Moss plugins\n *\n * These functions provide access to project files (user content).\n * Project path is auto-detected from the runtime context.\n *\n * For plugin's private storage, use the plugin-storage API instead.\n */\n\nimport { getTauriCore } from \"./tauri\";\nimport { getInternalContext } from \"./context\";\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Read a file from the project directory\n *\n * Project path is auto-detected from the runtime context.\n *\n * @param relativePath - Path relative to the project root\n * @returns File contents as a string\n * @throws Error if file cannot be read or called outside a hook\n *\n * @example\n * ```typescript\n * // Read an article\n * const content = await readFile(\"article/hello-world.md\");\n *\n * // Read package.json\n * const pkg = JSON.parse(await readFile(\"package.json\"));\n * ```\n */\nexport async function readFile(relativePath: string): Promise<string> {\n const ctx = getInternalContext();\n\n return getTauriCore().invoke<string>(\"read_project_file\", {\n projectPath: ctx.project_path,\n relativePath,\n });\n}\n\n/**\n * Write content to a file in the project directory\n *\n * Creates parent directories if they don't exist.\n * Project path is auto-detected from the runtime context.\n *\n * @param relativePath - Path relative to the project root\n * @param content - Content to write to the file\n * @throws Error if file cannot be written or called outside a hook\n *\n * @example\n * ```typescript\n * // Write a generated article\n * await writeFile(\"article/new-post.md\", \"# Hello World\\n\\nContent here.\");\n *\n * // Write index page\n * await writeFile(\"index.md\", markdownContent);\n * ```\n */\nexport async function writeFile(\n relativePath: string,\n content: string\n): Promise<void> {\n const ctx = getInternalContext();\n\n await getTauriCore().invoke(\"write_project_file\", {\n projectPath: ctx.project_path,\n relativePath,\n data: content,\n });\n}\n\n/**\n * List all files in the project directory\n *\n * Returns file paths relative to the project root.\n * Project path is auto-detected from the runtime context.\n *\n * @returns Array of relative file paths\n * @throws Error if directory cannot be listed or called outside a hook\n *\n * @example\n * ```typescript\n * const files = await listFiles();\n * // [\"index.md\", \"article/hello.md\", \"assets/logo.png\"]\n *\n * const mdFiles = files.filter(f => f.endsWith(\".md\"));\n * ```\n */\nexport async function listFiles(): Promise<string[]> {\n const ctx = getInternalContext();\n\n return getTauriCore().invoke<string[]>(\"list_project_files\", {\n projectPath: ctx.project_path,\n });\n}\n\n/**\n * Check if a file exists in the project directory\n *\n * Project path is auto-detected from the runtime context.\n *\n * @param relativePath - Path relative to the project root\n * @returns true if file exists, false otherwise\n * @throws Error if called outside a hook\n *\n * @example\n * ```typescript\n * if (await fileExists(\"index.md\")) {\n * const content = await readFile(\"index.md\");\n * }\n * ```\n */\nexport async function fileExists(relativePath: string): Promise<boolean> {\n // First, verify we have context (this will throw if not in a hook)\n getInternalContext();\n\n try {\n await readFile(relativePath);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Plugin storage API for Moss plugins\n *\n * Provides access to a plugin's private storage directory at:\n * .moss/plugins/{plugin-name}/\n *\n * Plugin identity is auto-detected from the runtime context -\n * plugins never need to know their own name or path.\n *\n * Config is just a file: readPluginFile(\"config.json\")\n */\n\nimport { getTauriCore } from \"./tauri\";\nimport { getInternalContext } from \"./context\";\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Read a file from the plugin's private storage directory\n *\n * Storage path: .moss/plugins/{plugin-name}/{relativePath}\n *\n * @param relativePath - Path relative to the plugin's storage directory\n * @returns File contents as a string\n * @throws Error if file cannot be read or called outside a hook\n *\n * @example\n * ```typescript\n * // Read plugin config\n * const configJson = await readPluginFile(\"config.json\");\n * const config = JSON.parse(configJson);\n *\n * // Read cached data\n * const cached = await readPluginFile(\"cache/articles.json\");\n * ```\n */\nexport async function readPluginFile(relativePath: string): Promise<string> {\n const ctx = getInternalContext();\n\n return getTauriCore().invoke<string>(\"read_plugin_file\", {\n pluginName: ctx.plugin_name,\n projectPath: ctx.project_path,\n relativePath,\n });\n}\n\n/**\n * Write a file to the plugin's private storage directory\n *\n * Creates parent directories if they don't exist.\n * Storage path: .moss/plugins/{plugin-name}/{relativePath}\n *\n * @param relativePath - Path relative to the plugin's storage directory\n * @param content - Content to write to the file\n * @throws Error if file cannot be written or called outside a hook\n *\n * @example\n * ```typescript\n * // Save plugin config\n * await writePluginFile(\"config.json\", JSON.stringify(config, null, 2));\n *\n * // Cache data\n * await writePluginFile(\"cache/articles.json\", JSON.stringify(articles));\n * ```\n */\nexport async function writePluginFile(\n relativePath: string,\n content: string\n): Promise<void> {\n const ctx = getInternalContext();\n\n await getTauriCore().invoke(\"write_plugin_file\", {\n pluginName: ctx.plugin_name,\n projectPath: ctx.project_path,\n relativePath,\n content,\n });\n}\n\n/**\n * List all files in the plugin's private storage directory\n *\n * Returns file paths relative to the plugin's storage directory.\n *\n * @returns Array of relative file paths\n * @throws Error if directory cannot be listed or called outside a hook\n *\n * @example\n * ```typescript\n * const files = await listPluginFiles();\n * // [\"config.json\", \"cache/articles.json\", \"cache/images.json\"]\n * ```\n */\nexport async function listPluginFiles(): Promise<string[]> {\n const ctx = getInternalContext();\n\n return getTauriCore().invoke<string[]>(\"list_plugin_files\", {\n pluginName: ctx.plugin_name,\n projectPath: ctx.project_path,\n });\n}\n\n/**\n * Check if a file exists in the plugin's private storage directory\n *\n * @param relativePath - Path relative to the plugin's storage directory\n * @returns true if file exists, false otherwise\n * @throws Error if called outside a hook\n *\n * @example\n * ```typescript\n * if (await pluginFileExists(\"config.json\")) {\n * const config = JSON.parse(await readPluginFile(\"config.json\"));\n * } else {\n * // Use default config\n * }\n * ```\n */\nexport async function pluginFileExists(relativePath: string): Promise<boolean> {\n const ctx = getInternalContext();\n\n return getTauriCore().invoke<boolean>(\"plugin_file_exists\", {\n pluginName: ctx.plugin_name,\n projectPath: ctx.project_path,\n relativePath,\n });\n}\n","/**\n * HTTP operations for Moss plugins\n *\n * These functions provide HTTP capabilities that bypass browser CORS\n * restrictions by using Rust's HTTP client under the hood.\n *\n * Project path for downloads is auto-detected from the runtime context.\n */\n\nimport { getTauriCore } from \"./tauri\";\nimport { getInternalContext } from \"./context\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Options for HTTP fetch requests\n */\nexport interface FetchOptions {\n /** Timeout in milliseconds (default: 30000) */\n timeoutMs?: number;\n}\n\n/**\n * Result from an HTTP fetch operation\n */\nexport interface FetchResult {\n /** HTTP status code */\n status: number;\n /** Whether the request was successful (2xx status) */\n ok: boolean;\n /** Content-Type header from response */\n contentType: string | null;\n /** Response body as Uint8Array */\n body: Uint8Array;\n /** Get response body as text */\n text(): string;\n}\n\n/**\n * Options for asset download\n */\nexport interface DownloadOptions {\n /** Timeout in milliseconds (default: 30000) */\n timeoutMs?: number;\n}\n\n/**\n * Result from an asset download operation\n */\nexport interface DownloadResult {\n /** HTTP status code */\n status: number;\n /** Whether the request was successful (2xx status) */\n ok: boolean;\n /** Content-Type header from response */\n contentType: string | null;\n /** Number of bytes written to disk */\n bytesWritten: number;\n /** Actual path where file was saved (relative to project) */\n actualPath: string;\n}\n\n// ============================================================================\n// Internal Types (Tauri response shapes)\n// ============================================================================\n\ninterface TauriFetchResult {\n status: number;\n ok: boolean;\n body_base64: string;\n content_type: string | null;\n}\n\ninterface TauriDownloadResult {\n status: number;\n ok: boolean;\n content_type: string | null;\n bytes_written: number;\n actual_path: string;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Fetch a URL using Rust's HTTP client (bypasses CORS)\n *\n * @param url - URL to fetch\n * @param options - Optional fetch configuration\n * @returns Fetch result with status, body, and helpers\n * @throws Error if network request fails\n *\n * @example\n * ```typescript\n * const result = await fetchUrl(\"https://api.example.com/data\");\n * if (result.ok) {\n * const data = JSON.parse(result.text());\n * }\n * ```\n */\nexport async function fetchUrl(\n url: string,\n options: FetchOptions = {}\n): Promise<FetchResult> {\n const { timeoutMs = 30000 } = options;\n\n const result = await getTauriCore().invoke<TauriFetchResult>(\"fetch_url\", {\n url,\n timeoutMs,\n });\n\n // Decode base64 body to Uint8Array\n const binaryString = atob(result.body_base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n\n return {\n status: result.status,\n ok: result.ok,\n contentType: result.content_type,\n body: bytes,\n text(): string {\n return new TextDecoder().decode(bytes);\n },\n };\n}\n\n/**\n * Download a URL and save directly to disk\n *\n * Downloads the file and writes it directly to disk without passing\n * the binary data through JavaScript. The filename is derived from\n * the URL, and file extension is inferred from Content-Type if needed.\n *\n * Project path is auto-detected from the runtime context.\n *\n * @param url - URL to download\n * @param targetDir - Target directory within project (e.g., \"assets\")\n * @param options - Optional download configuration\n * @returns Download result with actual path where file was saved\n * @throws Error if download or write fails, or called outside a hook\n *\n * @example\n * ```typescript\n * const result = await downloadAsset(\n * \"https://example.com/image\",\n * \"assets\"\n * );\n * if (result.ok) {\n * console.log(`Saved to ${result.actualPath}`); // e.g., \"assets/image.png\"\n * }\n * ```\n */\nexport async function downloadAsset(\n url: string,\n targetDir: string,\n options: DownloadOptions = {}\n): Promise<DownloadResult> {\n const ctx = getInternalContext();\n const { timeoutMs = 30000 } = options;\n\n const result = await getTauriCore().invoke<TauriDownloadResult>(\n \"download_asset\",\n {\n url,\n projectPath: ctx.project_path,\n targetDir,\n timeoutMs,\n }\n );\n\n return {\n status: result.status,\n ok: result.ok,\n contentType: result.content_type,\n bytesWritten: result.bytes_written,\n actualPath: result.actual_path,\n };\n}\n","/**\n * Binary execution for Moss plugins\n *\n * Allows plugins to execute external binaries (git, npm, etc.)\n * in a controlled environment.\n *\n * Working directory is auto-detected from the runtime context\n * (always the project root).\n */\n\nimport { getTauriCore } from \"./tauri\";\nimport { getInternalContext } from \"./context\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Options for executing a binary\n */\nexport interface ExecuteOptions {\n /** Path to the binary (can be just the name if in PATH) */\n binaryPath: string;\n /** Arguments to pass to the binary */\n args: string[];\n /** Timeout in milliseconds (default: 60000) */\n timeoutMs?: number;\n /** Additional environment variables */\n env?: Record<string, string>;\n}\n\n/**\n * Result from binary execution\n */\nexport interface ExecuteResult {\n /** Whether the command succeeded (exit code 0) */\n success: boolean;\n /** Exit code from the process */\n exitCode: number;\n /** Standard output from the process */\n stdout: string;\n /** Standard error output from the process */\n stderr: string;\n}\n\n// ============================================================================\n// Internal Types (Tauri response shape)\n// ============================================================================\n\ninterface TauriBinaryResult {\n success: boolean;\n exit_code: number;\n stdout: string;\n stderr: string;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Execute an external binary\n *\n * Working directory is auto-detected from the runtime context\n * (always the project root).\n *\n * @param options - Execution options including binary path and args\n * @returns Execution result with stdout, stderr, and exit code\n * @throws Error if binary cannot be executed or called outside a hook\n *\n * @example\n * ```typescript\n * // Run git status\n * const result = await executeBinary({\n * binaryPath: \"git\",\n * args: [\"status\"],\n * });\n *\n * if (result.success) {\n * console.log(result.stdout);\n * } else {\n * console.error(result.stderr);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Run npm install with timeout\n * const result = await executeBinary({\n * binaryPath: \"npm\",\n * args: [\"install\"],\n * timeoutMs: 120000,\n * env: { NODE_ENV: \"production\" },\n * });\n * ```\n */\nexport async function executeBinary(\n options: ExecuteOptions\n): Promise<ExecuteResult> {\n const ctx = getInternalContext();\n const { binaryPath, args, timeoutMs = 60000, env } = options;\n\n const result = await getTauriCore().invoke<TauriBinaryResult>(\n \"execute_binary\",\n {\n binaryPath,\n args,\n workingDir: ctx.project_path,\n timeoutMs,\n env,\n }\n );\n\n return {\n success: result.success,\n exitCode: result.exit_code,\n stdout: result.stdout,\n stderr: result.stderr,\n };\n}\n","/**\n * Cookie management for Moss plugins\n *\n * Allows plugins to store and retrieve authentication cookies\n * for external services (e.g., Matters.town, GitHub).\n *\n * Cookies are automatically scoped to the plugin's registered domain\n * (defined in manifest.json) - plugins cannot access other plugins' cookies.\n */\n\nimport { getTauriCore } from \"./tauri\";\nimport { getInternalContext } from \"./context\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A cookie stored for plugin authentication\n */\nexport interface Cookie {\n /** Cookie name */\n name: string;\n /** Cookie value */\n value: string;\n /** Optional domain for the cookie */\n domain?: string;\n /** Optional path for the cookie */\n path?: string;\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\n/**\n * Get stored cookies for the current plugin.\n *\n * The plugin's identity is automatically detected from the runtime context.\n * Cookies are filtered by the domain declared in the plugin's manifest.json.\n *\n * **Must be called from within a plugin hook** (process, generate, deploy, syndicate).\n *\n * @returns Array of cookies for the plugin's registered domain\n * @throws Error if called outside of a plugin hook execution\n *\n * @example\n * ```typescript\n * // Inside a hook function:\n * const cookies = await getPluginCookie();\n * const token = cookies.find(c => c.name === \"__access_token\");\n * if (token) {\n * // Use token for authenticated requests\n * }\n * ```\n */\nexport async function getPluginCookie(): Promise<Cookie[]> {\n const ctx = getInternalContext();\n\n return getTauriCore().invoke<Cookie[]>(\"get_plugin_cookie\", {\n pluginName: ctx.plugin_name,\n projectPath: ctx.project_path,\n });\n}\n\n/**\n * Store cookies for the current plugin.\n *\n * The plugin's identity is automatically detected from the runtime context.\n *\n * **Must be called from within a plugin hook** (process, generate, deploy, syndicate).\n *\n * @param cookies - Array of cookies to store\n * @throws Error if called outside of a plugin hook execution\n *\n * @example\n * ```typescript\n * // Inside a hook function:\n * await setPluginCookie([\n * { name: \"session\", value: \"abc123\" }\n * ]);\n * ```\n */\nexport async function setPluginCookie(cookies: Cookie[]): Promise<void> {\n const ctx = getInternalContext();\n\n await getTauriCore().invoke(\"set_plugin_cookie\", {\n pluginName: ctx.plugin_name,\n projectPath: ctx.project_path,\n cookies,\n });\n}\n"],"mappings":"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"}
|