@immediately-run/sdk 0.15.0 → 0.17.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.
Files changed (122) hide show
  1. package/README.md +27 -3
  2. package/dist/MDXProvider.cjs.map +1 -1
  3. package/dist/MDXProvider.d.cts +4 -0
  4. package/dist/MDXProvider.d.ts +4 -0
  5. package/dist/MDXProvider.js.map +1 -1
  6. package/dist/RoutingSpec.cjs.map +1 -1
  7. package/dist/RoutingSpec.d.cts +20 -3
  8. package/dist/RoutingSpec.d.ts +20 -3
  9. package/dist/auth.cjs.map +1 -1
  10. package/dist/auth.d.cts +2 -0
  11. package/dist/auth.d.ts +2 -0
  12. package/dist/auth.js.map +1 -1
  13. package/dist/boot.cjs +17 -7
  14. package/dist/boot.cjs.map +1 -1
  15. package/dist/boot.d.cts +28 -4
  16. package/dist/boot.d.ts +28 -4
  17. package/dist/boot.js +16 -7
  18. package/dist/boot.js.map +1 -1
  19. package/dist/components/Include.cjs.map +1 -1
  20. package/dist/components/Include.d.cts +7 -0
  21. package/dist/components/Include.d.ts +7 -0
  22. package/dist/components/Include.js.map +1 -1
  23. package/dist/components/MDXComponents.cjs.map +1 -1
  24. package/dist/components/MDXComponents.d.cts +6 -0
  25. package/dist/components/MDXComponents.d.ts +6 -0
  26. package/dist/components/MDXComponents.js.map +1 -1
  27. package/dist/components/Routes.cjs +59 -0
  28. package/dist/components/Routes.cjs.map +1 -0
  29. package/dist/components/Routes.d.cts +34 -0
  30. package/dist/components/Routes.d.ts +34 -0
  31. package/dist/components/Routes.js +34 -0
  32. package/dist/components/Routes.js.map +1 -0
  33. package/dist/contribute.cjs.map +1 -1
  34. package/dist/contribute.d.cts +2 -0
  35. package/dist/contribute.d.ts +2 -0
  36. package/dist/contribute.js.map +1 -1
  37. package/dist/debug.cjs +168 -0
  38. package/dist/debug.cjs.map +1 -0
  39. package/dist/debug.d.cts +22 -0
  40. package/dist/debug.d.ts +22 -0
  41. package/dist/debug.js +141 -0
  42. package/dist/debug.js.map +1 -0
  43. package/dist/diagnostics.cjs.map +1 -1
  44. package/dist/diagnostics.d.cts +3 -0
  45. package/dist/diagnostics.d.ts +3 -0
  46. package/dist/diagnostics.js.map +1 -1
  47. package/dist/formFactor.cjs.map +1 -1
  48. package/dist/formFactor.d.cts +2 -0
  49. package/dist/formFactor.d.ts +2 -0
  50. package/dist/formFactor.js.map +1 -1
  51. package/dist/hooks.cjs +27 -28
  52. package/dist/hooks.cjs.map +1 -1
  53. package/dist/hooks.d.cts +39 -4
  54. package/dist/hooks.d.ts +39 -4
  55. package/dist/hooks.js +27 -29
  56. package/dist/hooks.js.map +1 -1
  57. package/dist/index.cjs +6 -0
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.d.cts +7 -4
  60. package/dist/index.d.ts +7 -4
  61. package/dist/index.js +3 -0
  62. package/dist/index.js.map +1 -1
  63. package/dist/irMarkers.cjs.map +1 -1
  64. package/dist/irMarkers.d.cts +1 -0
  65. package/dist/irMarkers.d.ts +1 -0
  66. package/dist/irMarkers.js.map +1 -1
  67. package/dist/llm.cjs.map +1 -1
  68. package/dist/llm.d.cts +5 -0
  69. package/dist/llm.d.ts +5 -0
  70. package/dist/llm.js.map +1 -1
  71. package/dist/loading.cjs +186 -0
  72. package/dist/loading.cjs.map +1 -0
  73. package/dist/loading.d.cts +48 -0
  74. package/dist/loading.d.ts +48 -0
  75. package/dist/loading.js +162 -0
  76. package/dist/loading.js.map +1 -0
  77. package/dist/mounts.cjs.map +1 -1
  78. package/dist/mounts.d.cts +3 -1
  79. package/dist/mounts.d.ts +3 -1
  80. package/dist/mounts.js.map +1 -1
  81. package/dist/netFetch.cjs.map +1 -1
  82. package/dist/netFetch.d.cts +2 -0
  83. package/dist/netFetch.d.ts +2 -0
  84. package/dist/netFetch.js.map +1 -1
  85. package/dist/onFsChange.cjs.map +1 -1
  86. package/dist/onFsChange.d.cts +1 -0
  87. package/dist/onFsChange.d.ts +1 -0
  88. package/dist/onFsChange.js.map +1 -1
  89. package/dist/protocolStream.cjs.map +1 -1
  90. package/dist/protocolStream.d.cts +3 -0
  91. package/dist/protocolStream.d.ts +3 -0
  92. package/dist/protocolStream.js.map +1 -1
  93. package/dist/ready.cjs.map +1 -1
  94. package/dist/ready.d.cts +7 -0
  95. package/dist/ready.d.ts +7 -0
  96. package/dist/ready.js.map +1 -1
  97. package/dist/routeMatch.cjs +72 -0
  98. package/dist/routeMatch.cjs.map +1 -0
  99. package/dist/routeMatch.d.cts +19 -0
  100. package/dist/routeMatch.d.ts +19 -0
  101. package/dist/routeMatch.js +46 -0
  102. package/dist/routeMatch.js.map +1 -0
  103. package/dist/routing.cjs +35 -14
  104. package/dist/routing.cjs.map +1 -1
  105. package/dist/routing.d.cts +33 -4
  106. package/dist/routing.d.ts +33 -4
  107. package/dist/routing.js +32 -14
  108. package/dist/routing.js.map +1 -1
  109. package/dist/runtime.cjs.map +1 -1
  110. package/dist/runtime.d.cts +1 -0
  111. package/dist/runtime.d.ts +1 -0
  112. package/dist/runtime.js.map +1 -1
  113. package/dist/sandboxTypes.cjs.map +1 -1
  114. package/dist/sandboxTypes.d.cts +30 -7
  115. package/dist/sandboxTypes.d.ts +30 -7
  116. package/dist/version.cjs +1 -1
  117. package/dist/version.cjs.map +1 -1
  118. package/dist/version.d.cts +1 -1
  119. package/dist/version.d.ts +1 -1
  120. package/dist/version.js +1 -1
  121. package/dist/version.js.map +1 -1
  122. package/package.json +6 -2
@@ -4,14 +4,21 @@ import { EvaluationContext } from '../sandboxTypes.js';
4
4
  import { defaultLoadingComponent, defaultErrorComponent } from './defaults.js';
5
5
  import 'react-error-boundary';
6
6
 
7
+ /** The value exposed on {@link RenderExportedComponentContext}: the evaluation
8
+ * context of the module {@link Include} resolved. */
7
9
  type RenderFileContextType = {
8
10
  evaluationContext: EvaluationContext;
9
11
  };
12
+ /** Context carrying the included module's {@link EvaluationContext} to its subtree. */
10
13
  declare const RenderExportedComponentContext: react.Context<RenderFileContextType | null>;
14
+ /** Low-level: render one export of an already-resolving module evaluation. Most
15
+ * code should use {@link Include}, which resolves the module and adds Suspense. */
11
16
  declare const RenderExportedComponent: ({ evaluationContextPromise, exportedSymbol, }: {
12
17
  evaluationContextPromise: Promise<EvaluationContext>;
13
18
  exportedSymbol: string;
14
19
  }) => react_jsx_runtime.JSX.Element;
