@microsoft/rayfin-client 1.35.0-alpha.1374 → 1.35.0-alpha.1541

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/client.d.ts CHANGED
@@ -8,6 +8,7 @@ import { type EntitySchema, createDataApi } from '@microsoft/rayfin-data';
8
8
  import { createFunctionsApi, type FunctionsSchema } from '@microsoft/rayfin-functions';
9
9
  import { SdkError, NetworkError } from '@microsoft/rayfin-lib';
10
10
  import { ApiClient, ApiClientConfig } from '@microsoft/rayfin-lib';
11
+ import { type RayfinRuntimeConfig } from './config.js';
11
12
  /**
12
13
  * Auth error specific to the Rayfin SDK.
13
14
  */
@@ -36,6 +37,8 @@ export interface RayfinClientConfig extends ApiClientConfig {
36
37
  autoRefreshToken?: boolean;
37
38
  /** When false, StorageEvent listener is not registered. Default: auto-detected (true in browser with localStorage). */
38
39
  multiTabSync?: boolean;
40
+ /** Values passed through to `resolveRayfinConfig()`'s `runtimeConfig` result when constructed via that helper (e.g. build-time `VITE_*` vars as defaults); exposed as `client.runtimeConfig`. */
41
+ runtimeConfig?: RayfinRuntimeConfig;
39
42
  }
40
43
  /**
41
44
  * Configuration for the server/worker-oriented {@link RayfinServerClient}.
@@ -45,13 +48,17 @@ export interface RayfinClientConfig extends ApiClientConfig {
45
48
  export interface RayfinServerClientConfig extends Omit<ApiClientConfig, 'getAccessToken'> {
46
49
  /** Access token (string or function) for Authorization: Bearer <token>. Use the function form to rotate per request. */
47
50
  accessToken?: string | (() => string | null);
51
+ /** Values passed through to `resolveRayfinConfig()`'s `runtimeConfig` result when constructed via that helper (e.g. build-time env vars as defaults); exposed as `client.runtimeConfig`. */
52
+ runtimeConfig?: RayfinRuntimeConfig;
48
53
  }
49
54
  /** Shared base for Rayfin clients: owns the typed data API and the underlying HTTP client. */
