@salesforce/sdk-data 1.21.0 → 1.29.1

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.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import type { DataSDK } from "@salesforce/sdk-core";
2
- export declare const sdk: DataSDK;
2
+ /**
3
+ * Create and initialize a DataSDK instance based on the detected surface
4
+ *
5
+ * @returns Promise resolving to an initialized DataSDK instance
6
+ */
7
+ export declare function createDataSDK(): Promise<DataSDK>;
3
8
  export { gql } from "./gql.js";
4
- export type { DataSDK } from "@salesforce/sdk-core";
9
+ export type { DataSDK, LabelRequest, ResourceUrlRequest, SchemaDescriptor, SchemaRequest, UserInfo, } from "@salesforce/sdk-core";
5
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAiBpD,eAAO,MAAM,GAAG,SAAe,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,YAAY,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGpD;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAetD;AAED,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,YAAY,EACX,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,QAAQ,GACR,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -4,19 +4,26 @@
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
6
  import { getSurface, Surface } from "@salesforce/sdk-core";
7
- import { OpenAIDataSDK } from "./openai/index.js";
8
7
  import { WebAppDataSDK } from "./webapp/index.js";
9
- function initialize() {
8
+ /**
9
+ * Create and initialize a DataSDK instance based on the detected surface
10
+ *
11
+ * @returns Promise resolving to an initialized DataSDK instance
12
+ */
13
+ export async function createDataSDK() {
10
14
  const surface = getSurface();
11
15
  switch (surface) {
12
16
  case Surface.OpenAI:
13
- return new OpenAIDataSDK();
14
- case Surface.Webapp:
17
+ return {};
18
+ case Surface.WebApp:
15
19
  case Surface.MicroFrontend:
16
20
  return new WebAppDataSDK();
21
+ case Surface.SalesforceACC:
22
+ return {};
23
+ case Surface.MCPApps:
24
+ return {};
17
25
  default:
18
26
  return {};
19
27
  }
20
28
  }
21
- export const sdk = initialize();
22
29
  export { gql } from "./gql.js";
@@ -1,9 +1,5 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
1
  import type { DataSDK, GraphQLResponse } from "@salesforce/sdk-core";
2
+ export declare const API_VERSION: string;
7
3
  /**
8
4
  * Data SDK implementation for web apps, which is based on making `fetch` calls to REST endpoints
9
5
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webapp/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGrE;;GAEG;AACH,qBAAa,aAAc,YAAW,OAAO;IACtC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAK9E,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;CAG3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webapp/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQrE,eAAO,MAAM,WAAW,QAA+B,CAAC;AAexD;;GAEG;AACH,qBAAa,aAAc,YAAW,OAAO;IACtC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAaxE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;CAgBjF"}
@@ -1,13 +1,78 @@
1
- import { baseDataClient, conduitClient } from "./clients.js";
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { ConduitClient } from "@conduit-client/salesforce-lightning-service-worker";
7
+ const CACHE_VERSION = 1;
8
+ const CACHE_NAME = `@salesforce/sdk-data_v${CACHE_VERSION}`;
9
+ export const API_VERSION = __SF_API_VERSION__ || "65.0";
10
+ const BASE = __SF_SERVER_BASE_PATH__ || "";
11
+ const PATH_DATA = `/services/data/v${API_VERSION}`;
12
+ const PATH_UIAPI = `${PATH_DATA}/ui-api`;
13
+ ConduitClient.initialize({
14
+ csrf: {
15
+ endpoint: `${BASE}${PATH_UIAPI}/session/csrf`,
16
+ cacheName: CACHE_NAME,
17
+ protectedUrls: ["/services/data/v"],
18
+ },
19
+ });
20
+ const conduitClient = ConduitClient.instance();
2
21
  /**
3
22
  * Data SDK implementation for web apps, which is based on making `fetch` calls to REST endpoints
4
23
  */
5
24
  export class WebAppDataSDK {
6
25
  async graphql(query, variables) {
7
- const res = await baseDataClient.post("/graphql", { query, variables });
26
+ const res = await this.fetch(`${PATH_DATA}/graphql`, {
27
+ method: "POST",
28
+ body: JSON.stringify({ query, variables }),
29
+ headers: {
30
+ "Content-Type": "application/json",
31
+ Accept: "application/json",
32
+ },
33
+ });
8
34
  return res.json();
9
35
  }
10
- fetch(input, init) {
11
- return conduitClient.fetch(input, init);
36
+ async fetch(input, init) {
37
+ const updatedInput = applySalesforceBase(input);
38
+ const response = await conduitClient.fetch(updatedInput, init);
39
+ // NOTE: In dev mode the server proxy owns authentication (adding, refreshing, etc., as needed). If it
40
+ // fails to do so properly then the result will be a reload infinite loop. As for deployed mode, reload
41
+ // triggers the standard Salesforce authentication checks/flow.
42
+ if (response.status === 401 || response.status === 403) {
43
+ if (import.meta.env.PROD) {
44
+ window.location.reload();
45
+ }
46
+ }
47
+ return response;
48
+ }
49
+ }
50
+ /**
51
+ * If the url is relative, convert to it to an absolute Salesforce URL. This is due to the way Code
52
+ * Builder deployments structure the url for Salesforce
53
+ *
54
+ * @param input
55
+ */
56
+ function applySalesforceBase(input) {
57
+ // Handle string input
58
+ if (typeof input === "string") {
59
+ if (input.startsWith("http")) {
60
+ // already absolute, return as-is
61
+ return input;
62
+ }
63
+ // make absolute
64
+ return BASE + input;
65
+ }
66
+ // Handle Request input
67
+ if (input instanceof Request) {
68
+ const url = input.url;
69
+ if (url.startsWith("http")) {
70
+ // already absolute, return as-is
71
+ return input;
72
+ }
73
+ // make absolute
74
+ return new Request(BASE + url, input);
12
75
  }
76
+ // URLs require a protocol and domain, thus are already absolute
77
+ return input;
13
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/sdk-data",
3
- "version": "1.21.0",
3
+ "version": "1.29.1",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@conduit-client/salesforce-lightning-service-worker": "^3.7.0",
30
- "@salesforce/sdk-core": "^1.21.0"
30
+ "@salesforce/sdk-core": "^1.29.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "vitest": "^4.0.6"
@@ -35,5 +35,5 @@
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  },
38
- "gitHead": "8a7b85936ce26a4200ee052fb09f981e738bdb89"
38
+ "gitHead": "a9638ee25f6b90f08f032bb06fabc218a3b0ebd4"
39
39
  }
@@ -1,12 +0,0 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- import type { DataSDK } from "@salesforce/sdk-core";
7
- /**
8
- * Data SDK implementation based on the existence of `window.openai`
9
- */
10
- export declare class OpenAIDataSDK implements DataSDK {
11
- }
12
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;GAEG;AACH,qBAAa,aAAc,YAAW,OAAO;CAAG"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Data SDK implementation based on the existence of `window.openai`
3
- */
4
- export class OpenAIDataSDK {
5
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- export {};
7
- //# sourceMappingURL=clients.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"clients.test.d.ts","sourceRoot":"","sources":["../../../src/webapp/__tests__/clients.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,154 +0,0 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- import { ConduitClient } from "@conduit-client/salesforce-lightning-service-worker";
7
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
8
- import { baseDataClient } from "../clients.js";
9
- vi.mock("@conduit-client/salesforce-lightning-service-worker", () => {
10
- return {
11
- ConduitClient: {
12
- initialize: vi.fn(),
13
- instance: vi.fn().mockReturnValue({ fetch: vi.fn() }),
14
- },
15
- };
16
- });
17
- // Mock window.location.reload
18
- const mockReload = vi.fn();
19
- vi.stubGlobal("window", {
20
- location: { reload: mockReload },
21
- });
22
- describe("clients", () => {
23
- let mockFetch;
24
- beforeEach(() => {
25
- const mockClient = vi.mocked(ConduitClient.instance());
26
- mockFetch = mockClient.fetch;
27
- mockFetch.mockClear();
28
- mockReload.mockClear();
29
- });
30
- afterEach(() => {
31
- vi.clearAllMocks();
32
- });
33
- it("should have configured ConduitClient", () => {
34
- expect(ConduitClient.initialize).toHaveBeenCalledWith({
35
- csrf: {
36
- endpoint: "/services/data/v99.0/ui-api/session/csrf",
37
- cacheName: "vibe-coding-starter-1",
38
- protectedUrls: ["/services/data/v", "/lwr/apex/v"],
39
- },
40
- });
41
- });
42
- describe("HTTP methods", () => {
43
- beforeEach(() => {
44
- mockFetch.mockResolvedValue({
45
- status: 200,
46
- json: () => Promise.resolve({ success: true }),
47
- });
48
- });
49
- it("should make GET requests", async () => {
50
- await baseDataClient.get("/users");
51
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users", {
52
- method: "GET",
53
- headers: {
54
- "Content-Type": "application/json",
55
- Accept: "application/json",
56
- },
57
- });
58
- });
59
- it("should make POST requests with JSON body", async () => {
60
- const data = { name: "John" };
61
- await baseDataClient.post("/users", data);
62
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users", {
63
- method: "POST",
64
- body: JSON.stringify(data),
65
- headers: {
66
- "Content-Type": "application/json",
67
- Accept: "application/json",
68
- },
69
- });
70
- });
71
- it("should make PUT requests with JSON body", async () => {
72
- const data = { name: "John Updated" };
73
- await baseDataClient.put("/users/1", data);
74
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users/1", {
75
- method: "PUT",
76
- body: JSON.stringify(data),
77
- headers: {
78
- "Content-Type": "application/json",
79
- Accept: "application/json",
80
- },
81
- });
82
- });
83
- it("should make PATCH requests with JSON body", async () => {
84
- const data = { name: "John Patched" };
85
- await baseDataClient.patch("/users/1", data);
86
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users/1", {
87
- method: "PATCH",
88
- body: JSON.stringify(data),
89
- headers: {
90
- "Content-Type": "application/json",
91
- Accept: "application/json",
92
- },
93
- });
94
- });
95
- it("should make DELETE requests", async () => {
96
- await baseDataClient.delete("/users/1");
97
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users/1", {
98
- method: "DELETE",
99
- headers: {
100
- "Content-Type": "application/json",
101
- Accept: "application/json",
102
- },
103
- });
104
- });
105
- });
106
- describe("body processing", () => {
107
- beforeEach(() => {
108
- mockFetch.mockResolvedValue({
109
- status: 200,
110
- json: () => Promise.resolve({}),
111
- });
112
- });
113
- it.each([
114
- { name: "null", value: null },
115
- { name: "undefined", value: undefined },
116
- { name: "other", value: () => "dummy" },
117
- ])("should return undefined for $name body", async ({ value }) => {
118
- await baseDataClient.post("/users", value);
119
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users", expect.objectContaining({ body: undefined }));
120
- });
121
- it("should use string bodies as is", async () => {
122
- const data = "foobar";
123
- await baseDataClient.post("/users", data);
124
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users", expect.objectContaining({
125
- body: "foobar",
126
- }));
127
- });
128
- it("should stringify object bodies for JSON content-type", async () => {
129
- const data = { name: "John" };
130
- await baseDataClient.post("/users", data);
131
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users", expect.objectContaining({
132
- body: JSON.stringify(data),
133
- }));
134
- });
135
- it("should not stringify non-object bodies", async () => {
136
- const formData = new FormData();
137
- await baseDataClient.post("/upload", formData);
138
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/upload", expect.objectContaining({
139
- body: formData,
140
- }));
141
- });
142
- it("should not stringify when content-type is not JSON", async () => {
143
- const data = { name: "John" };
144
- await baseDataClient.post("/users", data, {
145
- headers: { "Content-Type": "multipart/form-data" },
146
- });
147
- // When content-type is not JSON and body is a plain object (not FormData/string),
148
- // processBody returns undefined since it can't serialize non-JSON content
149
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/users", expect.objectContaining({
150
- body: undefined,
151
- }));
152
- });
153
- });
154
- });
@@ -1,23 +0,0 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- import { ConduitClient } from "@conduit-client/salesforce-lightning-service-worker";
7
- export declare const API_VERSION: string;
8
- export declare const conduitClient: ConduitClient;
9
- export declare class ApiClient {
10
- private readonly baseURL;
11
- private readonly defaultOptions;
12
- constructor(baseURL: string, defaultOptions?: RequestInit);
13
- private isJsonContentType;
14
- private fetch;
15
- private processBody;
16
- post(url: string, body?: unknown, options?: RequestInit): Promise<Response>;
17
- get(url: string, options?: RequestInit): Promise<Response>;
18
- put(url: string, body?: unknown, options?: RequestInit): Promise<Response>;
19
- patch(url: string, body?: unknown, options?: RequestInit): Promise<Response>;
20
- delete(url: string, options?: RequestInit): Promise<Response>;
21
- }
22
- export declare const baseDataClient: ApiClient;
23
- //# sourceMappingURL=clients.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/webapp/clients.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAC;AAMpF,eAAO,MAAM,WAAW,QAA+B,CAAC;AAkBxD,eAAO,MAAM,aAAa,eAA2B,CAAC;AAEtD,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;gBAEjC,OAAO,EAAE,MAAM,EAAE,cAAc,GAAE,WAAgB;IAY7D,OAAO,CAAC,iBAAiB;YASX,KAAK;IAenB,OAAO,CAAC,WAAW;IAab,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ/E,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI9D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ9E,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQhF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAGvE;AAED,eAAO,MAAM,cAAc,WAAwC,CAAC"}
@@ -1,100 +0,0 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- import { ConduitClient } from "@conduit-client/salesforce-lightning-service-worker";
7
- // Project standard API version from environment variable with fallback
8
- export const API_VERSION = __SF_API_VERSION__ || "65.0";
9
- const BASE = __SF_SERVER_BASE_PATH__ || "";
10
- const SERVICES = `/services`;
11
- const DATA = `/data/v${API_VERSION}`;
12
- const UI_API = `/ui-api`;
13
- const CACHE_VERSION = 1;
14
- const CACHE_NAME = `vibe-coding-starter-${CACHE_VERSION}`;
15
- ConduitClient.initialize({
16
- csrf: {
17
- endpoint: BASE + SERVICES + DATA + UI_API + "/session/csrf",
18
- cacheName: CACHE_NAME,
19
- protectedUrls: ["/services/data/v", "/lwr/apex/v"],
20
- },
21
- });
22
- export const conduitClient = ConduitClient.instance();
23
- export class ApiClient {
24
- baseURL;
25
- defaultOptions;
26
- constructor(baseURL, defaultOptions = {}) {
27
- this.baseURL = baseURL;
28
- this.defaultOptions = {
29
- ...defaultOptions,
30
- headers: {
31
- "Content-Type": "application/json",
32
- Accept: "application/json",
33
- ...(defaultOptions.headers || {}),
34
- },
35
- };
36
- }
37
- isJsonContentType(headers) {
38
- // default to JSON if no headers specified
39
- if (!headers)
40
- return true;
41
- const headersObj = new Headers(headers);
42
- const contentType = headersObj.get("content-type");
43
- return !contentType || contentType.includes("application/json");
44
- }
45
- async fetch(info, options = {}) {
46
- const fullURL = info instanceof URL || info.startsWith("http") ? info : `${this.baseURL}${info}`;
47
- const mergedOptions = {
48
- ...this.defaultOptions,
49
- ...options,
50
- headers: {
51
- ...this.defaultOptions.headers,
52
- ...(options.headers || {}),
53
- },
54
- };
55
- return await conduitClient.fetch(fullURL, mergedOptions);
56
- }
57
- processBody(body, options) {
58
- if (body === undefined || body === null) {
59
- return undefined;
60
- }
61
- else if (body instanceof FormData) {
62
- return body;
63
- }
64
- else if (typeof body === "string") {
65
- return body;
66
- }
67
- else if (typeof body === "object" && this.isJsonContentType(options.headers)) {
68
- return JSON.stringify(body);
69
- }
70
- return undefined;
71
- }
72
- async post(url, body, options = {}) {
73
- return this.fetch(url, {
74
- method: "POST",
75
- body: this.processBody(body, options),
76
- ...options,
77
- });
78
- }
79
- async get(url, options = {}) {
80
- return this.fetch(url, { method: "GET", ...options });
81
- }
82
- async put(url, body, options = {}) {
83
- return this.fetch(url, {
84
- method: "PUT",
85
- body: this.processBody(body, options),
86
- ...options,
87
- });
88
- }
89
- async patch(url, body, options = {}) {
90
- return this.fetch(url, {
91
- method: "PATCH",
92
- body: this.processBody(body, options),
93
- ...options,
94
- });
95
- }
96
- async delete(url, options = {}) {
97
- return this.fetch(url, { method: "DELETE", ...options });
98
- }
99
- }
100
- export const baseDataClient = new ApiClient(BASE + SERVICES + DATA);