@apollo/client-ai-apps 0.3.2 → 0.4.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 (140) hide show
  1. package/.github/workflows/pr.yaml +52 -3
  2. package/.github/workflows/prep-release.yml +38 -0
  3. package/.github/workflows/release.yaml +8 -4
  4. package/.github/workflows/verify-changeset.yml +58 -0
  5. package/CHANGELOG.md +88 -0
  6. package/dist/core/ApolloClient.d.ts +3 -2
  7. package/dist/core/ApolloClient.d.ts.map +1 -0
  8. package/dist/core/ApolloClient.js +65 -0
  9. package/dist/core/ApolloClient.js.map +1 -0
  10. package/dist/index.d.ts +18 -18
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +16 -279
  13. package/dist/index.js.map +1 -0
  14. package/dist/link/ToolCallLink.d.ts +1 -0
  15. package/dist/link/ToolCallLink.d.ts.map +1 -0
  16. package/dist/link/ToolCallLink.js +39 -0
  17. package/dist/link/ToolCallLink.js.map +1 -0
  18. package/dist/react/ApolloProvider.d.ts +4 -3
  19. package/dist/react/ApolloProvider.d.ts.map +1 -0
  20. package/dist/react/ApolloProvider.js +30 -0
  21. package/dist/react/ApolloProvider.js.map +1 -0
  22. package/dist/react/context/ToolUseContext.d.ts +4 -3
  23. package/dist/react/context/ToolUseContext.d.ts.map +1 -0
  24. package/dist/react/context/ToolUseContext.js +11 -0
  25. package/dist/react/context/ToolUseContext.js.map +1 -0
  26. package/dist/react/hooks/useCallTool.d.ts +4 -0
  27. package/dist/react/hooks/useCallTool.d.ts.map +1 -0
  28. package/dist/react/hooks/useCallTool.js +5 -0
  29. package/dist/react/hooks/useCallTool.js.map +1 -0
  30. package/dist/react/hooks/useOpenAiGlobal.d.ts +2 -1
  31. package/dist/react/hooks/useOpenAiGlobal.d.ts.map +1 -0
  32. package/dist/react/hooks/useOpenAiGlobal.js +20 -0
  33. package/dist/react/hooks/useOpenAiGlobal.js.map +1 -0
  34. package/dist/react/hooks/useOpenExternal.d.ts +1 -0
  35. package/dist/react/hooks/useOpenExternal.d.ts.map +1 -0
  36. package/dist/react/hooks/useOpenExternal.js +5 -0
  37. package/dist/react/hooks/useOpenExternal.js.map +1 -0
  38. package/dist/react/hooks/useRequestDisplayMode.d.ts +2 -1
  39. package/dist/react/hooks/useRequestDisplayMode.d.ts.map +1 -0
  40. package/dist/react/hooks/useRequestDisplayMode.js +6 -0
  41. package/dist/react/hooks/useRequestDisplayMode.js.map +1 -0
  42. package/dist/react/hooks/useSendFollowUpMessage.d.ts +1 -0
  43. package/dist/react/hooks/useSendFollowUpMessage.d.ts.map +1 -0
  44. package/dist/react/hooks/useSendFollowUpMessage.js +8 -0
  45. package/dist/react/hooks/useSendFollowUpMessage.js.map +1 -0
  46. package/dist/react/hooks/useToolEffect.d.ts +1 -0
  47. package/dist/react/hooks/useToolEffect.d.ts.map +1 -0
  48. package/dist/react/hooks/useToolEffect.js +28 -0
  49. package/dist/react/hooks/useToolEffect.js.map +1 -0
  50. package/dist/react/hooks/useToolInput.d.ts +1 -0
  51. package/dist/react/hooks/useToolInput.d.ts.map +1 -0
  52. package/dist/react/hooks/useToolInput.js +6 -0
  53. package/dist/react/hooks/useToolInput.js.map +1 -0
  54. package/dist/react/hooks/useToolName.d.ts +1 -0
  55. package/dist/react/hooks/useToolName.d.ts.map +1 -0
  56. package/dist/react/hooks/useToolName.js +6 -0
  57. package/dist/react/hooks/useToolName.js.map +1 -0
  58. package/dist/react/hooks/useToolOutput.d.ts +2 -1
  59. package/dist/react/hooks/useToolOutput.d.ts.map +1 -0
  60. package/dist/react/hooks/useToolOutput.js +5 -0
  61. package/dist/react/hooks/useToolOutput.js.map +1 -0
  62. package/dist/react/hooks/useToolResponseMetadata.d.ts +2 -1
  63. package/dist/react/hooks/useToolResponseMetadata.d.ts.map +1 -0
  64. package/dist/react/hooks/useToolResponseMetadata.js +5 -0
  65. package/dist/react/hooks/useToolResponseMetadata.js.map +1 -0
  66. package/dist/react/hooks/useWidgetState.d.ts +3 -2
  67. package/dist/react/hooks/useWidgetState.d.ts.map +1 -0
  68. package/dist/react/hooks/useWidgetState.js +27 -0
  69. package/dist/react/hooks/useWidgetState.js.map +1 -0
  70. package/dist/types/application-manifest.d.ts +15 -0
  71. package/dist/types/application-manifest.d.ts.map +1 -0
  72. package/dist/types/application-manifest.js +2 -0
  73. package/dist/types/application-manifest.js.map +1 -0
  74. package/dist/types/openai.d.ts +1 -0
  75. package/dist/types/openai.d.ts.map +1 -0
  76. package/dist/types/openai.js +6 -0
  77. package/dist/types/openai.js.map +1 -0
  78. package/dist/vite/absolute_asset_imports_plugin.d.ts +1 -0
  79. package/dist/vite/absolute_asset_imports_plugin.d.ts.map +1 -0
  80. package/dist/vite/absolute_asset_imports_plugin.js +17 -0
  81. package/dist/vite/absolute_asset_imports_plugin.js.map +1 -0
  82. package/dist/vite/application_manifest_plugin.d.ts +2 -1
  83. package/dist/vite/application_manifest_plugin.d.ts.map +1 -0
  84. package/dist/vite/application_manifest_plugin.js +317 -0
  85. package/dist/vite/application_manifest_plugin.js.map +1 -0
  86. package/dist/vite/index.d.ts +3 -2
  87. package/dist/vite/index.d.ts.map +1 -0
  88. package/dist/vite/index.js +3 -307
  89. package/dist/vite/index.js.map +1 -0
  90. package/knope.toml +63 -0
  91. package/package.json +19 -11
  92. package/src/core/ApolloClient.ts +10 -5
  93. package/src/core/__tests__/ApolloClient.test.ts +33 -10
  94. package/src/index.ts +19 -18
  95. package/src/react/ApolloProvider.tsx +4 -3
  96. package/src/react/__tests__/ApolloProvider.test.tsx +3 -3
  97. package/src/react/context/ToolUseContext.tsx +2 -1
  98. package/src/react/hooks/__tests__/useCallTool.test.ts +1 -1
  99. package/src/react/hooks/__tests__/useOpenAiGlobal.test.ts +6 -6
  100. package/src/react/hooks/__tests__/useOpenExternal.test.tsx +2 -2
  101. package/src/react/hooks/__tests__/useRequestDisplayMode.test.ts +2 -2
  102. package/src/react/hooks/__tests__/useSendFollowUpMessage.test.ts +1 -1
  103. package/src/react/hooks/__tests__/useToolEffect.test.tsx +2 -2
  104. package/src/react/hooks/__tests__/useToolInput.test.ts +1 -1
  105. package/src/react/hooks/__tests__/useToolName.test.ts +1 -1
  106. package/src/react/hooks/__tests__/useToolOutput.test.tsx +2 -2
  107. package/src/react/hooks/__tests__/useToolResponseMetadata.test.tsx +2 -2
  108. package/src/react/hooks/__tests__/useWidgetState.test.tsx +2 -2
  109. package/src/react/hooks/useOpenAiGlobal.ts +2 -5
  110. package/src/react/hooks/useOpenExternal.ts +1 -1
  111. package/src/react/hooks/useRequestDisplayMode.ts +1 -1
  112. package/src/react/hooks/useToolEffect.tsx +3 -3
  113. package/src/react/hooks/useToolInput.ts +1 -1
  114. package/src/react/hooks/useToolName.ts +1 -1
  115. package/src/react/hooks/useToolOutput.ts +1 -1
  116. package/src/react/hooks/useToolResponseMetadata.ts +1 -1
  117. package/src/react/hooks/useWidgetState.ts +4 -3
  118. package/src/testing/internal/index.ts +2 -2
  119. package/src/testing/internal/matchers/index.ts +1 -1
  120. package/src/testing/internal/matchers/toRerender.ts +2 -2
  121. package/src/testing/internal/matchers/{index.d.ts → types.ts} +1 -1
  122. package/src/testing/internal/openai/dispatchStateChange.ts +1 -1
  123. package/src/testing/internal/openai/stubOpenAiGlobals.ts +6 -2
  124. package/src/types/application-manifest.ts +16 -0
  125. package/src/vite/__tests__/absolute_asset_imports_plugin.test.ts +2 -2
  126. package/src/vite/__tests__/application_manifest_plugin.test.ts +460 -240
  127. package/src/vite/application_manifest_plugin.ts +253 -93
  128. package/src/vite/index.ts +2 -2
  129. package/tsconfig.base.build.json +13 -0
  130. package/tsconfig.base.json +21 -0
  131. package/tsconfig.config.json +9 -0
  132. package/tsconfig.json +10 -0
  133. package/tsconfig.src.build.json +14 -0
  134. package/tsconfig.src.json +17 -0
  135. package/tsconfig.test.json +20 -0
  136. package/tsconfig.vite.build.json +6 -0
  137. package/tsconfig.vite.json +16 -0
  138. package/scripts/build-vite.mjs +0 -18
  139. package/scripts/build.mjs +0 -7
  140. package/scripts/shared.mjs +0 -9
