@immediately-run/sdk 0.1.3 → 0.1.4
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 +6 -0
- package/dist/components/FileRouter.cjs +2 -1
- package/dist/components/FileRouter.cjs.map +1 -1
- package/dist/components/FileRouter.js +2 -1
- package/dist/components/FileRouter.js.map +1 -1
- package/dist/components/MainContent.cjs +1 -1
- package/dist/components/MainContent.cjs.map +1 -1
- package/dist/components/MainContent.js +2 -2
- package/dist/components/MainContent.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mounts.cjs +61 -0
- package/dist/mounts.cjs.map +1 -0
- package/dist/mounts.d.cts +44 -0
- package/dist/mounts.d.ts +44 -0
- package/dist/mounts.js +33 -0
- package/dist/mounts.js.map +1 -0
- package/dist/urlUtils.cjs +8 -2
- package/dist/urlUtils.cjs.map +1 -1
- package/dist/urlUtils.d.cts +10 -1
- package/dist/urlUtils.d.ts +10 -1
- package/dist/urlUtils.js +5 -1
- package/dist/urlUtils.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,12 @@ also reachable via subpaths (`@immediately-run/sdk/boot`, `@immediately-run/sdk/
|
|
|
26
26
|
login / account state (`{ status, user: { login } }`). Poll with `getAuthState()`,
|
|
27
27
|
subscribe with `onAuthChange(listener)` (the listener is called immediately with the
|
|
28
28
|
current state), or use the `useAuth()` React hook.
|
|
29
|
+
- `getMounts`, `findMount`, `onMountsChange`, `useMounts`, `waitForMount` (`mounts`) —
|
|
30
|
+
read or subscribe to the filesystem mounts available to the sandbox (e.g. a
|
|
31
|
+
Firestore-backed store mounted at `/firestore` after sign-in). Poll with
|
|
32
|
+
`getMounts()` / `findMount({ type })`, subscribe with `onMountsChange(listener)` or
|
|
33
|
+
the `useMounts()` hook, or `await waitForMount({ type: 'firestore' })` before using a
|
|
34
|
+
mount. Access the files via the `fs` module at the mount's `path`.
|
|
29
35
|
- routing helpers (`Router`, `SandboxRouter`, …).
|
|
30
36
|
- `MDXProvider` — the MDX context provider used by transformed `.mdx` files.
|
|
31
37
|
- `sandboxTypes` — shared TypeScript types for the sandbox runtime.
|
|
@@ -24,6 +24,7 @@ module.exports = __toCommonJS(FileRouter_exports);
|
|
|
24
24
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
25
25
|
var import_react = require("react");
|
|
26
26
|
var import_TinkerableContext = require("../TinkerableContext");
|
|
27
|
+
var import_urlUtils = require("../urlUtils");
|
|
27
28
|
var import_defaults = require("./defaults");
|
|
28
29
|
var import_Include = require("./Include");
|
|
29
30
|
const FileRouter = ({
|
|
@@ -39,7 +40,7 @@ const FileRouter = ({
|
|
|
39
40
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
40
41
|
import_Include.Include,
|
|
41
42
|
{
|
|
42
|
-
filename,
|
|
43
|
+
filename: (0, import_urlUtils.underAppRoot)(filename),
|
|
43
44
|
LoadingComponent,
|
|
44
45
|
ErrorComponent,
|
|
45
46
|
baseModule: module
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/FileRouter.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useContext } from 'react';\n\nimport { TinkerableContext } from '../TinkerableContext';\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\nimport { Include } from './Include';\n\nexport const FileRouter: FC = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n const { navigationState: { pathParameters, sandboxPath } } = useContext(TinkerableContext);\n const filename = pathParameters?.filename;\n if (!filename) {\n return <ErrorComponent error={new Error(`No filename could be extracted from ${sandboxPath}`)} resetErrorBoundary={() => {}}/>;\n }\n return <Include\n filename={filename}\n LoadingComponent={LoadingComponent}\n ErrorComponent={ErrorComponent}\n // @ts-ignore\n baseModule={module}\n />\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../../src/components/FileRouter.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useContext } from 'react';\n\nimport { TinkerableContext } from '../TinkerableContext';\nimport { underAppRoot } from '../urlUtils';\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\nimport { Include } from './Include';\n\nexport const FileRouter: FC = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n const { navigationState: { pathParameters, sandboxPath } } = useContext(TinkerableContext);\n const filename = pathParameters?.filename;\n if (!filename) {\n return <ErrorComponent error={new Error(`No filename could be extracted from ${sandboxPath}`)} resetErrorBoundary={() => {}}/>;\n }\n // URL subpaths are repo-relative; the sandbox fs is rooted at `/` with the\n // repo mounted at `APP_ROOT`, so anchor the file path there before resolving.\n return <Include\n filename={underAppRoot(filename)}\n LoadingComponent={LoadingComponent}\n ErrorComponent={ErrorComponent}\n // @ts-ignore\n baseModule={module}\n />\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBW;AAjBX,mBAA2B;AAE3B,+BAAkC;AAClC,sBAA6B;AAC7B,sBAA+D;AAC/D,qBAAwB;AAEjB,MAAM,aAAiB,CAAC;AAAA,EAC7B,mBAAmB;AAAA,EACnB,iBAAiB;AACnB,IAGI,CAAC,MAAM;AACT,QAAM,EAAE,iBAAiB,EAAE,gBAAgB,YAAY,EAAE,QAAI,yBAAW,0CAAiB;AACzF,QAAM,WAAW,gBAAgB;AACjC,MAAI,CAAC,UAAU;AACb,WAAO,4CAAC,kBAAe,OAAO,IAAI,MAAM,uCAAuC,WAAW,EAAE,GAAG,oBAAoB,MAAM;AAAA,IAAC,GAAE;AAAA,EAC9H;AAGA,SAAO;AAAA,IAAC;AAAA;AAAA,MACN,cAAU,8BAAa,QAAQ;AAAA,MAC/B;AAAA,MACA;AAAA,MAEA,YAAY;AAAA;AAAA,EACd;AACF;","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useContext } from "react";
|
|
3
3
|
import { TinkerableContext } from "../TinkerableContext";
|
|
4
|
+
import { underAppRoot } from "../urlUtils";
|
|
4
5
|
import { defaultErrorComponent, defaultLoadingComponent } from "./defaults";
|
|
5
6
|
import { Include } from "./Include";
|
|
6
7
|
const FileRouter = ({
|
|
@@ -16,7 +17,7 @@ const FileRouter = ({
|
|
|
16
17
|
return /* @__PURE__ */ jsx(
|
|
17
18
|
Include,
|
|
18
19
|
{
|
|
19
|
-
filename,
|
|
20
|
+
filename: underAppRoot(filename),
|
|
20
21
|
LoadingComponent,
|
|
21
22
|
ErrorComponent,
|
|
22
23
|
baseModule: module
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/FileRouter.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useContext } from 'react';\n\nimport { TinkerableContext } from '../TinkerableContext';\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\nimport { Include } from './Include';\n\nexport const FileRouter: FC = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n const { navigationState: { pathParameters, sandboxPath } } = useContext(TinkerableContext);\n const filename = pathParameters?.filename;\n if (!filename) {\n return <ErrorComponent error={new Error(`No filename could be extracted from ${sandboxPath}`)} resetErrorBoundary={() => {}}/>;\n }\n return <Include\n filename={filename}\n LoadingComponent={LoadingComponent}\n ErrorComponent={ErrorComponent}\n // @ts-ignore\n baseModule={module}\n />\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/components/FileRouter.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useContext } from 'react';\n\nimport { TinkerableContext } from '../TinkerableContext';\nimport { underAppRoot } from '../urlUtils';\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\nimport { Include } from './Include';\n\nexport const FileRouter: FC = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n const { navigationState: { pathParameters, sandboxPath } } = useContext(TinkerableContext);\n const filename = pathParameters?.filename;\n if (!filename) {\n return <ErrorComponent error={new Error(`No filename could be extracted from ${sandboxPath}`)} resetErrorBoundary={() => {}}/>;\n }\n // URL subpaths are repo-relative; the sandbox fs is rooted at `/` with the\n // repo mounted at `APP_ROOT`, so anchor the file path there before resolving.\n return <Include\n filename={underAppRoot(filename)}\n LoadingComponent={LoadingComponent}\n ErrorComponent={ErrorComponent}\n // @ts-ignore\n baseModule={module}\n />\n};\n"],"mappings":"AAkBW;AAjBX,SAAS,kBAAkB;AAE3B,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB,+BAA+B;AAC/D,SAAS,eAAe;AAEjB,MAAM,aAAiB,CAAC;AAAA,EAC7B,mBAAmB;AAAA,EACnB,iBAAiB;AACnB,IAGI,CAAC,MAAM;AACT,QAAM,EAAE,iBAAiB,EAAE,gBAAgB,YAAY,EAAE,IAAI,WAAW,iBAAiB;AACzF,QAAM,WAAW,gBAAgB;AACjC,MAAI,CAAC,UAAU;AACb,WAAO,oBAAC,kBAAe,OAAO,IAAI,MAAM,uCAAuC,WAAW,EAAE,GAAG,oBAAoB,MAAM;AAAA,IAAC,GAAE;AAAA,EAC9H;AAGA,SAAO;AAAA,IAAC;AAAA;AAAA,MACN,UAAU,aAAa,QAAQ;AAAA,MAC/B;AAAA,MACA;AAAA,MAEA,YAAY;AAAA;AAAA,EACd;AACF;","names":[]}
|
|
@@ -32,7 +32,7 @@ var import_defaults = require("./defaults");
|
|
|
32
32
|
const candidates = ["/src/App.tsx", "/src/App.ts", "/src/App.js", "/App.tsx", "/App.ts", "/App.js", "/README.md", "/README.mdx", "/README.html"];
|
|
33
33
|
const fileExists = async (path) => {
|
|
34
34
|
const bundler = module.evaluation.module.bundler;
|
|
35
|
-
const exists = await bundler.fs.isFile.async(path);
|
|
35
|
+
const exists = await bundler.fs.isFile.async((0, import_urlUtils.underAppRoot)(path));
|
|
36
36
|
return [path, exists];
|
|
37
37
|
};
|
|
38
38
|
const MainContentRedirect = ({ filename }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/MainContent.tsx"],"sourcesContent":["import { Suspense, use, useMemo } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { navigate, useTinkerableLink } from '../routing';\nimport { FILES_PREFIX } from '../urlUtils';\n\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\nconst candidates = ['/src/App.tsx', '/src/App.ts', '/src/App.js', '/App.tsx', '/App.ts', '/App.js', '/README.md', '/README.mdx', '/README.html'];\n\nconst fileExists = async (path: string): Promise<[string, boolean]> => {\n // @ts-ignore\n const bundler = module.evaluation.module.bundler;\n const exists = await bundler.fs.isFile.async(path);\n return [path, exists];\n};\n\nexport const MainContentRedirect = ({filename}:{filename:string}) => {\n const url = useTinkerableLink(filename);\n navigate(url);\n return <>Redirecting to {filename}</>;\n}\n\nexport const MainContentInner = ({\n candidatesExistPromise,\n}: {\n candidatesExistPromise: Promise<[string, boolean][]>;\n}) => {\n const candidatesExist = use(candidatesExistPromise);\n const filename = candidatesExist.find(([_, exists]) => exists)?.[0];\n if (!filename) {\n // todo: show file list\n throw new Error(`No main content file present`);\n }\n return <MainContentRedirect filename={FILES_PREFIX + filename}/>;\n};\n\nexport const MainContent = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n // TODO: when to invalidate?\n const candidatesExistPromise = useMemo(() => Promise.all(candidates.map(fileExists)), []);\n return (\n <ErrorBoundary fallbackRender={ErrorComponent}>\n <Suspense fallback={<LoadingComponent />}>\n <MainContentInner candidatesExistPromise={candidatesExistPromise} />\n </Suspense>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../../src/components/MainContent.tsx"],"sourcesContent":["import { Suspense, use, useMemo } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { navigate, useTinkerableLink } from '../routing';\nimport { FILES_PREFIX, underAppRoot } from '../urlUtils';\n\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\n// Repo-relative candidate paths. These are kept repo-relative because the\n// returned path is reused below to build the redirect URL (which is anchored to\n// `/app` by the file router); only the filesystem existence check is resolved\n// under `APP_ROOT`, since `bundler.fs` is rooted at `/`.\nconst candidates = ['/src/App.tsx', '/src/App.ts', '/src/App.js', '/App.tsx', '/App.ts', '/App.js', '/README.md', '/README.mdx', '/README.html'];\n\nconst fileExists = async (path: string): Promise<[string, boolean]> => {\n // @ts-ignore\n const bundler = module.evaluation.module.bundler;\n const exists = await bundler.fs.isFile.async(underAppRoot(path));\n return [path, exists];\n};\n\nexport const MainContentRedirect = ({filename}:{filename:string}) => {\n const url = useTinkerableLink(filename);\n navigate(url);\n return <>Redirecting to {filename}</>;\n}\n\nexport const MainContentInner = ({\n candidatesExistPromise,\n}: {\n candidatesExistPromise: Promise<[string, boolean][]>;\n}) => {\n const candidatesExist = use(candidatesExistPromise);\n const filename = candidatesExist.find(([_, exists]) => exists)?.[0];\n if (!filename) {\n // todo: show file list\n throw new Error(`No main content file present`);\n }\n return <MainContentRedirect filename={FILES_PREFIX + filename}/>;\n};\n\nexport const MainContent = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n // TODO: when to invalidate?\n const candidatesExistPromise = useMemo(() => Promise.all(candidates.map(fileExists)), []);\n return (\n <ErrorBoundary fallbackRender={ErrorComponent}>\n <Suspense fallback={<LoadingComponent />}>\n <MainContentInner candidatesExistPromise={candidatesExistPromise} />\n </Suspense>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBS;AAvBT,mBAAuC;AACvC,kCAA8B;AAC9B,qBAA4C;AAC5C,sBAA2C;AAE3C,sBAA+D;AAM/D,MAAM,aAAa,CAAC,gBAAgB,eAAe,eAAe,YAAY,WAAW,WAAW,cAAc,eAAe,cAAc;AAE/I,MAAM,aAAa,OAAO,SAA6C;AAErE,QAAM,UAAU,OAAO,WAAW,OAAO;AACzC,QAAM,SAAS,MAAM,QAAQ,GAAG,OAAO,UAAM,8BAAa,IAAI,CAAC;AAC/D,SAAO,CAAC,MAAM,MAAM;AACtB;AAEO,MAAM,sBAAsB,CAAC,EAAC,SAAQ,MAAwB;AACnE,QAAM,UAAM,kCAAkB,QAAQ;AACtC,+BAAS,GAAG;AACZ,SAAO,4EAAE;AAAA;AAAA,IAAgB;AAAA,KAAS;AACpC;AAEO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AACF,MAEM;AACJ,QAAM,sBAAkB,kBAAI,sBAAsB;AAClD,QAAM,WAAW,gBAAgB,KAAK,CAAC,CAAC,GAAG,MAAM,MAAM,MAAM,IAAI,CAAC;AAClE,MAAI,CAAC,UAAU;AAEb,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AACA,SAAO,4CAAC,uBAAoB,UAAU,+BAAe,UAAS;AAChE;AAEO,MAAM,cAAc,CAAC;AAAA,EAC1B,mBAAmB;AAAA,EACnB,iBAAiB;AACnB,IAGI,CAAC,MAAM;AAET,QAAM,6BAAyB,sBAAQ,MAAM,QAAQ,IAAI,WAAW,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AACxF,SACE,4CAAC,6CAAc,gBAAgB,gBAC7B,sDAAC,yBAAS,UAAU,4CAAC,oBAAiB,GACpC,sDAAC,oBAAiB,wBAAgD,GACpE,GACF;AAEJ;","names":[]}
|
|
@@ -2,12 +2,12 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Suspense, use, useMemo } from "react";
|
|
3
3
|
import { ErrorBoundary } from "react-error-boundary";
|
|
4
4
|
import { navigate, useTinkerableLink } from "../routing";
|
|
5
|
-
import { FILES_PREFIX } from "../urlUtils";
|
|
5
|
+
import { FILES_PREFIX, underAppRoot } from "../urlUtils";
|
|
6
6
|
import { defaultErrorComponent, defaultLoadingComponent } from "./defaults";
|
|
7
7
|
const candidates = ["/src/App.tsx", "/src/App.ts", "/src/App.js", "/App.tsx", "/App.ts", "/App.js", "/README.md", "/README.mdx", "/README.html"];
|
|
8
8
|
const fileExists = async (path) => {
|
|
9
9
|
const bundler = module.evaluation.module.bundler;
|
|
10
|
-
const exists = await bundler.fs.isFile.async(path);
|
|
10
|
+
const exists = await bundler.fs.isFile.async(underAppRoot(path));
|
|
11
11
|
return [path, exists];
|
|
12
12
|
};
|
|
13
13
|
const MainContentRedirect = ({ filename }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/MainContent.tsx"],"sourcesContent":["import { Suspense, use, useMemo } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { navigate, useTinkerableLink } from '../routing';\nimport { FILES_PREFIX } from '../urlUtils';\n\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\nconst candidates = ['/src/App.tsx', '/src/App.ts', '/src/App.js', '/App.tsx', '/App.ts', '/App.js', '/README.md', '/README.mdx', '/README.html'];\n\nconst fileExists = async (path: string): Promise<[string, boolean]> => {\n // @ts-ignore\n const bundler = module.evaluation.module.bundler;\n const exists = await bundler.fs.isFile.async(path);\n return [path, exists];\n};\n\nexport const MainContentRedirect = ({filename}:{filename:string}) => {\n const url = useTinkerableLink(filename);\n navigate(url);\n return <>Redirecting to {filename}</>;\n}\n\nexport const MainContentInner = ({\n candidatesExistPromise,\n}: {\n candidatesExistPromise: Promise<[string, boolean][]>;\n}) => {\n const candidatesExist = use(candidatesExistPromise);\n const filename = candidatesExist.find(([_, exists]) => exists)?.[0];\n if (!filename) {\n // todo: show file list\n throw new Error(`No main content file present`);\n }\n return <MainContentRedirect filename={FILES_PREFIX + filename}/>;\n};\n\nexport const MainContent = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n // TODO: when to invalidate?\n const candidatesExistPromise = useMemo(() => Promise.all(candidates.map(fileExists)), []);\n return (\n <ErrorBoundary fallbackRender={ErrorComponent}>\n <Suspense fallback={<LoadingComponent />}>\n <MainContentInner candidatesExistPromise={candidatesExistPromise} />\n </Suspense>\n </ErrorBoundary>\n );\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/components/MainContent.tsx"],"sourcesContent":["import { Suspense, use, useMemo } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { navigate, useTinkerableLink } from '../routing';\nimport { FILES_PREFIX, underAppRoot } from '../urlUtils';\n\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\n// Repo-relative candidate paths. These are kept repo-relative because the\n// returned path is reused below to build the redirect URL (which is anchored to\n// `/app` by the file router); only the filesystem existence check is resolved\n// under `APP_ROOT`, since `bundler.fs` is rooted at `/`.\nconst candidates = ['/src/App.tsx', '/src/App.ts', '/src/App.js', '/App.tsx', '/App.ts', '/App.js', '/README.md', '/README.mdx', '/README.html'];\n\nconst fileExists = async (path: string): Promise<[string, boolean]> => {\n // @ts-ignore\n const bundler = module.evaluation.module.bundler;\n const exists = await bundler.fs.isFile.async(underAppRoot(path));\n return [path, exists];\n};\n\nexport const MainContentRedirect = ({filename}:{filename:string}) => {\n const url = useTinkerableLink(filename);\n navigate(url);\n return <>Redirecting to {filename}</>;\n}\n\nexport const MainContentInner = ({\n candidatesExistPromise,\n}: {\n candidatesExistPromise: Promise<[string, boolean][]>;\n}) => {\n const candidatesExist = use(candidatesExistPromise);\n const filename = candidatesExist.find(([_, exists]) => exists)?.[0];\n if (!filename) {\n // todo: show file list\n throw new Error(`No main content file present`);\n }\n return <MainContentRedirect filename={FILES_PREFIX + filename}/>;\n};\n\nexport const MainContent = ({\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n}: {\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n} = {}) => {\n // TODO: when to invalidate?\n const candidatesExistPromise = useMemo(() => Promise.all(candidates.map(fileExists)), []);\n return (\n <ErrorBoundary fallbackRender={ErrorComponent}>\n <Suspense fallback={<LoadingComponent />}>\n <MainContentInner candidatesExistPromise={candidatesExistPromise} />\n </Suspense>\n </ErrorBoundary>\n );\n};\n"],"mappings":"AAuBS,mBAcA,KAdA;AAvBT,SAAS,UAAU,KAAK,eAAe;AACvC,SAAS,qBAAqB;AAC9B,SAAS,UAAU,yBAAyB;AAC5C,SAAS,cAAc,oBAAoB;AAE3C,SAAS,uBAAuB,+BAA+B;AAM/D,MAAM,aAAa,CAAC,gBAAgB,eAAe,eAAe,YAAY,WAAW,WAAW,cAAc,eAAe,cAAc;AAE/I,MAAM,aAAa,OAAO,SAA6C;AAErE,QAAM,UAAU,OAAO,WAAW,OAAO;AACzC,QAAM,SAAS,MAAM,QAAQ,GAAG,OAAO,MAAM,aAAa,IAAI,CAAC;AAC/D,SAAO,CAAC,MAAM,MAAM;AACtB;AAEO,MAAM,sBAAsB,CAAC,EAAC,SAAQ,MAAwB;AACnE,QAAM,MAAM,kBAAkB,QAAQ;AACtC,WAAS,GAAG;AACZ,SAAO,iCAAE;AAAA;AAAA,IAAgB;AAAA,KAAS;AACpC;AAEO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AACF,MAEM;AACJ,QAAM,kBAAkB,IAAI,sBAAsB;AAClD,QAAM,WAAW,gBAAgB,KAAK,CAAC,CAAC,GAAG,MAAM,MAAM,MAAM,IAAI,CAAC;AAClE,MAAI,CAAC,UAAU;AAEb,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AACA,SAAO,oBAAC,uBAAoB,UAAU,eAAe,UAAS;AAChE;AAEO,MAAM,cAAc,CAAC;AAAA,EAC1B,mBAAmB;AAAA,EACnB,iBAAiB;AACnB,IAGI,CAAC,MAAM;AAET,QAAM,yBAAyB,QAAQ,MAAM,QAAQ,IAAI,WAAW,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AACxF,SACE,oBAAC,iBAAc,gBAAgB,gBAC7B,8BAAC,YAAS,UAAU,oBAAC,oBAAiB,GACpC,8BAAC,oBAAiB,wBAAgD,GACpE,GACF;AAEJ;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ __reExport(index_exports, require("./components/Include"), module.exports);
|
|
|
22
22
|
__reExport(index_exports, require("./components/MDXComponents"), module.exports);
|
|
23
23
|
__reExport(index_exports, require("./hooks"), module.exports);
|
|
24
24
|
__reExport(index_exports, require("./auth"), module.exports);
|
|
25
|
+
__reExport(index_exports, require("./mounts"), module.exports);
|
|
25
26
|
__reExport(index_exports, require("./sandboxTypes"), module.exports);
|
|
26
27
|
// Annotate the CommonJS export names for ESM import in node:
|
|
27
28
|
0 && (module.exports = {
|
|
@@ -32,6 +33,7 @@ __reExport(index_exports, require("./sandboxTypes"), module.exports);
|
|
|
32
33
|
...require("./components/MDXComponents"),
|
|
33
34
|
...require("./hooks"),
|
|
34
35
|
...require("./auth"),
|
|
36
|
+
...require("./mounts"),
|
|
35
37
|
...require("./sandboxTypes")
|
|
36
38
|
});
|
|
37
39
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './sandboxTypes';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAIA,0BAAc,uCAJd;AAKA,0BAAc,oBALd;AAMA,0BAAc,mBANd;AAOA,0BAAc,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './mounts';\nexport * from './sandboxTypes';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAIA,0BAAc,uCAJd;AAKA,0BAAc,oBALd;AAMA,0BAAc,mBANd;AAOA,0BAAc,qBAPd;AAQA,0BAAc,2BARd;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -5,6 +5,7 @@ export { Include, RenderExportedComponent, RenderExportedComponentContext, Rende
|
|
|
5
5
|
export { DEFAULT_MDX_COMPONENTS, InternalLink, Link } from './components/MDXComponents.cjs';
|
|
6
6
|
export { useFileMetadata, useMetadataQuery } from './hooks.cjs';
|
|
7
7
|
export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth } from './auth.cjs';
|
|
8
|
+
export { MountQuery, SandboxMount, findMount, getMounts, onMountsChange, useMounts, waitForMount } from './mounts.cjs';
|
|
8
9
|
export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryFunction, MetadataQueryResult, ModuleExports } from './sandboxTypes.cjs';
|
|
9
10
|
import 'react';
|
|
10
11
|
import './TinkerableContext.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { Include, RenderExportedComponent, RenderExportedComponentContext, Rende
|
|
|
5
5
|
export { DEFAULT_MDX_COMPONENTS, InternalLink, Link } from './components/MDXComponents.js';
|
|
6
6
|
export { useFileMetadata, useMetadataQuery } from './hooks.js';
|
|
7
7
|
export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth } from './auth.js';
|
|
8
|
+
export { MountQuery, SandboxMount, findMount, getMounts, onMountsChange, useMounts, waitForMount } from './mounts.js';
|
|
8
9
|
export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryFunction, MetadataQueryResult, ModuleExports } from './sandboxTypes.js';
|
|
9
10
|
import 'react';
|
|
10
11
|
import './TinkerableContext.js';
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './sandboxTypes';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './mounts';\nexport * from './sandboxTypes';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
package/dist/mounts.cjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var mounts_exports = {};
|
|
20
|
+
__export(mounts_exports, {
|
|
21
|
+
findMount: () => findMount,
|
|
22
|
+
getMounts: () => getMounts,
|
|
23
|
+
onMountsChange: () => onMountsChange,
|
|
24
|
+
useMounts: () => useMounts,
|
|
25
|
+
waitForMount: () => waitForMount
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(mounts_exports);
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
const mountService = () => {
|
|
30
|
+
return module.evaluation.module.bundler.mounts;
|
|
31
|
+
};
|
|
32
|
+
const matches = (mount, query) => (query.type === void 0 || mount.type === query.type) && (query.id === void 0 || mount.id === query.id) && (query.path === void 0 || mount.path === query.path);
|
|
33
|
+
const getMounts = () => mountService().getMounts();
|
|
34
|
+
const findMount = (query) => getMounts().find((m) => matches(m, query));
|
|
35
|
+
const onMountsChange = (listener) => {
|
|
36
|
+
const disposable = mountService().onChange(listener);
|
|
37
|
+
return () => disposable.dispose();
|
|
38
|
+
};
|
|
39
|
+
const waitForMount = (query) => new Promise((resolve) => {
|
|
40
|
+
const unsubscribe = onMountsChange((mounts) => {
|
|
41
|
+
const found = mounts.find((m) => matches(m, query));
|
|
42
|
+
if (found) {
|
|
43
|
+
Promise.resolve().then(unsubscribe);
|
|
44
|
+
resolve(found);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
const useMounts = () => {
|
|
49
|
+
const [mounts, setMounts] = (0, import_react.useState)(getMounts);
|
|
50
|
+
(0, import_react.useEffect)(() => onMountsChange(setMounts), []);
|
|
51
|
+
return mounts;
|
|
52
|
+
};
|
|
53
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
54
|
+
0 && (module.exports = {
|
|
55
|
+
findMount,
|
|
56
|
+
getMounts,
|
|
57
|
+
onMountsChange,
|
|
58
|
+
useMounts,
|
|
59
|
+
waitForMount
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=mounts.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear and disappear at runtime — e.g. a Firestore-backed store is\n * mounted at `/firestore` after the user signs in and removed on logout. Read\n * or subscribe to the set, then access the files through the `fs` module at the\n * mount's `path`.\n */\nexport interface SandboxMount {\n /** Absolute path where the mount is reachable (e.g. `/firestore`). */\n path: string;\n /** Backend kind, e.g. `'firestore'`. */\n type: string;\n /** Optional stable identifier. */\n id?: string;\n}\n\ninterface MountService {\n getMounts(): SandboxMount[];\n onChange(listener: (mounts: SandboxMount[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler` is the sandbox bundler injected into the\n// evaluation context (same path the other SDK helpers reach for `messageBus`).\nconst mountService = (): MountService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.mounts;\n};\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */\nexport type MountQuery = { type?: string; id?: string; path?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean =>\n (query.type === undefined || mount.type === query.type) &&\n (query.id === undefined || mount.id === query.id) &&\n (query.path === undefined || mount.path === query.path);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined =>\n getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts, then again on every change. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[]) => void): (() => void) => {\n const disposable = mountService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n */\nexport const waitForMount = (query: MountQuery): Promise<SandboxMount> =>\n new Promise((resolve) => {\n const unsubscribe = onMountsChange((mounts) => {\n const found = mounts.find((m) => matches(m, query));\n if (found) {\n // Defer unsubscribe so we don't dispose during the initial replay call.\n Promise.resolve().then(unsubscribe);\n resolve(found);\n }\n });\n });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n useEffect(() => onMountsChange(setMounts), []);\n return mounts;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAoC;AA0BpC,MAAM,eAAe,MAAoB;AAEvC,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAKA,MAAM,UAAU,CAAC,OAAqB,WACnC,MAAM,SAAS,UAAa,MAAM,SAAS,MAAM,UACjD,MAAM,OAAO,UAAa,MAAM,OAAO,MAAM,QAC7C,MAAM,SAAS,UAAa,MAAM,SAAS,MAAM;AAM7C,MAAM,YAAY,MAAsB,aAAa,EAAE,UAAU;AAGjE,MAAM,YAAY,CAAC,UACxB,UAAU,EAAE,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAMpC,MAAM,iBAAiB,CAAC,aAA6D;AAC1F,QAAM,aAAa,aAAa,EAAE,SAAS,QAAQ;AACnD,SAAO,MAAM,WAAW,QAAQ;AAClC;AAOO,MAAM,eAAe,CAAC,UAC3B,IAAI,QAAQ,CAAC,YAAY;AACvB,QAAM,cAAc,eAAe,CAAC,WAAW;AAC7C,UAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAClD,QAAI,OAAO;AAET,cAAQ,QAAQ,EAAE,KAAK,WAAW;AAClC,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH,CAAC;AAGI,MAAM,YAAY,MAAsB;AAC7C,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAyB,SAAS;AAC9D,8BAAU,MAAM,eAAe,SAAS,GAAG,CAAC,CAAC;AAC7C,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A filesystem mount available to the sandbox, mirrored from the host window.
|
|
3
|
+
*
|
|
4
|
+
* Mounts appear and disappear at runtime — e.g. a Firestore-backed store is
|
|
5
|
+
* mounted at `/firestore` after the user signs in and removed on logout. Read
|
|
6
|
+
* or subscribe to the set, then access the files through the `fs` module at the
|
|
7
|
+
* mount's `path`.
|
|
8
|
+
*/
|
|
9
|
+
interface SandboxMount {
|
|
10
|
+
/** Absolute path where the mount is reachable (e.g. `/firestore`). */
|
|
11
|
+
path: string;
|
|
12
|
+
/** Backend kind, e.g. `'firestore'`. */
|
|
13
|
+
type: string;
|
|
14
|
+
/** Optional stable identifier. */
|
|
15
|
+
id?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */
|
|
18
|
+
type MountQuery = {
|
|
19
|
+
type?: string;
|
|
20
|
+
id?: string;
|
|
21
|
+
path?: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Returns the mounts currently available. Poll this whenever you need a one-off
|
|
25
|
+
* read; use {@link onMountsChange} or {@link useMounts} to react to changes.
|
|
26
|
+
*/
|
|
27
|
+
declare const getMounts: () => SandboxMount[];
|
|
28
|
+
/** Returns the first mount matching `query`, or `undefined`. */
|
|
29
|
+
declare const findMount: (query: MountQuery) => SandboxMount | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to mount changes. The listener is invoked immediately with the
|
|
32
|
+
* current mounts, then again on every change. Returns an unsubscribe fn.
|
|
33
|
+
*/
|
|
34
|
+
declare const onMountsChange: (listener: (mounts: SandboxMount[]) => void) => (() => void);
|
|
35
|
+
/**
|
|
36
|
+
* Resolves once a mount matching `query` is present (immediately if it already
|
|
37
|
+
* is). Handy for "use it when it appears" — e.g.
|
|
38
|
+
* `await waitForMount({ type: 'firestore' })` before reading `/firestore`.
|
|
39
|
+
*/
|
|
40
|
+
declare const waitForMount: (query: MountQuery) => Promise<SandboxMount>;
|
|
41
|
+
/** React hook returning the mounts currently available, re-rendering on change. */
|
|
42
|
+
declare const useMounts: () => SandboxMount[];
|
|
43
|
+
|
|
44
|
+
export { type MountQuery, type SandboxMount, findMount, getMounts, onMountsChange, useMounts, waitForMount };
|
package/dist/mounts.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A filesystem mount available to the sandbox, mirrored from the host window.
|
|
3
|
+
*
|
|
4
|
+
* Mounts appear and disappear at runtime — e.g. a Firestore-backed store is
|
|
5
|
+
* mounted at `/firestore` after the user signs in and removed on logout. Read
|
|
6
|
+
* or subscribe to the set, then access the files through the `fs` module at the
|
|
7
|
+
* mount's `path`.
|
|
8
|
+
*/
|
|
9
|
+
interface SandboxMount {
|
|
10
|
+
/** Absolute path where the mount is reachable (e.g. `/firestore`). */
|
|
11
|
+
path: string;
|
|
12
|
+
/** Backend kind, e.g. `'firestore'`. */
|
|
13
|
+
type: string;
|
|
14
|
+
/** Optional stable identifier. */
|
|
15
|
+
id?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */
|
|
18
|
+
type MountQuery = {
|
|
19
|
+
type?: string;
|
|
20
|
+
id?: string;
|
|
21
|
+
path?: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Returns the mounts currently available. Poll this whenever you need a one-off
|
|
25
|
+
* read; use {@link onMountsChange} or {@link useMounts} to react to changes.
|
|
26
|
+
*/
|
|
27
|
+
declare const getMounts: () => SandboxMount[];
|
|
28
|
+
/** Returns the first mount matching `query`, or `undefined`. */
|
|
29
|
+
declare const findMount: (query: MountQuery) => SandboxMount | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to mount changes. The listener is invoked immediately with the
|
|
32
|
+
* current mounts, then again on every change. Returns an unsubscribe fn.
|
|
33
|
+
*/
|
|
34
|
+
declare const onMountsChange: (listener: (mounts: SandboxMount[]) => void) => (() => void);
|
|
35
|
+
/**
|
|
36
|
+
* Resolves once a mount matching `query` is present (immediately if it already
|
|
37
|
+
* is). Handy for "use it when it appears" — e.g.
|
|
38
|
+
* `await waitForMount({ type: 'firestore' })` before reading `/firestore`.
|
|
39
|
+
*/
|
|
40
|
+
declare const waitForMount: (query: MountQuery) => Promise<SandboxMount>;
|
|
41
|
+
/** React hook returning the mounts currently available, re-rendering on change. */
|
|
42
|
+
declare const useMounts: () => SandboxMount[];
|
|
43
|
+
|
|
44
|
+
export { type MountQuery, type SandboxMount, findMount, getMounts, onMountsChange, useMounts, waitForMount };
|
package/dist/mounts.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
const mountService = () => {
|
|
3
|
+
return module.evaluation.module.bundler.mounts;
|
|
4
|
+
};
|
|
5
|
+
const matches = (mount, query) => (query.type === void 0 || mount.type === query.type) && (query.id === void 0 || mount.id === query.id) && (query.path === void 0 || mount.path === query.path);
|
|
6
|
+
const getMounts = () => mountService().getMounts();
|
|
7
|
+
const findMount = (query) => getMounts().find((m) => matches(m, query));
|
|
8
|
+
const onMountsChange = (listener) => {
|
|
9
|
+
const disposable = mountService().onChange(listener);
|
|
10
|
+
return () => disposable.dispose();
|
|
11
|
+
};
|
|
12
|
+
const waitForMount = (query) => new Promise((resolve) => {
|
|
13
|
+
const unsubscribe = onMountsChange((mounts) => {
|
|
14
|
+
const found = mounts.find((m) => matches(m, query));
|
|
15
|
+
if (found) {
|
|
16
|
+
Promise.resolve().then(unsubscribe);
|
|
17
|
+
resolve(found);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
const useMounts = () => {
|
|
22
|
+
const [mounts, setMounts] = useState(getMounts);
|
|
23
|
+
useEffect(() => onMountsChange(setMounts), []);
|
|
24
|
+
return mounts;
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
findMount,
|
|
28
|
+
getMounts,
|
|
29
|
+
onMountsChange,
|
|
30
|
+
useMounts,
|
|
31
|
+
waitForMount
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=mounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear and disappear at runtime — e.g. a Firestore-backed store is\n * mounted at `/firestore` after the user signs in and removed on logout. Read\n * or subscribe to the set, then access the files through the `fs` module at the\n * mount's `path`.\n */\nexport interface SandboxMount {\n /** Absolute path where the mount is reachable (e.g. `/firestore`). */\n path: string;\n /** Backend kind, e.g. `'firestore'`. */\n type: string;\n /** Optional stable identifier. */\n id?: string;\n}\n\ninterface MountService {\n getMounts(): SandboxMount[];\n onChange(listener: (mounts: SandboxMount[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler` is the sandbox bundler injected into the\n// evaluation context (same path the other SDK helpers reach for `messageBus`).\nconst mountService = (): MountService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.mounts;\n};\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */\nexport type MountQuery = { type?: string; id?: string; path?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean =>\n (query.type === undefined || mount.type === query.type) &&\n (query.id === undefined || mount.id === query.id) &&\n (query.path === undefined || mount.path === query.path);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined =>\n getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts, then again on every change. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[]) => void): (() => void) => {\n const disposable = mountService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n */\nexport const waitForMount = (query: MountQuery): Promise<SandboxMount> =>\n new Promise((resolve) => {\n const unsubscribe = onMountsChange((mounts) => {\n const found = mounts.find((m) => matches(m, query));\n if (found) {\n // Defer unsubscribe so we don't dispose during the initial replay call.\n Promise.resolve().then(unsubscribe);\n resolve(found);\n }\n });\n });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n useEffect(() => onMountsChange(setMounts), []);\n return mounts;\n};\n"],"mappings":"AAAA,SAAS,WAAW,gBAAgB;AA0BpC,MAAM,eAAe,MAAoB;AAEvC,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAKA,MAAM,UAAU,CAAC,OAAqB,WACnC,MAAM,SAAS,UAAa,MAAM,SAAS,MAAM,UACjD,MAAM,OAAO,UAAa,MAAM,OAAO,MAAM,QAC7C,MAAM,SAAS,UAAa,MAAM,SAAS,MAAM;AAM7C,MAAM,YAAY,MAAsB,aAAa,EAAE,UAAU;AAGjE,MAAM,YAAY,CAAC,UACxB,UAAU,EAAE,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAMpC,MAAM,iBAAiB,CAAC,aAA6D;AAC1F,QAAM,aAAa,aAAa,EAAE,SAAS,QAAQ;AACnD,SAAO,MAAM,WAAW,QAAQ;AAClC;AAOO,MAAM,eAAe,CAAC,UAC3B,IAAI,QAAQ,CAAC,YAAY;AACvB,QAAM,cAAc,eAAe,CAAC,WAAW;AAC7C,UAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAClD,QAAI,OAAO;AAET,cAAQ,QAAQ,EAAE,KAAK,WAAW;AAClC,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH,CAAC;AAGI,MAAM,YAAY,MAAsB;AAC7C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAyB,SAAS;AAC9D,YAAU,MAAM,eAAe,SAAS,GAAG,CAAC,CAAC;AAC7C,SAAO;AACT;","names":[]}
|
package/dist/urlUtils.cjs
CHANGED
|
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var urlUtils_exports = {};
|
|
20
20
|
__export(urlUtils_exports, {
|
|
21
|
+
APP_ROOT: () => APP_ROOT,
|
|
21
22
|
FILES_PREFIX: () => FILES_PREFIX,
|
|
22
23
|
constructOuterUrl: () => constructOuterUrl,
|
|
23
24
|
constructUrl: () => constructUrl,
|
|
@@ -29,11 +30,14 @@ __export(urlUtils_exports, {
|
|
|
29
30
|
parseHref: () => parseHref,
|
|
30
31
|
parsePath: () => parsePath,
|
|
31
32
|
parseTarget: () => parseTarget,
|
|
32
|
-
repositoryPrefixURL: () => repositoryPrefixURL
|
|
33
|
+
repositoryPrefixURL: () => repositoryPrefixURL,
|
|
34
|
+
underAppRoot: () => underAppRoot
|
|
33
35
|
});
|
|
34
36
|
module.exports = __toCommonJS(urlUtils_exports);
|
|
35
37
|
var import_pathUtils = require("./pathUtils");
|
|
36
38
|
const FILES_PREFIX = "/files";
|
|
39
|
+
const APP_ROOT = "/app";
|
|
40
|
+
const underAppRoot = (repoRelativePath) => (0, import_pathUtils.joinPaths)(APP_ROOT, repoRelativePath);
|
|
37
41
|
const getOuterHostname = (outerHref) => {
|
|
38
42
|
const url = new URL(outerHref);
|
|
39
43
|
return `${url.protocol}//${url.hostname}`;
|
|
@@ -147,6 +151,7 @@ const constructUrl = (outerHref, navigationState) => {
|
|
|
147
151
|
};
|
|
148
152
|
// Annotate the CommonJS export names for ESM import in node:
|
|
149
153
|
0 && (module.exports = {
|
|
154
|
+
APP_ROOT,
|
|
150
155
|
FILES_PREFIX,
|
|
151
156
|
constructOuterUrl,
|
|
152
157
|
constructUrl,
|
|
@@ -158,6 +163,7 @@ const constructUrl = (outerHref, navigationState) => {
|
|
|
158
163
|
parseHref,
|
|
159
164
|
parsePath,
|
|
160
165
|
parseTarget,
|
|
161
|
-
repositoryPrefixURL
|
|
166
|
+
repositoryPrefixURL,
|
|
167
|
+
underAppRoot
|
|
162
168
|
});
|
|
163
169
|
//# sourceMappingURL=urlUtils.cjs.map
|
package/dist/urlUtils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/urlUtils.ts"],"sourcesContent":["import { joinPaths } from \"./pathUtils\";\nimport { NavigationState, PathState } from \"./TinkerableContext\";\n\nexport const FILES_PREFIX = '/files';\n\nexport const getOuterHostname = (outerHref:string) => {\n const url = new URL(outerHref);\n return `${url.protocol}//${url.hostname}`;\n}\n\nexport const getSearchParams = (search?: string): Record<string, string> => Object.fromEntries(\n [...(new URLSearchParams(search ?? window.location.search).entries())]);\n\n\nexport const parseTarget = (target: string, navigation: NavigationState): NavigationState => {\n const newNavigation = { ...navigation };\n let [prehash, hash] = target.split(\"#\")\n if (prehash) {\n let [path, search] = prehash.split(\"?\")\n if (path) {\n newNavigation.sandboxPath = path\n }\n newNavigation.search = search ? search : '';\n }\n newNavigation.hash = hash ? hash : '';\n return newNavigation\n}\n\n\nexport const maybeParseUrl = (str: string): URL | null => {\n try {\n return new URL(str);\n } catch (_) {\n return null;\n }\n}\n\nexport const isAbsolutePath = (sandboxPath: string) => sandboxPath.startsWith('/');\n\nexport const repositoryPrefixURL = (outerHref:string, navigationState: NavigationState) => constructUrl(outerHref, {\n ...navigationState,\n sandboxPath: ''\n });\n\nexport const constructOuterUrl = (previousOuterHref:string, sandboxTarget:string, navigationState: NavigationState, addFilesPrefix=true):string => {\n if (isAbsolutePath(sandboxTarget)) {\n return constructUrl(\n previousOuterHref,\n {\n ...navigationState,\n sandboxPath: addFilesPrefix ? joinPaths(FILES_PREFIX, sandboxTarget) : sandboxTarget\n })\n }\n return (\n new URL(\n sandboxTarget,\n constructUrl(\n previousOuterHref,\n navigationState\n )\n )\n ).toString();\n}\n\nexport const isInternalHref = (outerHref:string, target: string, navigationState: NavigationState) => {\n const parsedUrl = maybeParseUrl(target);\n if (parsedUrl) {\n return target.startsWith(repositoryPrefixURL(outerHref, navigationState));\n }\n // if target is not a valid URL, then assume it's relative.\n return true;\n}\n\nexport type PathSegment = {\n name: string,\n pattern: string,\n transform?: (pathSegment: string) => string,\n // When true, the leading slash that delimits this segment is optional, so the\n // whole `/segment` group can be absent. Used for the trailing sandboxPath:\n // an outer href of `/mode/provider/namespace/repository/ref` (no trailing\n // slash, no sub-path) must still parse, otherwise the regex matches nothing\n // and every segment comes back empty.\n optionalLeadingSlash?: boolean\n}\n\nconst PATH_SEGMENTS: PathSegment[] = [\n { name: 'mode', pattern: '\\\\w+' },\n { name: 'provider', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'namespace', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'repository', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'ref', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'sandboxPath', pattern: '.*', transform: s => `/${s}`, optionalLeadingSlash: true }\n];\n\nconst OUTER_HREF_REGEXP = new RegExp(\n '^' +\n PATH_SEGMENTS.map(({ name, pattern, optionalLeadingSlash }) =>\n optionalLeadingSlash\n ? `(?:\\/(?<${name}>${pattern}))?`\n : `\\/(?<${name}>${pattern})`\n ).join('') +\n \"$\"\n);\n\n\nexport const parsePath = (pathname: string): PathState => {\n const matchResults = pathname.match(OUTER_HREF_REGEXP)?.groups ?? {};\n return PATH_SEGMENTS.reduce((acc: Partial<PathState>, { name, transform }: PathSegment) => {\n let value: string | undefined = undefined;\n if (name in matchResults) {\n value = matchResults[name];\n }\n if (!value) {\n // fall back to default value if var not present in\n value = '';\n }\n if (typeof value === 'string') {\n acc[name] = transform ? transform(value) : value;\n }\n return acc;\n }, {}) as PathState;\n}\n\nexport const parseHref = (href: string): NavigationState => {\n const parsedUrl = new URL(href);\n const pathnameState = parsePath(parsedUrl.pathname);\n return {\n ...pathnameState,\n search: parsedUrl.search.substring(1),\n hash: parsedUrl.hash.substring(1),\n } as NavigationState\n}\n\nconst stripSlashPrefix = (s: string): string => s.startsWith('/') ? s.substring(1) : s;\n\nexport const constructUrl = (outerHref:string, navigationState: NavigationState): string => {\n const path = PATH_SEGMENTS.map(({ name }) => {\n let value = navigationState[name];\n return stripSlashPrefix(value ?? '');\n }).join('/');\n const host = getOuterHostname(outerHref);\n let url = `${host}/${path}`\n if (navigationState.search) {\n url += '?' + navigationState.search\n }\n if (navigationState.hash) {\n url += '#' + navigationState.hash\n }\n return url;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA0B;AAGnB,MAAM,eAAe;
|
|
1
|
+
{"version":3,"sources":["../src/urlUtils.ts"],"sourcesContent":["import { joinPaths } from \"./pathUtils\";\nimport { NavigationState, PathState } from \"./TinkerableContext\";\n\nexport const FILES_PREFIX = '/files';\n\n/**\n * Mount point of the Git repository inside the sandbox filesystem. The sandbox\n * fs is rooted at `/` (so apps can reach dynamic mounts like `/firestore`), with\n * the repo mounted here. URL subpaths are repo-relative, so the file router\n * resolves them under `APP_ROOT`.\n */\nexport const APP_ROOT = '/app';\n\n/** Resolve a repo-relative path (e.g. a URL subpath) to its absolute sandbox path. */\nexport const underAppRoot = (repoRelativePath: string): string =>\n joinPaths(APP_ROOT, repoRelativePath);\n\nexport const getOuterHostname = (outerHref:string) => {\n const url = new URL(outerHref);\n return `${url.protocol}//${url.hostname}`;\n}\n\nexport const getSearchParams = (search?: string): Record<string, string> => Object.fromEntries(\n [...(new URLSearchParams(search ?? window.location.search).entries())]);\n\n\nexport const parseTarget = (target: string, navigation: NavigationState): NavigationState => {\n const newNavigation = { ...navigation };\n let [prehash, hash] = target.split(\"#\")\n if (prehash) {\n let [path, search] = prehash.split(\"?\")\n if (path) {\n newNavigation.sandboxPath = path\n }\n newNavigation.search = search ? search : '';\n }\n newNavigation.hash = hash ? hash : '';\n return newNavigation\n}\n\n\nexport const maybeParseUrl = (str: string): URL | null => {\n try {\n return new URL(str);\n } catch (_) {\n return null;\n }\n}\n\nexport const isAbsolutePath = (sandboxPath: string) => sandboxPath.startsWith('/');\n\nexport const repositoryPrefixURL = (outerHref:string, navigationState: NavigationState) => constructUrl(outerHref, {\n ...navigationState,\n sandboxPath: ''\n });\n\nexport const constructOuterUrl = (previousOuterHref:string, sandboxTarget:string, navigationState: NavigationState, addFilesPrefix=true):string => {\n if (isAbsolutePath(sandboxTarget)) {\n return constructUrl(\n previousOuterHref,\n {\n ...navigationState,\n sandboxPath: addFilesPrefix ? joinPaths(FILES_PREFIX, sandboxTarget) : sandboxTarget\n })\n }\n return (\n new URL(\n sandboxTarget,\n constructUrl(\n previousOuterHref,\n navigationState\n )\n )\n ).toString();\n}\n\nexport const isInternalHref = (outerHref:string, target: string, navigationState: NavigationState) => {\n const parsedUrl = maybeParseUrl(target);\n if (parsedUrl) {\n return target.startsWith(repositoryPrefixURL(outerHref, navigationState));\n }\n // if target is not a valid URL, then assume it's relative.\n return true;\n}\n\nexport type PathSegment = {\n name: string,\n pattern: string,\n transform?: (pathSegment: string) => string,\n // When true, the leading slash that delimits this segment is optional, so the\n // whole `/segment` group can be absent. Used for the trailing sandboxPath:\n // an outer href of `/mode/provider/namespace/repository/ref` (no trailing\n // slash, no sub-path) must still parse, otherwise the regex matches nothing\n // and every segment comes back empty.\n optionalLeadingSlash?: boolean\n}\n\nconst PATH_SEGMENTS: PathSegment[] = [\n { name: 'mode', pattern: '\\\\w+' },\n { name: 'provider', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'namespace', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'repository', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'ref', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'sandboxPath', pattern: '.*', transform: s => `/${s}`, optionalLeadingSlash: true }\n];\n\nconst OUTER_HREF_REGEXP = new RegExp(\n '^' +\n PATH_SEGMENTS.map(({ name, pattern, optionalLeadingSlash }) =>\n optionalLeadingSlash\n ? `(?:\\/(?<${name}>${pattern}))?`\n : `\\/(?<${name}>${pattern})`\n ).join('') +\n \"$\"\n);\n\n\nexport const parsePath = (pathname: string): PathState => {\n const matchResults = pathname.match(OUTER_HREF_REGEXP)?.groups ?? {};\n return PATH_SEGMENTS.reduce((acc: Partial<PathState>, { name, transform }: PathSegment) => {\n let value: string | undefined = undefined;\n if (name in matchResults) {\n value = matchResults[name];\n }\n if (!value) {\n // fall back to default value if var not present in\n value = '';\n }\n if (typeof value === 'string') {\n acc[name] = transform ? transform(value) : value;\n }\n return acc;\n }, {}) as PathState;\n}\n\nexport const parseHref = (href: string): NavigationState => {\n const parsedUrl = new URL(href);\n const pathnameState = parsePath(parsedUrl.pathname);\n return {\n ...pathnameState,\n search: parsedUrl.search.substring(1),\n hash: parsedUrl.hash.substring(1),\n } as NavigationState\n}\n\nconst stripSlashPrefix = (s: string): string => s.startsWith('/') ? s.substring(1) : s;\n\nexport const constructUrl = (outerHref:string, navigationState: NavigationState): string => {\n const path = PATH_SEGMENTS.map(({ name }) => {\n let value = navigationState[name];\n return stripSlashPrefix(value ?? '');\n }).join('/');\n const host = getOuterHostname(outerHref);\n let url = `${host}/${path}`\n if (navigationState.search) {\n url += '?' + navigationState.search\n }\n if (navigationState.hash) {\n url += '#' + navigationState.hash\n }\n return url;\n}\n"],"mappings":"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","names":[]}
|
package/dist/urlUtils.d.cts
CHANGED
|
@@ -4,6 +4,15 @@ import './RoutingSpec.cjs';
|
|
|
4
4
|
import './sandboxTypes.cjs';
|
|
5
5
|
|
|
6
6
|
declare const FILES_PREFIX = "/files";
|
|
7
|
+
/**
|
|
8
|
+
* Mount point of the Git repository inside the sandbox filesystem. The sandbox
|
|
9
|
+
* fs is rooted at `/` (so apps can reach dynamic mounts like `/firestore`), with
|
|
10
|
+
* the repo mounted here. URL subpaths are repo-relative, so the file router
|
|
11
|
+
* resolves them under `APP_ROOT`.
|
|
12
|
+
*/
|
|
13
|
+
declare const APP_ROOT = "/app";
|
|
14
|
+
/** Resolve a repo-relative path (e.g. a URL subpath) to its absolute sandbox path. */
|
|
15
|
+
declare const underAppRoot: (repoRelativePath: string) => string;
|
|
7
16
|
declare const getOuterHostname: (outerHref: string) => string;
|
|
8
17
|
declare const getSearchParams: (search?: string) => Record<string, string>;
|
|
9
18
|
declare const parseTarget: (target: string, navigation: NavigationState) => NavigationState;
|
|
@@ -22,4 +31,4 @@ declare const parsePath: (pathname: string) => PathState;
|
|
|
22
31
|
declare const parseHref: (href: string) => NavigationState;
|
|
23
32
|
declare const constructUrl: (outerHref: string, navigationState: NavigationState) => string;
|
|
24
33
|
|
|
25
|
-
export { FILES_PREFIX, type PathSegment, constructOuterUrl, constructUrl, getOuterHostname, getSearchParams, isAbsolutePath, isInternalHref, maybeParseUrl, parseHref, parsePath, parseTarget, repositoryPrefixURL };
|
|
34
|
+
export { APP_ROOT, FILES_PREFIX, type PathSegment, constructOuterUrl, constructUrl, getOuterHostname, getSearchParams, isAbsolutePath, isInternalHref, maybeParseUrl, parseHref, parsePath, parseTarget, repositoryPrefixURL, underAppRoot };
|
package/dist/urlUtils.d.ts
CHANGED
|
@@ -4,6 +4,15 @@ import './RoutingSpec.js';
|
|
|
4
4
|
import './sandboxTypes.js';
|
|
5
5
|
|
|
6
6
|
declare const FILES_PREFIX = "/files";
|
|
7
|
+
/**
|
|
8
|
+
* Mount point of the Git repository inside the sandbox filesystem. The sandbox
|
|
9
|
+
* fs is rooted at `/` (so apps can reach dynamic mounts like `/firestore`), with
|
|
10
|
+
* the repo mounted here. URL subpaths are repo-relative, so the file router
|
|
11
|
+
* resolves them under `APP_ROOT`.
|
|
12
|
+
*/
|
|
13
|
+
declare const APP_ROOT = "/app";
|
|
14
|
+
/** Resolve a repo-relative path (e.g. a URL subpath) to its absolute sandbox path. */
|
|
15
|
+
declare const underAppRoot: (repoRelativePath: string) => string;
|
|
7
16
|
declare const getOuterHostname: (outerHref: string) => string;
|
|
8
17
|
declare const getSearchParams: (search?: string) => Record<string, string>;
|
|
9
18
|
declare const parseTarget: (target: string, navigation: NavigationState) => NavigationState;
|
|
@@ -22,4 +31,4 @@ declare const parsePath: (pathname: string) => PathState;
|
|
|
22
31
|
declare const parseHref: (href: string) => NavigationState;
|
|
23
32
|
declare const constructUrl: (outerHref: string, navigationState: NavigationState) => string;
|
|
24
33
|
|
|
25
|
-
export { FILES_PREFIX, type PathSegment, constructOuterUrl, constructUrl, getOuterHostname, getSearchParams, isAbsolutePath, isInternalHref, maybeParseUrl, parseHref, parsePath, parseTarget, repositoryPrefixURL };
|
|
34
|
+
export { APP_ROOT, FILES_PREFIX, type PathSegment, constructOuterUrl, constructUrl, getOuterHostname, getSearchParams, isAbsolutePath, isInternalHref, maybeParseUrl, parseHref, parsePath, parseTarget, repositoryPrefixURL, underAppRoot };
|
package/dist/urlUtils.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { joinPaths } from "./pathUtils";
|
|
2
2
|
const FILES_PREFIX = "/files";
|
|
3
|
+
const APP_ROOT = "/app";
|
|
4
|
+
const underAppRoot = (repoRelativePath) => joinPaths(APP_ROOT, repoRelativePath);
|
|
3
5
|
const getOuterHostname = (outerHref) => {
|
|
4
6
|
const url = new URL(outerHref);
|
|
5
7
|
return `${url.protocol}//${url.hostname}`;
|
|
@@ -112,6 +114,7 @@ const constructUrl = (outerHref, navigationState) => {
|
|
|
112
114
|
return url;
|
|
113
115
|
};
|
|
114
116
|
export {
|
|
117
|
+
APP_ROOT,
|
|
115
118
|
FILES_PREFIX,
|
|
116
119
|
constructOuterUrl,
|
|
117
120
|
constructUrl,
|
|
@@ -123,6 +126,7 @@ export {
|
|
|
123
126
|
parseHref,
|
|
124
127
|
parsePath,
|
|
125
128
|
parseTarget,
|
|
126
|
-
repositoryPrefixURL
|
|
129
|
+
repositoryPrefixURL,
|
|
130
|
+
underAppRoot
|
|
127
131
|
};
|
|
128
132
|
//# sourceMappingURL=urlUtils.js.map
|
package/dist/urlUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/urlUtils.ts"],"sourcesContent":["import { joinPaths } from \"./pathUtils\";\nimport { NavigationState, PathState } from \"./TinkerableContext\";\n\nexport const FILES_PREFIX = '/files';\n\nexport const getOuterHostname = (outerHref:string) => {\n const url = new URL(outerHref);\n return `${url.protocol}//${url.hostname}`;\n}\n\nexport const getSearchParams = (search?: string): Record<string, string> => Object.fromEntries(\n [...(new URLSearchParams(search ?? window.location.search).entries())]);\n\n\nexport const parseTarget = (target: string, navigation: NavigationState): NavigationState => {\n const newNavigation = { ...navigation };\n let [prehash, hash] = target.split(\"#\")\n if (prehash) {\n let [path, search] = prehash.split(\"?\")\n if (path) {\n newNavigation.sandboxPath = path\n }\n newNavigation.search = search ? search : '';\n }\n newNavigation.hash = hash ? hash : '';\n return newNavigation\n}\n\n\nexport const maybeParseUrl = (str: string): URL | null => {\n try {\n return new URL(str);\n } catch (_) {\n return null;\n }\n}\n\nexport const isAbsolutePath = (sandboxPath: string) => sandboxPath.startsWith('/');\n\nexport const repositoryPrefixURL = (outerHref:string, navigationState: NavigationState) => constructUrl(outerHref, {\n ...navigationState,\n sandboxPath: ''\n });\n\nexport const constructOuterUrl = (previousOuterHref:string, sandboxTarget:string, navigationState: NavigationState, addFilesPrefix=true):string => {\n if (isAbsolutePath(sandboxTarget)) {\n return constructUrl(\n previousOuterHref,\n {\n ...navigationState,\n sandboxPath: addFilesPrefix ? joinPaths(FILES_PREFIX, sandboxTarget) : sandboxTarget\n })\n }\n return (\n new URL(\n sandboxTarget,\n constructUrl(\n previousOuterHref,\n navigationState\n )\n )\n ).toString();\n}\n\nexport const isInternalHref = (outerHref:string, target: string, navigationState: NavigationState) => {\n const parsedUrl = maybeParseUrl(target);\n if (parsedUrl) {\n return target.startsWith(repositoryPrefixURL(outerHref, navigationState));\n }\n // if target is not a valid URL, then assume it's relative.\n return true;\n}\n\nexport type PathSegment = {\n name: string,\n pattern: string,\n transform?: (pathSegment: string) => string,\n // When true, the leading slash that delimits this segment is optional, so the\n // whole `/segment` group can be absent. Used for the trailing sandboxPath:\n // an outer href of `/mode/provider/namespace/repository/ref` (no trailing\n // slash, no sub-path) must still parse, otherwise the regex matches nothing\n // and every segment comes back empty.\n optionalLeadingSlash?: boolean\n}\n\nconst PATH_SEGMENTS: PathSegment[] = [\n { name: 'mode', pattern: '\\\\w+' },\n { name: 'provider', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'namespace', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'repository', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'ref', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'sandboxPath', pattern: '.*', transform: s => `/${s}`, optionalLeadingSlash: true }\n];\n\nconst OUTER_HREF_REGEXP = new RegExp(\n '^' +\n PATH_SEGMENTS.map(({ name, pattern, optionalLeadingSlash }) =>\n optionalLeadingSlash\n ? `(?:\\/(?<${name}>${pattern}))?`\n : `\\/(?<${name}>${pattern})`\n ).join('') +\n \"$\"\n);\n\n\nexport const parsePath = (pathname: string): PathState => {\n const matchResults = pathname.match(OUTER_HREF_REGEXP)?.groups ?? {};\n return PATH_SEGMENTS.reduce((acc: Partial<PathState>, { name, transform }: PathSegment) => {\n let value: string | undefined = undefined;\n if (name in matchResults) {\n value = matchResults[name];\n }\n if (!value) {\n // fall back to default value if var not present in\n value = '';\n }\n if (typeof value === 'string') {\n acc[name] = transform ? transform(value) : value;\n }\n return acc;\n }, {}) as PathState;\n}\n\nexport const parseHref = (href: string): NavigationState => {\n const parsedUrl = new URL(href);\n const pathnameState = parsePath(parsedUrl.pathname);\n return {\n ...pathnameState,\n search: parsedUrl.search.substring(1),\n hash: parsedUrl.hash.substring(1),\n } as NavigationState\n}\n\nconst stripSlashPrefix = (s: string): string => s.startsWith('/') ? s.substring(1) : s;\n\nexport const constructUrl = (outerHref:string, navigationState: NavigationState): string => {\n const path = PATH_SEGMENTS.map(({ name }) => {\n let value = navigationState[name];\n return stripSlashPrefix(value ?? '');\n }).join('/');\n const host = getOuterHostname(outerHref);\n let url = `${host}/${path}`\n if (navigationState.search) {\n url += '?' + navigationState.search\n }\n if (navigationState.hash) {\n url += '#' + navigationState.hash\n }\n return url;\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAGnB,MAAM,eAAe;
|
|
1
|
+
{"version":3,"sources":["../src/urlUtils.ts"],"sourcesContent":["import { joinPaths } from \"./pathUtils\";\nimport { NavigationState, PathState } from \"./TinkerableContext\";\n\nexport const FILES_PREFIX = '/files';\n\n/**\n * Mount point of the Git repository inside the sandbox filesystem. The sandbox\n * fs is rooted at `/` (so apps can reach dynamic mounts like `/firestore`), with\n * the repo mounted here. URL subpaths are repo-relative, so the file router\n * resolves them under `APP_ROOT`.\n */\nexport const APP_ROOT = '/app';\n\n/** Resolve a repo-relative path (e.g. a URL subpath) to its absolute sandbox path. */\nexport const underAppRoot = (repoRelativePath: string): string =>\n joinPaths(APP_ROOT, repoRelativePath);\n\nexport const getOuterHostname = (outerHref:string) => {\n const url = new URL(outerHref);\n return `${url.protocol}//${url.hostname}`;\n}\n\nexport const getSearchParams = (search?: string): Record<string, string> => Object.fromEntries(\n [...(new URLSearchParams(search ?? window.location.search).entries())]);\n\n\nexport const parseTarget = (target: string, navigation: NavigationState): NavigationState => {\n const newNavigation = { ...navigation };\n let [prehash, hash] = target.split(\"#\")\n if (prehash) {\n let [path, search] = prehash.split(\"?\")\n if (path) {\n newNavigation.sandboxPath = path\n }\n newNavigation.search = search ? search : '';\n }\n newNavigation.hash = hash ? hash : '';\n return newNavigation\n}\n\n\nexport const maybeParseUrl = (str: string): URL | null => {\n try {\n return new URL(str);\n } catch (_) {\n return null;\n }\n}\n\nexport const isAbsolutePath = (sandboxPath: string) => sandboxPath.startsWith('/');\n\nexport const repositoryPrefixURL = (outerHref:string, navigationState: NavigationState) => constructUrl(outerHref, {\n ...navigationState,\n sandboxPath: ''\n });\n\nexport const constructOuterUrl = (previousOuterHref:string, sandboxTarget:string, navigationState: NavigationState, addFilesPrefix=true):string => {\n if (isAbsolutePath(sandboxTarget)) {\n return constructUrl(\n previousOuterHref,\n {\n ...navigationState,\n sandboxPath: addFilesPrefix ? joinPaths(FILES_PREFIX, sandboxTarget) : sandboxTarget\n })\n }\n return (\n new URL(\n sandboxTarget,\n constructUrl(\n previousOuterHref,\n navigationState\n )\n )\n ).toString();\n}\n\nexport const isInternalHref = (outerHref:string, target: string, navigationState: NavigationState) => {\n const parsedUrl = maybeParseUrl(target);\n if (parsedUrl) {\n return target.startsWith(repositoryPrefixURL(outerHref, navigationState));\n }\n // if target is not a valid URL, then assume it's relative.\n return true;\n}\n\nexport type PathSegment = {\n name: string,\n pattern: string,\n transform?: (pathSegment: string) => string,\n // When true, the leading slash that delimits this segment is optional, so the\n // whole `/segment` group can be absent. Used for the trailing sandboxPath:\n // an outer href of `/mode/provider/namespace/repository/ref` (no trailing\n // slash, no sub-path) must still parse, otherwise the regex matches nothing\n // and every segment comes back empty.\n optionalLeadingSlash?: boolean\n}\n\nconst PATH_SEGMENTS: PathSegment[] = [\n { name: 'mode', pattern: '\\\\w+' },\n { name: 'provider', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'namespace', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'repository', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'ref', pattern: '[a-zA-Z0-9-_]+' },\n { name: 'sandboxPath', pattern: '.*', transform: s => `/${s}`, optionalLeadingSlash: true }\n];\n\nconst OUTER_HREF_REGEXP = new RegExp(\n '^' +\n PATH_SEGMENTS.map(({ name, pattern, optionalLeadingSlash }) =>\n optionalLeadingSlash\n ? `(?:\\/(?<${name}>${pattern}))?`\n : `\\/(?<${name}>${pattern})`\n ).join('') +\n \"$\"\n);\n\n\nexport const parsePath = (pathname: string): PathState => {\n const matchResults = pathname.match(OUTER_HREF_REGEXP)?.groups ?? {};\n return PATH_SEGMENTS.reduce((acc: Partial<PathState>, { name, transform }: PathSegment) => {\n let value: string | undefined = undefined;\n if (name in matchResults) {\n value = matchResults[name];\n }\n if (!value) {\n // fall back to default value if var not present in\n value = '';\n }\n if (typeof value === 'string') {\n acc[name] = transform ? transform(value) : value;\n }\n return acc;\n }, {}) as PathState;\n}\n\nexport const parseHref = (href: string): NavigationState => {\n const parsedUrl = new URL(href);\n const pathnameState = parsePath(parsedUrl.pathname);\n return {\n ...pathnameState,\n search: parsedUrl.search.substring(1),\n hash: parsedUrl.hash.substring(1),\n } as NavigationState\n}\n\nconst stripSlashPrefix = (s: string): string => s.startsWith('/') ? s.substring(1) : s;\n\nexport const constructUrl = (outerHref:string, navigationState: NavigationState): string => {\n const path = PATH_SEGMENTS.map(({ name }) => {\n let value = navigationState[name];\n return stripSlashPrefix(value ?? '');\n }).join('/');\n const host = getOuterHostname(outerHref);\n let url = `${host}/${path}`\n if (navigationState.search) {\n url += '?' + navigationState.search\n }\n if (navigationState.hash) {\n url += '#' + navigationState.hash\n }\n return url;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED