@apollo/client-ai-apps 0.2.3 → 0.3.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.
@@ -0,0 +1,2 @@
1
+ # Run prettier on the repo
2
+ 22f22733a5c5f98266b3817767739d6968e8014e
@@ -1,24 +1,32 @@
1
1
  name: Build on PR
2
2
 
3
3
  on:
4
- pull_request:
5
- types: [opened, synchronize, reopened]
4
+ pull_request:
5
+ types: [opened, synchronize, reopened]
6
6
 
7
7
  jobs:
8
- build:
9
- runs-on: ubuntu-latest
8
+ build:
9
+ runs-on: ubuntu-latest
10
10
 
11
- steps:
12
- - name: Checkout code
13
- uses: actions/checkout@v4
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v4
14
14
 
15
- - name: Set up Node.js
16
- uses: actions/setup-node@v4
17
- with:
18
- node-version: 20.x
15
+ - name: Set up Node.js
16
+ uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 20.x
19
19
 
20
- - name: Install dependencies
21
- run: npm ci
20
+ - name: Install dependencies
21
+ run: npm ci
22
22
 
23
- - name: Run build
24
- run: npm run build
23
+ - name: Run build
24
+ run: npm run build
25
+
26
+ - name: Test
27
+ shell: bash
28
+ run: npm run test
29
+
30
+ - name: Check formatting
31
+ shell: bash
32
+ run: npm run format:check
@@ -1,53 +1,53 @@
1
1
  name: Release new Version
2
2
 
3
3
  on:
4
- workflow_dispatch:
4
+ workflow_dispatch:
5
5
 
6
6
  permissions:
7
- contents: write
8
- id-token: write # Required for OIDC
7
+ contents: write
8
+ id-token: write # Required for OIDC
9
9
 
10
10
  jobs:
11
- release:
12
- name: Release
13
- if: github.repository == 'apollographql/apollo-ai-apps-client'
14
- runs-on: ubuntu-latest
15
- steps:
16
- - uses: actions/checkout@v4
17
-
18
- - name: Setup Node.js 20.x
19
- uses: actions/setup-node@v4
20
- with:
21
- node-version: ">=23.6.0"
22
- registry-url: "https://registry.npmjs.org/"
23
- env:
24
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
25
-
26
- - name: Install dependencies
27
- shell: bash
28
- run: npm ci
29
-
30
- - name: Build
31
- shell: bash
32
- run: npm run build
33
-
34
- - name: Test
35
- shell: bash
36
- run: npm run test
37
-
38
- - name: Configure Git
39
- run: |
40
- git config --global user.name GitHub Actions
41
- git config user.email github-actions@github.com
42
-
43
- - uses: knope-dev/action@v2.1.0
44
- with:
45
- version: 0.21.5
46
-
47
- - run: knope release
48
- env:
49
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50
-
51
- - name: Publish to npm
52
- shell: bash
53
- run: npm publish --provenance --access public
11
+ release:
12
+ name: Release
13
+ if: github.repository == 'apollographql/apollo-ai-apps-client'
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js 20.x
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: ">=23.6.0"
22
+ registry-url: "https://registry.npmjs.org/"
23
+ env:
24
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
25
+
26
+ - name: Install dependencies
27
+ shell: bash
28
+ run: npm ci
29
+
30
+ - name: Build
31
+ shell: bash
32
+ run: npm run build
33
+
34
+ - name: Test
35
+ shell: bash
36
+ run: npm run test
37
+
38
+ - name: Configure Git
39
+ run: |
40
+ git config --global user.name GitHub Actions
41
+ git config user.email github-actions@github.com
42
+
43
+ - uses: knope-dev/action@v2.1.0
44
+ with:
45
+ version: 0.21.5
46
+
47
+ - run: knope release
48
+ env:
49
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50
+
51
+ - name: Publish to npm
52
+ shell: bash
53
+ run: npm publish --provenance --access public
package/.prettierrc ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "bracketSpacing": true,
3
+ "printWidth": 80,
4
+ "semi": true,
5
+ "singleQuote": false,
6
+ "tabWidth": 2,
7
+ "trailingComma": "es5",
8
+ "experimentalTernaries": true
9
+ }
@@ -1,9 +1,8 @@
1
1
  import { ApolloClient } from "@apollo/client";