20
+ /** Render another repo file's exported component inline, resolving + evaluating it
21
+ * through the module cache (with Suspense + an error boundary). */
15
22
  declare const Include: ({ filename, exportedSymbol, LoadingComponent, ErrorComponent, baseModule, }: {
16
23
  filename: string;
17
24
  exportedSymbol?: string;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Include.tsx"],"sourcesContent":["import { Suspense, createContext, use } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\n\nimport { ModuleCacheContext } from '../moduleCache';\nimport { EvaluationContext } from '../sandboxTypes';\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\nexport type RenderFileContextType = {\n evaluationContext: EvaluationContext;\n};\n\nexport const RenderExportedComponentContext = createContext<RenderFileContextType | null>(null);\n\nexport const RenderExportedComponent = ({\n evaluationContextPromise,\n exportedSymbol = 'default',\n}: {\n evaluationContextPromise: Promise<EvaluationContext>;\n exportedSymbol: string;\n}) => {\n const evaluationContext = use(evaluationContextPromise);\n // TODO: handle case where exported symbol not found.\n const Component = exportedSymbol === '*' ? evaluationContext.exports : evaluationContext.exports[exportedSymbol];\n return (\n <RenderExportedComponentContext value={{ evaluationContext }}>\n <Component />\n </RenderExportedComponentContext>\n );\n};\n\nexport const Include = ({\n filename,\n exportedSymbol = 'default',\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n baseModule,\n}: {\n filename: string;\n exportedSymbol?: string;\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n baseModule?: EvaluationContext;\n}) => {\n const moduleCache = use(ModuleCacheContext);\n // @ts-ignore\n const evaluationContextPromise = moduleCache!.getEvaluationContext(filename, baseModule ?? module);\n return (\n <ErrorBoundary fallbackRender={ErrorComponent}>\n <Suspense fallback={<LoadingComponent />}>\n <RenderExportedComponent evaluationContextPromise={evaluationContextPromise} exportedSymbol={exportedSymbol} />\n </Suspense>\n </ErrorBoundary>\n );\n};\n"],"mappings":"AAyBM;AAzBN,SAAS,UAAU,eAAe,WAAW;AAC7C,SAAS,qBAAqB;AAE9B,SAAS,0BAA0B;AAEnC,SAAS,uBAAuB,+BAA+B;AAMxD,MAAM,iCAAiC,cAA4C,IAAI;AAEvF,MAAM,0BAA0B,CAAC;AAAA,EACtC;AAAA,EACA,iBAAiB;AACnB,MAGM;AACJ,QAAM,oBAAoB,IAAI,wBAAwB;AAEtD,QAAM,YAAY,mBAAmB,MAAM,kBAAkB,UAAU,kBAAkB,QAAQ,cAAc;AAC/G,SACE,oBAAC,kCAA+B,OAAO,EAAE,kBAAkB,GACzD,8BAAC,aAAU,GACb;AAEJ;AAEO,MAAM,UAAU,CAAC;AAAA,EACtB;AAAA,EACA,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB;AACF,MAMM;AACJ,QAAM,cAAc,IAAI,kBAAkB;AAE1C,QAAM,2BAA2B,YAAa,qBAAqB,UAAU,cAAc,MAAM;AACjG,SACE,oBAAC,iBAAc,gBAAgB,gBAC7B,8BAAC,YAAS,UAAU,oBAAC,oBAAiB,GACpC,8BAAC,2BAAwB,0BAAoD,gBAAgC,GAC/G,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/Include.tsx"],"sourcesContent":["import { Suspense, createContext, use } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\n\nimport { ModuleCacheContext } from '../moduleCache';\nimport { EvaluationContext } from '../sandboxTypes';\nimport { defaultErrorComponent, defaultLoadingComponent } from './defaults';\n\n/** The value exposed on {@link RenderExportedComponentContext}: the evaluation\n * context of the module {@link Include} resolved. */\nexport type RenderFileContextType = {\n evaluationContext: EvaluationContext;\n};\n\n/** Context carrying the included module's {@link EvaluationContext} to its subtree. */\nexport const RenderExportedComponentContext = createContext<RenderFileContextType | null>(null);\n\n/** Low-level: render one export of an already-resolving module evaluation. Most\n * code should use {@link Include}, which resolves the module and adds Suspense. */\nexport const RenderExportedComponent = ({\n evaluationContextPromise,\n exportedSymbol = 'default',\n}: {\n evaluationContextPromise: Promise<EvaluationContext>;\n exportedSymbol: string;\n}) => {\n const evaluationContext = use(evaluationContextPromise);\n // TODO: handle case where exported symbol not found.\n const Component = exportedSymbol === '*' ? evaluationContext.exports : evaluationContext.exports[exportedSymbol];\n return (\n <RenderExportedComponentContext value={{ evaluationContext }}>\n <Component />\n </RenderExportedComponentContext>\n );\n};\n\n/** Render another repo file's exported component inline, resolving + evaluating it\n * through the module cache (with Suspense + an error boundary). */\nexport const Include = ({\n filename,\n exportedSymbol = 'default',\n LoadingComponent = defaultLoadingComponent,\n ErrorComponent = defaultErrorComponent,\n baseModule,\n}: {\n filename: string;\n exportedSymbol?: string;\n LoadingComponent?: typeof defaultLoadingComponent;\n ErrorComponent?: typeof defaultErrorComponent;\n baseModule?: EvaluationContext;\n}) => {\n const moduleCache = use(ModuleCacheContext);\n // @ts-ignore\n const evaluationContextPromise = moduleCache!.getEvaluationContext(filename, baseModule ?? module);\n return (\n <ErrorBoundary fallbackRender={ErrorComponent}>\n <Suspense fallback={<LoadingComponent />}>\n <RenderExportedComponent evaluationContextPromise={evaluationContextPromise} exportedSymbol={exportedSymbol} />\n </Suspense>\n </ErrorBoundary>\n );\n};\n"],"mappings":"AA8BM;AA9BN,SAAS,UAAU,eAAe,WAAW;AAC7C,SAAS,qBAAqB;AAE9B,SAAS,0BAA0B;AAEnC,SAAS,uBAAuB,+BAA+B;AASxD,MAAM,iCAAiC,cAA4C,IAAI;AAIvF,MAAM,0BAA0B,CAAC;AAAA,EACtC;AAAA,EACA,iBAAiB;AACnB,MAGM;AACJ,QAAM,oBAAoB,IAAI,wBAAwB;AAEtD,QAAM,YAAY,mBAAmB,MAAM,kBAAkB,UAAU,kBAAkB,QAAQ,cAAc;AAC/G,SACE,oBAAC,kCAA+B,OAAO,EAAE,kBAAkB,GACzD,8BAAC,aAAU,GACb;AAEJ;AAIO,MAAM,UAAU,CAAC;AAAA,EACtB;AAAA,EACA,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB;AACF,MAMM;AACJ,QAAM,cAAc,IAAI,kBAAkB;AAE1C,QAAM,2BAA2B,YAAa,qBAAqB,UAAU,cAAc,MAAM;AACjG,SACE,oBAAC,iBAAc,gBAAgB,gBAC7B,8BAAC,YAAS,UAAU,oBAAC,oBAAiB,GACpC,8BAAC,2BAAwB,0BAAoD,gBAAgC,GAC/G,GACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/MDXComponents.tsx"],"sourcesContent":["import { ReactNode, use, useCallback } from 'react';\nimport { navigate } from '../routing';\nimport { TinkerableContext } from '../TinkerableContext';\nimport { constructOuterUrl, constructUrl, isInternalHref, repositoryPrefixURL } from '../urlUtils';\n\nexport const InternalLink = ({\n href,\n children,\n ...props\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const clickHandler = useCallback(\n (e: any) => {\n if (href) {\n e.preventDefault();\n navigate(href);\n }\n },\n [href]\n );\n return (\n <a href={href} onClick={clickHandler} {...props}>\n {children}\n </a>\n );\n};\n\nexport const Link = ({\n href,\n children,\n ...properties\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const { outerHref, navigationState } = use(TinkerableContext);\n if (href && isInternalHref(outerHref, href, navigationState)) {\n const targetHref = constructOuterUrl(outerHref, href, navigationState);\n return (\n <InternalLink href={targetHref} {...properties}>\n {children}\n </InternalLink>\n );\n } else {\n // create a regular link to external resource\n return <a {...{ href, ...properties }}>{children}</a>;\n }\n};\n\nexport const DEFAULT_MDX_COMPONENTS = {\n a({\n href,\n children,\n ...properties\n }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) {\n return (\n <Link href={href} {...properties}>\n {children}\n </Link>\n );\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBI;AApBJ,mBAA4C;AAC5C,qBAAyB;AACzB,+BAAkC;AAClC,sBAAqF;AAE9E,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,mBAAe;AAAA,IACnB,CAAC,MAAW;AACV,UAAI,MAAM;AACR,UAAE,eAAe;AACjB,qCAAS,IAAI;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AACA,SACE,4CAAC,OAAE,MAAY,SAAS,cAAe,GAAG,OACvC,UACH;AAEJ;AAEO,MAAM,OAAO,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,EAAE,WAAW,gBAAgB,QAAI,kBAAI,0CAAiB;AAC5D,MAAI,YAAQ,gCAAe,WAAW,MAAM,eAAe,GAAG;AAC5D,UAAM,iBAAa,mCAAkB,WAAW,MAAM,eAAe;AACrE,WACE,4CAAC,gBAAa,MAAM,YAAa,GAAG,YACjC,UACH;AAAA,EAEJ,OAAO;AAEL,WAAO,4CAAC,OAAG,GAAG,EAAE,MAAM,GAAG,WAAW,GAAI,UAAS;AAAA,EACnD;AACF;AAEO,MAAM,yBAAyB;AAAA,EACpC,EAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAA8F;AAC5F,WACE,4CAAC,QAAK,MAAa,GAAG,YACnB,UACH;AAAA,EAEJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/components/MDXComponents.tsx"],"sourcesContent":["import { ReactNode, use, useCallback } from 'react';\nimport { navigate } from '../routing';\nimport { TinkerableContext } from '../TinkerableContext';\nimport { constructOuterUrl, constructUrl, isInternalHref, repositoryPrefixURL } from '../urlUtils';\n\n/** An `<a>` that performs in-sandbox navigation on click (prevents the default\n * full-page load and routes via {@link navigate}). */\nexport const InternalLink = ({\n href,\n children,\n ...props\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const clickHandler = useCallback(\n (e: any) => {\n if (href) {\n e.preventDefault();\n navigate(href);\n }\n },\n [href]\n );\n return (\n <a href={href} onClick={clickHandler} {...props}>\n {children}\n </a>\n );\n};\n\n/** A link that routes same-app hrefs through the sandbox router (as an\n * {@link InternalLink}) and renders external hrefs as a plain `<a>`. */\nexport const Link = ({\n href,\n children,\n ...properties\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const { outerHref, navigationState } = use(TinkerableContext);\n if (href && isInternalHref(outerHref, href, navigationState)) {\n const targetHref = constructOuterUrl(outerHref, href, navigationState);\n return (\n <InternalLink href={targetHref} {...properties}>\n {children}\n </InternalLink>\n );\n } else {\n // create a regular link to external resource\n return <a {...{ href, ...properties }}>{children}</a>;\n }\n};\n\n/** Default MDX component overrides: routes `<a>` through {@link Link} so links in\n * MDX prose navigate within the app. Passed to {@link MDXProvider} by `boot`. */\nexport const DEFAULT_MDX_COMPONENTS = {\n a({\n href,\n children,\n ...properties\n }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) {\n return (\n <Link href={href} {...properties}>\n {children}\n </Link>\n );\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBI;AAtBJ,mBAA4C;AAC5C,qBAAyB;AACzB,+BAAkC;AAClC,sBAAqF;AAI9E,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,mBAAe;AAAA,IACnB,CAAC,MAAW;AACV,UAAI,MAAM;AACR,UAAE,eAAe;AACjB,qCAAS,IAAI;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AACA,SACE,4CAAC,OAAE,MAAY,SAAS,cAAe,GAAG,OACvC,UACH;AAEJ;AAIO,MAAM,OAAO,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,EAAE,WAAW,gBAAgB,QAAI,kBAAI,0CAAiB;AAC5D,MAAI,YAAQ,gCAAe,WAAW,MAAM,eAAe,GAAG;AAC5D,UAAM,iBAAa,mCAAkB,WAAW,MAAM,eAAe;AACrE,WACE,4CAAC,gBAAa,MAAM,YAAa,GAAG,YACjC,UACH;AAAA,EAEJ,OAAO;AAEL,WAAO,4CAAC,OAAG,GAAG,EAAE,MAAM,GAAG,WAAW,GAAI,UAAS;AAAA,EACnD;AACF;AAIO,MAAM,yBAAyB;AAAA,EACpC,EAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAA8F;AAC5F,WACE,4CAAC,QAAK,MAAa,GAAG,YACnB,UACH;AAAA,EAEJ;AACF;","names":[]}
@@ -1,8 +1,14 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
 
4
+ /** An `<a>` that performs in-sandbox navigation on click (prevents the default
5
+ * full-page load and routes via {@link navigate}). */
4
6
  declare const InternalLink: ({ href, children, ...props }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => ReactNode;
7
+ /** A link that routes same-app hrefs through the sandbox router (as an
8
+ * {@link InternalLink}) and renders external hrefs as a plain `<a>`. */
5
9
  declare const Link: ({ href, children, ...properties }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => ReactNode;
10
+ /** Default MDX component overrides: routes `<a>` through {@link Link} so links in
11
+ * MDX prose navigate within the app. Passed to {@link MDXProvider} by `boot`. */
6
12
  declare const DEFAULT_MDX_COMPONENTS: {
7
13
  a({ href, children, ...properties }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): react_jsx_runtime.JSX.Element;
8
14
  };
@@ -1,8 +1,14 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
 
4
+ /** An `<a>` that performs in-sandbox navigation on click (prevents the default
5
+ * full-page load and routes via {@link navigate}). */
4
6
  declare const InternalLink: ({ href, children, ...props }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => ReactNode;
7
+ /** A link that routes same-app hrefs through the sandbox router (as an
8
+ * {@link InternalLink}) and renders external hrefs as a plain `<a>`. */
5
9
  declare const Link: ({ href, children, ...properties }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => ReactNode;
10
+ /** Default MDX component overrides: routes `<a>` through {@link Link} so links in
11
+ * MDX prose navigate within the app. Passed to {@link MDXProvider} by `boot`. */
6
12
  declare const DEFAULT_MDX_COMPONENTS: {
7
13
  a({ href, children, ...properties }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): react_jsx_runtime.JSX.Element;
8
14
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/MDXComponents.tsx"],"sourcesContent":["import { ReactNode, use, useCallback } from 'react';\nimport { navigate } from '../routing';\nimport { TinkerableContext } from '../TinkerableContext';\nimport { constructOuterUrl, constructUrl, isInternalHref, repositoryPrefixURL } from '../urlUtils';\n\nexport const InternalLink = ({\n href,\n children,\n ...props\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const clickHandler = useCallback(\n (e: any) => {\n if (href) {\n e.preventDefault();\n navigate(href);\n }\n },\n [href]\n );\n return (\n <a href={href} onClick={clickHandler} {...props}>\n {children}\n </a>\n );\n};\n\nexport const Link = ({\n href,\n children,\n ...properties\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const { outerHref, navigationState } = use(TinkerableContext);\n if (href && isInternalHref(outerHref, href, navigationState)) {\n const targetHref = constructOuterUrl(outerHref, href, navigationState);\n return (\n <InternalLink href={targetHref} {...properties}>\n {children}\n </InternalLink>\n );\n } else {\n // create a regular link to external resource\n return <a {...{ href, ...properties }}>{children}</a>;\n }\n};\n\nexport const DEFAULT_MDX_COMPONENTS = {\n a({\n href,\n children,\n ...properties\n }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) {\n return (\n <Link href={href} {...properties}>\n {children}\n </Link>\n );\n },\n};\n"],"mappings":"AAoBI;AApBJ,SAAoB,KAAK,mBAAmB;AAC5C,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,mBAAiC,sBAA2C;AAE9E,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,eAAe;AAAA,IACnB,CAAC,MAAW;AACV,UAAI,MAAM;AACR,UAAE,eAAe;AACjB,iBAAS,IAAI;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AACA,SACE,oBAAC,OAAE,MAAY,SAAS,cAAe,GAAG,OACvC,UACH;AAEJ;AAEO,MAAM,OAAO,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,EAAE,WAAW,gBAAgB,IAAI,IAAI,iBAAiB;AAC5D,MAAI,QAAQ,eAAe,WAAW,MAAM,eAAe,GAAG;AAC5D,UAAM,aAAa,kBAAkB,WAAW,MAAM,eAAe;AACrE,WACE,oBAAC,gBAAa,MAAM,YAAa,GAAG,YACjC,UACH;AAAA,EAEJ,OAAO;AAEL,WAAO,oBAAC,OAAG,GAAG,EAAE,MAAM,GAAG,WAAW,GAAI,UAAS;AAAA,EACnD;AACF;AAEO,MAAM,yBAAyB;AAAA,EACpC,EAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAA8F;AAC5F,WACE,oBAAC,QAAK,MAAa,GAAG,YACnB,UACH;AAAA,EAEJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/components/MDXComponents.tsx"],"sourcesContent":["import { ReactNode, use, useCallback } from 'react';\nimport { navigate } from '../routing';\nimport { TinkerableContext } from '../TinkerableContext';\nimport { constructOuterUrl, constructUrl, isInternalHref, repositoryPrefixURL } from '../urlUtils';\n\n/** An `<a>` that performs in-sandbox navigation on click (prevents the default\n * full-page load and routes via {@link navigate}). */\nexport const InternalLink = ({\n href,\n children,\n ...props\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const clickHandler = useCallback(\n (e: any) => {\n if (href) {\n e.preventDefault();\n navigate(href);\n }\n },\n [href]\n );\n return (\n <a href={href} onClick={clickHandler} {...props}>\n {children}\n </a>\n );\n};\n\n/** A link that routes same-app hrefs through the sandbox router (as an\n * {@link InternalLink}) and renders external hrefs as a plain `<a>`. */\nexport const Link = ({\n href,\n children,\n ...properties\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n const { outerHref, navigationState } = use(TinkerableContext);\n if (href && isInternalHref(outerHref, href, navigationState)) {\n const targetHref = constructOuterUrl(outerHref, href, navigationState);\n return (\n <InternalLink href={targetHref} {...properties}>\n {children}\n </InternalLink>\n );\n } else {\n // create a regular link to external resource\n return <a {...{ href, ...properties }}>{children}</a>;\n }\n};\n\n/** Default MDX component overrides: routes `<a>` through {@link Link} so links in\n * MDX prose navigate within the app. Passed to {@link MDXProvider} by `boot`. */\nexport const DEFAULT_MDX_COMPONENTS = {\n a({\n href,\n children,\n ...properties\n }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) {\n return (\n <Link href={href} {...properties}>\n {children}\n </Link>\n );\n },\n};\n"],"mappings":"AAsBI;AAtBJ,SAAoB,KAAK,mBAAmB;AAC5C,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,mBAAiC,sBAA2C;AAI9E,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,eAAe;AAAA,IACnB,CAAC,MAAW;AACV,UAAI,MAAM;AACR,UAAE,eAAe;AACjB,iBAAS,IAAI;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AACA,SACE,oBAAC,OAAE,MAAY,SAAS,cAAe,GAAG,OACvC,UACH;AAEJ;AAIO,MAAM,OAAO,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,EAAE,WAAW,gBAAgB,IAAI,IAAI,iBAAiB;AAC5D,MAAI,QAAQ,eAAe,WAAW,MAAM,eAAe,GAAG;AAC5D,UAAM,aAAa,kBAAkB,WAAW,MAAM,eAAe;AACrE,WACE,oBAAC,gBAAa,MAAM,YAAa,GAAG,YACjC,UACH;AAAA,EAEJ,OAAO;AAEL,WAAO,oBAAC,OAAG,GAAG,EAAE,MAAM,GAAG,WAAW,GAAI,UAAS;AAAA,EACnD;AACF;AAIO,MAAM,yBAAyB;AAAA,EACpC,EAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAA8F;AAC5F,WACE,oBAAC,QAAK,MAAa,GAAG,YACnB,UACH;AAAA,EAEJ;AACF;","names":[]}
@@ -0,0 +1,59 @@
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 Routes_exports = {};
20
+ __export(Routes_exports, {
21
+ Route: () => Route,
22
+ Routes: () => Routes
23
+ });
24
+ module.exports = __toCommonJS(Routes_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_react = require("react");
27
+ var import_TinkerableContext = require("../TinkerableContext");
28
+ var import_routeMatch = require("../routeMatch");
29
+ var import_routing = require("../routing");
30
+ const Route = (_props) => null;
31
+ const Routes = ({
32
+ children,
33
+ fallback = null
34
+ }) => {
35
+ const context = (0, import_react.use)(import_TinkerableContext.TinkerableContext);
36
+ const { sandboxPath } = context.navigationState;
37
+ for (const child of import_react.Children.toArray(children)) {
38
+ if (!(0, import_react.isValidElement)(child) || child.type !== Route) {
39
+ continue;
40
+ }
41
+ const { path, element, component, name } = child.props;
42
+ const params = (0, import_routeMatch.matchRoute)(path, sandboxPath);
43
+ if (params) {
44
+ const routingRule = { name, pattern: path, element, component };
45
+ const scoped = {
46
+ ...context,
47
+ navigationState: { ...context.navigationState, routingRule, pathParameters: params }
48
+ };
49
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TinkerableContext.TinkerableContext, { value: scoped, children: (0, import_routing.renderRoute)(routingRule, params) });
50
+ }
51
+ }
52
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback });
53
+ };
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ Route,
57
+ Routes
58
+ });
59
+ //# sourceMappingURL=Routes.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Routes.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Children, isValidElement, use } from 'react';\n\nimport { TinkerableContext } from '../TinkerableContext';\nimport type { RouteComponent, RoutingRule } from '../RoutingSpec';\nimport { matchRoute } from '../routeMatch';\nimport { renderRoute } from '../routing';\n\n/** Props for a {@link Route} declared inside {@link Routes}. */\nexport type RouteProps = {\n /** A path template (`/posts/:slug`, `/files/*`, `/`) or a raw RegExp. */\n path: string | RegExp;\n name?: string;\n /** Element to render; reads params via `useRouteParams()`. */\n element?: ReactNode;\n /** Component to render; receives matched params as a prop. */\n component?: RouteComponent;\n};\n\n/**\n * Declares a route. Rendered as a child of `<Routes>`, where it is read for its\n * props — it renders nothing on its own. Mounting a `<Route>` registers it;\n * unmounting (or conditionally not rendering it) removes it, which is how routes\n * become dynamic without a mutable registry.\n */\nexport const Route = (_props: RouteProps): null => null;\n\n/**\n * Resolves the active `sandboxPath` against its mounted `<Route>` children,\n * first-match-wins in render order, and renders the winner (or `fallback`). The\n * match scopes a nested context so `useRouteParams()` / `useRoute()` inside the\n * rendered route see this match. Use instead of (or nested within) a `boot`-time\n * `routingSpec`.\n */\nexport const Routes = ({\n children,\n fallback = null,\n}: {\n children?: ReactNode;\n fallback?: ReactNode;\n}) => {\n const context = use(TinkerableContext);\n const { sandboxPath } = context.navigationState;\n\n for (const child of Children.toArray(children)) {\n if (!isValidElement(child) || child.type !== Route) {\n continue;\n }\n const { path, element, component, name } = child.props as RouteProps;\n const params = matchRoute(path, sandboxPath);\n if (params) {\n const routingRule: RoutingRule = { name, pattern: path, element, component };\n const scoped = {\n ...context,\n navigationState: { ...context.navigationState, routingRule, pathParameters: params },\n };\n return (\n <TinkerableContext value={scoped}>\n {renderRoute(routingRule, params)}\n </TinkerableContext>\n );\n }\n }\n\n return <>{fallback}</>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDQ;AAxDR,mBAA8C;AAE9C,+BAAkC;AAElC,wBAA2B;AAC3B,qBAA4B;AAmBrB,MAAM,QAAQ,CAAC,WAA6B;AAS5C,MAAM,SAAS,CAAC;AAAA,EACrB;AAAA,EACA,WAAW;AACb,MAGM;AACJ,QAAM,cAAU,kBAAI,0CAAiB;AACrC,QAAM,EAAE,YAAY,IAAI,QAAQ;AAEhC,aAAW,SAAS,sBAAS,QAAQ,QAAQ,GAAG;AAC9C,QAAI,KAAC,6BAAe,KAAK,KAAK,MAAM,SAAS,OAAO;AAClD;AAAA,IACF;AACA,UAAM,EAAE,MAAM,SAAS,WAAW,KAAK,IAAI,MAAM;AACjD,UAAM,aAAS,8BAAW,MAAM,WAAW;AAC3C,QAAI,QAAQ;AACV,YAAM,cAA2B,EAAE,MAAM,SAAS,MAAM,SAAS,UAAU;AAC3E,YAAM,SAAS;AAAA,QACb,GAAG;AAAA,QACH,iBAAiB,EAAE,GAAG,QAAQ,iBAAiB,aAAa,gBAAgB,OAAO;AAAA,MACrF;AACA,aACE,4CAAC,8CAAkB,OAAO,QACvB,0CAAY,aAAa,MAAM,GAClC;AAAA,IAEJ;AAAA,EACF;AAEA,SAAO,2EAAG,oBAAS;AACrB;","names":[]}
@@ -0,0 +1,34 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { RouteComponent } from '../RoutingSpec.cjs';
4
+
5
+ /** Props for a {@link Route} declared inside {@link Routes}. */
6
+ type RouteProps = {
7
+ /** A path template (`/posts/:slug`, `/files/*`, `/`) or a raw RegExp. */
8
+ path: string | RegExp;
9
+ name?: string;
10
+ /** Element to render; reads params via `useRouteParams()`. */
11
+ element?: ReactNode;
12
+ /** Component to render; receives matched params as a prop. */
13
+ component?: RouteComponent;
14
+ };
15
+ /**
16
+ * Declares a route. Rendered as a child of `<Routes>`, where it is read for its
17
+ * props — it renders nothing on its own. Mounting a `<Route>` registers it;
18
+ * unmounting (or conditionally not rendering it) removes it, which is how routes
19
+ * become dynamic without a mutable registry.
20
+ */
21
+ declare const Route: (_props: RouteProps) => null;
22
+ /**
23
+ * Resolves the active `sandboxPath` against its mounted `<Route>` children,
24
+ * first-match-wins in render order, and renders the winner (or `fallback`). The
25
+ * match scopes a nested context so `useRouteParams()` / `useRoute()` inside the
26
+ * rendered route see this match. Use instead of (or nested within) a `boot`-time
27
+ * `routingSpec`.
28
+ */
29
+ declare const Routes: ({ children, fallback, }: {
30
+ children?: ReactNode;
31
+ fallback?: ReactNode;
32
+ }) => react_jsx_runtime.JSX.Element;
33
+
34
+ export { Route, type RouteProps, Routes };
@@ -0,0 +1,34 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { RouteComponent } from '../RoutingSpec.js';
4
+
5
+ /** Props for a {@link Route} declared inside {@link Routes}. */
6
+ type RouteProps = {
7
+ /** A path template (`/posts/:slug`, `/files/*`, `/`) or a raw RegExp. */
8
+ path: string | RegExp;
9
+ name?: string;
10
+ /** Element to render; reads params via `useRouteParams()`. */
11
+ element?: ReactNode;
12
+ /** Component to render; receives matched params as a prop. */
13
+ component?: RouteComponent;
14
+ };
15
+ /**
16
+ * Declares a route. Rendered as a child of `<Routes>`, where it is read for its
17
+ * props — it renders nothing on its own. Mounting a `<Route>` registers it;
18
+ * unmounting (or conditionally not rendering it) removes it, which is how routes
19
+ * become dynamic without a mutable registry.
20
+ */
21
+ declare const Route: (_props: RouteProps) => null;
22
+ /**
23
+ * Resolves the active `sandboxPath` against its mounted `<Route>` children,
24
+ * first-match-wins in render order, and renders the winner (or `fallback`). The
25
+ * match scopes a nested context so `useRouteParams()` / `useRoute()` inside the
26
+ * rendered route see this match. Use instead of (or nested within) a `boot`-time
27
+ * `routingSpec`.
28
+ */
29
+ declare const Routes: ({ children, fallback, }: {
30
+ children?: ReactNode;
31
+ fallback?: ReactNode;
32
+ }) => react_jsx_runtime.JSX.Element;
33
+
34
+ export { Route, type RouteProps, Routes };
@@ -0,0 +1,34 @@
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
+ import { Children, isValidElement, use } from "react";
3
+ import { TinkerableContext } from "../TinkerableContext";
4
+ import { matchRoute } from "../routeMatch";
5
+ import { renderRoute } from "../routing";
6
+ const Route = (_props) => null;
7
+ const Routes = ({
8
+ children,
9
+ fallback = null
10
+ }) => {
11
+ const context = use(TinkerableContext);
12
+ const { sandboxPath } = context.navigationState;
13
+ for (const child of Children.toArray(children)) {
14
+ if (!isValidElement(child) || child.type !== Route) {
15
+ continue;
16
+ }
17
+ const { path, element, component, name } = child.props;
18
+ const params = matchRoute(path, sandboxPath);
19
+ if (params) {
20
+ const routingRule = { name, pattern: path, element, component };
21
+ const scoped = {
22
+ ...context,
23
+ navigationState: { ...context.navigationState, routingRule, pathParameters: params }
24
+ };
25
+ return /* @__PURE__ */ jsx(TinkerableContext, { value: scoped, children: renderRoute(routingRule, params) });
26
+ }
27
+ }
28
+ return /* @__PURE__ */ jsx(Fragment, { children: fallback });
29
+ };
30
+ export {
31
+ Route,
32
+ Routes
33
+ };
34
+ //# sourceMappingURL=Routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Routes.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Children, isValidElement, use } from 'react';\n\nimport { TinkerableContext } from '../TinkerableContext';\nimport type { RouteComponent, RoutingRule } from '../RoutingSpec';\nimport { matchRoute } from '../routeMatch';\nimport { renderRoute } from '../routing';\n\n/** Props for a {@link Route} declared inside {@link Routes}. */\nexport type RouteProps = {\n /** A path template (`/posts/:slug`, `/files/*`, `/`) or a raw RegExp. */\n path: string | RegExp;\n name?: string;\n /** Element to render; reads params via `useRouteParams()`. */\n element?: ReactNode;\n /** Component to render; receives matched params as a prop. */\n component?: RouteComponent;\n};\n\n/**\n * Declares a route. Rendered as a child of `<Routes>`, where it is read for its\n * props — it renders nothing on its own. Mounting a `<Route>` registers it;\n * unmounting (or conditionally not rendering it) removes it, which is how routes\n * become dynamic without a mutable registry.\n */\nexport const Route = (_props: RouteProps): null => null;\n\n/**\n * Resolves the active `sandboxPath` against its mounted `<Route>` children,\n * first-match-wins in render order, and renders the winner (or `fallback`). The\n * match scopes a nested context so `useRouteParams()` / `useRoute()` inside the\n * rendered route see this match. Use instead of (or nested within) a `boot`-time\n * `routingSpec`.\n */\nexport const Routes = ({\n children,\n fallback = null,\n}: {\n children?: ReactNode;\n fallback?: ReactNode;\n}) => {\n const context = use(TinkerableContext);\n const { sandboxPath } = context.navigationState;\n\n for (const child of Children.toArray(children)) {\n if (!isValidElement(child) || child.type !== Route) {\n continue;\n }\n const { path, element, component, name } = child.props as RouteProps;\n const params = matchRoute(path, sandboxPath);\n if (params) {\n const routingRule: RoutingRule = { name, pattern: path, element, component };\n const scoped = {\n ...context,\n navigationState: { ...context.navigationState, routingRule, pathParameters: params },\n };\n return (\n <TinkerableContext value={scoped}>\n {renderRoute(routingRule, params)}\n </TinkerableContext>\n );\n }\n }\n\n return <>{fallback}</>;\n};\n"],"mappings":"AAyDQ,SAOC,UAPD;AAxDR,SAAS,UAAU,gBAAgB,WAAW;AAE9C,SAAS,yBAAyB;AAElC,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAmBrB,MAAM,QAAQ,CAAC,WAA6B;AAS5C,MAAM,SAAS,CAAC;AAAA,EACrB;AAAA,EACA,WAAW;AACb,MAGM;AACJ,QAAM,UAAU,IAAI,iBAAiB;AACrC,QAAM,EAAE,YAAY,IAAI,QAAQ;AAEhC,aAAW,SAAS,SAAS,QAAQ,QAAQ,GAAG;AAC9C,QAAI,CAAC,eAAe,KAAK,KAAK,MAAM,SAAS,OAAO;AAClD;AAAA,IACF;AACA,UAAM,EAAE,MAAM,SAAS,WAAW,KAAK,IAAI,MAAM;AACjD,UAAM,SAAS,WAAW,MAAM,WAAW;AAC3C,QAAI,QAAQ;AACV,YAAM,cAA2B,EAAE,MAAM,SAAS,MAAM,SAAS,UAAU;AAC3E,YAAM,SAAS;AAAA,QACb,GAAG;AAAA,QACH,iBAAiB,EAAE,GAAG,QAAQ,iBAAiB,aAAa,gBAAgB,OAAO;AAAA,MACrF;AACA,aACE,oBAAC,qBAAkB,OAAO,QACvB,sBAAY,aAAa,MAAM,GAClC;AAAA,IAEJ;AAAA,EACF;AAEA,SAAO,gCAAG,oBAAS;AACrB;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/contribute.ts"],"sourcesContent":["// Contribute — stream a save (PR or direct commit) from app code\n// (UI_AS_APPS_SPEC §5.1, CONTRIBUTE_SPEC). The host runs the *existing*\n// contribution orchestrator and streams its stages back; this is the typed\n// front door over `protocolStream`.\n//\n// The OAuth token never reaches here — it stays on the host. The app passes a\n// commit message + save mode and watches stages go by; the host owns the token,\n// the GitHub API calls, and the user-facing consent.\nimport { protocolStream } from './protocolStream';\n\n/** The save strategy. `direct` requires the first-party `contribute:direct`\n * capability and a scarier consent line — a `contribute:any` app asking for it\n * is REJECTED (`forbidden`), never silently downgraded to a PR (threat T11). */\nexport type ContributeMode = 'pr' | 'direct';\n\n/** A stage emitted as the contribution runs. Mirrors the host orchestrator's\n * event union; carries progress metadata only — never the token or file blobs. */\nexport type ContributionEvent =\n | { stage: 'auth-check' }\n | { stage: 'diff-compute' }\n | { stage: 'permission-check' }\n | { stage: 'install-required'; targetOwner: string; targetRepo: string; installUrl: string }\n | { stage: 'conflict-check' }\n | { stage: 'fork-prepare'; forkOwner: string; alreadyExists: boolean }\n | { stage: 'upload-blob'; path: string; index: number; total: number }\n | { stage: 'create-tree' }\n | { stage: 'create-commit' }\n | { stage: 'create-branch'; branchName: string }\n | { stage: 'create-pr' }\n | { stage: 'pr-updated'; prNumber: number; prUrl: string; commitSha: string }\n | { stage: 'commit-pushed'; ref: string; commitSha: string }\n | { stage: 'switch-branch'; provider: 'github'; pushOwner: string; repository: string; branchName: string }\n | { stage: 'done'; prUrl?: string; prNumber?: number; commitSha: string }\n | { stage: 'warning'; message: string; details?: unknown }\n | { stage: 'error'; message: string; recoverable: boolean };\n\n/** The settled outcome (the stream's return value). */\nexport interface ContributionResult {\n prUrl?: string;\n prNumber?: number;\n commitSha: string;\n treeSha: string;\n branchName: string;\n mode: 'direct-commit' | 'new-branch-pr' | 'extend-existing';\n}\n\nexport interface ContributeOptions {\n /** The commit message / PR title. */\n commitMessage: string;\n /** `'pr'` (default) opens a PR; `'direct'` commits to the branch and needs\n * the first-party `contribute:direct` capability. */\n mode?: ContributeMode;\n /** Override the generated branch name (PR mode). */\n branchName?: string;\n}\n\n/**\n * Save the current working tree, streaming each stage.\n *\n * ```ts\n * for await (const ev of contribute({ commitMessage: 'Edit post' })) {\n * if (ev.stage === 'done') console.log(ev.prUrl);\n * }\n * ```\n *\n * Yields {@link ContributionEvent}s and returns a {@link ContributionResult}.\n * Throws a `StreamError` (`.code`) if the host rejects the request — notably\n * `forbidden` when a `contribute:any` app asks for `mode: 'direct'` (T11).\n */\nexport function contribute(\n opts: ContributeOptions\n): AsyncGenerator<ContributionEvent, ContributionResult, void> {\n return protocolStream<ContributionEvent, ContributionResult>('protocol-contribute', 'run', [opts]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,4BAA+B;AA6DxB,SAAS,WACd,MAC6D;AAC7D,aAAO,sCAAsD,uBAAuB,OAAO,CAAC,IAAI,CAAC;AACnG;","names":[]}
1
+ {"version":3,"sources":["../src/contribute.ts"],"sourcesContent":["// Contribute — stream a save (PR or direct commit) from app code\n// (UI_AS_APPS_SPEC §5.1, CONTRIBUTE_SPEC). The host runs the *existing*\n// contribution orchestrator and streams its stages back; this is the typed\n// front door over `protocolStream`.\n//\n// The OAuth token never reaches here — it stays on the host. The app passes a\n// commit message + save mode and watches stages go by; the host owns the token,\n// the GitHub API calls, and the user-facing consent.\nimport { protocolStream } from './protocolStream';\n\n/** The save strategy. `direct` requires the first-party `contribute:direct`\n * capability and a scarier consent line — a `contribute:any` app asking for it\n * is REJECTED (`forbidden`), never silently downgraded to a PR (threat T11). */\nexport type ContributeMode = 'pr' | 'direct';\n\n/** A stage emitted as the contribution runs. Mirrors the host orchestrator's\n * event union; carries progress metadata only — never the token or file blobs. */\nexport type ContributionEvent =\n | { stage: 'auth-check' }\n | { stage: 'diff-compute' }\n | { stage: 'permission-check' }\n | { stage: 'install-required'; targetOwner: string; targetRepo: string; installUrl: string }\n | { stage: 'conflict-check' }\n | { stage: 'fork-prepare'; forkOwner: string; alreadyExists: boolean }\n | { stage: 'upload-blob'; path: string; index: number; total: number }\n | { stage: 'create-tree' }\n | { stage: 'create-commit' }\n | { stage: 'create-branch'; branchName: string }\n | { stage: 'create-pr' }\n | { stage: 'pr-updated'; prNumber: number; prUrl: string; commitSha: string }\n | { stage: 'commit-pushed'; ref: string; commitSha: string }\n | { stage: 'switch-branch'; provider: 'github'; pushOwner: string; repository: string; branchName: string }\n | { stage: 'done'; prUrl?: string; prNumber?: number; commitSha: string }\n | { stage: 'warning'; message: string; details?: unknown }\n | { stage: 'error'; message: string; recoverable: boolean };\n\n/** The settled outcome (the stream's return value). */\nexport interface ContributionResult {\n prUrl?: string;\n prNumber?: number;\n commitSha: string;\n treeSha: string;\n branchName: string;\n mode: 'direct-commit' | 'new-branch-pr' | 'extend-existing';\n}\n\n/** Options for a contribution: the commit message, save {@link ContributeMode},\n * and (PR mode) an optional branch name. */\nexport interface ContributeOptions {\n /** The commit message / PR title. */\n commitMessage: string;\n /** `'pr'` (default) opens a PR; `'direct'` commits to the branch and needs\n * the first-party `contribute:direct` capability. */\n mode?: ContributeMode;\n /** Override the generated branch name (PR mode). */\n branchName?: string;\n}\n\n/**\n * Save the current working tree, streaming each stage.\n *\n * ```ts\n * for await (const ev of contribute({ commitMessage: 'Edit post' })) {\n * if (ev.stage === 'done') console.log(ev.prUrl);\n * }\n * ```\n *\n * Yields {@link ContributionEvent}s and returns a {@link ContributionResult}.\n * Throws a `StreamError` (`.code`) if the host rejects the request — notably\n * `forbidden` when a `contribute:any` app asks for `mode: 'direct'` (T11).\n */\nexport function contribute(\n opts: ContributeOptions\n): AsyncGenerator<ContributionEvent, ContributionResult, void> {\n return protocolStream<ContributionEvent, ContributionResult>('protocol-contribute', 'run', [opts]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,4BAA+B;AA+DxB,SAAS,WACd,MAC6D;AAC7D,aAAO,sCAAsD,uBAAuB,OAAO,CAAC,IAAI,CAAC;AACnG;","names":[]}
@@ -73,6 +73,8 @@ interface ContributionResult {
73
73
  branchName: string;
74
74
  mode: 'direct-commit' | 'new-branch-pr' | 'extend-existing';
75
75
  }
76
+ /** Options for a contribution: the commit message, save {@link ContributeMode},
77
+ * and (PR mode) an optional branch name. */
76
78
  interface ContributeOptions {
77
79
  /** The commit message / PR title. */
78
80
  commitMessage: string;
@@ -73,6 +73,8 @@ interface ContributionResult {
73
73
  branchName: string;
74
74
  mode: 'direct-commit' | 'new-branch-pr' | 'extend-existing';
75
75
  }
76
+ /** Options for a contribution: the commit message, save {@link ContributeMode},
77
+ * and (PR mode) an optional branch name. */
76
78
  interface ContributeOptions {
77
79
  /** The commit message / PR title. */
78
80
  commitMessage: string;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/contribute.ts"],"sourcesContent":["// Contribute — stream a save (PR or direct commit) from app code\n// (UI_AS_APPS_SPEC §5.1, CONTRIBUTE_SPEC). The host runs the *existing*\n// contribution orchestrator and streams its stages back; this is the typed\n// front door over `protocolStream`.\n//\n// The OAuth token never reaches here — it stays on the host. The app passes a\n// commit message + save mode and watches stages go by; the host owns the token,\n// the GitHub API calls, and the user-facing consent.\nimport { protocolStream } from './protocolStream';\n\n/** The save strategy. `direct` requires the first-party `contribute:direct`\n * capability and a scarier consent line — a `contribute:any` app asking for it\n * is REJECTED (`forbidden`), never silently downgraded to a PR (threat T11). */\nexport type ContributeMode = 'pr' | 'direct';\n\n/** A stage emitted as the contribution runs. Mirrors the host orchestrator's\n * event union; carries progress metadata only — never the token or file blobs. */\nexport type ContributionEvent =\n | { stage: 'auth-check' }\n | { stage: 'diff-compute' }\n | { stage: 'permission-check' }\n | { stage: 'install-required'; targetOwner: string; targetRepo: string; installUrl: string }\n | { stage: 'conflict-check' }\n | { stage: 'fork-prepare'; forkOwner: string; alreadyExists: boolean }\n | { stage: 'upload-blob'; path: string; index: number; total: number }\n | { stage: 'create-tree' }\n | { stage: 'create-commit' }\n | { stage: 'create-branch'; branchName: string }\n | { stage: 'create-pr' }\n | { stage: 'pr-updated'; prNumber: number; prUrl: string; commitSha: string }\n | { stage: 'commit-pushed'; ref: string; commitSha: string }\n | { stage: 'switch-branch'; provider: 'github'; pushOwner: string; repository: string; branchName: string }\n | { stage: 'done'; prUrl?: string; prNumber?: number; commitSha: string }\n | { stage: 'warning'; message: string; details?: unknown }\n | { stage: 'error'; message: string; recoverable: boolean };\n\n/** The settled outcome (the stream's return value). */\nexport interface ContributionResult {\n prUrl?: string;\n prNumber?: number;\n commitSha: string;\n treeSha: string;\n branchName: string;\n mode: 'direct-commit' | 'new-branch-pr' | 'extend-existing';\n}\n\nexport interface ContributeOptions {\n /** The commit message / PR title. */\n commitMessage: string;\n /** `'pr'` (default) opens a PR; `'direct'` commits to the branch and needs\n * the first-party `contribute:direct` capability. */\n mode?: ContributeMode;\n /** Override the generated branch name (PR mode). */\n branchName?: string;\n}\n\n/**\n * Save the current working tree, streaming each stage.\n *\n * ```ts\n * for await (const ev of contribute({ commitMessage: 'Edit post' })) {\n * if (ev.stage === 'done') console.log(ev.prUrl);\n * }\n * ```\n *\n * Yields {@link ContributionEvent}s and returns a {@link ContributionResult}.\n * Throws a `StreamError` (`.code`) if the host rejects the request — notably\n * `forbidden` when a `contribute:any` app asks for `mode: 'direct'` (T11).\n */\nexport function contribute(\n opts: ContributeOptions\n): AsyncGenerator<ContributionEvent, ContributionResult, void> {\n return protocolStream<ContributionEvent, ContributionResult>('protocol-contribute', 'run', [opts]);\n}\n"],"mappings":"AAQA,SAAS,sBAAsB;AA6DxB,SAAS,WACd,MAC6D;AAC7D,SAAO,eAAsD,uBAAuB,OAAO,CAAC,IAAI,CAAC;AACnG;","names":[]}
1
+ {"version":3,"sources":["../src/contribute.ts"],"sourcesContent":["// Contribute — stream a save (PR or direct commit) from app code\n// (UI_AS_APPS_SPEC §5.1, CONTRIBUTE_SPEC). The host runs the *existing*\n// contribution orchestrator and streams its stages back; this is the typed\n// front door over `protocolStream`.\n//\n// The OAuth token never reaches here — it stays on the host. The app passes a\n// commit message + save mode and watches stages go by; the host owns the token,\n// the GitHub API calls, and the user-facing consent.\nimport { protocolStream } from './protocolStream';\n\n/** The save strategy. `direct` requires the first-party `contribute:direct`\n * capability and a scarier consent line — a `contribute:any` app asking for it\n * is REJECTED (`forbidden`), never silently downgraded to a PR (threat T11). */\nexport type ContributeMode = 'pr' | 'direct';\n\n/** A stage emitted as the contribution runs. Mirrors the host orchestrator's\n * event union; carries progress metadata only — never the token or file blobs. */\nexport type ContributionEvent =\n | { stage: 'auth-check' }\n | { stage: 'diff-compute' }\n | { stage: 'permission-check' }\n | { stage: 'install-required'; targetOwner: string; targetRepo: string; installUrl: string }\n | { stage: 'conflict-check' }\n | { stage: 'fork-prepare'; forkOwner: string; alreadyExists: boolean }\n | { stage: 'upload-blob'; path: string; index: number; total: number }\n | { stage: 'create-tree' }\n | { stage: 'create-commit' }\n | { stage: 'create-branch'; branchName: string }\n | { stage: 'create-pr' }\n | { stage: 'pr-updated'; prNumber: number; prUrl: string; commitSha: string }\n | { stage: 'commit-pushed'; ref: string; commitSha: string }\n | { stage: 'switch-branch'; provider: 'github'; pushOwner: string; repository: string; branchName: string }\n | { stage: 'done'; prUrl?: string; prNumber?: number; commitSha: string }\n | { stage: 'warning'; message: string; details?: unknown }\n | { stage: 'error'; message: string; recoverable: boolean };\n\n/** The settled outcome (the stream's return value). */\nexport interface ContributionResult {\n prUrl?: string;\n prNumber?: number;\n commitSha: string;\n treeSha: string;\n branchName: string;\n mode: 'direct-commit' | 'new-branch-pr' | 'extend-existing';\n}\n\n/** Options for a contribution: the commit message, save {@link ContributeMode},\n * and (PR mode) an optional branch name. */\nexport interface ContributeOptions {\n /** The commit message / PR title. */\n commitMessage: string;\n /** `'pr'` (default) opens a PR; `'direct'` commits to the branch and needs\n * the first-party `contribute:direct` capability. */\n mode?: ContributeMode;\n /** Override the generated branch name (PR mode). */\n branchName?: string;\n}\n\n/**\n * Save the current working tree, streaming each stage.\n *\n * ```ts\n * for await (const ev of contribute({ commitMessage: 'Edit post' })) {\n * if (ev.stage === 'done') console.log(ev.prUrl);\n * }\n * ```\n *\n * Yields {@link ContributionEvent}s and returns a {@link ContributionResult}.\n * Throws a `StreamError` (`.code`) if the host rejects the request — notably\n * `forbidden` when a `contribute:any` app asks for `mode: 'direct'` (T11).\n */\nexport function contribute(\n opts: ContributeOptions\n): AsyncGenerator<ContributionEvent, ContributionResult, void> {\n return protocolStream<ContributionEvent, ContributionResult>('protocol-contribute', 'run', [opts]);\n}\n"],"mappings":"AAQA,SAAS,sBAAsB;AA+DxB,SAAS,WACd,MAC6D;AAC7D,SAAO,eAAsD,uBAAuB,OAAO,CAAC,IAAI,CAAC;AACnG;","names":[]}
package/dist/debug.cjs ADDED
@@ -0,0 +1,168 @@
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 debug_exports = {};
20
+ __export(debug_exports, {
21
+ debug: () => debug,
22
+ isDebugEnabled: () => isDebugEnabled,
23
+ log: () => log,
24
+ useDebugEnabled: () => useDebugEnabled
25
+ });
26
+ module.exports = __toCommonJS(debug_exports);
27
+ var import_pushChannel = require("./pushChannel");
28
+ var import_sandboxUtils = require("./sandboxUtils");
29
+ const enabledChannel = (0, import_pushChannel.createPushChannel)({
30
+ pushType: "debug-enabled",
31
+ requestType: "request-debug-enabled",
32
+ initial: false,
33
+ parse: (msg) => typeof msg.enabled === "boolean" ? msg.enabled : void 0
34
+ });
35
+ const isDebugEnabled = () => enabledChannel.get();
36
+ const useDebugEnabled = () => enabledChannel.use();
37
+ const MAX_DATA_BYTES = 16 * 1024;
38
+ function safeData(data) {
39
+ if (data === void 0) return void 0;
40
+ try {
41
+ const json = JSON.stringify(data);
42
+ if (json === void 0) return "[unserializable]";
43
+ if (json.length > MAX_DATA_BYTES) return `[truncated ${json.length}B]`;
44
+ return JSON.parse(json);
45
+ } catch {
46
+ return "[unserializable]";
47
+ }
48
+ }
49
+ function log(level, message, data) {
50
+ if (!enabledChannel.get()) return;
51
+ try {
52
+ (0, import_sandboxUtils.sendMessage)("debug-log", { level, message: String(message), data: safeData(data) });
53
+ } catch {
54
+ }
55
+ }
56
+ const ATTR_ALLOW = /* @__PURE__ */ new Set(["role", "aria-hidden", "data-theme", "data-active", "href", "type", "hidden"]);
57
+ const MAX_NODES = 2e3;
58
+ const MAX_DEPTH = 25;
59
+ const MAX_TEXT = 200;
60
+ function round(n) {
61
+ return Math.round(n);
62
+ }
63
+ function snapshotDom(params) {
64
+ if (typeof document === "undefined") return null;
65
+ const root = params.selector ? document.querySelector(params.selector) : document.body;
66
+ if (!root) return null;
67
+ const maxDepth = Math.min(params.maxDepth ?? MAX_DEPTH, MAX_DEPTH);
68
+ const maxNodes = Math.min(params.maxNodes ?? MAX_NODES, MAX_NODES);
69
+ let budget = maxNodes;
70
+ const walk = (el, depth) => {
71
+ budget--;
72
+ const r = el.getBoundingClientRect();
73
+ const classes = el.classList.length ? [...el.classList] : void 0;
74
+ const attrs = {};
75
+ for (const name of el.getAttributeNames()) {
76
+ if (ATTR_ALLOW.has(name)) attrs[name] = el.getAttribute(name) ?? "";
77
+ }
78
+ const ownText = [...el.childNodes].filter((n) => n.nodeType === 3).map((n) => (n.textContent ?? "").trim()).join(" ").trim();
79
+ const node = {
80
+ tag: el.tagName.toLowerCase(),
81
+ ...el.id ? { id: el.id } : {},
82
+ ...classes ? { classes } : {},
83
+ ...Object.keys(attrs).length ? { attrs } : {},
84
+ rect: { x: round(r.x), y: round(r.y), w: round(r.width), h: round(r.height) },
85
+ ...ownText ? { text: ownText.slice(0, MAX_TEXT) } : {}
86
+ };
87
+ if (depth < maxDepth && el.children.length && budget > 0) {
88
+ const children = [];
89
+ for (const child of el.children) {
90
+ if (budget <= 0) {
91
+ node.truncated = true;
92
+ break;
93
+ }
94
+ children.push(walk(child, depth + 1));
95
+ }
96
+ if (children.length) node.children = children;
97
+ } else if (el.children.length) {
98
+ node.truncated = true;
99
+ }
100
+ return node;
101
+ };
102
+ return walk(root, 0);
103
+ }
104
+ function computedStyle(params) {
105
+ if (typeof document === "undefined") return null;
106
+ const el = document.querySelector(params.selector);
107
+ if (!el) return null;
108
+ const cs = getComputedStyle(el);
109
+ const out = {};
110
+ for (const p of params.props.slice(0, 50)) out[p] = cs.getPropertyValue(p) || cs[p]?.toString?.() || "";
111
+ return out;
112
+ }
113
+ function rects(params) {
114
+ if (typeof document === "undefined") return [];
115
+ return [...document.querySelectorAll(params.selector)].slice(0, 200).map((el) => {
116
+ const r = el.getBoundingClientRect();
117
+ return { x: round(r.x), y: round(r.y), w: round(r.width), h: round(r.height) };
118
+ });
119
+ }
120
+ let responderStarted = false;
121
+ function startResponder() {
122
+ if (responderStarted || typeof window === "undefined") return;
123
+ responderStarted = true;
124
+ (0, import_sandboxUtils.addListener)("debug-query", (msg) => {
125
+ if (!enabledChannel.get()) return;
126
+ const id = msg.id;
127
+ const method = msg.method;
128
+ const params = msg.params ?? {};
129
+ let ok = true;
130
+ let result = null;
131
+ let error;
132
+ try {
133
+ switch (method) {
134
+ case "snapshotDom":
135
+ result = snapshotDom(params);
136
+ break;
137
+ case "computedStyle":
138
+ result = computedStyle(params);
139
+ break;
140
+ case "rect":
141
+ result = rects(params);
142
+ break;
143
+ default:
144
+ ok = false;
145
+ error = `unknown debug method: ${String(method)}`;
146
+ }
147
+ } catch (e) {
148
+ ok = false;
149
+ error = e instanceof Error ? e.message : String(e);
150
+ }
151
+ try {
152
+ (0, import_sandboxUtils.sendMessage)("debug-query-result", { id, ok, result, error });
153
+ } catch {
154
+ }
155
+ });
156
+ }
157
+ enabledChannel.onChange((enabled) => {
158
+ if (enabled) startResponder();
159
+ });
160
+ const debug = { log, isEnabled: isDebugEnabled };
161
+ // Annotate the CommonJS export names for ESM import in node:
162
+ 0 && (module.exports = {
163
+ debug,
164
+ isDebugEnabled,
165
+ log,
166
+ useDebugEnabled
167
+ });
168
+ //# sourceMappingURL=debug.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/debug.ts"],"sourcesContent":["// System-app devtools — the app-facing surface (plan: docs/plans/system-app-devtools.md).\n//\n// Two opt-in, DEV-ONLY instruments for debugging a sandboxed UI-as-app region:\n// 1. `debug.log(...)` — an app→host one-way log surfaced in the host dev panel\n// / CLI `/debug` stream (instead of hand-fishing console output out of a\n// cross-origin iframe's devtools).\n// 2. a READ-ONLY DOM/layout responder the host can query from outside — the\n// thing a cross-origin screenshot can't reliably give you (a blank capture\n// is ambiguous between a real 0-height collapse and a paint artifact).\n//\n// SECURITY (the gating constraint — see the plan's §0):\n// - Both are inert unless the HOST signals dev mode via the `debug-enabled`\n// channel. The host only sets it for a dev/override session (the `ir-dev-*`\n// deep link) or an explicit operator developer-mode. A published app served\n// to a normal user gets `enabled:false` → `debug.log` is a no-op and the\n// responder never answers. Production isolation is therefore unchanged.\n// - The responder is READ-ONLY with a fixed vocabulary (snapshotDom /\n// computedStyle / rect). There is deliberately NO eval bridge — that would\n// turn a debug aid into remote code execution into the sandbox.\n// - The responder reads only its OWN `document` (it lives in its own opaque\n// iframe and cannot reach a sibling app), so there is no app↔app leak even\n// in dev.\n// - Output is bounded (node/depth/text caps) so a query can't exfiltrate an\n// unbounded payload or wedge the app.\n//\n// Apps that want the strongest guarantee can additionally guard their own usage\n// behind `import.meta.env.DEV` so the calls are tree-shaken from prod bundles;\n// the runtime gate here is the backstop that holds regardless.\n\nimport { createPushChannel } from './pushChannel';\nimport { sendMessage, addListener } from './sandboxUtils';\n\n/** Severity of a {@link debug.log} entry. */\nexport type DebugLevel = 'debug' | 'info' | 'warn' | 'error';\n\n// ── Dev gate ────────────────────────────────────────────────────────────────\n// The host pushes `debug-enabled:true` only for a dev/override session. Until\n// then (and always in production) it stays false and every instrument is inert.\nconst enabledChannel = createPushChannel<boolean>({\n pushType: 'debug-enabled',\n requestType: 'request-debug-enabled',\n initial: false,\n parse: (msg) => (typeof msg.enabled === 'boolean' ? msg.enabled : undefined),\n});\n\n/** Is the host dev-debug surface active for this session? `false` in production. */\nexport const isDebugEnabled = (): boolean => enabledChannel.get();\n\n/** React hook: whether the host dev-debug surface is active (re-renders on change).\n * Handy for showing a debug affordance only when it would do something. */\nexport const useDebugEnabled = (): boolean => enabledChannel.use();\n\n// ── 1. App→host debug log ─────────────────────────────────────────────────────\n// Best-effort: a value that can't be structured-cloned is replaced with a marker\n// rather than throwing — `debug.log` must never break the app.\nconst MAX_DATA_BYTES = 16 * 1024;\n\nfunction safeData(data: unknown): unknown {\n if (data === undefined) return undefined;\n try {\n const json = JSON.stringify(data);\n if (json === undefined) return '[unserializable]';\n if (json.length > MAX_DATA_BYTES) return `[truncated ${json.length}B]`;\n return JSON.parse(json);\n } catch {\n return '[unserializable]';\n }\n}\n\n/**\n * Emit a structured debug entry to the host dev surface. A NO-OP unless the host\n * has enabled the dev-debug session ({@link isDebugEnabled}); in production it\n * does nothing and sends nothing.\n *\n * debug.log('info', 'mounted', { activeFile });\n */\nexport function log(level: DebugLevel, message: string, data?: unknown): void {\n if (!enabledChannel.get()) return; // inert in prod / non-dev sessions\n try {\n sendMessage('debug-log', { level, message: String(message), data: safeData(data) });\n } catch {\n /* transport not ready — drop silently; logging must never throw */\n }\n}\n\n// ── 2. Read-only DOM / layout responder ───────────────────────────────────────\n// The host sends `debug-query` { id, method, params }; we reply with\n// `debug-query-result` { id, ok, result | error }. Only ever active while the dev\n// gate is enabled. Vocabulary is fixed and read-only.\n\ninterface DomNode {\n tag: string;\n id?: string;\n classes?: string[];\n attrs?: Record<string, string>;\n rect?: { x: number; y: number; w: number; h: number };\n text?: string;\n children?: DomNode[];\n truncated?: true;\n}\n\nconst ATTR_ALLOW = new Set(['role', 'aria-hidden', 'data-theme', 'data-active', 'href', 'type', 'hidden']);\nconst MAX_NODES = 2000;\nconst MAX_DEPTH = 25;\nconst MAX_TEXT = 200;\n\nfunction round(n: number): number {\n return Math.round(n);\n}\n\nfunction snapshotDom(params: { selector?: string; maxDepth?: number; maxNodes?: number }): DomNode | null {\n if (typeof document === 'undefined') return null;\n const root = params.selector ? document.querySelector(params.selector) : document.body;\n if (!root) return null;\n const maxDepth = Math.min(params.maxDepth ?? MAX_DEPTH, MAX_DEPTH);\n const maxNodes = Math.min(params.maxNodes ?? MAX_NODES, MAX_NODES);\n let budget = maxNodes;\n\n const walk = (el: Element, depth: number): DomNode => {\n budget--;\n const r = el.getBoundingClientRect();\n const classes = el.classList.length ? [...el.classList] : undefined;\n const attrs: Record<string, string> = {};\n for (const name of el.getAttributeNames()) {\n if (ATTR_ALLOW.has(name)) attrs[name] = el.getAttribute(name) ?? '';\n }\n // Direct text (not descendants') so a leaf's label is visible without dumping\n // the whole subtree's text.\n const ownText = [...el.childNodes]\n .filter((n) => n.nodeType === 3)\n .map((n) => (n.textContent ?? '').trim())\n .join(' ')\n .trim();\n const node: DomNode = {\n tag: el.tagName.toLowerCase(),\n ...(el.id ? { id: el.id } : {}),\n ...(classes ? { classes } : {}),\n ...(Object.keys(attrs).length ? { attrs } : {}),\n rect: { x: round(r.x), y: round(r.y), w: round(r.width), h: round(r.height) },\n ...(ownText ? { text: ownText.slice(0, MAX_TEXT) } : {}),\n };\n if (depth < maxDepth && el.children.length && budget > 0) {\n const children: DomNode[] = [];\n for (const child of el.children) {\n if (budget <= 0) {\n node.truncated = true;\n break;\n }\n children.push(walk(child, depth + 1));\n }\n if (children.length) node.children = children;\n } else if (el.children.length) {\n node.truncated = true;\n }\n return node;\n };\n\n return walk(root, 0);\n}\n\nfunction computedStyle(params: { selector: string; props: string[] }): Record<string, string> | null {\n if (typeof document === 'undefined') return null;\n const el = document.querySelector(params.selector);\n if (!el) return null;\n const cs = getComputedStyle(el);\n const out: Record<string, string> = {};\n for (const p of params.props.slice(0, 50)) out[p] = cs.getPropertyValue(p) || cs[p as keyof CSSStyleDeclaration]?.toString?.() || '';\n return out;\n}\n\nfunction rects(params: { selector: string }): Array<{ x: number; y: number; w: number; h: number }> {\n if (typeof document === 'undefined') return [];\n return [...document.querySelectorAll(params.selector)].slice(0, 200).map((el) => {\n const r = el.getBoundingClientRect();\n return { x: round(r.x), y: round(r.y), w: round(r.width), h: round(r.height) };\n });\n}\n\nlet responderStarted = false;\n\n/** Wire the read-only DOM/layout responder. Idempotent; called lazily once the\n * dev gate turns on. No effect when `document` is absent (non-browser realm). */\nfunction startResponder(): void {\n if (responderStarted || typeof window === 'undefined') return;\n responderStarted = true;\n addListener('debug-query', (msg: { id?: unknown; method?: unknown; params?: unknown }) => {\n if (!enabledChannel.get()) return; // gate: ignore unless dev-enabled\n const id = msg.id;\n const method = msg.method;\n const params = (msg.params ?? {}) as Record<string, unknown>;\n let ok = true;\n let result: unknown = null;\n let error: string | undefined;\n try {\n switch (method) {\n case 'snapshotDom':\n result = snapshotDom(params as never);\n break;\n case 'computedStyle':\n result = computedStyle(params as never);\n break;\n case 'rect':\n result = rects(params as never);\n break;\n default:\n ok = false;\n error = `unknown debug method: ${String(method)}`;\n }\n } catch (e) {\n ok = false;\n error = e instanceof Error ? e.message : String(e);\n }\n try {\n sendMessage('debug-query-result', { id, ok, result, error });\n } catch {\n /* transport gone — nothing to do */\n }\n });\n}\n\n// Start the responder as soon as the gate flips on (and not before).\nenabledChannel.onChange((enabled) => {\n if (enabled) startResponder();\n});\n\n/** The dev-only debug surface. Inert unless the host enables it ({@link isDebugEnabled}). */\nexport const debug = { log, isEnabled: isDebugEnabled } as const;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,22 @@
1
+ /** Severity of a {@link debug.log} entry. */
2
+ type DebugLevel = 'debug' | 'info' | 'warn' | 'error';
3
+ /** Is the host dev-debug surface active for this session? `false` in production. */
4
+ declare const isDebugEnabled: () => boolean;
5
+ /** React hook: whether the host dev-debug surface is active (re-renders on change).
6
+ * Handy for showing a debug affordance only when it would do something. */
7
+ declare const useDebugEnabled: () => boolean;
8
+ /**
9
+ * Emit a structured debug entry to the host dev surface. A NO-OP unless the host
10
+ * has enabled the dev-debug session ({@link isDebugEnabled}); in production it
11
+ * does nothing and sends nothing.
12
+ *
13
+ * debug.log('info', 'mounted', { activeFile });
14
+ */
15
+ declare function log(level: DebugLevel, message: string, data?: unknown): void;
16
+ /** The dev-only debug surface. Inert unless the host enables it ({@link isDebugEnabled}). */
17
+ declare const debug: {
18
+ readonly log: typeof log;
19
+ readonly isEnabled: () => boolean;
20
+ };
21
+
22
+ export { type DebugLevel, debug, isDebugEnabled, log, useDebugEnabled };
@@ -0,0 +1,22 @@
1
+ /** Severity of a {@link debug.log} entry. */
2
+ type DebugLevel = 'debug' | 'info' | 'warn' | 'error';
3
+ /** Is the host dev-debug surface active for this session? `false` in production. */
4
+ declare const isDebugEnabled: () => boolean;
5
+ /** React hook: whether the host dev-debug surface is active (re-renders on change).
6
+ * Handy for showing a debug affordance only when it would do something. */
7
+ declare const useDebugEnabled: () => boolean;
8
+ /**
9
+ * Emit a structured debug entry to the host dev surface. A NO-OP unless the host
10
+ * has enabled the dev-debug session ({@link isDebugEnabled}); in production it
11
+ * does nothing and sends nothing.
12
+ *
13
+ * debug.log('info', 'mounted', { activeFile });
14
+ */
15
+ declare function log(level: DebugLevel, message: string, data?: unknown): void;
16
+ /** The dev-only debug surface. Inert unless the host enables it ({@link isDebugEnabled}). */
17
+ declare const debug: {
18
+ readonly log: typeof log;
19
+ readonly isEnabled: () => boolean;
20
+ };
21
+
22
+ export { type DebugLevel, debug, isDebugEnabled, log, useDebugEnabled };