@immediately-run/sdk 0.5.0 → 0.7.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/editor.cjs +21 -5
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.d.cts +19 -1
- package/dist/editor.d.ts +19 -1
- package/dist/editor.js +15 -4
- package/dist/editor.js.map +1 -1
- package/dist/editorContext.cjs +11 -2
- package/dist/editorContext.cjs.map +1 -1
- package/dist/editorContext.d.cts +12 -0
- package/dist/editorContext.d.ts +12 -0
- package/dist/editorContext.js +11 -2
- package/dist/editorContext.js.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/editor.cjs
CHANGED
|
@@ -18,20 +18,36 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var editor_exports = {};
|
|
20
20
|
__export(editor_exports, {
|
|
21
|
-
|
|
21
|
+
createFile: () => createFile,
|
|
22
|
+
createFolder: () => createFolder,
|
|
23
|
+
deleteEntry: () => deleteEntry,
|
|
24
|
+
openInEditor: () => openInEditor,
|
|
25
|
+
renameEntry: () => renameEntry,
|
|
26
|
+
uploadFile: () => uploadFile
|
|
22
27
|
});
|
|
23
28
|
module.exports = __toCommonJS(editor_exports);
|
|
24
29
|
var import_sandboxUtils = require("./sandboxUtils");
|
|
25
|
-
const
|
|
26
|
-
const res = await (0, import_sandboxUtils.protocolRequest)("editor",
|
|
30
|
+
const editorRequest = async (method, arg) => {
|
|
31
|
+
const res = await (0, import_sandboxUtils.protocolRequest)("editor", method, [arg]);
|
|
27
32
|
if (!res || res.ok !== true) {
|
|
28
|
-
const err = new Error(res?.message ??
|
|
33
|
+
const err = new Error(res?.message ?? `editor ${method} failed`);
|
|
29
34
|
err.code = res?.code ?? "unknown";
|
|
30
35
|
throw err;
|
|
31
36
|
}
|
|
32
37
|
};
|
|
38
|
+
const openInEditor = (path) => editorRequest("open", { path });
|
|
39
|
+
const createFile = (path) => editorRequest("createFile", { path });
|
|
40
|
+
const createFolder = (path) => editorRequest("createFolder", { path });
|
|
41
|
+
const deleteEntry = (path) => editorRequest("deleteEntry", { path });
|
|
42
|
+
const renameEntry = (from, to) => editorRequest("rename", { from, to });
|
|
43
|
+
const uploadFile = (path, bytes) => editorRequest("upload", { path, bytes });
|
|
33
44
|
// Annotate the CommonJS export names for ESM import in node:
|
|
34
45
|
0 && (module.exports = {
|
|
35
|
-
|
|
46
|
+
createFile,
|
|
47
|
+
createFolder,
|
|
48
|
+
deleteEntry,
|
|
49
|
+
openInEditor,
|
|
50
|
+
renameEntry,
|
|
51
|
+
uploadFile
|
|
36
52
|
});
|
|
37
53
|
//# sourceMappingURL=editor.cjs.map
|
package/dist/editor.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n */\nexport const openInEditor =
|
|
1
|
+
{"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\nconst editorRequest = async (\n method: string,\n arg: Record<string, unknown>,\n): Promise<void> => {\n const res = (await protocolRequest('editor', method, [arg])) as EditorResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `editor ${method} failed`) as EditorWriteError;\n err.code = (res?.code as EditorWriteError['code']) ?? 'unknown';\n throw err;\n }\n};\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n */\nexport const openInEditor = (path: string): Promise<void> => editorRequest('open', { path });\n\n// ---------------------------------------------------------------------------\n// Working-tree mutation (UI_AS_APPS_SPEC §4 / EDITOR_AS_APP_SPEC §5.2). The file\n// explorer NAMES a working-tree path and the HOST performs the COW write (and\n// refreshes the preview) — the app holds no write port; it asks. Gated by the\n// first-party `editor:write` capability, so only a first-party chrome app (the\n// file explorer) can call these; anyone else is refused at the gate.\n// ---------------------------------------------------------------------------\n\n/** An error from a working-tree mutation, carrying a machine-readable `.code`. */\nexport interface EditorWriteError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:write` (first-party-only)\n | 'not-found' // the target file/folder does not exist (delete/rename)\n | 'exists' // the target already exists (create/rename would clobber)\n | 'protected' // the host refuses to delete this file (e.g. package.json)\n | 'too-large' // an upload exceeds the host's size limit\n | 'invalid-params' // a path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a\n * file is already there. */\nexport const createFile = (path: string): Promise<void> => editorRequest('createFile', { path });\n\n/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */\nexport const createFolder = (path: string): Promise<void> =>\n editorRequest('createFolder', { path });\n\n/** Delete a working-tree file, or a folder and everything under it. Rejects\n * `protected` for files the host won't remove, `not-found` if absent. */\nexport const deleteEntry = (path: string): Promise<void> => editorRequest('deleteEntry', { path });\n\n/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`\n * is taken, `not-found` if `from` is absent. */\nexport const renameEntry = (from: string, to: string): Promise<void> =>\n editorRequest('rename', { from, to });\n\n/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects\n * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */\nexport const uploadFile = (path: string, bytes: Uint8Array): Promise<void> =>\n editorRequest('upload', { path, bytes });\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAgC;AA4BhC,MAAM,gBAAgB,OACpB,QACA,QACkB;AAClB,QAAM,MAAO,UAAM,qCAAgB,UAAU,QAAQ,CAAC,GAAG,CAAC;AAC1D,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU,MAAM,SAAS;AAC/D,QAAI,OAAQ,KAAK,QAAqC;AACtD,UAAM;AAAA,EACR;AACF;AAQO,MAAM,eAAe,CAAC,SAAgC,cAAc,QAAQ,EAAE,KAAK,CAAC;AAyBpF,MAAM,aAAa,CAAC,SAAgC,cAAc,cAAc,EAAE,KAAK,CAAC;AAGxF,MAAM,eAAe,CAAC,SAC3B,cAAc,gBAAgB,EAAE,KAAK,CAAC;AAIjC,MAAM,cAAc,CAAC,SAAgC,cAAc,eAAe,EAAE,KAAK,CAAC;AAI1F,MAAM,cAAc,CAAC,MAAc,OACxC,cAAc,UAAU,EAAE,MAAM,GAAG,CAAC;AAI/B,MAAM,aAAa,CAAC,MAAc,UACvC,cAAc,UAAU,EAAE,MAAM,MAAM,CAAC;","names":[]}
|
package/dist/editor.d.cts
CHANGED
|
@@ -20,5 +20,23 @@ interface EditorOpenError extends Error {
|
|
|
20
20
|
* app may not open files.
|
|
21
21
|
*/
|
|
22
22
|
declare const openInEditor: (path: string) => Promise<void>;
|
|
23
|
+
/** An error from a working-tree mutation, carrying a machine-readable `.code`. */
|
|
24
|
+
interface EditorWriteError extends Error {
|
|
25
|
+
code: 'forbidden' | 'not-found' | 'exists' | 'protected' | 'too-large' | 'invalid-params' | 'no-target' | 'unknown';
|
|
26
|
+
}
|
|
27
|
+
/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a
|
|
28
|
+
* file is already there. */
|
|
29
|
+
declare const createFile: (path: string) => Promise<void>;
|
|
30
|
+
/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */
|
|
31
|
+
declare const createFolder: (path: string) => Promise<void>;
|
|
32
|
+
/** Delete a working-tree file, or a folder and everything under it. Rejects
|
|
33
|
+
* `protected` for files the host won't remove, `not-found` if absent. */
|
|
34
|
+
declare const deleteEntry: (path: string) => Promise<void>;
|
|
35
|
+
/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`
|
|
36
|
+
* is taken, `not-found` if `from` is absent. */
|
|
37
|
+
declare const renameEntry: (from: string, to: string) => Promise<void>;
|
|
38
|
+
/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects
|
|
39
|
+
* `too-large` past the host's size limit. The bytes are transferred (zero-copy). */
|
|
40
|
+
declare const uploadFile: (path: string, bytes: Uint8Array) => Promise<void>;
|
|
23
41
|
|
|
24
|
-
export { type EditorOpenError, openInEditor };
|
|
42
|
+
export { type EditorOpenError, type EditorWriteError, createFile, createFolder, deleteEntry, openInEditor, renameEntry, uploadFile };
|
package/dist/editor.d.ts
CHANGED
|
@@ -20,5 +20,23 @@ interface EditorOpenError extends Error {
|
|
|
20
20
|
* app may not open files.
|
|
21
21
|
*/
|
|
22
22
|
declare const openInEditor: (path: string) => Promise<void>;
|
|
23
|
+
/** An error from a working-tree mutation, carrying a machine-readable `.code`. */
|
|
24
|
+
interface EditorWriteError extends Error {
|
|
25
|
+
code: 'forbidden' | 'not-found' | 'exists' | 'protected' | 'too-large' | 'invalid-params' | 'no-target' | 'unknown';
|
|
26
|
+
}
|
|
27
|
+
/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a
|
|
28
|
+
* file is already there. */
|
|
29
|
+
declare const createFile: (path: string) => Promise<void>;
|
|
30
|
+
/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */
|
|
31
|
+
declare const createFolder: (path: string) => Promise<void>;
|
|
32
|
+
/** Delete a working-tree file, or a folder and everything under it. Rejects
|
|
33
|
+
* `protected` for files the host won't remove, `not-found` if absent. */
|
|
34
|
+
declare const deleteEntry: (path: string) => Promise<void>;
|
|
35
|
+
/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`
|
|
36
|
+
* is taken, `not-found` if `from` is absent. */
|
|
37
|
+
declare const renameEntry: (from: string, to: string) => Promise<void>;
|
|
38
|
+
/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects
|
|
39
|
+
* `too-large` past the host's size limit. The bytes are transferred (zero-copy). */
|
|
40
|
+
declare const uploadFile: (path: string, bytes: Uint8Array) => Promise<void>;
|
|
23
41
|
|
|
24
|
-
export { type EditorOpenError, openInEditor };
|
|
42
|
+
export { type EditorOpenError, type EditorWriteError, createFile, createFolder, deleteEntry, openInEditor, renameEntry, uploadFile };
|
package/dist/editor.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { protocolRequest } from "./sandboxUtils";
|
|
2
|
-
const
|
|
3
|
-
const res = await protocolRequest("editor",
|
|
2
|
+
const editorRequest = async (method, arg) => {
|
|
3
|
+
const res = await protocolRequest("editor", method, [arg]);
|
|
4
4
|
if (!res || res.ok !== true) {
|
|
5
|
-
const err = new Error(res?.message ??
|
|
5
|
+
const err = new Error(res?.message ?? `editor ${method} failed`);
|
|
6
6
|
err.code = res?.code ?? "unknown";
|
|
7
7
|
throw err;
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
|
+
const openInEditor = (path) => editorRequest("open", { path });
|
|
11
|
+
const createFile = (path) => editorRequest("createFile", { path });
|
|
12
|
+
const createFolder = (path) => editorRequest("createFolder", { path });
|
|
13
|
+
const deleteEntry = (path) => editorRequest("deleteEntry", { path });
|
|
14
|
+
const renameEntry = (from, to) => editorRequest("rename", { from, to });
|
|
15
|
+
const uploadFile = (path, bytes) => editorRequest("upload", { path, bytes });
|
|
10
16
|
export {
|
|
11
|
-
|
|
17
|
+
createFile,
|
|
18
|
+
createFolder,
|
|
19
|
+
deleteEntry,
|
|
20
|
+
openInEditor,
|
|
21
|
+
renameEntry,
|
|
22
|
+
uploadFile
|
|
12
23
|
};
|
|
13
24
|
//# sourceMappingURL=editor.js.map
|
package/dist/editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n */\nexport const openInEditor =
|
|
1
|
+
{"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\nconst editorRequest = async (\n method: string,\n arg: Record<string, unknown>,\n): Promise<void> => {\n const res = (await protocolRequest('editor', method, [arg])) as EditorResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `editor ${method} failed`) as EditorWriteError;\n err.code = (res?.code as EditorWriteError['code']) ?? 'unknown';\n throw err;\n }\n};\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n */\nexport const openInEditor = (path: string): Promise<void> => editorRequest('open', { path });\n\n// ---------------------------------------------------------------------------\n// Working-tree mutation (UI_AS_APPS_SPEC §4 / EDITOR_AS_APP_SPEC §5.2). The file\n// explorer NAMES a working-tree path and the HOST performs the COW write (and\n// refreshes the preview) — the app holds no write port; it asks. Gated by the\n// first-party `editor:write` capability, so only a first-party chrome app (the\n// file explorer) can call these; anyone else is refused at the gate.\n// ---------------------------------------------------------------------------\n\n/** An error from a working-tree mutation, carrying a machine-readable `.code`. */\nexport interface EditorWriteError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:write` (first-party-only)\n | 'not-found' // the target file/folder does not exist (delete/rename)\n | 'exists' // the target already exists (create/rename would clobber)\n | 'protected' // the host refuses to delete this file (e.g. package.json)\n | 'too-large' // an upload exceeds the host's size limit\n | 'invalid-params' // a path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a\n * file is already there. */\nexport const createFile = (path: string): Promise<void> => editorRequest('createFile', { path });\n\n/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */\nexport const createFolder = (path: string): Promise<void> =>\n editorRequest('createFolder', { path });\n\n/** Delete a working-tree file, or a folder and everything under it. Rejects\n * `protected` for files the host won't remove, `not-found` if absent. */\nexport const deleteEntry = (path: string): Promise<void> => editorRequest('deleteEntry', { path });\n\n/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`\n * is taken, `not-found` if `from` is absent. */\nexport const renameEntry = (from: string, to: string): Promise<void> =>\n editorRequest('rename', { from, to });\n\n/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects\n * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */\nexport const uploadFile = (path: string, bytes: Uint8Array): Promise<void> =>\n editorRequest('upload', { path, bytes });\n"],"mappings":"AAAA,SAAS,uBAAuB;AA4BhC,MAAM,gBAAgB,OACpB,QACA,QACkB;AAClB,QAAM,MAAO,MAAM,gBAAgB,UAAU,QAAQ,CAAC,GAAG,CAAC;AAC1D,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU,MAAM,SAAS;AAC/D,QAAI,OAAQ,KAAK,QAAqC;AACtD,UAAM;AAAA,EACR;AACF;AAQO,MAAM,eAAe,CAAC,SAAgC,cAAc,QAAQ,EAAE,KAAK,CAAC;AAyBpF,MAAM,aAAa,CAAC,SAAgC,cAAc,cAAc,EAAE,KAAK,CAAC;AAGxF,MAAM,eAAe,CAAC,SAC3B,cAAc,gBAAgB,EAAE,KAAK,CAAC;AAIjC,MAAM,cAAc,CAAC,SAAgC,cAAc,eAAe,EAAE,KAAK,CAAC;AAI1F,MAAM,cAAc,CAAC,MAAc,OACxC,cAAc,UAAU,EAAE,MAAM,GAAG,CAAC;AAI/B,MAAM,aAAa,CAAC,MAAc,UACvC,cAAc,UAAU,EAAE,MAAM,MAAM,CAAC;","names":[]}
|
package/dist/editorContext.cjs
CHANGED
|
@@ -24,11 +24,20 @@ __export(editorContext_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(editorContext_exports);
|
|
26
26
|
var import_pushChannel = require("./pushChannel");
|
|
27
|
+
const isStringArray = (v) => Array.isArray(v) && v.every((p) => typeof p === "string");
|
|
27
28
|
const channel = (0, import_pushChannel.createPushChannel)({
|
|
28
29
|
pushType: "editor-context",
|
|
29
30
|
requestType: "request-editor-context",
|
|
30
|
-
initial: { dirtyPaths: [] },
|
|
31
|
-
parse: (msg) =>
|
|
31
|
+
initial: { dirtyPaths: [], openFiles: [], activeFile: null },
|
|
32
|
+
parse: (msg) => isStringArray(msg.dirtyPaths) ? {
|
|
33
|
+
dirtyPaths: msg.dirtyPaths,
|
|
34
|
+
// `openFiles` is newer than `dirtyPaths`; tolerate an older host that
|
|
35
|
+
// omits it (defensive SDK — defaults to empty rather than rejecting).
|
|
36
|
+
openFiles: isStringArray(msg.openFiles) ? msg.openFiles : [],
|
|
37
|
+
// `activeFile` is newer still; an older host that omits it (or sends a
|
|
38
|
+
// non-string) reads as `null` — no file highlighted, never a throw.
|
|
39
|
+
activeFile: typeof msg.activeFile === "string" ? msg.activeFile : null
|
|
40
|
+
} : void 0
|
|
32
41
|
});
|
|
33
42
|
const getEditorContext = () => channel.get();
|
|
34
43
|
const onEditorContextChange = (listener) => channel.onChange(listener);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editorContext.ts"],"sourcesContent":["import { createPushChannel } from './pushChannel';\n\n/**\n * The editor \"dirty set\" mirrored from the immediately.run host into the sandbox\n * (UI_AS_APPS_SPEC §5.3): which files the user has changed but not yet saved.\n *\n * This is the ELEVATED `editor:read` capability — only a system app whose binding\n * grants it (e.g. the contribute dialog) receives it. The active file and ref are\n * already available to every app via routing (`useNavigationState`), so this\n * channel carries only the genuine delta: the unsaved paths. An app without\n * `editor:read` simply sees an empty dirty set.\n */\nexport interface EditorContext {\n /** Repo-relative paths the user has modified but not yet saved. */\n dirtyPaths: string[];\n}\n\n// Read over the transport (SDK_PACKAGING_SPEC §4): the host pushes `editor-context`\n// and answers `request-editor-context` — but only for a frame holding `editor:read`\n// (gated by the channel router). An app without it gets no reply, so the empty\n// default below stands. Wire format: site-main channelBridge.ts.\nconst channel = createPushChannel<EditorContext>({\n pushType: 'editor-context',\n requestType: 'request-editor-context',\n initial: { dirtyPaths: [] },\n parse: (msg) =>\n
|
|
1
|
+
{"version":3,"sources":["../src/editorContext.ts"],"sourcesContent":["import { createPushChannel } from './pushChannel';\n\n/**\n * The editor \"dirty set\" mirrored from the immediately.run host into the sandbox\n * (UI_AS_APPS_SPEC §5.3): which files the user has changed but not yet saved.\n *\n * This is the ELEVATED `editor:read` capability — only a system app whose binding\n * grants it (e.g. the contribute dialog) receives it. The active file and ref are\n * already available to every app via routing (`useNavigationState`), so this\n * channel carries only the genuine delta: the unsaved paths. An app without\n * `editor:read` simply sees an empty dirty set.\n */\nexport interface EditorContext {\n /** Repo-relative paths the user has modified but not yet saved. */\n dirtyPaths: string[];\n /** Repo-relative paths currently open as tabs in the host editor (§4.2). */\n openFiles: string[];\n /**\n * The one file currently focused in the host editor (repo-relative, leading\n * slash — e.g. `/src/index.ts`), or `null` when no file is open. Distinct from\n * {@link dirtyPaths} (the unsaved SET) and {@link openFiles} (the open-tab set):\n * this is the single ACTIVE file. A baseline app reads its own active file from\n * the route, but a self-routed system panel (`drivesHostRoute=false`, e.g. the\n * file explorer) does not see the host editor's route, so it receives the active\n * file here instead (UI_AS_APPS_SPEC §5.3 self-routed-panel refinement).\n */\n activeFile: string | null;\n}\n\n// Read over the transport (SDK_PACKAGING_SPEC §4): the host pushes `editor-context`\n// and answers `request-editor-context` — but only for a frame holding `editor:read`\n// (gated by the channel router). An app without it gets no reply, so the empty\n// default below stands. Wire format: site-main channelBridge.ts.\nconst isStringArray = (v: unknown): v is string[] =>\n Array.isArray(v) && v.every((p) => typeof p === 'string');\n\nconst channel = createPushChannel<EditorContext>({\n pushType: 'editor-context',\n requestType: 'request-editor-context',\n initial: { dirtyPaths: [], openFiles: [], activeFile: null },\n parse: (msg) =>\n isStringArray(msg.dirtyPaths)\n ? {\n dirtyPaths: msg.dirtyPaths,\n // `openFiles` is newer than `dirtyPaths`; tolerate an older host that\n // omits it (defensive SDK — defaults to empty rather than rejecting).\n openFiles: isStringArray(msg.openFiles) ? msg.openFiles : [],\n // `activeFile` is newer still; an older host that omits it (or sends a\n // non-string) reads as `null` — no file highlighted, never a throw.\n activeFile: typeof msg.activeFile === 'string' ? msg.activeFile : null,\n }\n : undefined,\n});\n\n/**\n * Returns the current editor context (dirty set). Poll this for a one-off read;\n * use {@link onEditorContextChange} or {@link useEditorContext} to react.\n */\nexport const getEditorContext = (): EditorContext => channel.get();\n\n/**\n * Subscribe to editor-context changes. The listener is invoked immediately with\n * the current context, then again on every change. Returns an unsubscribe fn.\n */\nexport const onEditorContextChange = (listener: (context: EditorContext) => void): (() => void) =>\n channel.onChange(listener);\n\n/**\n * React hook returning the current editor context (dirty set), re-rendering when\n * it changes. Handy for a contribute dialog: `const { dirtyPaths } =\n * useEditorContext()` to show \"you'll save N files\" before calling `contribute()`.\n */\nexport const useEditorContext = (): EditorContext => channel.use();\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAkC;AAiClC,MAAM,gBAAgB,CAAC,MACrB,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ;AAE1D,MAAM,cAAU,sCAAiC;AAAA,EAC/C,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC,GAAG,YAAY,KAAK;AAAA,EAC3D,OAAO,CAAC,QACN,cAAc,IAAI,UAAU,IACxB;AAAA,IACE,YAAY,IAAI;AAAA;AAAA;AAAA,IAGhB,WAAW,cAAc,IAAI,SAAS,IAAI,IAAI,YAAY,CAAC;AAAA;AAAA;AAAA,IAG3D,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,EACpE,IACA;AACR,CAAC;AAMM,MAAM,mBAAmB,MAAqB,QAAQ,IAAI;AAM1D,MAAM,wBAAwB,CAAC,aACpC,QAAQ,SAAS,QAAQ;AAOpB,MAAM,mBAAmB,MAAqB,QAAQ,IAAI;","names":[]}
|
package/dist/editorContext.d.cts
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
interface EditorContext {
|
|
12
12
|
/** Repo-relative paths the user has modified but not yet saved. */
|
|
13
13
|
dirtyPaths: string[];
|
|
14
|
+
/** Repo-relative paths currently open as tabs in the host editor (§4.2). */
|
|
15
|
+
openFiles: string[];
|
|
16
|
+
/**
|
|
17
|
+
* The one file currently focused in the host editor (repo-relative, leading
|
|
18
|
+
* slash — e.g. `/src/index.ts`), or `null` when no file is open. Distinct from
|
|
19
|
+
* {@link dirtyPaths} (the unsaved SET) and {@link openFiles} (the open-tab set):
|
|
20
|
+
* this is the single ACTIVE file. A baseline app reads its own active file from
|
|
21
|
+
* the route, but a self-routed system panel (`drivesHostRoute=false`, e.g. the
|
|
22
|
+
* file explorer) does not see the host editor's route, so it receives the active
|
|
23
|
+
* file here instead (UI_AS_APPS_SPEC §5.3 self-routed-panel refinement).
|
|
24
|
+
*/
|
|
25
|
+
activeFile: string | null;
|
|
14
26
|
}
|
|
15
27
|
/**
|
|
16
28
|
* Returns the current editor context (dirty set). Poll this for a one-off read;
|
package/dist/editorContext.d.ts
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
interface EditorContext {
|
|
12
12
|
/** Repo-relative paths the user has modified but not yet saved. */
|
|
13
13
|
dirtyPaths: string[];
|
|
14
|
+
/** Repo-relative paths currently open as tabs in the host editor (§4.2). */
|
|
15
|
+
openFiles: string[];
|
|
16
|
+
/**
|
|
17
|
+
* The one file currently focused in the host editor (repo-relative, leading
|
|
18
|
+
* slash — e.g. `/src/index.ts`), or `null` when no file is open. Distinct from
|
|
19
|
+
* {@link dirtyPaths} (the unsaved SET) and {@link openFiles} (the open-tab set):
|
|
20
|
+
* this is the single ACTIVE file. A baseline app reads its own active file from
|
|
21
|
+
* the route, but a self-routed system panel (`drivesHostRoute=false`, e.g. the
|
|
22
|
+
* file explorer) does not see the host editor's route, so it receives the active
|
|
23
|
+
* file here instead (UI_AS_APPS_SPEC §5.3 self-routed-panel refinement).
|
|
24
|
+
*/
|
|
25
|
+
activeFile: string | null;
|
|
14
26
|
}
|
|
15
27
|
/**
|
|
16
28
|
* Returns the current editor context (dirty set). Poll this for a one-off read;
|
package/dist/editorContext.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { createPushChannel } from "./pushChannel";
|
|
2
|
+
const isStringArray = (v) => Array.isArray(v) && v.every((p) => typeof p === "string");
|
|
2
3
|
const channel = createPushChannel({
|
|
3
4
|
pushType: "editor-context",
|
|
4
5
|
requestType: "request-editor-context",
|
|
5
|
-
initial: { dirtyPaths: [] },
|
|
6
|
-
parse: (msg) =>
|
|
6
|
+
initial: { dirtyPaths: [], openFiles: [], activeFile: null },
|
|
7
|
+
parse: (msg) => isStringArray(msg.dirtyPaths) ? {
|
|
8
|
+
dirtyPaths: msg.dirtyPaths,
|
|
9
|
+
// `openFiles` is newer than `dirtyPaths`; tolerate an older host that
|
|
10
|
+
// omits it (defensive SDK — defaults to empty rather than rejecting).
|
|
11
|
+
openFiles: isStringArray(msg.openFiles) ? msg.openFiles : [],
|
|
12
|
+
// `activeFile` is newer still; an older host that omits it (or sends a
|
|
13
|
+
// non-string) reads as `null` — no file highlighted, never a throw.
|
|
14
|
+
activeFile: typeof msg.activeFile === "string" ? msg.activeFile : null
|
|
15
|
+
} : void 0
|
|
7
16
|
});
|
|
8
17
|
const getEditorContext = () => channel.get();
|
|
9
18
|
const onEditorContextChange = (listener) => channel.onChange(listener);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editorContext.ts"],"sourcesContent":["import { createPushChannel } from './pushChannel';\n\n/**\n * The editor \"dirty set\" mirrored from the immediately.run host into the sandbox\n * (UI_AS_APPS_SPEC §5.3): which files the user has changed but not yet saved.\n *\n * This is the ELEVATED `editor:read` capability — only a system app whose binding\n * grants it (e.g. the contribute dialog) receives it. The active file and ref are\n * already available to every app via routing (`useNavigationState`), so this\n * channel carries only the genuine delta: the unsaved paths. An app without\n * `editor:read` simply sees an empty dirty set.\n */\nexport interface EditorContext {\n /** Repo-relative paths the user has modified but not yet saved. */\n dirtyPaths: string[];\n}\n\n// Read over the transport (SDK_PACKAGING_SPEC §4): the host pushes `editor-context`\n// and answers `request-editor-context` — but only for a frame holding `editor:read`\n// (gated by the channel router). An app without it gets no reply, so the empty\n// default below stands. Wire format: site-main channelBridge.ts.\nconst channel = createPushChannel<EditorContext>({\n pushType: 'editor-context',\n requestType: 'request-editor-context',\n initial: { dirtyPaths: [] },\n parse: (msg) =>\n
|
|
1
|
+
{"version":3,"sources":["../src/editorContext.ts"],"sourcesContent":["import { createPushChannel } from './pushChannel';\n\n/**\n * The editor \"dirty set\" mirrored from the immediately.run host into the sandbox\n * (UI_AS_APPS_SPEC §5.3): which files the user has changed but not yet saved.\n *\n * This is the ELEVATED `editor:read` capability — only a system app whose binding\n * grants it (e.g. the contribute dialog) receives it. The active file and ref are\n * already available to every app via routing (`useNavigationState`), so this\n * channel carries only the genuine delta: the unsaved paths. An app without\n * `editor:read` simply sees an empty dirty set.\n */\nexport interface EditorContext {\n /** Repo-relative paths the user has modified but not yet saved. */\n dirtyPaths: string[];\n /** Repo-relative paths currently open as tabs in the host editor (§4.2). */\n openFiles: string[];\n /**\n * The one file currently focused in the host editor (repo-relative, leading\n * slash — e.g. `/src/index.ts`), or `null` when no file is open. Distinct from\n * {@link dirtyPaths} (the unsaved SET) and {@link openFiles} (the open-tab set):\n * this is the single ACTIVE file. A baseline app reads its own active file from\n * the route, but a self-routed system panel (`drivesHostRoute=false`, e.g. the\n * file explorer) does not see the host editor's route, so it receives the active\n * file here instead (UI_AS_APPS_SPEC §5.3 self-routed-panel refinement).\n */\n activeFile: string | null;\n}\n\n// Read over the transport (SDK_PACKAGING_SPEC §4): the host pushes `editor-context`\n// and answers `request-editor-context` — but only for a frame holding `editor:read`\n// (gated by the channel router). An app without it gets no reply, so the empty\n// default below stands. Wire format: site-main channelBridge.ts.\nconst isStringArray = (v: unknown): v is string[] =>\n Array.isArray(v) && v.every((p) => typeof p === 'string');\n\nconst channel = createPushChannel<EditorContext>({\n pushType: 'editor-context',\n requestType: 'request-editor-context',\n initial: { dirtyPaths: [], openFiles: [], activeFile: null },\n parse: (msg) =>\n isStringArray(msg.dirtyPaths)\n ? {\n dirtyPaths: msg.dirtyPaths,\n // `openFiles` is newer than `dirtyPaths`; tolerate an older host that\n // omits it (defensive SDK — defaults to empty rather than rejecting).\n openFiles: isStringArray(msg.openFiles) ? msg.openFiles : [],\n // `activeFile` is newer still; an older host that omits it (or sends a\n // non-string) reads as `null` — no file highlighted, never a throw.\n activeFile: typeof msg.activeFile === 'string' ? msg.activeFile : null,\n }\n : undefined,\n});\n\n/**\n * Returns the current editor context (dirty set). Poll this for a one-off read;\n * use {@link onEditorContextChange} or {@link useEditorContext} to react.\n */\nexport const getEditorContext = (): EditorContext => channel.get();\n\n/**\n * Subscribe to editor-context changes. The listener is invoked immediately with\n * the current context, then again on every change. Returns an unsubscribe fn.\n */\nexport const onEditorContextChange = (listener: (context: EditorContext) => void): (() => void) =>\n channel.onChange(listener);\n\n/**\n * React hook returning the current editor context (dirty set), re-rendering when\n * it changes. Handy for a contribute dialog: `const { dirtyPaths } =\n * useEditorContext()` to show \"you'll save N files\" before calling `contribute()`.\n */\nexport const useEditorContext = (): EditorContext => channel.use();\n"],"mappings":"AAAA,SAAS,yBAAyB;AAiClC,MAAM,gBAAgB,CAAC,MACrB,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ;AAE1D,MAAM,UAAU,kBAAiC;AAAA,EAC/C,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC,GAAG,YAAY,KAAK;AAAA,EAC3D,OAAO,CAAC,QACN,cAAc,IAAI,UAAU,IACxB;AAAA,IACE,YAAY,IAAI;AAAA;AAAA;AAAA,IAGhB,WAAW,cAAc,IAAI,SAAS,IAAI,IAAI,YAAY,CAAC;AAAA;AAAA;AAAA,IAG3D,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,EACpE,IACA;AACR,CAAC;AAMM,MAAM,mBAAmB,MAAqB,QAAQ,IAAI;AAM1D,MAAM,wBAAwB,CAAC,aACpC,QAAQ,SAAS,QAAQ;AAOpB,MAAM,mBAAmB,MAAqB,QAAQ,IAAI;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -7,7 +7,7 @@ export { useFileMetadata, useMetadataQuery } from './hooks.cjs';
|
|
|
7
7
|
export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth } from './auth.cjs';
|
|
8
8
|
export { HostTheme, getHostTheme, onHostThemeChange, setHostTheme, useHostTheme } from './theme.cjs';
|
|
9
9
|
export { EditorContext, getEditorContext, onEditorContextChange, useEditorContext } from './editorContext.cjs';
|
|
10
|
-
export { EditorOpenError, openInEditor } from './editor.cjs';
|
|
10
|
+
export { EditorOpenError, EditorWriteError, createFile, createFolder, deleteEntry, openInEditor, renameEntry, uploadFile } from './editor.cjs';
|
|
11
11
|
export { FormFactor, FormFactorClass, Orientation, getFormFactor, onFormFactorChange, useFormFactor } from './formFactor.cjs';
|
|
12
12
|
export { GrantRecord, Member, MountQuery, ResolvedUser, Role, SandboxMount, SpaceError, SpaceInfo, createSpace, findMount, getAppMountPath, getMounts, getSpaceMembers, listAllSpaces, listGrants, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, revokeGrant, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount } from './mounts.cjs';
|
|
13
13
|
export { ContributeMode, ContributeOptions, ContributionEvent, ContributionResult, contribute } from './contribute.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { useFileMetadata, useMetadataQuery } from './hooks.js';
|
|
|
7
7
|
export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth } from './auth.js';
|
|
8
8
|
export { HostTheme, getHostTheme, onHostThemeChange, setHostTheme, useHostTheme } from './theme.js';
|
|
9
9
|
export { EditorContext, getEditorContext, onEditorContextChange, useEditorContext } from './editorContext.js';
|
|
10
|
-
export { EditorOpenError, openInEditor } from './editor.js';
|
|
10
|
+
export { EditorOpenError, EditorWriteError, createFile, createFolder, deleteEntry, openInEditor, renameEntry, uploadFile } from './editor.js';
|
|
11
11
|
export { FormFactor, FormFactorClass, Orientation, getFormFactor, onFormFactorChange, useFormFactor } from './formFactor.js';
|
|
12
12
|
export { GrantRecord, Member, MountQuery, ResolvedUser, Role, SandboxMount, SpaceError, SpaceInfo, createSpace, findMount, getAppMountPath, getMounts, getSpaceMembers, listAllSpaces, listGrants, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, revokeGrant, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount } from './mounts.js';
|
|
13
13
|
export { ContributeMode, ContributeOptions, ContributionEvent, ContributionResult, contribute } from './contribute.js';
|
package/package.json
CHANGED