@mutka-explorer/module 1.0.0-rc.2 → 1.0.0-rc.3
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/README.md +19 -13
- package/index.d.ts +22 -10
- package/index.js +7 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# @mutka-explorer/module
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Types + the `defineModule()` helper for authoring [Mutka](https://github.com/ilianAZZ/mutka) modules.
|
|
4
4
|
|
|
5
5
|
A Mutka module is a single self-contained ESM file that
|
|
6
|
-
`export default`s a module definition. It
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
`export default`s a module definition. It reaches the system only through the
|
|
7
|
+
`host` object passed to `setup(host)`, and every `host.*` call is checked against
|
|
8
|
+
the permissions it declares.
|
|
9
9
|
|
|
10
|
-
This package
|
|
11
|
-
`
|
|
12
|
-
|
|
10
|
+
This package is **types plus one tiny runtime export**: `defineModule`, an identity
|
|
11
|
+
function (`def => def`). Everything else is types, erased at compile time. The only
|
|
12
|
+
reason `defineModule` exists at runtime is type inference — it captures your
|
|
13
|
+
`commands[].id`s so `host.onCommand` only accepts ids you declared (a typo or stale
|
|
14
|
+
id is a compile error). A bundler inlines the call, so your built `index.js` stays
|
|
15
|
+
import-free — exactly what Mutka loads.
|
|
13
16
|
|
|
14
17
|
## Install
|
|
15
18
|
|
|
@@ -20,9 +23,9 @@ npm i -D @mutka-explorer/module
|
|
|
20
23
|
## Usage
|
|
21
24
|
|
|
22
25
|
```ts
|
|
23
|
-
import
|
|
26
|
+
import { defineModule } from "@mutka-explorer/module";
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
export default defineModule({
|
|
26
29
|
id: "you.hello",
|
|
27
30
|
name: "Hello",
|
|
28
31
|
version: "1.0.0",
|
|
@@ -31,19 +34,22 @@ const mod: SandboxModuleDef = {
|
|
|
31
34
|
{ id: "you.hello.count", label: "Count items", contextMenu: true, when: { selection: "any" } },
|
|
32
35
|
],
|
|
33
36
|
setup(host) {
|
|
34
|
-
host.onCommand("you.hello.count", async (snap) => {
|
|
37
|
+
host.onCommand("you.hello.count", async (snap) => { // ✓ autocompleted from commands[]
|
|
35
38
|
const items = await host.fs.readDir(snap.currentDirectory);
|
|
36
39
|
host.log(`${items.length} items`);
|
|
37
40
|
});
|
|
41
|
+
// host.onCommand("you.hello.typo", …) ← compile error: not a declared command id
|
|
38
42
|
},
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export default mod;
|
|
43
|
+
});
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
`host` is fully typed (`host.fs`, `host.ui`, `host.net`, `host.dialog`, …), as
|
|
45
47
|
are permissions, `when` clauses, the declarative `UINode` tree, and `FormSchema`.
|
|
46
48
|
|
|
49
|
+
> Prefer no runtime import at all? `import type { SandboxModuleDef } from
|
|
50
|
+
> "@mutka-explorer/module"` and annotate `const mod: SandboxModuleDef<"you.hello.count">
|
|
51
|
+
> = { … }` — the generic param enforces the same command-id matching, purely in types.
|
|
52
|
+
|
|
47
53
|
### Build to a single file
|
|
48
54
|
|
|
49
55
|
Mutka loads one ESM file with the default export intact. Bundle your TypeScript
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Type definitions for @mutka-explorer/module v1.0.0-rc.
|
|
1
|
+
// Type definitions for @mutka-explorer/module v1.0.0-rc.3
|
|
2
2
|
// Mutka module SDK — author-facing types only (no runtime code).
|
|
3
3
|
// Generated from the Mutka app source; do not edit by hand.
|
|
4
4
|
|
|
@@ -99,8 +99,8 @@ export interface WhenClause {
|
|
|
99
99
|
* e.g. ["js"]). */
|
|
100
100
|
extensions?: string[];
|
|
101
101
|
}
|
|
102
|
-
export interface SandboxCommand {
|
|
103
|
-
id:
|
|
102
|
+
export interface SandboxCommand<Id extends string = string> {
|
|
103
|
+
id: Id;
|
|
104
104
|
label: string;
|
|
105
105
|
icon?: string;
|
|
106
106
|
shortcut?: string;
|
|
@@ -456,7 +456,7 @@ export interface ClipboardFiles {
|
|
|
456
456
|
}
|
|
457
457
|
/** Whether a file's data is materialized locally or still cloud-only. */
|
|
458
458
|
export type CloudStatus = "downloaded" | "cloud";
|
|
459
|
-
export interface SandboxHostApi {
|
|
459
|
+
export interface SandboxHostApi<TCommandId extends string = string> {
|
|
460
460
|
fs: {
|
|
461
461
|
/** List a directory's entries (works for local paths and provider schemes). */
|
|
462
462
|
readDir(path: string): Promise<FileItem[]>;
|
|
@@ -614,8 +614,10 @@ export interface SandboxHostApi {
|
|
|
614
614
|
refresh(): Promise<void>;
|
|
615
615
|
/** Run an item through the open-resolution pipeline (keyboard double-click). */
|
|
616
616
|
activate(item: FileItem): Promise<void>;
|
|
617
|
-
/** Register the function that runs when one of this module's commands fires.
|
|
618
|
-
|
|
617
|
+
/** Register the function that runs when one of this module's commands fires.
|
|
618
|
+
* When you use `defineModule`, `commandId` is constrained to the ids you
|
|
619
|
+
* declared in `commands[]`, so a typo or stale id is a compile error. */
|
|
620
|
+
onCommand(commandId: TCommandId, handler: CommandHandler): void;
|
|
619
621
|
/** Register the function that runs when an item matches one of this module's open handlers. */
|
|
620
622
|
onOpen(handlerId: string, handler: OpenHandler): void;
|
|
621
623
|
/** Register the value provider for one of this module's custom columns. */
|
|
@@ -653,7 +655,7 @@ export interface SandboxHostApi {
|
|
|
653
655
|
/** Forwarded to the host console, prefixed with the module id. */
|
|
654
656
|
log(...args: unknown[]): void;
|
|
655
657
|
}
|
|
656
|
-
export interface SandboxModuleDef {
|
|
658
|
+
export interface SandboxModuleDef<TCommandId extends string = string> {
|
|
657
659
|
/** Unique module id, "author.name" convention. */
|
|
658
660
|
id: string;
|
|
659
661
|
name?: string;
|
|
@@ -674,8 +676,10 @@ export interface SandboxModuleDef {
|
|
|
674
676
|
tags?: string[];
|
|
675
677
|
/** Every privileged capability this module uses MUST be listed here. */
|
|
676
678
|
permissions?: ModulePermission[];
|
|
677
|
-
/** Commands surfaced into the app's menus / toolbar.
|
|
678
|
-
|
|
679
|
+
/** Commands surfaced into the app's menus / toolbar. The literal `id`s here are
|
|
680
|
+
* captured (via `defineModule`) and become the only values `host.onCommand`
|
|
681
|
+
* accepts in `setup`. */
|
|
682
|
+
commands?: SandboxCommand<TCommandId>[];
|
|
679
683
|
/** Open handlers (double-click behavior) by item type. */
|
|
680
684
|
openHandlers?: SandboxOpenHandler[];
|
|
681
685
|
/** Declarative entries in the left "Places" sidebar, grouped by category. */
|
|
@@ -730,8 +734,16 @@ export interface SandboxModuleDef {
|
|
|
730
734
|
/**
|
|
731
735
|
* Runs once after load. Register command/open handlers and event subscriptions
|
|
732
736
|
* here. Reaches the system only through `host.*` (each gated by permissions).
|
|
737
|
+
* `host.onCommand` is typed to the `commands[].id`s declared above.
|
|
733
738
|
*/
|
|
734
|
-
setup?: (host: SandboxHostApi) => void | Promise<void>;
|
|
739
|
+
setup?: (host: SandboxHostApi<TCommandId>) => void | Promise<void>;
|
|
735
740
|
}
|
|
741
|
+
/**
|
|
742
|
+
* Author-facing helper. At runtime it returns its argument unchanged (so the
|
|
743
|
+
* built file is import-free once bundled); at the type level it infers the union
|
|
744
|
+
* of `commands[].id` literals and threads it into `host.onCommand`, so a typo'd
|
|
745
|
+
* or stale command id is a compile error. With no `commands`, ids stay `string`.
|
|
746
|
+
*/
|
|
747
|
+
export declare function defineModule<const TCommandId extends string = string>(def: SandboxModuleDef<TCommandId>): SandboxModuleDef<TCommandId>;
|
|
736
748
|
|
|
737
749
|
export {};
|
package/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Runtime for @mutka-explorer/module.
|
|
2
|
+
//
|
|
3
|
+
// The ONLY runtime export is `defineModule`, an identity function — it exists
|
|
4
|
+
// purely so TypeScript can infer your `commands[].id`s and type `host.onCommand`
|
|
5
|
+
// to them (all the typing lives in index.d.ts). A bundler inlines this call, so
|
|
6
|
+
// an authored module's built `index.js` stays import-free and self-contained.
|
|
7
|
+
export const defineModule = (def) => def;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutka-explorer/module",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0-rc.3",
|
|
4
|
+
"description": "Types + the defineModule() helper for authoring Mutka modules — the SandboxModuleDef shape, the full typed host API, and command-id inference.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Mutka contributors",
|
|
7
7
|
"homepage": "https://github.com/ilianAZZ/mutka",
|
|
@@ -17,14 +17,18 @@
|
|
|
17
17
|
"sdk",
|
|
18
18
|
"file-explorer"
|
|
19
19
|
],
|
|
20
|
+
"type": "module",
|
|
20
21
|
"types": "./index.d.ts",
|
|
22
|
+
"main": "./index.js",
|
|
21
23
|
"exports": {
|
|
22
24
|
".": {
|
|
23
|
-
"types": "./index.d.ts"
|
|
25
|
+
"types": "./index.d.ts",
|
|
26
|
+
"import": "./index.js"
|
|
24
27
|
}
|
|
25
28
|
},
|
|
26
29
|
"files": [
|
|
27
30
|
"index.d.ts",
|
|
31
|
+
"index.js",
|
|
28
32
|
"README.md"
|
|
29
33
|
],
|
|
30
34
|
"publishConfig": {
|