2
2
  import "../types/openai";
3
3
  import { ApplicationManifest } from "../types/application-manifest";
4
- type ExtendedApolloClientOptions = Omit<ApolloClient.Options, "link" | "cache"> & {
4
+ type ExtendedApolloClientOptions = Omit<ApolloClient.Options, "link"> & {
5
5
  link?: ApolloClient.Options["link"];
6
- cache?: ApolloClient.Options["cache"];
7
6
  manifest: ApplicationManifest;
8
7
  };
9
8
  export declare class ExtendedApolloClient extends ApolloClient {
@@ -0,0 +1,26 @@
1
+ import { ApolloLink, Observable } from "@apollo/client";
2
+ /**
3
+ * A terminating link that sends a GraphQL request through an agent tool call.
4
+ * When providing a custom link chain to `ApolloClient`, `ApolloClient` will
5
+ * validate that the terminating link is an instance of this link.
6
+ *
7
+ * @example Provding a custom link chain
8
+ *
9
+ * ```ts
10
+ * import { ApolloLink } from "@apollo/client";
11
+ * import { ApolloClient, ToolCallLink } from "@apollo/client-ai-apps";
12
+ *
13
+ * const link = ApolloLink.from([
14
+ * ...otherLinks,
15
+ * new ToolCallLink()
16
+ * ]);
17
+ *
18
+ * const client = new ApolloClient({
19
+ * link,
20
+ * // ...
21
+ * });
22
+ * ```
23
+ */
24
+ export declare class ToolCallLink extends ApolloLink {
25
+ request(operation: ApolloLink.Operation): Observable<ApolloLink.Result>;
26
+ }
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- export declare function ToolUseProvider({ children, appName }: {
2
+ export declare function ToolUseProvider({ children, appName, }: {
3
3
  children: any;
4
4
  appName: string;
5
5
  }): React.JSX.Element;
package/dist/index.d.ts CHANGED
@@ -9,3 +9,4 @@ export * from "./hooks/useToolEffect";
9
9
  export * from "@apollo/client";
10
10
  export { ExtendedApolloClient as ApolloClient } from "./apollo_client/client";
11
11
  export { ExtendedApolloProvider as ApolloProvider } from "./apollo_client/provider";
12
+ export { ToolCallLink } from "./apollo_client/link/ToolCallLink";
package/dist/index.js CHANGED
@@ -58,7 +58,10 @@ var useRequestDisplayMode = () => {
58
58
  // src/hooks/useToolEffect.tsx
59
59
  import React, { useEffect, useState } from "react";
60
60
  var ToolUseContext = React.createContext(null);
61
- function ToolUseProvider({ children, appName }) {
61
+ function ToolUseProvider({
62
+ children,
63
+ appName
64
+ }) {
62
65
  const [hasNavigated, setHasNavigated] = useState(false);
63
66
  return /* @__PURE__ */ React.createElement(ToolUseContext.Provider, { value: { hasNavigated, setHasNavigated, appName } }, children);
64
67
  }
@@ -66,50 +69,82 @@ var useToolEffect = (toolName, effect, deps = []) => {
66
69
  const ctx = React.useContext(ToolUseContext);
67
70
  const fullToolName = useToolName();
68
71
  const toolInput = useToolInput();
69
- if (!ctx) throw new Error("useToolEffect must be used within ToolUseProvider");
72
+ if (!ctx)
73
+ throw new Error("useToolEffect must be used within ToolUseProvider");
70
74
  const toolNames = Array.isArray(toolName) ? toolName : [toolName];
71
75
  useEffect(() => {
72
- const matches = toolNames.some((name) => fullToolName === `${ctx.appName}--${name}`);
76
+ const matches = toolNames.some(
77
+ (name) => fullToolName === `${ctx.appName}--${name}`
78
+ );
73
79
  if (!ctx.hasNavigated && matches) {
74
80
  effect(toolInput);
75
81
  ctx.setHasNavigated(true);
76
82
  }
77
- }, [ctx.hasNavigated, ctx.setHasNavigated, ctx.appName, toolNames, fullToolName, toolInput, ...deps]);
83
+ }, [
84
+ ctx.hasNavigated,
85
+ ctx.setHasNavigated,
86
+ ctx.appName,
87
+ toolNames,
88
+ fullToolName,
89
+ toolInput,
90
+ ...deps
91
+ ]);
78
92
  };
79
93
 
80
94
  // src/index.ts
81
95
  export * from "@apollo/client";
82
96
 
83
97
  // src/apollo_client/client.ts
84
- import { ApolloClient, ApolloLink, InMemoryCache } from "@apollo/client";
85
- import * as Observable from "rxjs";
86
- import { selectHttpOptionsAndBody } from "@apollo/client/link/http";
87
- import { fallbackHttpConfig } from "@apollo/client/link/http";
98
+ import { ApolloClient } from "@apollo/client";
88
99
  import { DocumentTransform } from "@apollo/client";
89
100
  import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
90
101
  import { parse } from "graphql";
91
- var toolCallLink = new ApolloLink((operation) => {
92
- const context = operation.getContext();
93
- const contextConfig = {
94
- http: context.http,
95
- options: context.fetchOptions,
96
- credentials: context.credentials,
97
- headers: context.headers
98
- };
99
- const { query, variables } = selectHttpOptionsAndBody(operation, fallbackHttpConfig, contextConfig).body;
100
- return Observable.from(window.openai.callTool("execute", { query, variables })).pipe(
101
- Observable.map((result) => ({ data: result.structuredContent.data }))
102
- );
103
- });
102
+ import { __DEV__ } from "@apollo/client/utilities/environment";
103
+
104
+ // src/apollo_client/link/ToolCallLink.ts
105
+ import { ApolloLink } from "@apollo/client";
106
+ import { from, map } from "rxjs";
107
+ import {
108
+ fallbackHttpConfig,
109
+ selectHttpOptionsAndBody
110
+ } from "@apollo/client/link/http";
111
+ var ToolCallLink = class extends ApolloLink {
112
+ request(operation) {
113
+ const context = operation.getContext();
114
+ const contextConfig = {
115
+ http: context.http,
116
+ options: context.fetchOptions,
117
+ credentials: context.credentials,
118
+ headers: context.headers
119
+ };
120
+ const { query, variables } = selectHttpOptionsAndBody(
121
+ operation,
122
+ fallbackHttpConfig,
123
+ contextConfig
124
+ ).body;
125
+ return from(window.openai.callTool("execute", { query, variables })).pipe(
126
+ map((result) => ({ data: result.structuredContent.data }))
127
+ );
128
+ }
129
+ };
130
+
131
+ // src/apollo_client/client.ts
104
132
  var ExtendedApolloClient = class extends ApolloClient {
105
133
  manifest;
106
134
  constructor(options) {
135
+ const link = options.link ?? new ToolCallLink();
136
+ if (__DEV__) {
137
+ validateTerminatingLink(link);
138
+ }
107
139
  super({
108
- link: toolCallLink,
109
- cache: options.cache ?? new InMemoryCache(),
140
+ ...options,
141
+ link,
110
142
  // Strip out the prefetch/tool directives so they don't get sent with the operation to the server
111
143
  documentTransform: new DocumentTransform((document) => {
112
- return removeDirectivesFromDocument([{ name: "prefetch" }, { name: "tool" }], document);
144
+ return removeDirectivesFromDocument(
145
+ [{ name: "prefetch" }, { name: "tool" }],
146
+ document
147
+ );
113
148
  })
114
149
  });
115
150
  this.manifest = options.manifest;
@@ -138,6 +173,17 @@ var ExtendedApolloClient = class extends ApolloClient {
138
173
  });
139
174
  }
140
175
  };
176
+ function validateTerminatingLink(link) {
177
+ let terminatingLink = link;
178
+ while (terminatingLink.right) {
179
+ terminatingLink = terminatingLink.right;
180
+ }
181
+ if (terminatingLink.constructor.name !== "ToolCallLink") {
182
+ throw new Error(
183
+ "The terminating link must be a `ToolCallLink`. If you are using a `split` link, ensure the `right` branch uses a `ToolCallLink` as the terminating link."
184
+ );
185
+ }
186
+ }
141
187
 
142
188
  // src/apollo_client/provider.tsx
143
189
  import React2, { useEffect as useEffect2, useState as useState2 } from "react";
@@ -159,7 +205,10 @@ var ExtendedApolloProvider = ({
159
205
  if (window.openai?.toolOutput) {
160
206
  window.dispatchEvent(new CustomEvent(SET_GLOBALS_EVENT_TYPE));
161
207
  }
162
- }, [setHasPreloaded]);
208
+ return () => {
209
+ window.removeEventListener(SET_GLOBALS_EVENT_TYPE, prefetchData);
210
+ };
211
+ }, []);
163
212
  return hasPreloaded ? /* @__PURE__ */ React2.createElement(ApolloProvider, { client }, children) : null;
164
213
  };
