@microsoft/rayfin-functions 1.30.0 → 1.32.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.
@@ -43,11 +43,23 @@ export declare class FunctionClient<TInput = any, TOutput = any> {
43
43
  private functionName;
44
44
  constructor(apiClient: ApiClient, functionName: string);
45
45
  /**
46
- * Invoke the function.
46
+ * Invoke the function and return its typed output.
47
47
  *
48
48
  * @param params - Input parameters (omit when the function takes no input).
49
49
  * @param options - Optional per-call settings (extra headers, etc.).
50
- * @returns A response whose `output` field is typed as `TOutput`.
50
+ * @returns The function's success-path output, typed as `TOutput`.
51
+ *
52
+ * Failure modes throw — a non-empty `errors` array or a non-success
53
+ * status on the wire response is surfaced as {@link FunctionsError}.
54
+ * Network and unknown errors are wrapped in {@link NetworkError} and
55
+ * {@link FunctionsError} respectively. By the time this method
56
+ * resolves, the caller can use the value without defending against
57
+ * `undefined`.
58
+ *
59
+ * The server-side `invocationId` from the underlying envelope is
60
+ * emitted via `console.debug` (along with the function name) so the
61
+ * value is available in the browser/Node console for correlation
62
+ * without polluting the public return type.
51
63
  *
52
64
  * @throws {FunctionsError} If the function invocation fails.
53
65
  * @throws {NetworkError} For network-related issues.
@@ -55,13 +67,13 @@ export declare class FunctionClient<TInput = any, TOutput = any> {
55
67
  *
56
68
  * @example
57
69
  * ```typescript
58
- * const res = await client.functions.helloWorld.invoke({
70
+ * const greeting = await client.functions.helloWorld.invoke({
59
71
  * firstName: 'Ada',
60
72
  * lastName: 'Lovelace',
61
73
  * });
62
- * console.log(res.output); // typed as string
74
+ * console.log(greeting); // typed as string
63
75
  * ```
64
76
  */
65
- invoke(...args: TInput extends void ? [options?: InvokeOptions] : [params: TInput, options?: InvokeOptions]): Promise<FunctionInvocationResponse<TOutput>>;
77
+ invoke(...args: TInput extends void ? [options?: InvokeOptions] : [params: TInput, options?: InvokeOptions]): Promise<TOutput>;
66
78
  }
67
79
  //# sourceMappingURL=FunctionClient.d.ts.map
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { SdkError, NetworkError } from '@microsoft/rayfin-lib';
9
9
  import { FUNCTIONS_BASE_PATH } from '@microsoft/rayfin-lib';
10
- import { FunctionsError } from './Functions';
10
+ import { FunctionsError } from './Functions.js';
11
11
  /**
12
12
  * A strongly-typed client for a single function.
13
13
  *
@@ -22,11 +22,23 @@ export class FunctionClient {
22
22
  this.functionName = functionName;
23
23
  }
24
24
  /**
25
- * Invoke the function.
25
+ * Invoke the function and return its typed output.
26
26
  *
27
27
  * @param params - Input parameters (omit when the function takes no input).
28
28
  * @param options - Optional per-call settings (extra headers, etc.).
29
- * @returns A response whose `output` field is typed as `TOutput`.
29
+ * @returns The function's success-path output, typed as `TOutput`.
30
+ *
31
+ * Failure modes throw — a non-empty `errors` array or a non-success
32
+ * status on the wire response is surfaced as {@link FunctionsError}.
33
+ * Network and unknown errors are wrapped in {@link NetworkError} and
34
+ * {@link FunctionsError} respectively. By the time this method
35
+ * resolves, the caller can use the value without defending against
36
+ * `undefined`.
37
+ *
38
+ * The server-side `invocationId` from the underlying envelope is
39
+ * emitted via `console.debug` (along with the function name) so the
40
+ * value is available in the browser/Node console for correlation
41
+ * without polluting the public return type.
30
42
  *
31
43
  * @throws {FunctionsError} If the function invocation fails.
32
44
  * @throws {NetworkError} For network-related issues.
@@ -34,11 +46,11 @@ export class FunctionClient {
34
46
  *
35
47
  * @example
36
48
  * ```typescript
37
- * const res = await client.functions.helloWorld.invoke({
49
+ * const greeting = await client.functions.helloWorld.invoke({
38
50
  * firstName: 'Ada',
39
51
  * lastName: 'Lovelace',
40
52
  * });
41
- * console.log(res.output); // typed as string
53
+ * console.log(greeting); // typed as string
42
54
  * ```
43
55
  */