50
55
  export declare abstract class RayfinClientBase<TSchema extends EntitySchema = Record<string, any>> {
51
56
  /** Typed data API for querying and mutating your entities. */
52
57
  readonly data: ReturnType<typeof createDataApi<TSchema>>;
53
58
  protected apiClient: ApiClient;
54
- protected constructor(config: ApiClientConfig);
59
+ protected constructor(config: ApiClientConfig & {
60
+ runtimeConfig?: RayfinRuntimeConfig;
61
+ });
55
62
  /** SDK error classes, exposed for convenient `instanceof` checks. */
56
63
  static readonly errors: {
57
64
  SdkError: typeof SdkError;
@@ -84,12 +91,22 @@ export declare abstract class RayfinClientBase<TSchema extends EntitySchema = Re
84
91
  * .where({ isActive: true })
85
92
  * .execute();
86
93
  * ```
94
+ *
95
+ * @example ALM-aware deployments — resolve runtime config, then construct
96
+ * ```typescript
97
+ * import { RayfinClient, resolveRayfinConfig } from '@microsoft/rayfin-client';
98
+ *
99
+ * const resolved = await resolveRayfinConfig({ baseUrl, publishableKey });
100
+ * const client = new RayfinClient({ ...resolved, authStorage: true });
101
+ * ```
87
102
  */
88
103
  export declare class RayfinClient<TSchema extends EntitySchema = Record<string, any>, TFunctionsSchema extends FunctionsSchema = FunctionsSchema> extends RayfinClientBase<TSchema> {
89
104
  /** Authentication operations (sign up, sign in, sign out, session state). */
90
105
  readonly auth: Auth;
91
106
  /** Typed, schema-aware accessors for invoking your backend functions. */
92
107
  readonly functions: ReturnType<typeof createFunctionsApi<TFunctionsSchema>>;
108
+ /** All resolved `rayfin.config.json` values, for apps that need more than just `baseUrl`/`publishableKey` (e.g. Fabric embed auth coordinates). */
109
+ readonly runtimeConfig?: RayfinRuntimeConfig;
93
110
  /**
94
111
  * Creates a browser Rayfin client and wires up authentication.
95
112
  *
@@ -111,6 +128,19 @@ export declare class RayfinClient<TSchema extends EntitySchema = Record<string,
111
128
  *
112
129
  * const todos = await client.data.Todo.select(['id', 'title']).execute();
113
130
  * ```
131
+ *
132
+ * @example ALM-aware deployments — resolve runtime config, then construct
133
+ * ```typescript
134
+ * import { RayfinServerClient, resolveRayfinConfig } from '@microsoft/rayfin-client';
135
+ *
136
+ * // Node.js/workers have no implicit document origin, so pass an absolute
137
+ * // configUrl to enable remote config loading.
138
+ * const resolved = await resolveRayfinConfig(
139
+ * { baseUrl, publishableKey },
140
+ * { configUrl: `${process.env.RAYFIN_API_URL}/rayfin.config.json` }
141
+ * );
142
+ * const client = new RayfinServerClient({ ...resolved, accessToken });
143
+ * ```
114
144
  */
115
145
  export declare class RayfinServerClient<TSchema extends EntitySchema = Record<string, any>> extends RayfinClientBase<TSchema> {
116
146
  /**
@@ -119,6 +149,8 @@ export declare class RayfinServerClient<TSchema extends EntitySchema = Record<st
119
149
  * @param config - Client configuration, including the access token (string or
120
150
  * function form for per-request rotation).
121
151
  */
152
+ /** All resolved `rayfin.config.json` values, for callers that need more than just `baseUrl`/`publishableKey`. */
153
+ readonly runtimeConfig?: RayfinRuntimeConfig;
122
154
  constructor(config: RayfinServerClientConfig);
123
155
  }
124
156
  export default RayfinClient;
package/dist/client.js CHANGED
@@ -49,6 +49,7 @@ export class RayfinClientBase {
49
49
  functionsBaseUrl: config.functionsBaseUrl,
50
50
  useProxy: config.useProxy,
51
51
  headers: config.headers,
52
+ moniker: config.runtimeConfig?.itemId,
52
53
  timeout: config.timeout,
53
54
  getAccessToken: config.getAccessToken,
54
55
  });
@@ -87,12 +88,22 @@ export class RayfinClientBase {
87
88
  * .where({ isActive: true })
88
89
  * .execute();
89
90
  * ```
91
+ *
92
+ * @example ALM-aware deployments — resolve runtime config, then construct
93
+ * ```typescript
94
+ * import { RayfinClient, resolveRayfinConfig } from '@microsoft/rayfin-client';
95
+ *
96
+ * const resolved = await resolveRayfinConfig({ baseUrl, publishableKey });
97
+ * const client = new RayfinClient({ ...resolved, authStorage: true });
98
+ * ```
90
99
  */
91
100
  export class RayfinClient extends RayfinClientBase {
92
101
  /** Authentication operations (sign up, sign in, sign out, session state). */
93
102
  auth;
94
103
  /** Typed, schema-aware accessors for invoking your backend functions. */
95
104
  functions;
105
+ /** All resolved `rayfin.config.json` values, for apps that need more than just `baseUrl`/`publishableKey` (e.g. Fabric embed auth coordinates). */
106
+ runtimeConfig;
96
107
  /**
97
108
  * Creates a browser Rayfin client and wires up authentication.
98
109
  *
@@ -108,6 +119,7 @@ export class RayfinClient extends RayfinClientBase {
108
119
  });
109
120
  this.auth.attachToClient(this.apiClient);
110
121
  this.functions = createFunctionsApi(this.apiClient);
122
+ this.runtimeConfig = config.runtimeConfig;
111
123
  }
112
124
  }
113
125
  /**
@@ -124,6 +136,19 @@ export class RayfinClient extends RayfinClientBase {
124
136
  *
125
137
  * const todos = await client.data.Todo.select(['id', 'title']).execute();
126
138
  * ```
139
+ *
140
+ * @example ALM-aware deployments — resolve runtime config, then construct
141
+ * ```typescript
142
+ * import { RayfinServerClient, resolveRayfinConfig } from '@microsoft/rayfin-client';
143
+ *
144
+ * // Node.js/workers have no implicit document origin, so pass an absolute
145
+ * // configUrl to enable remote config loading.
146
+ * const resolved = await resolveRayfinConfig(
147
+ * { baseUrl, publishableKey },
148
+ * { configUrl: `${process.env.RAYFIN_API_URL}/rayfin.config.json` }
149
+ * );
150
+ * const client = new RayfinServerClient({ ...resolved, accessToken });
151
+ * ```
127
152
  */
128
153
  export class RayfinServerClient extends RayfinClientBase {
129
154
  /**
@@ -132,6 +157,8 @@ export class RayfinServerClient extends RayfinClientBase {
132
157
  * @param config - Client configuration, including the access token (string or
133
158
  * function form for per-request rotation).
134
159
  */
160
+ /** All resolved `rayfin.config.json` values, for callers that need more than just `baseUrl`/`publishableKey`. */
161
+ runtimeConfig;
135
162
  constructor(config) {
136
163
  super(config);
137
164
  if (config.accessToken !== undefined) {
@@ -140,6 +167,7 @@ export class RayfinServerClient extends RayfinClientBase {
140
167
  : () => config.accessToken;
141
168
  this.apiClient.setAccessTokenCallback(tokenFn);
142
169
  }
170
+ this.runtimeConfig = config.runtimeConfig;
143
171
  }
144
172
  }
145
173
  // Default export remains the browser client for backward compatibility.
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Runtime configuration loading for Rayfin SPAs.
3
+ *
4
+ * Instead of baking environment-specific values into the bundle at build time
5
+ * (via `import.meta.env.VITE_*`), the SPA fetches a `rayfin.config.json` file
6
+ * at startup. This allows the same compiled bundle to work across all
7
+ * environments — only the config file changes per stage.
8
+ *
9
+ * The file is a deploy-time artifact: `rayfin up` emits it into the static
10
+ * build so it is bundled and served alongside the app, then removes it from the
11
+ * working tree afterward. In local development the file is intentionally absent
12
+ * — `rayfin dev` relies on build-time `VITE_*` values instead — so
13
+ * `loadRayfinConfig` returns `null` and the SPA falls back to those values.
14
+ */
15
+ /**
16
+ * Error thrown when runtime configuration loading fails.
17
+ */
18
+ export declare class RayfinConfigError extends Error {
19
+ readonly code: string;
20
+ constructor(message: string, code: string);
21
+ }
22
+ /**
23
+ * Runtime configuration shape for a Rayfin SPA.
24
+ * Loaded from `rayfin.config.json` at startup — contains only
25
+ * deployment-specific values that change per environment.
26
+ * Service mode (mock / rayfin / fabric) is controlled separately
27
+ * via `VITE_SERVICE_MODE` and is not part of this config.
28
+ */
29
+ export interface RayfinConfig {
30
+ /** Base URL of the Rayfin backend API. */
31
+ apiUrl: string;
32
+ /** Publishable key for service-level authentication. */
33
+ publishableKey?: string;
34
+ /** Fabric workspace ID (present in Fabric deployments). */
35
+ workspaceId?: string;
36
+ /** Fabric item ID (present in Fabric deployments). */
37
+ itemId?: string;
38
+ /** Fabric portal URL (present in Fabric deployments). */
39
+ portalUrl?: string;
40
+ /** Fabric tenant ID (present in Fabric deployments). */
41
+ tenantId?: string;
42
+ }
43
+ /**
44
+ * Loads the Rayfin runtime configuration from the well-known config file.
45
+ *
46
+ * @param path - Override the config file URL (defaults to `/rayfin.config.json`).
47
+ * @returns The validated runtime configuration, or `null` if the config is
48
+ * genuinely absent (HTTP 404, an HTML SPA fallback body, or — in a
49
+ * non-browser runtime with no explicit `configUrl` — a relative path with
50
+ * no origin to resolve against). Throws {@link RayfinConfigError} if the
51
+ * file could not be loaded for any other reason (`CONFIG_LOAD_FAILED`,
52
+ * e.g. a 5xx or 401/403 response, or a fetch-level failure such as a
53
+ * network error — these are real failures, not absence, and are not
54
+ * silently swallowed), or if the file is present but malformed or
55
+ * incomplete (`CONFIG_PARSE_FAILED`, `CONFIG_INVALID`, `CONFIG_INCOMPLETE`).
56
+ *
57
+ * Not part of the public API — {@link resolveRayfinConfig} calls this
58
+ * internally. Prefer that over calling this directly.
59
+ */
60
+ export declare function loadRayfinConfig(path?: string): Promise<RayfinConfig | null>;
61
+ /**
62
+ * Options controlling how {@link resolveRayfinConfig} fetches remote runtime
63
+ * configuration. To skip remote loading entirely, don't call it — construct
64
+ * the client directly from your own values instead.
65
+ */
66
+ export interface ResolveRayfinConfigOptions {
67
+ /**
68
+ * Absolute URL to fetch the runtime config from, overriding the default
69
+ * relative `/rayfin.config.json`.
70
+ *
71
+ * The default relative path only resolves in a browser, where `fetch`
72
+ * implicitly uses the page's document origin. Non-browser runtimes (e.g.
73
+ * `RayfinServerClient` in Node.js) have no such origin, so omitting
74
+ * `configUrl` there skips the fetch entirely and falls back to
75
+ * caller-supplied values, rather than attempting a relative fetch that
76
+ * would always reject. Pass an absolute `configUrl` (e.g.
77
+ * `${process.env.RAYFIN_API_URL}/rayfin.config.json`) to enable remote
78
+ * config loading outside the browser — once set (or in the browser, where
79
+ * a fetch is always attempted), a fetch failure (unreachable host,
80
+ * DNS/TLS error, offline, etc.) throws {@link RayfinConfigError}
81
+ * (`CONFIG_LOAD_FAILED`) rather than silently falling back, since it's a
82
+ * real failure, not evidence of absence.
83
+ */
84
+ configUrl?: string;
85
+ }
86
+ /**
87
+ * All `rayfin.config.json` values as a single optional-field bag — every
88
+ * field is optional because neither the remote config nor a caller-supplied
89
+ * set of defaults is guaranteed to provide it. Used both as the defaults
90
+ * shape (typically build-time `VITE_*` values) and as the resolved shape
91
+ * returned by {@link resolveRayfinConfig}.
92
+ */
93
+ export interface RayfinRuntimeConfig {
94
+ /** Base URL of the Rayfin backend API. */
95
+ apiUrl?: string;
96
+ /** Publishable key for service-level authentication. */
97
+ publishableKey?: string;
98
+ /** Fabric workspace ID (present in Fabric deployments). */
99
+ workspaceId?: string;
100
+ /** Fabric item ID (present in Fabric deployments). */
101
+ itemId?: string;
102
+ /** Fabric portal URL (present in Fabric deployments). */
103
+ portalUrl?: string;
104
+ /** Fabric tenant ID (present in Fabric deployments). */
105
+ tenantId?: string;
106
+ }
107
+ /**
108
+ * Resolves the config a `RayfinClient` / `RayfinServerClient` should be
109
+ * constructed with: loads the remote `rayfin.config.json` (unless the caller
110
+ * skips calling this function entirely), overlays it over the supplied
111
+ * `defaults` per-field, and returns the merged `baseUrl` / `publishableKey` /
112
+ * `runtimeConfig`. Construction itself is a plain, synchronous
113
+ * `new RayfinClient(...)` call — this function only resolves values.
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * import { RayfinClient, resolveRayfinConfig } from '@microsoft/rayfin-client';
118
+ *
119
+ * const resolved = await resolveRayfinConfig({ baseUrl, publishableKey });
120
+ * const client = new RayfinClient({ ...resolved, authStorage: true });
121
+ * ```
122
+ */
123
+ export declare function resolveRayfinConfig(defaults: Pick<RayfinRuntimeConfig, 'apiUrl' | 'publishableKey'> & Partial<RayfinRuntimeConfig>, options?: ResolveRayfinConfigOptions): Promise<{
124
+ baseUrl?: string;
125
+ publishableKey?: string;
126
+ runtimeConfig: RayfinRuntimeConfig;
127
+ }>;
128
+ //# sourceMappingURL=config.d.ts.map
package/dist/config.js ADDED
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Runtime configuration loading for Rayfin SPAs.
3
+ *
4
+ * Instead of baking environment-specific values into the bundle at build time
5
+ * (via `import.meta.env.VITE_*`), the SPA fetches a `rayfin.config.json` file
6
+ * at startup. This allows the same compiled bundle to work across all
7
+ * environments — only the config file changes per stage.
8
+ *
9
+ * The file is a deploy-time artifact: `rayfin up` emits it into the static
10
+ * build so it is bundled and served alongside the app, then removes it from the
11
+ * working tree afterward. In local development the file is intentionally absent
12
+ * — `rayfin dev` relies on build-time `VITE_*` values instead — so
13
+ * `loadRayfinConfig` returns `null` and the SPA falls back to those values.
14
+ */
15
+ /**
16
+ * Error thrown when runtime configuration loading fails.
17
+ */
18
+ export class RayfinConfigError extends Error {
19
+ code;
20
+ constructor(message, code) {
21
+ super(message);
22
+ this.name = 'RayfinConfigError';
23
+ this.code = code;
24
+ }
25
+ }
26
+ /** Default path for the runtime config file (served from `public/`). */
27
+ const DEFAULT_CONFIG_PATH = '/rayfin.config.json';
28
+ /**
29
+ * Loads the Rayfin runtime configuration from the well-known config file.
30
+ *
31
+ * @param path - Override the config file URL (defaults to `/rayfin.config.json`).
32
+ * @returns The validated runtime configuration, or `null` if the config is
33
+ * genuinely absent (HTTP 404, an HTML SPA fallback body, or — in a
34
+ * non-browser runtime with no explicit `configUrl` — a relative path with
35
+ * no origin to resolve against). Throws {@link RayfinConfigError} if the
36
+ * file could not be loaded for any other reason (`CONFIG_LOAD_FAILED`,
37
+ * e.g. a 5xx or 401/403 response, or a fetch-level failure such as a
38
+ * network error — these are real failures, not absence, and are not
39
+ * silently swallowed), or if the file is present but malformed or
40
+ * incomplete (`CONFIG_PARSE_FAILED`, `CONFIG_INVALID`, `CONFIG_INCOMPLETE`).
41
+ *
42
+ * Not part of the public API — {@link resolveRayfinConfig} calls this
43
+ * internally. Prefer that over calling this directly.
44
+ */
45
+ export async function loadRayfinConfig(path = DEFAULT_CONFIG_PATH) {
46
+ if (typeof window === 'undefined' && path === DEFAULT_CONFIG_PATH) {
47
+ // Non-browser runtime with no explicit configUrl: a relative fetch has
48
+ // no origin to resolve against and would always reject. Skip it rather
49
+ // than triggering (and swallowing) that rejection — callers that want
50
+ // remote config outside the browser must pass an absolute configUrl.
51
+ return null;
52
+ }
53
+ let response;
54
+ try {
55
+ response = await fetch(path);
56
+ }
57
+ catch (err) {
58
+ // A fetch-level failure (offline, DNS, CORS, a transient network error)
59
+ // is a real failure, not absence — local-dev absence is identified below
60
+ // via 404 / the SPA HTML fallback, once a response is actually received.
61
+ // Swallowing this would let a promoted Prod bundle silently keep using
62
+ // its compiled Dev endpoint and key.
63
+ throw new RayfinConfigError(`Failed to load Rayfin config from "${path}": ` +
64
+ `${err instanceof Error ? err.message : String(err)}.`, 'CONFIG_LOAD_FAILED');
65
+ }
66
+ if (!response.ok) {
67
+ if (response.status === 404) {
68
+ // Genuinely absent (e.g. local dev, where no config was emitted).
69
+ return null;
70
+ }
71
+ // Any other non-2xx (5xx, 401/403, etc.) is a real load failure, not
72
+ // absence. Treating it as "absent" would silently fall back to the
73
+ // build-time source-stage values, which in a deployed stage can mean
74
+ // sending users to the wrong backend. Fail closed instead.
75
+ throw new RayfinConfigError(`Failed to load Rayfin config from "${path}": ` +
76
+ `${response.status} ${response.statusText}.`, 'CONFIG_LOAD_FAILED');
77
+ }
78
+ const contentType = response.headers.get('content-type')?.toLowerCase() ?? '';
79
+ const text = await response.text();
80
+ const trimmed = text.trimStart();
81
+ // A missing /rayfin.config.json is not always a 404: Vite's dev server and
82
+ // SPA static hosts serve index.html (200) for unknown paths. An HTML response
83
+ // therefore means "no config file" (e.g. local dev, where `rayfin dev` relies
84
+ // on build-time VITE_* values) — treat it as absent rather than a malformed
85
+ // config. Check the declared content type first, then fall back to sniffing
86
+ // the body for hosts that mislabel the fallback.
87
+ if (contentType.includes('html') || trimmed.startsWith('<')) {
88
+ return null;
89
+ }
90
+ let json;
91
+ try {
92
+ json = JSON.parse(trimmed);
93
+ }
94
+ catch {
95
+ throw new RayfinConfigError(`Rayfin config at "${path}" is not valid JSON.`, 'CONFIG_PARSE_FAILED');
96
+ }
97
+ return validateConfig(json, path);
98
+ }
99
+ function validateConfig(json, path) {
100
+ if (typeof json !== 'object' || json === null || Array.isArray(json)) {
101
+ throw new RayfinConfigError(`Rayfin config at "${path}" must be a JSON object.`, 'CONFIG_INVALID');
102
+ }
103
+ const obj = json;
104
+ const missing = [];
105
+ if (!obj.apiUrl || typeof obj.apiUrl !== 'string') {
106
+ missing.push('apiUrl');
107
+ }
108
+ if (missing.length > 0) {
109
+ throw new RayfinConfigError(`Rayfin config at "${path}" is incomplete. ` +
110
+ `Missing required fields: ${missing.join(', ')}.`, 'CONFIG_INCOMPLETE');
111
+ }
112
+ const rawApiUrl = obj.apiUrl;
113
+ const publishableKey = readOptionalStringField(obj, 'publishableKey', path);
114
+ const workspaceId = readOptionalStringField(obj, 'workspaceId', path);
115
+ const portalUrl = readOptionalStringField(obj, 'portalUrl', path);
116
+ const itemId = readOptionalStringField(obj, 'itemId', path);
117
+ const tenantId = readOptionalStringField(obj, 'tenantId', path);
118
+ const config = {
119
+ apiUrl: rawApiUrl.endsWith('/') ? rawApiUrl : `${rawApiUrl}/`,
120
+ ...(publishableKey ? { publishableKey } : {}),
121
+ };
122
+ if (workspaceId) {
123
+ config.workspaceId = workspaceId;
124
+ }
125
+ if (portalUrl) {
126
+ config.portalUrl = portalUrl;
127
+ }
128
+ if (itemId) {
129
+ config.itemId = itemId;
130
+ }
131
+ if (tenantId) {
132
+ config.tenantId = tenantId;
133
+ }
134
+ return config;
135
+ }
136
+ /**
137
+ * Reads an optional string field from a parsed config object.
138
+ *
139
+ * A missing, `null`, or empty-string value is treated as absent
140
+ * (`undefined`). A present value of any other type is a malformed config —
141
+ * rather than silently dropping it via an unchecked cast, this throws so the
142
+ * caller finds out immediately instead of the SDK crashing later with an
143
+ * untyped error (e.g. a numeric `publishableKey` reaching `.trim()`).
144
+ */
145
+ function readOptionalStringField(obj, field, path) {
146
+ const value = obj[field];
147
+ if (value === undefined || value === null || value === '') {
148
+ return undefined;
149
+ }
150
+ if (typeof value !== 'string') {
151
+ throw new RayfinConfigError(`Rayfin config at "${path}" has an invalid "${field}" field: ` +
152
+ `expected a string.`, 'CONFIG_INVALID');
153
+ }
154
+ return value;
155
+ }
156
+ /**
157
+ * Resolves the config a `RayfinClient` / `RayfinServerClient` should be
158
+ * constructed with: loads the remote `rayfin.config.json` (unless the caller
159
+ * skips calling this function entirely), overlays it over the supplied
160
+ * `defaults` per-field, and returns the merged `baseUrl` / `publishableKey` /
161
+ * `runtimeConfig`. Construction itself is a plain, synchronous
162
+ * `new RayfinClient(...)` call — this function only resolves values.
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * import { RayfinClient, resolveRayfinConfig } from '@microsoft/rayfin-client';
167
+ *
168
+ * const resolved = await resolveRayfinConfig({ baseUrl, publishableKey });
169
+ * const client = new RayfinClient({ ...resolved, authStorage: true });
170
+ * ```
171
+ */
172
+ export async function resolveRayfinConfig(defaults, options = {}) {
173
+ const remote = await loadRayfinConfig(options.configUrl);
174
+ const baseUrl = remote?.apiUrl ?? defaults.apiUrl;
175
+ const publishableKey = remote?.publishableKey ?? defaults.publishableKey;
176
+ return {
177
+ baseUrl,
178
+ publishableKey,
179
+ runtimeConfig: {
180
+ apiUrl: baseUrl,
181
+ publishableKey,
182
+ workspaceId: remote?.workspaceId ?? defaults.workspaceId,
183
+ itemId: remote?.itemId ?? defaults.itemId,
184
+ portalUrl: remote?.portalUrl ?? defaults.portalUrl,
185
+ tenantId: remote?.tenantId ?? defaults.tenantId,
186
+ },
187
+ };
188
+ }
189
+ //# sourceMappingURL=config.js.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from './client.js';
2
2
  export { default } from './client.js';
3
+ export { RayfinConfigError, resolveRayfinConfig } from './config.js';
4
+ export type { RayfinRuntimeConfig, ResolveRayfinConfigOptions } from './config.js';
3
5
  export type { TypedDataClients, EntitySchema } from '@microsoft/rayfin-data';
4
6
  export type { FunctionsSchema } from '@microsoft/rayfin-functions';
5
7
  export type { ApiClientConfig } from '@microsoft/rayfin-lib';
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  // Export all from client.ts
2
2
  export * from './client.js';
3
3
  export { default } from './client.js';
4
+ // Runtime configuration loading
5
+ export { RayfinConfigError, resolveRayfinConfig } from './config.js';
4
6
  // Re-export deprecation silencing controls from rayfin-lib so consumers have a
5
7
  // stable public import path here; emitter helpers stay internal to the SDK.
6
8
  export { setDeprecationsSilenced, isDeprecationSilenced, } from '@microsoft/rayfin-lib';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/rayfin-client",
3
- "version": "1.35.0-alpha.1374",
3
+ "version": "1.35.0-alpha.1541",
4
4
  "description": "Main client SDK for Rayfin services",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,11 +21,11 @@
21
21
  "assets/docs"
22
22
  ],
23
23
  "dependencies": {
24
- "@microsoft/rayfin-auth": "1.35.0-alpha.1374",
25
- "@microsoft/rayfin-connectors": "1.35.0-alpha.1374",
26
- "@microsoft/rayfin-data": "1.35.0-alpha.1374",
27
- "@microsoft/rayfin-lib": "1.35.0-alpha.1374",
28
- "@microsoft/rayfin-functions": "1.35.0-alpha.1374"
24
+ "@microsoft/rayfin-connectors": "1.35.0-alpha.1541",
25
+ "@microsoft/rayfin-auth": "1.35.0-alpha.1541",
26
+ "@microsoft/rayfin-data": "1.35.0-alpha.1541",
27
+ "@microsoft/rayfin-lib": "1.35.0-alpha.1541",
28
+ "@microsoft/rayfin-functions": "1.35.0-alpha.1541"
29
29
  },
30
30
  "devDependencies": {
31
31
  "typescript": "^5.8.3",