@@ -2,27 +2,33 @@ import { readFileSync, writeFileSync, mkdirSync } from "fs";
2
2
  import { glob } from "glob";
3
3
  import { gqlPluckFromCodeStringSync } from "@graphql-tools/graphql-tag-pluck";
4
4
  import { createHash } from "crypto";
5
- import {
5
+ import type {
6
6
  ArgumentNode,
7
- Kind,
8
7
  ListTypeNode,
9
8
  NamedTypeNode,
10
9
  NonNullTypeNode,
11
- parse,
12
- print,
13
10
  TypeNode,
14
11
  ValueNode,
15
- visit,
16
- type DocumentNode,
17
- type OperationDefinitionNode,
12
+ DocumentNode,
13
+ OperationDefinitionNode,
14
+ DirectiveNode,
18
15
  } from "graphql";
16
+ import { Kind, parse, print } from "graphql";
19
17
  import { ApolloClient, ApolloLink, InMemoryCache } from "@apollo/client";
20
- import Observable from "rxjs";
18
+ import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
19
+ import { of } from "rxjs";
21
20
  import path from "path";
21
+ import type {
22
+ ApplicationManifest,
23
+ ManifestExtraInput,
24
+ ManifestLabels,
25
+ ManifestTool,
26
+ ManifestWidgetSettings,
27
+ } from "../types/application-manifest.js";
22
28
 
23
29
  const root = process.cwd();
24
30
 
25
- const getRawValue = (node: ValueNode): any => {
31
+ function getRawValue(node: ValueNode): unknown {
26
32
  switch (node.kind) {
27
33
  case Kind.STRING:
28
34
  case Kind.BOOLEAN:
@@ -39,33 +45,71 @@ const getRawValue = (node: ValueNode): any => {
39
45
  `Error when parsing directive values: unexpected type '${node.kind}'`
40
46
  );
41
47
  }
42
- };
48
+ }
49
+
50
+ function getArgumentValue(
51
+ argument: ArgumentNode,
52
+ expectedType: Kind.STRING
53
+ ): string;
54
+
55
+ function getArgumentValue(
56
+ argument: ArgumentNode,
57
+ expectedType: Kind.BOOLEAN
58
+ ): boolean;
59
+
60
+ function getArgumentValue(
61
+ argument: ArgumentNode,
62
+ expectedType: Kind.LIST
63
+ ): unknown[];
64
+
65
+ function getArgumentValue(
66
+ argument: ArgumentNode,
67
+ expectedType: Kind.OBJECT
68
+ ): Record<string, unknown>;
69
+
70
+ function getArgumentValue(argument: ArgumentNode, expectedType: Kind) {
71
+ const argumentType = argument.value.kind;
43
72
 
44
- const getTypedDirectiveArgument = (
73
+ invariant(
74
+ argumentType === expectedType,
75
+ `Expected argument '${argument.name.value}' to be of type '${expectedType}' but found '${argumentType}' instead.`
76
+ );
77
+
78
+ return getRawValue(argument.value);
79
+ }
80
+
81
+ interface GetArgumentNodeOptions {
82
+ required?: boolean;
83
+ }
84
+
85
+ function getDirectiveArgument(
45
86
  argumentName: string,
46
- expectedType: Kind,
47
- directiveArguments: readonly ArgumentNode[] | undefined
48
- ) => {
49
- if (!directiveArguments || directiveArguments.length === 0) {
50
- return undefined;
51
- }
87
+ directive: DirectiveNode,
88
+ opts: GetArgumentNodeOptions & { required: true }
89
+ ): ArgumentNode;
90
+
91
+ function getDirectiveArgument(
92
+ argumentName: string,
93
+ directive: DirectiveNode,
94
+ opts?: GetArgumentNodeOptions
95
+ ): ArgumentNode | undefined;
52
96
 
53
- let argument = directiveArguments.find(
97
+ function getDirectiveArgument(
98
+ argumentName: string,
99
+ directive: DirectiveNode,
100
+ { required = false }: { required?: boolean } = {}
101
+ ) {
102
+ const argument = directive.arguments?.find(
54
103
  (directiveArgument) => directiveArgument.name.value === argumentName
55
104
  );
56
105
 
57
- if (!argument) {
58
- return undefined;
59
- }
60
-
61
- if (argument.value.kind != expectedType) {
62
- throw new Error(
63
- `Expected argument '${argumentName}' to be of type '${expectedType}' but found '${argument.value.kind}' instead.`
64
- );
65
- }
106
+ invariant(
107
+ argument || !required,
108
+ `'${argumentName}' argument must be supplied for @tool`
109
+ );
66
110
 
67
- return getRawValue(argument.value);
68
- };
111
+ return argument;
112
+ }
69
113
 
70
114
  function getTypeName(type: TypeNode): string {
71
115
  let t = type;
@@ -88,78 +132,85 @@ export const ApplicationManifestPlugin = () => {
88
132
  removeClientDirective(sortTopLevelDefinitions(operation.query))
89
133
  );
90
134
  const name = operation.operationName;
91
- const variables = (
92
- operation.query.definitions.find(
93
- (d) => d.kind === "OperationDefinition"
94
- ) as OperationDefinitionNode
95
- ).variableDefinitions?.reduce(
135
+ const definition = operation.query.definitions.find(
136
+ (d) => d.kind === "OperationDefinition"
137
+ );
138
+
139
+ // Use `operation.query` so that the error reflects the end-user defined
140
+ // document, not our sorted one
141
+ invariant(
142
+ definition,
143
+ `Document does not contain an operation:\n${print(operation.query)}`
144
+ );
145
+
146
+ const { directives, operation: type } = definition;
147
+
148
+ const variables = definition.variableDefinitions?.reduce(
96
149
  (obj, varDef) => ({
97
150
  ...obj,
98
151
  [varDef.variable.name.value]: getTypeName(varDef.type),
99
152
  }),
100
153
  {}
101
154
  );
102
- const type = (
103
- operation.query.definitions.find(
104
- (d) => d.kind === "OperationDefinition"
105
- ) as OperationDefinitionNode
106
- ).operation;
107
- const prefetch = (
108
- operation.query.definitions.find(
109
- (d) => d.kind === "OperationDefinition"
110
- ) as OperationDefinitionNode
111
- ).directives?.some((d) => d.name.value === "prefetch");
155
+
156
+ const prefetch = directives?.some((d) => d.name.value === "prefetch");
112
157
  const id = createHash("sha256").update(body).digest("hex");
113
158
  // TODO: For now, you can only have 1 operation marked as prefetch. In the future, we'll likely support more than 1, and the "prefetchId" will be defined on the `@prefetch` itself as an argument
114
159
  const prefetchID = prefetch ? "__anonymous" : undefined;
115
160
 
116
- const tools = (
117
- operation.query.definitions.find(
118
- (d) => d.kind === "OperationDefinition"
119
- ) as OperationDefinitionNode
120
- ).directives
161
+ const tools = directives
121
162
  ?.filter((d) => d.name.value === "tool")
122
163
  .map((directive) => {
123
- const name = getTypedDirectiveArgument(
124
- "name",
125
- Kind.STRING,
126
- directive.arguments
164
+ const name = getArgumentValue(
165
+ getDirectiveArgument("name", directive, { required: true }),
166
+ Kind.STRING
167
+ );
168
+
169
+ invariant(
170
+ name.indexOf(" ") === -1,
171
+ `Tool with name "${name}" contains spaces which is not allowed.`
127
172
  );
128
- const description = getTypedDirectiveArgument(
129
- "description",
130
- Kind.STRING,
131
- directive.arguments
173
+
174
+ const description = getArgumentValue(
175
+ getDirectiveArgument("description", directive, { required: true }),
176
+ Kind.STRING
132
177
  );
133
- const extraInputs = getTypedDirectiveArgument(
178
+
179
+ const extraInputsNode = getDirectiveArgument(
134
180
  "extraInputs",
135
- Kind.LIST,
136
- directive.arguments
181
+ directive
137
182
  );
138
183
 
139
- if (!name) {
140
- throw new Error("'name' argument must be supplied for @tool");
141
- }
184
+ const labelsNode = getDirectiveArgument("labels", directive);
142
185
 
143
- if (name.indexOf(" ") > -1) {
144
- throw new Error(
145
- `Tool with name "${name}" contains spaces which is not allowed.`
146
- );
186
+ const toolOptions: ManifestTool = {
187
+ name,
188
+ description,
189
+ };
190
+
191
+ if (extraInputsNode) {
192
+ toolOptions.extraInputs = getArgumentValue(
193
+ extraInputsNode,
194
+ Kind.LIST
195
+ ) as ManifestExtraInput[];
147
196
  }
148
197
 
149
- if (!description) {
150
- throw new Error(
151
- "'description' argument must be supplied for @tool"
198
+ if (labelsNode) {
199
+ const labels = getLabelsFromConfig(
200
+ getArgumentValue(labelsNode, Kind.OBJECT)
152
201
  );
202
+
203
+ if (labels) {
204
+ toolOptions.labels = labels;
205
+ }
153
206
  }
154
207
 
155
- return {
156
- name,
157
- description,
158
- extraInputs,
159
- };
208
+ return toolOptions;
160
209
  });
161
210
 
162
- return Observable.of({
211
+ // TODO: Make this object satisfy the `ManifestOperation` type. Currently
212
+ // it errors because we need more validation on a few of these fields
213
+ return of({
163
214
  data: { id, name, type, body, variables, prefetch, prefetchID, tools },
164
215
  });
165
216
  }),
@@ -172,7 +223,7 @@ export const ApplicationManifestPlugin = () => {
172
223
 
173
224
  const fileHash = createHash("md5").update(code).digest("hex");
174
225
  if (cache.get("file")?.hash === fileHash) return;
175
- const sources = await gqlPluckFromCodeStringSync(file, code, {
226
+ const sources = gqlPluckFromCodeStringSync(file, code, {
176
227
  modules: [
177
228
  { name: "graphql-tag", identifier: "gql" },
178
229
  { name: "@apollo/client", identifier: "gql" },
@@ -221,11 +272,11 @@ export const ApplicationManifestPlugin = () => {
221
272
  const operations = Array.from(cache.values()).flatMap(
222
273
  (entry) => entry.operations
223
274
  );
224
- if (operations.filter((o) => o.prefetch).length > 1) {
225
- throw new Error(
226
- "Found multiple operations marked as `@prefetch`. You can only mark 1 operation with `@prefetch`."
227
- );
228
- }
275
+
276
+ invariant(
277
+ operations.filter((o) => o.prefetch).length <= 1,
278
+ "Found multiple operations marked as `@prefetch`. You can only mark 1 operation with `@prefetch`."
279
+ );
229
280
 
230
281
  let resource = "";
231
282
  if (config.command === "serve") {
@@ -245,7 +296,7 @@ export const ApplicationManifestPlugin = () => {
245
296
  }
246
297
  }
247
298
 
248
- const manifest = {
299
+ const manifest: ApplicationManifest = {
249
300
  format: "apollo-ai-app-manifest",
250
301
  version: "1",
251
302
  name: packageJson.name,
@@ -257,10 +308,46 @@ export const ApplicationManifestPlugin = () => {
257
308
  resource,
258
309
  csp: {
259
310
  connectDomains: packageJson.csp?.connectDomains ?? [],
311
+ frameDomains: packageJson.csp?.frameDomains ?? [],
312
+ redirectDomains: packageJson.csp?.redirectDomains ?? [],
260
313
  resourceDomains: packageJson.csp?.resourceDomains ?? [],
261
314
  },
262
315
  };
263
316
 
317
+ if (
318
+ packageJson.widgetSettings &&
319
+ isNonEmptyObject(packageJson.widgetSettings)
320
+ ) {
321
+ function validateWidgetSetting(
322
+ key: keyof ManifestWidgetSettings,
323
+ type: "string" | "boolean"
324
+ ) {
325
+ if (key in widgetSettings) {
326
+ invariant(
327
+ typeof widgetSettings[key] === type,
328
+ `Expected 'widgetSettings.${key}' to be of type '${type}' but found '${typeof widgetSettings[key]}' instead.`
329
+ );
330
+ }
331
+ }
332
+
333
+ const widgetSettings =
334
+ packageJson.widgetSettings as ManifestWidgetSettings;
335
+
336
+ validateWidgetSetting("prefersBorder", "boolean");
337
+ validateWidgetSetting("description", "string");
338
+ validateWidgetSetting("domain", "string");
339
+
340
+ manifest.widgetSettings = packageJson.widgetSettings;
341
+ }
342
+
343
+ if (packageJson.labels) {
344
+ const labels = getLabelsFromConfig(packageJson.labels);
345
+
346
+ if (labels) {
347
+ manifest.labels = labels;
348
+ }
349
+ }
350
+
264
351
  // Always write to build directory so the MCP server picks it up
265
352
  const dest = path.resolve(
266
353
  root,
@@ -365,15 +452,88 @@ export function sortTopLevelDefinitions(query: DocumentNode): DocumentNode {
365
452
  };
366
453
  }
367
454
 
455
+ interface LabelConfig {
456
+ toolInvocation?: {
457
+ invoking?: string;
458
+ invoked?: string;
459
+ };
460
+ }
461
+
462
+ function getLabelsFromConfig(config: LabelConfig): ManifestLabels | undefined {
463
+ if (!("toolInvocation" in config)) {
464
+ return;
465
+ }
466
+
467
+ const { toolInvocation } = config;
468
+ const labels: ManifestLabels = {};
469
+
470
+ if (Object.hasOwn(toolInvocation, "invoking")) {
471
+ validateType(toolInvocation.invoking, "string", {
472
+ propertyName: "labels.toolInvocation.invoking",
473
+ });
474
+
475
+ labels["toolInvocation/invoking"] = toolInvocation.invoking;
476
+ }
477
+
478
+ if (Object.hasOwn(toolInvocation, "invoked")) {
479
+ validateType(toolInvocation.invoked, "string", {
480
+ propertyName: "labels.toolInvocation.invoked",
481
+ });
482
+
483
+ labels["toolInvocation/invoked"] = toolInvocation.invoked;
484
+ }
485
+
486
+ if (isNonEmptyObject(labels)) {
487
+ return labels;
488
+ }
489
+ }
490
+
368
491
  function removeClientDirective(doc: DocumentNode) {
369
- return visit(doc, {
370
- OperationDefinition(node) {
371
- return {
372
- ...node,
373
- directives: node.directives?.filter(
374
- (d) => d.name.value !== "prefetch" && d.name.value !== "tool"
375
- ),
376
- };
377
- },
378
- });
492
+ return removeDirectivesFromDocument(
493
+ [{ name: "prefetch" }, { name: "tool" }],
494
+ doc
495
+ )!;
496
+ }
497
+
498
+ function invariant(condition: any, message: string): asserts condition {
499
+ if (!condition) {
500
+ throw new Error(message);
501
+ }
502
+ }
503
+
504
+ // possible values of `typeof`
505
+ type TypeofResult =
506
+ | "string"
507
+ | "number"
508
+ | "bigint"
509
+ | "boolean"
510
+ | "symbol"
511
+ | "undefined"
512
+ | "object"
513
+ | "function";
514
+
515
+ type TypeofResultToConcreteType<T extends TypeofResult> =
516
+ T extends "string" ? string
517
+ : T extends "number" ? number
518
+ : T extends "bigint" ? bigint
519
+ : T extends "boolean" ? boolean
520
+ : T extends "symbol" ? symbol
521
+ : T extends "undefined" ? undefined
522
+ : T extends "object" ? object
523
+ : T extends "function" ? Function
524
+ : never;
525
+
526
+ function validateType<Typeof extends TypeofResult>(
527
+ value: unknown,
528
+ expectedType: Typeof,
529
+ options: { propertyName: string }
530
+ ): asserts value is TypeofResultToConcreteType<Typeof> {
531
+ invariant(
532
+ typeof value === expectedType,
533
+ `Expected '${options.propertyName}' to be of type '${expectedType}' but found '${typeof value}' instead.`
534
+ );
535
+ }
536
+
537
+ function isNonEmptyObject(obj: object) {
538
+ return Object.keys(obj).length > 0;
379
539
  }
package/src/vite/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from "./application_manifest_plugin";
2
- export * from "./absolute_asset_imports_plugin";
1
+ export * from "./application_manifest_plugin.js";
2
+ export * from "./absolute_asset_imports_plugin.js";
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.json",
4
+ "compilerOptions": {
5
+ "noEmit": false,
6
+ "rootDir": "./src",
7
+ "outDir": "./dist",
8
+ "inlineSources": true,
9
+ "sourceMap": true,
10
+ "declaration": true,
11
+ "declarationMap": true
12
+ }
13
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "noImplicitAny": true,
5
+ "module": "nodenext",
6
+ "moduleResolution": "nodenext",
7
+ "target": "esnext",
8
+ "lib": ["esnext"],
9
+ "exactOptionalPropertyTypes": true,
10
+ "strict": true,
11
+ "jsx": "react-jsx",
12
+ "verbatimModuleSyntax": true,
13
+ "isolatedModules": true,
14
+ "importHelpers": true,
15
+ "noUncheckedSideEffectImports": true,
16
+ "noUnusedLocals": true,
17
+ "moduleDetection": "force",
18
+ "skipLibCheck": true,
19
+ "esModuleInterop": true
20
+ }
21
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.json",
4
+ "include": ["./vitest.config.ts"],
5
+ "compilerOptions": {
6
+ "rootDir": ".",
7
+ "composite": true
8
+ }
9
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "files": [],
4
+ "references": [
5
+ { "path": "./tsconfig.config.json" },
6
+ { "path": "./tsconfig.src.json" },
7
+ { "path": "./tsconfig.test.json" },
8
+ { "path": "./tsconfig.vite.json" }
9
+ ]
10
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.build.json",
4
+ "include": ["./src"],
5
+ "exclude": [
6
+ "./src/**/*.test.ts",
7
+ "./src/**/*.test.tsx",
8
+ "./src/vite/",
9
+ "./src/testing/internal/"
10
+ ],
11
+ "compilerOptions": {
12
+ "lib": ["DOM"]
13
+ }
14
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.json",
4
+ "include": ["./src"],
5
+ "exclude": [
6
+ "./src/**/*.test.ts",
7
+ "./src/**/*.test.tsx",
8
+ "./src/vite/",
9
+ "./src/testing/internal/"
10
+ ],
11
+ "compilerOptions": {
12
+ "rootDir": "src",
13
+ "outDir": "dist",
14
+ "composite": true,
15
+ "lib": ["dom", "esnext"]
16
+ }
17
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.json",
4
+ "include": [
5
+ "./src/**/*.test.ts",
6
+ "./src/**/*.test.tsx",
7
+ "./src/testing/internal/"
8
+ ],
9
+ "references": [
10
+ { "path": "./tsconfig.src.json" },
11
+ { "path": "./tsconfig.vite.json" }
12
+ ],
13
+ "compilerOptions": {
14
+ "rootDir": "src",
15
+ "outDir": "dist",
16
+ "composite": true,
17
+ "lib": ["dom", "esnext"],
18
+ "types": ["node"]
19
+ }
20
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.build.json",
4
+ "include": ["./src/vite/"],
5
+ "exclude": ["**/*.test.ts", "**/*.test.tsx"]
6
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.json",
4
+ "include": ["./src/vite", "./src/types/application-manifest.ts"],
5
+ "exclude": [
6
+ "./src/**/*.test.ts",
7
+ "./src/**/*.test.tsx",
8
+ "./src/testing/internal/"
9
+ ],
10
+ "compilerOptions": {
11
+ "rootDir": "src",
12
+ "outDir": "dist",
13
+ "lib": ["esnext"],
14
+ "composite": true
15
+ }
16
+ }
@@ -1,18 +0,0 @@
1
- import * as esbuild from "esbuild";
2
-
3
- // Separately build Vite plugin
4
- await esbuild.build({
5
- entryPoints: ["src/vite/index.ts"],
6
- bundle: true,
7
- outdir: "dist/vite",
8
- platform: "node",
9
- format: "esm",
10
- external: [
11
- "glob",
12
- "@graphql-tools/graphql-tag-pluck",
13
- "@graphql-tools/graphql-tag-pluck",
14
- "graphql",
15
- "@apollo/client",
16
- "rxjs",
17
- ],
18
- });
package/scripts/build.mjs DELETED
@@ -1,7 +0,0 @@
1
- import * as esbuild from "esbuild";
2
- import { sharedConfig } from "./shared.mjs";
3
-
4
- // Build react components
5
- await esbuild.build({
6
- ...sharedConfig,
7
- });
@@ -1,9 +0,0 @@
1
- export const sharedConfig = {
2
- entryPoints: ["src/index.ts"],
3
- bundle: true,
4
- outdir: "dist",
5
- platform: "browser",
6
- format: "esm",
7
- packages: "external",
8
- external: ["react", "react-dom"],
9
- };