44
56
  async invoke(...args) {
@@ -66,7 +78,16 @@ export class FunctionClient {
66
78
  parameters = args[0];
67
79
  options = args[1];
68
80
  }
69
- const url = `${FUNCTIONS_BASE_PATH}/${this.functionName}/invoke`;
81
+ // When a `functionsBaseUrl` is configured on the ApiClient (e.g. by
82
+ // local-debug flows that point at a `func start` process), invoke the
83
+ // function directly against `${functionsBaseUrl}/api/<name>` using the
84
+ // Azure Functions Core Tools routing convention. Otherwise fall back to
85
+ // the production path `${baseUrl}/functions/<name>/invoke` handled by
86
+ // the Fabric `InvokeController`.
87
+ const functionsBaseUrl = this.apiClient.getFunctionsBaseUrl();
88
+ const url = functionsBaseUrl
89
+ ? `${functionsBaseUrl}/api/${this.functionName}`
90
+ : `${FUNCTIONS_BASE_PATH}/${this.functionName}/invoke`;
70
91
  const response = await this.apiClient.post(url, parameters ?? {}, { headers: options?.headers });
71
92
  // Check for errors in the response body
72
93
  if (response.errors && response.errors.length > 0) {
@@ -80,23 +101,39 @@ export class FunctionClient {
80
101
  if (status !== 'success' && status !== 'succeeded') {
81
102
  throw new FunctionsError(`Function invocation failed with status: ${response.status}`, 'FUNCTION_EXECUTION_ERROR');
82
103
  }
83
- // Auto-parse JSON-encoded output strings
104
+ // Auto-parse JSON-encoded output strings. The Fabric runtime
105
+ // sometimes wraps the user's return value in an inner envelope
106
+ // (a stringified `{ output: <value> }`); peel that off so the
107
+ // caller always sees the original `TOutput`.
108
+ // To-Do Investigate why the double JSON encoding is necessary on the runtime side and whether it can be eliminated.
109
+ let output;
84
110
  if (typeof response.output === 'string') {
85
111
  try {
86
112
  const parsed = JSON.parse(response.output);
87
- // If the parsed envelope has its own `output` field, unwrap it
88
113
  if (parsed && typeof parsed === 'object' && 'output' in parsed) {
89
- response.output = parsed.output;
114
+ output = parsed.output;
90
115
  }
91
116
  else {
92
- response.output = parsed;
117
+ output = parsed;
93
118
  }
94
119
  }
95
120
  catch {
96
- // Not JSON — leave as-is (TOutput may be `string`)
121
+ // Not JSON — pass through (TOutput may be `string`)
122
+ output = response.output;
97
123
  }
98
124
  }
99
- return response;
125
+ else {
126
+ output = response.output;
127
+ }
128
+ // Surface invocationId via console.debug so callers can correlate
129
+ // a UI action with server-side telemetry without us having to
130
+ // bake the envelope into the return type. This is opt-in noise
131
+ // that DevTools / Node consoles hide unless the verbose level is
132
+ // turned on.
133
+ if (response.invocationId) {
134
+ console.debug(`[rayfin-functions] ${this.functionName} invocationId=${response.invocationId}`);
135
+ }
136
+ return output;
100
137
  }
101
138
  catch (error) {
102
139
  if (error instanceof FunctionsError ||
@@ -10,10 +10,10 @@
10
10
  * ```
11
11
  */
12
12
  import { ApiClient, SdkError } from '@microsoft/rayfin-lib';
13
- import { FunctionClient } from './FunctionClient';
14
- import type { FunctionsSchema } from './FunctionsSchema';
15
- export { FunctionClient } from './FunctionClient';
16
- export type { FunctionInvocationResponse, InvokeOptions, } from './FunctionClient';
13
+ import { FunctionClient } from './FunctionClient.js';
14
+ import type { FunctionsSchema } from './FunctionsSchema.js';
15
+ export { FunctionClient } from './FunctionClient.js';
16
+ export type { FunctionInvocationResponse, InvokeOptions, } from './FunctionClient.js';
17
17
  /**
18
18
  * Functions error specific to the Rayfin SDK.
19
19
  */
package/dist/Functions.js CHANGED
@@ -10,8 +10,8 @@
10
10
  * ```
11
11
  */
12
12
  import { SdkError } from '@microsoft/rayfin-lib';
13
- import { FunctionClient } from './FunctionClient';
14
- export { FunctionClient } from './FunctionClient';
13
+ import { FunctionClient } from './FunctionClient.js';
14
+ export { FunctionClient } from './FunctionClient.js';
15
15
  /**
16
16
  * Functions error specific to the Rayfin SDK.
17
17
  */
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { FunctionsError, createFunctionsApi, FunctionClient, } from './Functions';
2
- export type { FunctionInvocationResponse, InvokeOptions, TypedFunctionClients, } from './Functions';
3
- export type { FunctionsSchema } from './FunctionsSchema';
1
+ export { FunctionsError, createFunctionsApi, FunctionClient, } from './Functions.js';
2
+ export type { FunctionInvocationResponse, InvokeOptions, TypedFunctionClients, } from './Functions.js';
3
+ export type { FunctionsSchema } from './FunctionsSchema.js';
4
4
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { FunctionsError, createFunctionsApi, FunctionClient, } from './Functions';
1
+ export { FunctionsError, createFunctionsApi, FunctionClient, } from './Functions.js';
2
2
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/rayfin-functions",
3
- "version": "1.30.0",
3
+ "version": "1.32.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,7 +19,7 @@
19
19
  "rimraf": "~6.0.1"
20
20
  },
21
21
  "dependencies": {
22
- "@microsoft/rayfin-lib": "1.30.0"
22
+ "@microsoft/rayfin-lib": "1.32.0"
23
23
  },
24
24
  "publishConfig": {
25
25
  "registry": "https://npm.pkg.github.com",
@@ -35,7 +35,7 @@
35
35
  "license": "MIT",
36
36
  "type": "module",
37
37
  "scripts": {
38
- "build": "tsc",
38
+ "build": "tsc && node ../scripts/fix-esm-extensions.mjs ./dist",
39
39
  "build:watch": "tsc --watch",
40
40
  "clean": "rimraf dist && rimraf .tsbuildinfo",
41
41
  "test": "vitest run"