165
214
  export {
@@ -167,6 +216,7 @@ export {
167
216
  ExtendedApolloProvider as ApolloProvider,
168
217
  SET_GLOBALS_EVENT_TYPE,
169
218
  SetGlobalsEvent,
219
+ ToolCallLink,
170
220
  ToolUseProvider,
171
221
  useOpenAiGlobal,
172
222
  useRequestDisplayMode,
@@ -0,0 +1,4 @@
1
+ export declare const AbsoluteAssetImportsPlugin: () => {
2
+ name: string;
3
+ transformIndexHtml(html: string, ctx: any): string;
4
+ };
@@ -1 +1,2 @@
1
1
  export * from "./application_manifest_plugin";
2
+ export * from "./absolute_asset_imports_plugin";
@@ -26,14 +26,18 @@ var getRawValue = (node) => {
26
26
  return acc;
27
27
  }, {});
28
28
  default:
29
- throw new Error(`Error when parsing directive values: unexpected type '${node.kind}'`);
29
+ throw new Error(
30
+ `Error when parsing directive values: unexpected type '${node.kind}'`
31
+ );
30
32
  }
31
33
  };
32
34
  var getTypedDirectiveArgument = (argumentName, expectedType, directiveArguments) => {
33
35
  if (!directiveArguments || directiveArguments.length === 0) {
34
36
  return void 0;
35
37
  }
36
- let argument = directiveArguments.find((directiveArgument) => directiveArgument.name.value === argumentName);
38
+ let argument = directiveArguments.find(
39
+ (directiveArgument) => directiveArgument.name.value === argumentName
40
+ );
37
41
  if (!argument) {
38
42
  return void 0;
39
43
  }
@@ -59,25 +63,52 @@ var ApplicationManifestPlugin = () => {
59
63
  const client = new ApolloClient({
60
64
  cache: clientCache,
61
65
  link: new ApolloLink((operation) => {
62
- const body = print(removeClientDirective(sortTopLevelDefinitions(operation.query)));
66
+ const body = print(
67
+ removeClientDirective(sortTopLevelDefinitions(operation.query))
68
+ );
63
69
  const name = operation.operationName;
64
- const variables = operation.query.definitions.find((d) => d.kind === "OperationDefinition").variableDefinitions?.reduce(
65
- (obj, varDef) => ({ ...obj, [varDef.variable.name.value]: getTypeName(varDef.type) }),
70
+ const variables = operation.query.definitions.find(
71
+ (d) => d.kind === "OperationDefinition"
72
+ ).variableDefinitions?.reduce(
73
+ (obj, varDef) => ({
74
+ ...obj,
75
+ [varDef.variable.name.value]: getTypeName(varDef.type)
76
+ }),
66
77
  {}
67
78
  );
68
- const type = operation.query.definitions.find((d) => d.kind === "OperationDefinition").operation;
69
- const prefetch = operation.query.definitions.find((d) => d.kind === "OperationDefinition").directives?.some((d) => d.name.value === "prefetch");
79
+ const type = operation.query.definitions.find(
80
+ (d) => d.kind === "OperationDefinition"
81
+ ).operation;
82
+ const prefetch = operation.query.definitions.find(
83
+ (d) => d.kind === "OperationDefinition"
84
+ ).directives?.some((d) => d.name.value === "prefetch");
70
85
  const id = createHash("sha256").update(body).digest("hex");
71
86
  const prefetchID = prefetch ? "__anonymous" : void 0;
72
- const tools = operation.query.definitions.find((d) => d.kind === "OperationDefinition").directives?.filter((d) => d.name.value === "tool").map((directive) => {
73
- const name2 = getTypedDirectiveArgument("name", Kind.STRING, directive.arguments);
74
- const description = getTypedDirectiveArgument("description", Kind.STRING, directive.arguments);
75
- const extraInputs = getTypedDirectiveArgument("extraInputs", Kind.LIST, directive.arguments);
87
+ const tools = operation.query.definitions.find(
88
+ (d) => d.kind === "OperationDefinition"
89
+ ).directives?.filter((d) => d.name.value === "tool").map((directive) => {
90
+ const name2 = getTypedDirectiveArgument(
91
+ "name",
92
+ Kind.STRING,
93
+ directive.arguments
94
+ );
95
+ const description = getTypedDirectiveArgument(
96
+ "description",
97
+ Kind.STRING,
98
+ directive.arguments
99
+ );
100
+ const extraInputs = getTypedDirectiveArgument(
101
+ "extraInputs",
102
+ Kind.LIST,
103
+ directive.arguments
104
+ );
76
105
  if (!name2) {
77
106
  throw new Error("'name' argument must be supplied for @tool");
78
107
  }
79
108
  if (!description) {
80
- throw new Error("'description' argument must be supplied for @tool");
109
+ throw new Error(
110
+ "'description' argument must be supplied for @tool"
111
+ );
81
112
  }
82
113
  return {
83
114
  name: name2,
@@ -85,7 +116,9 @@ var ApplicationManifestPlugin = () => {
85
116
  extraInputs
86
117
  };
87
118
  });
88
- return Observable.of({ data: { id, name, type, body, variables, prefetch, prefetchID, tools } });
119
+ return Observable.of({
120
+ data: { id, name, type, body, variables, prefetch, prefetchID, tools }
121
+ });
89
122
  })
90
123
  });
91
124
  const processFile = async (file) => {
@@ -105,14 +138,24 @@ var ApplicationManifestPlugin = () => {
105
138
  }));
106
139
  const operations = [];
107
140
  for (const source of sources) {
108
- const type = source.node.definitions.find((d) => d.kind === "OperationDefinition").operation;
141
+ const type = source.node.definitions.find(
142
+ (d) => d.kind === "OperationDefinition"
143
+ ).operation;
109
144
  let result;
110
145
  if (type === "query") {
111
- result = await client.query({ query: source.node, fetchPolicy: "no-cache" });
146
+ result = await client.query({
147
+ query: source.node,
148
+ fetchPolicy: "no-cache"
149
+ });
112
150
  } else if (type === "mutation") {
113
- result = await client.mutate({ mutation: source.node, fetchPolicy: "no-cache" });
151
+ result = await client.mutate({
152
+ mutation: source.node,
153
+ fetchPolicy: "no-cache"
154
+ });
114
155
  } else {
115
- throw new Error("Found an unsupported operation type. Only Query and Mutation are supported.");
156
+ throw new Error(
157
+ "Found an unsupported operation type. Only Query and Mutation are supported."
158
+ );
116
159
  }
117
160
  operations.push(result.data);
118
161
  }
@@ -123,7 +166,9 @@ var ApplicationManifestPlugin = () => {
123
166
  });
124
167
  };
125
168
  const generateManifest = async () => {
126
- const operations = Array.from(cache.values()).flatMap((entry) => entry.operations);
169
+ const operations = Array.from(cache.values()).flatMap(
170
+ (entry) => entry.operations
171
+ );
127
172
  if (operations.filter((o) => o.prefetch).length > 1) {
128
173
  throw new Error(
129
174
  "Found multiple operations marked as `@prefetch`. You can only mark 1 operation with `@prefetch`."
@@ -150,18 +195,22 @@ var ApplicationManifestPlugin = () => {
150
195
  name: packageJson.name,
151
196
  description: packageJson.description,
152
197
  hash: createHash("sha256").update(Date.now().toString()).digest("hex"),
153
- operations: Array.from(cache.values()).flatMap((entry) => entry.operations),
198
+ operations: Array.from(cache.values()).flatMap(
199
+ (entry) => entry.operations
200
+ ),
154
201
  resource,
155
202
  csp: {
156
203
  connectDomains: packageJson.csp?.connectDomains ?? [],
157
204
  resourceDomains: packageJson.csp?.resourceDomains ?? []
158
205
  }
159
206
  };
160
- if (config.command === "build") {
161
- const dest = path.resolve(root, config.build.outDir, ".application-manifest.json");
162
- mkdirSync(path.dirname(dest), { recursive: true });
163
- writeFileSync(dest, JSON.stringify(manifest));
164
- }
207
+ const dest = path.resolve(
208
+ root,
209
+ config.build.outDir,
210
+ ".application-manifest.json"
211
+ );
212
+ mkdirSync(path.dirname(dest), { recursive: true });
213
+ writeFileSync(dest, JSON.stringify(manifest));
165
214
  writeFileSync(".application-manifest.json", JSON.stringify(manifest));
166
215
  };
167
216
  return {
@@ -226,12 +275,28 @@ function removeClientDirective(doc) {
226
275
  OperationDefinition(node) {
227
276
  return {
228
277
  ...node,
229
- directives: node.directives?.filter((d) => d.name.value !== "prefetch" && d.name.value !== "tool")
278
+ directives: node.directives?.filter(
279
+ (d) => d.name.value !== "prefetch" && d.name.value !== "tool"
280
+ )
230
281
  };
231
282
  }
232
283
  });
233
284
  }
285
+
286
+ // src/vite/absolute_asset_imports_plugin.ts
287
+ var AbsoluteAssetImportsPlugin = () => {
288
+ return {
289
+ name: "absolute-asset-imports",
290
+ transformIndexHtml(html, ctx) {
291
+ if (!ctx.server) return html;
292
+ let baseUrl = (ctx.server.config?.server?.origin ?? ctx.server.resolvedUrls?.local[0]).replace(/\/$/, "");
293
+ baseUrl = baseUrl.replace(/\/$/, "");
294
+ return html.replace(/(from\s+["'])\/([^"']+)/g, `$1${baseUrl}/$2`).replace(/(src=["'])\/([^"']+)/gi, `$1${baseUrl}/$2`);
295
+ }
296
+ };
297
+ };
234
298
  export {
299
+ AbsoluteAssetImportsPlugin,
235
300
  ApplicationManifestPlugin,
236
301
  sortTopLevelDefinitions
237
302
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apollo/client-ai-apps",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -22,7 +22,9 @@
22
22
  "build:vite": "node ./scripts/build-vite.mjs && tsc src/vite/index.ts --emitDeclarationOnly --declaration --outDir dist/vite --skipLibCheck --lib ES2015,DOM --target ES2020 --module esnext --moduleResolution node --allowSyntheticDefaultImports",
23
23
  "test": "vitest run --coverage",
24
24
  "test:watch": "vitest --coverage",
25
- "changeset": "knope document-change"
25
+ "changeset": "knope document-change",
26
+ "format": "prettier --write .",
27
+ "format:check": "prettier --check ."
26
28
  },
27
29
  "keywords": [],
28
30
  "author": "",
@@ -38,6 +40,7 @@
38
40
  "esbuild": "^0.25.12",
39
41
  "graphql": "^16.9.0",
40
42
  "happy-dom": "^20.0.10",
43
+ "prettier": "^3.7.4",
41
44
  "rxjs": "^7.8.1",
42
45
  "typescript": "^5.9.3",
43
46
  "vitest": "^4.0.13"
package/scripts/dev.mjs CHANGED
@@ -10,7 +10,9 @@ let ctx = await esbuild.context({
10
10
  name: "rebuild-logger",
11
11
  setup(build) {
12
12
  build.onEnd((result) => {
13
- console.log(`Rebuilt at ${new Date().toLocaleTimeString()} (${result.errors.length} errors)`);
13
+ console.log(
14
+ `Rebuilt at ${new Date().toLocaleTimeString()} (${result.errors.length} errors)`
15
+ );
14
16
  });
15
17
  },
16
18
  },