@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 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 abstract away the underlying Tauri commands,
222
- * providing a clean API for plugins to read/write project files.
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
- * @param projectPath - Absolute path to the project directory
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
- * const content = await readFile("/path/to/project", "src/index.ts");
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(projectPath: string, relativePath: string): Promise<string>;
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
- * await writeFile("/path/to/project", "output/result.md", "# Hello World");
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(projectPath: string, relativePath: string, content: string): Promise<void>;
265
+ declare function writeFile(relativePath: string, content: string): Promise<void>;
254
266
  /**
255
- * List all files in a project directory
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("/path/to/project");
266
- * // ["src/index.ts", "package.json", "README.md"]
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(projectPath: string): Promise<string[]>;
283
+ declare function listFiles(): Promise<string[]>;
270
284
  /**
271
285
  * Check if a file exists in the project directory
272
286
  *
273
- * @param projectPath - Absolute path to the project directory
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 fileExists("/path/to/project", "config.json")) {
280
- * // load config
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 fileExists(projectPath: string, relativePath: string): Promise<boolean>;
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, projectPath: string, targetDir: string, options?: DownloadOptions): Promise<DownloadResult>;
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
- * @param options - Execution options including binary path, args, and working directory
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 a plugin
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
- * @param pluginName - Name of the plugin
478
- * @param projectPath - Absolute path to the project directory
479
- * @returns Array of stored cookies
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
- * const cookies = await getPluginCookie("matters-syndicator", "/path/to/project");
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(pluginName: string, projectPath: string): Promise<Cookie[]>;
603
+ declare function getPluginCookie(): Promise<Cookie[]>;
491
604
  /**
492
- * Store cookies for a plugin
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
- * await setPluginCookie("my-plugin", "/path/to/project", [
616
+ * // Inside a hook function:
617
+ * await setPluginCookie([
501
618
  * { name: "session", value: "abc123" }
502
619
  * ]);
503
620
  * ```
504
621
  */
505
- declare function setPluginCookie(pluginName: string, projectPath: string, cookies: Cookie[]): Promise<void>;
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
@@ -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":"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"}
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 abstract away the underlying Tauri commands,
154
- * providing a clean API for plugins to read/write project files.
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
- * @param projectPath - Absolute path to the project directory
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
- * const content = await readFile("/path/to/project", "src/index.ts");
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(projectPath, relativePath) {
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
- * await writeFile("/path/to/project", "output/result.md", "# Hello World");
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(projectPath, relativePath, content) {
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 a project directory
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("/path/to/project");
209
- * // ["src/index.ts", "package.json", "README.md"]
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(projectPath) {
213
- return getTauriCore().invoke("list_project_files", { projectPath });
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
- * @param projectPath - Absolute path to the project directory
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("/path/to/project", "config.json")) {
225
- * // load config
261
+ * if (await fileExists("index.md")) {
262
+ * const content = await readFile("index.md");
226
263
  * }
227
264
  * ```
228
265
  */
229
- async function fileExists(projectPath, relativePath) {
266
+ async function fileExists(relativePath) {
267
+ getInternalContext();
230
268
  try {
231
- await readFile(projectPath, relativePath);
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, projectPath, targetDir, options = {}) {
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
- * @param options - Execution options including binary path, args, and working directory
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 { binaryPath, args, workingDir, timeoutMs = 6e4, env } = options;
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 a plugin
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
- * @param pluginName - Name of the plugin
396
- * @param projectPath - Absolute path to the project directory
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
- * const cookies = await getPluginCookie("matters-syndicator", "/path/to/project");
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(pluginName, projectPath) {
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 a plugin
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
- * await setPluginCookie("my-plugin", "/path/to/project", [
595
+ * // Inside a hook function:
596
+ * await setPluginCookie([
424
597
  * { name: "session", value: "abc123" }
425
598
  * ]);
426
599
  * ```
427
600
  */
428
- async function setPluginCookie(pluginName, projectPath, cookies) {
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
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiosis-lab/moss-api",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Official API for building Moss plugins - types and utilities for plugin development",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",