@assistant-ui/metro 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -8,6 +8,11 @@ const require$1 = (0, require("node:module").createRequire)(require("url").pathT
8
8
  */
9
9
  const UPSTREAM_TRANSFORMER_ENV = "AUI_METRO_UPSTREAM_TRANSFORMER";
10
10
  /**
11
+ * Env var carrying the `backendless` option to the transformer. Metro forks its
12
+ * transform workers after `metro.config` is evaluated, so they inherit it.
13
+ */
14
+ const BACKENDLESS_ENV = "AUI_METRO_BACKENDLESS";
15
+ /**
11
16
  * Wraps a Metro (or Expo) config so assistant-ui `"use generative"` modules are
12
17
  * compiled. Such a file colocates a tool's schema, its `execute`, and its
13
18
  * `render` via {@link https://www.assistant-ui.com/docs/tools/defining-tools | defineToolkit}.
@@ -23,7 +28,10 @@ const UPSTREAM_TRANSFORMER_ENV = "AUI_METRO_UPSTREAM_TRANSFORMER";
23
28
  * const { getDefaultConfig } = require("expo/metro-config");
24
29
  * const { withAui } = require("@assistant-ui/metro");
25
30
  *
26
- * module.exports = withAui(getDefaultConfig(__dirname));
31
+ * module.exports = withAui({
32
+ * ...getDefaultConfig(__dirname),
33
+ * aui: { backendless: true },
34
+ * });
27
35
  * ```
28
36
  *
29
37
  * Authoring is identical to the web: a `"use generative"` file whose default
@@ -31,10 +39,12 @@ const UPSTREAM_TRANSFORMER_ENV = "AUI_METRO_UPSTREAM_TRANSFORMER";
31
39
  */
32
40
  function withAui(config) {
33
41
  const self = require$1.resolve("@assistant-ui/metro/transformer");
42
+ const { aui, ...baseConfig } = config;
34
43
  const upstream = config.transformer?.babelTransformerPath;
44
+ if (aui?.backendless) process.env[BACKENDLESS_ENV] = "1";
35
45
  if (upstream && upstream !== self) process.env[UPSTREAM_TRANSFORMER_ENV] = upstream;
36
46
  return {
37
- ...config,
47
+ ...baseConfig,
38
48
  transformer: {
39
49
  ...config.transformer,
40
50
  babelTransformerPath: self
@@ -42,6 +52,7 @@ function withAui(config) {
42
52
  };
43
53
  }
44
54
  //#endregion
55
+ exports.BACKENDLESS_ENV = BACKENDLESS_ENV;
45
56
  exports.UPSTREAM_TRANSFORMER_ENV = UPSTREAM_TRANSFORMER_ENV;
46
57
  exports.withAui = withAui;
47
58
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["require","createRequire"],"sources":["../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\n/**\n * The shape of a Metro / Expo config `withAui` accepts. Typed loosely so this\n * package needs no hard dependency on `metro` or `expo`; the input shape is\n * preserved and only `transformer.babelTransformerPath` is augmented.\n */\nexport type MetroConfigLike = {\n transformer?:\n | {\n babelTransformerPath?: string | undefined;\n [key: string]: unknown;\n }\n | undefined;\n [key: string]: unknown;\n};\n\n/**\n * Env var the transformer reads to delegate to the project's existing\n * (Expo / React Native) babel transformer. Metro forks its transform workers\n * after `metro.config` is evaluated, so they inherit this value.\n */\nexport const UPSTREAM_TRANSFORMER_ENV = \"AUI_METRO_UPSTREAM_TRANSFORMER\";\n\n/**\n * Wraps a Metro (or Expo) config so assistant-ui `\"use generative\"` modules are\n * compiled. Such a file colocates a tool's schema, its `execute`, and its\n * `render` via {@link https://www.assistant-ui.com/docs/tools/defining-tools | defineToolkit}.\n *\n * It points Metro's `babelTransformerPath` at this package's transformer, which\n * runs the `\"use generative\"` compiler and then delegates to your project's\n * existing transformer. The device (client) build keeps each tool's `render`\n * and any frontend `execute`; a server build (an Expo Router `+api` route)\n * keeps a server `execute` instead.\n *\n * ```js\n * // metro.config.js\n * const { getDefaultConfig } = require(\"expo/metro-config\");\n * const { withAui } = require(\"@assistant-ui/metro\");\n *\n * module.exports = withAui(getDefaultConfig(__dirname));\n * ```\n *\n * Authoring is identical to the web: a `\"use generative\"` file whose default\n * export is `defineToolkit({ ... })`, registered with `Tools({ toolkit })`.\n */\nexport function withAui<T extends MetroConfigLike>(config: T): T {\n const self = require.resolve(\"@assistant-ui/metro/transformer\");\n const upstream = config.transformer?.babelTransformerPath;\n\n // Guard against a double-wrap (`withAui(withAui(config))`, or a shared config\n // already wrapped): if it already points at our transformer, keep the real\n // upstream captured earlier rather than overwriting it with our own path,\n // which would make `resolveUpstream()` return this transformer and recurse.\n if (upstream && upstream !== self) {\n process.env[UPSTREAM_TRANSFORMER_ENV] = upstream;\n }\n\n return {\n ...config,\n transformer: {\n ...config.transformer,\n babelTransformerPath: self,\n },\n };\n}\n"],"mappings":";;AAEA,MAAMA,aAAAA,wBAAUC,CAAAA,CAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAA6B;;;;;;AAsB7C,MAAa,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;AAwBxC,SAAgB,QAAmC,QAAc;CAC/D,MAAM,OAAOD,UAAQ,QAAQ,iCAAiC;CAC9D,MAAM,WAAW,OAAO,aAAa;CAMrC,IAAI,YAAY,aAAa,MAC3B,QAAQ,IAAI,4BAA4B;CAG1C,OAAO;EACL,GAAG;EACH,aAAa;GACX,GAAG,OAAO;GACV,sBAAsB;EACxB;CACF;AACF"}
1
+ {"version":3,"file":"index.cjs","names":["require","createRequire"],"sources":["../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\n/**\n * The shape of a Metro / Expo config `withAui` accepts. Typed loosely so this\n * package needs no hard dependency on `metro` or `expo`; the input shape is\n * preserved and only `transformer.babelTransformerPath` is augmented.\n */\nexport type MetroConfigLike = {\n /** assistant-ui options, stripped from the config handed back to Metro. */\n aui?: WithAuiOptions | undefined;\n transformer?:\n | {\n babelTransformerPath?: string | undefined;\n [key: string]: unknown;\n }\n | undefined;\n [key: string]: unknown;\n};\n\n/**\n * Env var the transformer reads to delegate to the project's existing\n * (Expo / React Native) babel transformer. Metro forks its transform workers\n * after `metro.config` is evaluated, so they inherit this value.\n */\nexport const UPSTREAM_TRANSFORMER_ENV = \"AUI_METRO_UPSTREAM_TRANSFORMER\";\n\n/**\n * Env var carrying the `backendless` option to the transformer. Metro forks its\n * transform workers after `metro.config` is evaluated, so they inherit it.\n */\nexport const BACKENDLESS_ENV = \"AUI_METRO_BACKENDLESS\";\n\nexport interface WithAuiOptions {\n /**\n * The app has no backend importing the server builds of its `\"use generative\"`\n * modules (e.g. cloud-hosted runs). Frontend/human tool schemas then stay\n * uploadable from the client instead of being assumed backend-known.\n */\n backendless?: boolean;\n}\n\n/**\n * Wraps a Metro (or Expo) config so assistant-ui `\"use generative\"` modules are\n * compiled. Such a file colocates a tool's schema, its `execute`, and its\n * `render` via {@link https://www.assistant-ui.com/docs/tools/defining-tools | defineToolkit}.\n *\n * It points Metro's `babelTransformerPath` at this package's transformer, which\n * runs the `\"use generative\"` compiler and then delegates to your project's\n * existing transformer. The device (client) build keeps each tool's `render`\n * and any frontend `execute`; a server build (an Expo Router `+api` route)\n * keeps a server `execute` instead.\n *\n * ```js\n * // metro.config.js\n * const { getDefaultConfig } = require(\"expo/metro-config\");\n * const { withAui } = require(\"@assistant-ui/metro\");\n *\n * module.exports = withAui({\n * ...getDefaultConfig(__dirname),\n * aui: { backendless: true },\n * });\n * ```\n *\n * Authoring is identical to the web: a `\"use generative\"` file whose default\n * export is `defineToolkit({ ... })`, registered with `Tools({ toolkit })`.\n */\nexport function withAui<T extends MetroConfigLike>(config: T): T {\n const self = require.resolve(\"@assistant-ui/metro/transformer\");\n // Metro validates config keys it does not recognize, so `aui` must not\n // survive into the returned config.\n const { aui, ...baseConfig } = config;\n const upstream = config.transformer?.babelTransformerPath;\n\n if (aui?.backendless) process.env[BACKENDLESS_ENV] = \"1\";\n\n // Guard against a double-wrap (`withAui(withAui(config))`, or a shared config\n // already wrapped): if it already points at our transformer, keep the real\n // upstream captured earlier rather than overwriting it with our own path,\n // which would make `resolveUpstream()` return this transformer and recurse.\n if (upstream && upstream !== self) {\n process.env[UPSTREAM_TRANSFORMER_ENV] = upstream;\n }\n\n return {\n ...baseConfig,\n transformer: {\n ...config.transformer,\n babelTransformerPath: self,\n },\n } as T;\n}\n"],"mappings":";;AAEA,MAAMA,aAAAA,wBAAUC,CAAAA,CAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAA6B;;;;;;AAwB7C,MAAa,2BAA2B;;;;;AAMxC,MAAa,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;AAoC/B,SAAgB,QAAmC,QAAc;CAC/D,MAAM,OAAOD,UAAQ,QAAQ,iCAAiC;CAG9D,MAAM,EAAE,KAAK,GAAG,eAAe;CAC/B,MAAM,WAAW,OAAO,aAAa;CAErC,IAAI,KAAK,aAAa,QAAQ,IAAI,mBAAmB;CAMrD,IAAI,YAAY,aAAa,MAC3B,QAAQ,IAAI,4BAA4B;CAG1C,OAAO;EACL,GAAG;EACH,aAAa;GACX,GAAG,OAAO;GACV,sBAAsB;EACxB;CACF;AACF"}
package/dist/index.d.cts CHANGED
@@ -5,6 +5,8 @@
5
5
  * preserved and only `transformer.babelTransformerPath` is augmented.
6
6
  */
7
7
  type MetroConfigLike = {
8
+ /** assistant-ui options, stripped from the config handed back to Metro. */
9
+ aui?: WithAuiOptions | undefined;
8
10
  transformer?: {
9
11
  babelTransformerPath?: string | undefined;
10
12
  [key: string]: unknown;
@@ -17,6 +19,19 @@ type MetroConfigLike = {
17
19
  * after `metro.config` is evaluated, so they inherit this value.
18
20
  */
19
21
  declare const UPSTREAM_TRANSFORMER_ENV = "AUI_METRO_UPSTREAM_TRANSFORMER";
22
+ /**
23
+ * Env var carrying the `backendless` option to the transformer. Metro forks its
24
+ * transform workers after `metro.config` is evaluated, so they inherit it.
25
+ */
26
+ declare const BACKENDLESS_ENV = "AUI_METRO_BACKENDLESS";
27
+ interface WithAuiOptions {
28
+ /**
29
+ * The app has no backend importing the server builds of its `"use generative"`
30
+ * modules (e.g. cloud-hosted runs). Frontend/human tool schemas then stay
31
+ * uploadable from the client instead of being assumed backend-known.
32
+ */
33
+ backendless?: boolean;
34
+ }
20
35
  /**
21
36
  * Wraps a Metro (or Expo) config so assistant-ui `"use generative"` modules are
22
37
  * compiled. Such a file colocates a tool's schema, its `execute`, and its
@@ -33,7 +48,10 @@ declare const UPSTREAM_TRANSFORMER_ENV = "AUI_METRO_UPSTREAM_TRANSFORMER";
33
48
  * const { getDefaultConfig } = require("expo/metro-config");
34
49
  * const { withAui } = require("@assistant-ui/metro");
35
50
  *
36
- * module.exports = withAui(getDefaultConfig(__dirname));
51
+ * module.exports = withAui({
52
+ * ...getDefaultConfig(__dirname),
53
+ * aui: { backendless: true },
54
+ * });
37
55
  * ```
38
56
  *
39
57
  * Authoring is identical to the web: a `"use generative"` file whose default
@@ -41,5 +59,5 @@ declare const UPSTREAM_TRANSFORMER_ENV = "AUI_METRO_UPSTREAM_TRANSFORMER";
41
59
  */
42
60
  declare function withAui<T extends MetroConfigLike>(config: T): T;
43
61
  //#endregion
44
- export { MetroConfigLike, UPSTREAM_TRANSFORMER_ENV, withAui };
62
+ export { BACKENDLESS_ENV, MetroConfigLike, UPSTREAM_TRANSFORMER_ENV, WithAuiOptions, withAui };
45
63
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;KASY;EACV;IAEM;KACC;;GAGN;;;;;;;cAQU;;;;;;;;;;;;;;;;;;;;;;;iBAwBG,QAAQ,UAAU,iBAAiB,QAAQ,IAAI"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;KASY;;EAEV,MAAM;EACN;IAEM;KACC;;GAGN;;;;;;;cAQU;;;;;cAMA;UAEI;;;;;;EAMf;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4Bc,QAAQ,UAAU,iBAAiB,QAAQ,IAAI"}
@@ -40,7 +40,7 @@ _babel_types = __toESM(_babel_types, 1);
40
40
  const DIRECTIVE = "use generative";
41
41
  //#endregion
42
42
  //#region ../x-generative-compiler/dist/package.js
43
- var version = "0.0.12";
43
+ var version = "0.0.14";
44
44
  //#endregion
45
45
  //#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/constants.js
46
46
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -1590,6 +1590,7 @@ function isLineTerminator(char) {
1590
1590
  */
1591
1591
  function compileGenerative(code, options) {
1592
1592
  const { target, filename } = options;
1593
+ const backendless = options.backendless ?? false;
1593
1594
  const ast = (0, _babel_parser.parse)(code, {
1594
1595
  sourceType: "module",
1595
1596
  plugins: parserPlugins
@@ -1616,7 +1617,7 @@ function compileGenerative(code, options) {
1616
1617
  }
1617
1618
  if (_babel_types.isIdentifier(callee, { name: TOOLKIT_WRAPPER })) {
1618
1619
  if (!object) throw new GenerativeCompileError(`${TOOLKIT_WRAPPER}() takes an inline object literal of tools`, filename);
1619
- compileToolkit(object, target, generativeInstances, interactableToolImports, toolkitSpreadNames, namespaceImports, flags, filename);
1620
+ compileToolkit(object, target, generativeInstances, interactableToolImports, toolkitSpreadNames, namespaceImports, flags, backendless, filename);
1620
1621
  path.replaceWith(object);
1621
1622
  path.skip();
1622
1623
  }
@@ -1777,6 +1778,15 @@ function collectGenerativeInstances(ast) {
1777
1778
  }
1778
1779
  return names;
1779
1780
  }
1781
+ /**
1782
+ * Wraps a pass-through generative entry (`generative.present()`) so the tool it
1783
+ * returns loses its `unstable_backendDefault` marker. The library stamps the
1784
+ * marker at runtime, out of this compiler's reach, so a backendless client
1785
+ * build strips it post-hoc instead of threading an option into the library.
1786
+ */
1787
+ function stripBackendDefaultExpression(expr) {
1788
+ return _babel_types.callExpression(_babel_types.arrowFunctionExpression([_babel_types.objectPattern([_babel_types.objectProperty(_babel_types.identifier("unstable_backendDefault"), _babel_types.identifier("_backendDefault")), _babel_types.restElement(_babel_types.identifier("tool"))])], _babel_types.identifier("tool")), [expr]);
1789
+ }
1780
1790
  function collectGenerativeFactoryImports(ast) {
1781
1791
  const names = /* @__PURE__ */ new Set();
1782
1792
  for (const statement of ast.program.body) {
@@ -2191,7 +2201,7 @@ function compileComponents(object, target, flags, filename) {
2191
2201
  * `generative.present()` passes through, the library having already split it.
2192
2202
  * Mutates the object in place and records outcomes in {@link TargetFlags}.
2193
2203
  */
2194
- function compileToolkit(object, target, instances, interactableToolImports, toolkitSpreadNames, namespaceImports, flags, filename) {
2204
+ function compileToolkit(object, target, instances, interactableToolImports, toolkitSpreadNames, namespaceImports, flags, backendless, filename) {
2195
2205
  if (target === "client") warnDuplicateToolkitNames(object, toolkitSpreadNames, filename);
2196
2206
  const nextProperties = [];
2197
2207
  for (const entry of object.properties) {
@@ -2203,6 +2213,7 @@ function compileToolkit(object, target, instances, interactableToolImports, tool
2203
2213
  }
2204
2214
  const raw = entryRawValue(entry);
2205
2215
  if (raw && isGenerativeToolEntry(raw, instances)) {
2216
+ if (backendless && target === "client" && _babel_types.isObjectProperty(entry)) entry.value = stripBackendDefaultExpression(raw);
2206
2217
  nextProperties.push(entry);
2207
2218
  continue;
2208
2219
  }
@@ -2247,7 +2258,7 @@ function compileToolkit(object, target, instances, interactableToolImports, tool
2247
2258
  }
2248
2259
  }
2249
2260
  setToolType(value, type);
2250
- setBackendDefault(value, target, type);
2261
+ setBackendDefault(value, target, type, backendless);
2251
2262
  nextProperties.push(entry);
2252
2263
  }
2253
2264
  object.properties = nextProperties;
@@ -2358,8 +2369,9 @@ function setToolType(object, type) {
2358
2369
  removeMember(object, "type");
2359
2370
  object.properties.push(_babel_types.objectProperty(_babel_types.identifier("type"), _babel_types.stringLiteral(type)));
2360
2371
  }
2361
- function setBackendDefault(object, target, type) {
2372
+ function setBackendDefault(object, target, type, backendless) {
2362
2373
  removeMember(object, "unstable_backendDefault");
2374
+ if (backendless) return;
2363
2375
  if (target !== "client" || type !== "frontend" && type !== "human") return;
2364
2376
  object.properties.push(_babel_types.objectProperty(_babel_types.identifier("unstable_backendDefault"), _babel_types.objectExpression([_babel_types.objectProperty(_babel_types.identifier("parameters"), _babel_types.booleanLiteral(true))])));
2365
2377
  }
@@ -2473,7 +2485,8 @@ function transform(props) {
2473
2485
  const { code } = compileGenerative(src, {
2474
2486
  target: isServerEnvironment(options?.customTransformOptions?.environment) ? "server" : "client",
2475
2487
  filename,
2476
- injectServerOnly: false
2488
+ injectServerOnly: false,
2489
+ backendless: process.env[require_index.BACKENDLESS_ENV] === "1"
2477
2490
  });
2478
2491
  return upstream.transform({
2479
2492
  ...props,
@@ -2494,7 +2507,9 @@ function selfCacheToken() {
2494
2507
  }
2495
2508
  function getCacheKey() {
2496
2509
  const upstream = upstreamTransformer();
2497
- return `${upstream.getCacheKey ? upstream.getCacheKey() : ""}$aui-metro:${selfCacheToken()}`;
2510
+ const base = upstream.getCacheKey ? upstream.getCacheKey() : "";
2511
+ const backendless = process.env["AUI_METRO_BACKENDLESS"] === "1" ? ":backendless" : "";
2512
+ return `${base}$aui-metro:${selfCacheToken()}${backendless}`;
2498
2513
  }
2499
2514
  //#endregion
2500
2515
  exports.getCacheKey = getCacheKey;