@salesforce/webapp-experimental 1.80.1 → 1.82.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 (52) hide show
  1. package/dist/api/clients.js +72 -77
  2. package/dist/api/index.d.ts +4 -4
  3. package/dist/api/index.d.ts.map +1 -1
  4. package/dist/api/index.js +13 -11
  5. package/dist/api/utils/accounts.js +16 -30
  6. package/dist/api/utils/records.js +21 -20
  7. package/dist/api/utils/user.js +20 -28
  8. package/dist/app/index.d.ts +4 -4
  9. package/dist/app/index.d.ts.map +1 -1
  10. package/dist/app/index.js +7 -7
  11. package/dist/app/manifest.js +23 -37
  12. package/dist/app/org.js +45 -58
  13. package/dist/design/index.js +12 -19
  14. package/dist/design/interactions/interactionsController.d.ts +1 -6
  15. package/dist/design/interactions/interactionsController.d.ts.map +1 -1
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +25 -10
  19. package/dist/package.json.js +4 -0
  20. package/dist/proxy/handler.d.ts +2 -7
  21. package/dist/proxy/handler.d.ts.map +1 -1
  22. package/dist/proxy/handler.js +462 -523
  23. package/dist/proxy/index.d.ts +2 -2
  24. package/dist/proxy/index.d.ts.map +1 -1
  25. package/dist/proxy/index.js +7 -6
  26. package/dist/proxy/livePreviewScript.js +11 -26
  27. package/dist/proxy/routing.d.ts +1 -6
  28. package/dist/proxy/routing.d.ts.map +1 -1
  29. package/dist/proxy/routing.js +73 -103
  30. package/package.json +7 -6
  31. package/dist/api/clients.test.d.ts +0 -7
  32. package/dist/api/clients.test.d.ts.map +0 -1
  33. package/dist/api/clients.test.js +0 -167
  34. package/dist/api/graphql-operations-types.js +0 -44
  35. package/dist/api/utils/records.test.d.ts +0 -7
  36. package/dist/api/utils/records.test.d.ts.map +0 -1
  37. package/dist/api/utils/records.test.js +0 -190
  38. package/dist/api/utils/user.test.d.ts +0 -7
  39. package/dist/api/utils/user.test.d.ts.map +0 -1
  40. package/dist/api/utils/user.test.js +0 -108
  41. package/dist/design/interactions/communicationManager.js +0 -108
  42. package/dist/design/interactions/componentMatcher.js +0 -80
  43. package/dist/design/interactions/editableManager.js +0 -95
  44. package/dist/design/interactions/eventHandlers.js +0 -125
  45. package/dist/design/interactions/index.js +0 -47
  46. package/dist/design/interactions/interactionsController.js +0 -135
  47. package/dist/design/interactions/styleManager.js +0 -97
  48. package/dist/design/interactions/utils/cssUtils.js +0 -72
  49. package/dist/design/interactions/utils/sourceUtils.js +0 -99
  50. package/dist/proxy/livePreviewScript.test.d.ts +0 -7
  51. package/dist/proxy/livePreviewScript.test.d.ts.map +0 -1
  52. package/dist/proxy/livePreviewScript.test.js +0 -96
@@ -3,6 +3,6 @@
3
3
  * All rights reserved.
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
- export type { ProxyOptions, ProxyHandler } from "./handler.js";
7
- export { createProxyHandler, injectLivePreviewScript, WEBAPP_HEALTH_CHECK_PARAM, WEBAPP_PROXY_HEADER, } from "./handler.js";
6
+ export type { ProxyOptions, ProxyHandler } from './handler';
7
+ export { createProxyHandler, injectLivePreviewScript, WEBAPP_HEALTH_CHECK_PARAM, WEBAPP_PROXY_HEADER, } from './handler';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACnB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACnB,MAAM,WAAW,CAAC"}
@@ -1,6 +1,7 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- export { createProxyHandler, injectLivePreviewScript, WEBAPP_HEALTH_CHECK_PARAM, WEBAPP_PROXY_HEADER, } from "./handler.js";
1
+ import { WEBAPP_HEALTH_CHECK_PARAM, WEBAPP_PROXY_HEADER, createProxyHandler, injectLivePreviewScript } from "./handler.js";
2
+ export {
3
+ WEBAPP_HEALTH_CHECK_PARAM,
4
+ WEBAPP_PROXY_HEADER,
5
+ createProxyHandler,
6
+ injectLivePreviewScript
7
+ };
@@ -1,31 +1,16 @@
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 { readFileSync } from "node:fs";
7
2
  import { dirname, join } from "node:path";
8
3
  import { fileURLToPath } from "node:url";
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
4
+ const __dirname$1 = dirname(fileURLToPath(import.meta.url));
10
5
  let cached = null;
11
- /**
12
- * Returns the JavaScript source that gets injected into previewed web apps.
13
- * Reads from templates/livePreviewScript.js at runtime (copied to dist/ by postbuild).
14
- * Cached after first read.
15
- *
16
- * Responsibilities:
17
- * - Fetch interceptor for network-error detection (runs synchronously on load)
18
- * - Runtime / compile / HMR error listeners
19
- * - Error deduplication
20
- * - postMessage bridge to the VS Code webview (when running inside an iframe)
21
- * - Copy / paste / right-click bridge for VS Code webview
22
- */
23
- export function getLivePreviewScriptContent() {
24
- if (cached)
25
- return cached;
26
- const scriptPath = join(__dirname, "templates", "livePreviewScript.js");
27
- cached = readFileSync(scriptPath, "utf-8");
28
- return cached;
6
+ function getLivePreviewScriptContent() {
7
+ if (cached) return cached;
8
+ const scriptPath = join(__dirname$1, "templates", "livePreviewScript.js");
9
+ cached = readFileSync(scriptPath, "utf-8");
10
+ return cached;
29
11
  }
30
- /** Data attribute used to detect (and prevent) double injection. */
31
- export const LIVE_PREVIEW_SCRIPT_MARKER = "data-live-preview";
12
+ const LIVE_PREVIEW_SCRIPT_MARKER = "data-live-preview";
13
+ export {
14
+ LIVE_PREVIEW_SCRIPT_MARKER,
15
+ getLivePreviewScriptContent
16
+ };
@@ -1,9 +1,4 @@
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 { RedirectRule, RewriteRule } from "../app/index.js";
1
+ import { RedirectRule, RewriteRule } from '../app/index';
7
2
  export interface RouteMatch {
8
3
  type: "rewrite" | "redirect" | "api" | "gql" | "file-upload";
9
4
  target?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/proxy/routing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEjE,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,aAAa,CAAC;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AASD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,WAAW,EAAE,EACxB,SAAS,CAAC,EAAE,YAAY,EAAE,GACxB,UAAU,GAAG,IAAI,CAqEnB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,OAAO,CAMpF;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GACzC,MAAM,CAiBR"}
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/proxy/routing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE9D,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,aAAa,CAAC;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AASD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,WAAW,EAAE,EACxB,SAAS,CAAC,EAAE,YAAY,EAAE,GACxB,UAAU,GAAG,IAAI,CAqEnB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,OAAO,CAMpF;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GACzC,MAAM,CAiBR"}
@@ -1,113 +1,83 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- import micromatch from "micromatch";
1
+ import "micromatch";
7
2
  import { match } from "path-to-regexp";
8
3
  function normalizeRoute(route) {
9
- let wildcardIndex = 0;
10
- return route.replace(/\*/g, () => {
11
- return `{*wildcard${wildcardIndex++}}`;
12
- });
4
+ let wildcardIndex = 0;
5
+ return route.replace(/\*/g, () => {
6
+ return `{*wildcard${wildcardIndex++}}`;
7
+ });
13
8
  }
14
- /**
15
- * Match URL path against routing rules
16
- *
17
- * @param pathname - The URL pathname to match
18
- * @param basePath - Optional base path of Salesforce server
19
- * @param rewrites - Optional array of rewrite rules
20
- * @param redirects - Optional array of redirect rules
21
- * @returns Route match result indicating the type and target, or null if no match
22
- */
23
- export function matchRoute(pathname, basePath, rewrites, redirects) {
24
- // under services, only allow graphql, ui-api, and file upload config instead of allowing all connect endpoints
25
- const servicesRegex = new RegExp(`^${basePath || ""}/services/data/v\\d{2}\\.\\d/(graphql|ui-api|connect/file/upload/config)`);
26
- if (servicesRegex.test(pathname) || pathname.startsWith(`${basePath || ""}/lwr/apex/v`)) {
27
- return { type: "api" };
28
- }
29
- if (pathname.startsWith(`${basePath || ""}/gql/endpoint`)) {
30
- return { type: "gql" };
31
- }
32
- if (pathname.startsWith(`${basePath || ""}/chatter/handlers/file/body`)) {
33
- return { type: "file-upload" };
34
- }
35
- if (redirects) {
36
- for (const redirect of redirects) {
37
- const normalizedRoute = normalizeRoute(redirect.route);
38
- const matcher = match(normalizedRoute, { decode: decodeURIComponent });
39
- const result = matcher(pathname);
40
- if (result) {
41
- let target = redirect.target;
42
- const params = result.params;
43
- for (const [key, value] of Object.entries(params)) {
44
- if (!key.startsWith("wildcard")) {
45
- target = target.replace(`:${key}`, value);
46
- }
47
- }
48
- return {
49
- type: "redirect",
50
- target,
51
- statusCode: redirect.statusCode,
52
- };
53
- }
9
+ function matchRoute(pathname, basePath, rewrites, redirects) {
10
+ const servicesRegex = new RegExp(
11
+ `^${basePath || ""}/services/data/v\\d{2}\\.\\d/(graphql|ui-api|connect/file/upload/config)`
12
+ );
13
+ if (servicesRegex.test(pathname) || pathname.startsWith(`${basePath || ""}/lwr/apex/v`)) {
14
+ return { type: "api" };
15
+ }
16
+ if (pathname.startsWith(`${basePath || ""}/gql/endpoint`)) {
17
+ return { type: "gql" };
18
+ }
19
+ if (pathname.startsWith(`${basePath || ""}/chatter/handlers/file/body`)) {
20
+ return { type: "file-upload" };
21
+ }
22
+ if (redirects) {
23
+ for (const redirect of redirects) {
24
+ const normalizedRoute = normalizeRoute(redirect.route);
25
+ const matcher = match(normalizedRoute, { decode: decodeURIComponent });
26
+ const result = matcher(pathname);
27
+ if (result) {
28
+ let target = redirect.target;
29
+ const params = result.params;
30
+ for (const [key, value] of Object.entries(params)) {
31
+ if (!key.startsWith("wildcard")) {
32
+ target = target.replace(`:${key}`, value);
33
+ }
54
34
  }
35
+ return {
36
+ type: "redirect",
37
+ target,
38
+ statusCode: redirect.statusCode
39
+ };
40
+ }
55
41
  }
56
- if (rewrites) {
57
- for (const rewrite of rewrites) {
58
- const normalizedRoute = normalizeRoute(rewrite.route);
59
- const matcher = match(normalizedRoute, { decode: decodeURIComponent });
60
- const result = matcher(pathname);
61
- if (result) {
62
- const params = {};
63
- const matchParams = result.params;
64
- for (const [key, value] of Object.entries(matchParams)) {
65
- if (!key.startsWith("wildcard")) {
66
- params[key] = value;
67
- }
68
- }
69
- return {
70
- type: "rewrite",
71
- target: rewrite.target,
72
- params,
73
- };
74
- }
42
+ }
43
+ if (rewrites) {
44
+ for (const rewrite of rewrites) {
45
+ const normalizedRoute = normalizeRoute(rewrite.route);
46
+ const matcher = match(normalizedRoute, { decode: decodeURIComponent });
47
+ const result = matcher(pathname);
48
+ if (result) {
49
+ const params = {};
50
+ const matchParams = result.params;
51
+ for (const [key, value] of Object.entries(matchParams)) {
52
+ if (!key.startsWith("wildcard")) {
53
+ params[key] = value;
54
+ }
75
55
  }
56
+ return {
57
+ type: "rewrite",
58
+ target: rewrite.target,
59
+ params
60
+ };
61
+ }
76
62
  }
77
- return null;
78
- }
79
- /**
80
- * Check if a path matches any of the given glob patterns
81
- * Supports glob wildcards: * (matches anything except /), ** (matches anything including /), ? (single character)
82
- *
83
- * @param path - The path to test
84
- * @param patterns - Array of glob patterns to match against
85
- * @returns True if the path matches any pattern, false otherwise
86
- */
87
- export function matchesPattern(path, patterns) {
88
- if (!patterns || patterns.length === 0) {
89
- return false;
90
- }
91
- return micromatch.isMatch(path, patterns);
63
+ }
64
+ return null;
92
65
  }
93
- /**
94
- * Apply trailing slash rules to pathname
95
- *
96
- * @param pathname - The URL pathname
97
- * @param trailingSlash - Trailing slash handling strategy
98
- * @returns Modified pathname with trailing slash applied according to rules
99
- */
100
- export function applyTrailingSlash(pathname, trailingSlash) {
101
- if (!trailingSlash || trailingSlash === "auto") {
102
- return pathname;
103
- }
104
- const hasTrailingSlash = pathname.endsWith("/");
105
- const isRoot = pathname === "/";
106
- if (trailingSlash === "always" && !hasTrailingSlash && !isRoot) {
107
- return `${pathname}/`;
108
- }
109
- if (trailingSlash === "never" && hasTrailingSlash && !isRoot) {
110
- return pathname.slice(0, -1);
111
- }
66
+ function applyTrailingSlash(pathname, trailingSlash) {
67
+ if (!trailingSlash || trailingSlash === "auto") {
112
68
  return pathname;
69
+ }
70
+ const hasTrailingSlash = pathname.endsWith("/");
71
+ const isRoot = pathname === "/";
72
+ if (trailingSlash === "always" && !hasTrailingSlash && !isRoot) {
73
+ return `${pathname}/`;
74
+ }
75
+ if (trailingSlash === "never" && hasTrailingSlash && !isRoot) {
76
+ return pathname.slice(0, -1);
77
+ }
78
+ return pathname;
113
79
  }
80
+ export {
81
+ applyTrailingSlash,
82
+ matchRoute
83
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-experimental",
3
3
  "description": "[experimental] Core package for Salesforce Web Applications",
4
- "version": "1.80.1",
4
+ "version": "1.82.0",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -34,18 +34,17 @@
34
34
  "dist"
35
35
  ],
36
36
  "scripts": {
37
- "build": "npm run build:design && tsc --build",
37
+ "build": "npm run build:design && vite build && node scripts/copy-templates.cjs",
38
38
  "build:design": "node src/design/bundle-interactions.mjs",
39
- "postbuild": "node scripts/copy-templates.cjs",
40
- "clean": "rm -rf dist tsconfig.tsbuildinfo",
41
- "dev": "tsc --build --watch",
39
+ "clean": "rm -rf dist",
40
+ "dev": "vite build --watch",
42
41
  "test": "vitest run",
43
42
  "test:watch": "vitest",
44
43
  "test:coverage": "vitest run --coverage"
45
44
  },
46
45
  "dependencies": {
47
46
  "@salesforce/core": "^8.23.4",
48
- "@salesforce/sdk-data": "^1.80.1",
47
+ "@salesforce/sdk-data": "^1.82.0",
49
48
  "axios": "^1.7.7",
50
49
  "micromatch": "^4.0.8",
51
50
  "path-to-regexp": "^8.3.0"
@@ -53,6 +52,8 @@
53
52
  "devDependencies": {
54
53
  "@types/micromatch": "^4.0.10",
55
54
  "esbuild": "^0.24.0",
55
+ "vite": "^7.3.1",
56
+ "vite-plugin-dts": "^4.5.4",
56
57
  "vitest": "^4.0.6"
57
58
  },
58
59
  "engines": {
@@ -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/api/clients.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,167 +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 { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
7
- import { uiApiClient } from "./clients.js";
8
- const mockFetchFn = vi.fn();
9
- vi.mock("@salesforce/sdk-data", () => {
10
- return {
11
- getDataSDK: vi.fn(() => Promise.resolve({
12
- fetch: mockFetchFn,
13
- })),
14
- };
15
- });
16
- vi.stubGlobal("window", {});
17
- // Mock window.location.reload
18
- const mockReload = vi.fn();
19
- Object.defineProperty(window, "location", {
20
- value: { reload: mockReload },
21
- writable: true,
22
- });
23
- describe("clients", () => {
24
- let mockFetch;
25
- beforeEach(() => {
26
- mockFetch = mockFetchFn;
27
- mockFetch.mockClear();
28
- mockReload.mockClear();
29
- });
30
- afterEach(() => {
31
- vi.clearAllMocks();
32
- });
33
- describe("uiApiClient", () => {
34
- it("should merge custom headers with defaults", async () => {
35
- mockFetch.mockResolvedValueOnce({
36
- status: 200,
37
- json: () => Promise.resolve({ success: true }),
38
- });
39
- await uiApiClient.get("/test", {
40
- headers: { "Custom-Header": "value" },
41
- });
42
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/test", {
43
- method: "GET",
44
- headers: {
45
- "Content-Type": "application/json",
46
- Accept: "application/json",
47
- "Custom-Header": "value",
48
- },
49
- });
50
- });
51
- describe("URL construction", () => {
52
- it("should combine base URL with relative paths", async () => {
53
- mockFetch.mockResolvedValueOnce({
54
- status: 200,
55
- json: () => Promise.resolve({}),
56
- });
57
- await uiApiClient.get("/users");
58
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", expect.any(Object));
59
- });
60
- it("should use absolute URLs as-is", async () => {
61
- mockFetch.mockResolvedValueOnce({
62
- status: 200,
63
- json: () => Promise.resolve({}),
64
- });
65
- await uiApiClient.get("https://external.com/data");
66
- expect(mockFetch).toHaveBeenCalledWith("https://external.com/data", expect.any(Object));
67
- });
68
- });
69
- describe("HTTP methods", () => {
70
- beforeEach(() => {
71
- mockFetch.mockResolvedValue({
72
- status: 200,
73
- json: () => Promise.resolve({ success: true }),
74
- });
75
- });
76
- it("should make GET requests", async () => {
77
- await uiApiClient.get("/users");
78
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", {
79
- method: "GET",
80
- headers: {
81
- "Content-Type": "application/json",
82
- Accept: "application/json",
83
- },
84
- });
85
- });
86
- it("should make POST requests with JSON body", async () => {
87
- const data = { name: "John" };
88
- await uiApiClient.post("/users", data);
89
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", {
90
- method: "POST",
91
- body: JSON.stringify(data),
92
- headers: {
93
- "Content-Type": "application/json",
94
- Accept: "application/json",
95
- },
96
- });
97
- });
98
- it("should make PUT requests with JSON body", async () => {
99
- const data = { name: "John Updated" };
100
- await uiApiClient.put("/users/1", data);
101
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users/1", {
102
- method: "PUT",
103
- body: JSON.stringify(data),
104
- headers: {
105
- "Content-Type": "application/json",
106
- Accept: "application/json",
107
- },
108
- });
109
- });
110
- it("should make PATCH requests with JSON body", async () => {
111
- const data = { name: "John Patched" };
112
- await uiApiClient.patch("/users/1", data);
113
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users/1", {
114
- method: "PATCH",
115
- body: JSON.stringify(data),
116
- headers: {
117
- "Content-Type": "application/json",
118
- Accept: "application/json",
119
- },
120
- });
121
- });
122
- it("should make DELETE requests", async () => {
123
- await uiApiClient.delete("/users/1");
124
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users/1", {
125
- method: "DELETE",
126
- headers: {
127
- "Content-Type": "application/json",
128
- Accept: "application/json",
129
- },
130
- });
131
- });
132
- });
133
- describe("body processing", () => {
134
- beforeEach(() => {
135
- mockFetch.mockResolvedValue({
136
- status: 200,
137
- json: () => Promise.resolve({}),
138
- });
139
- });
140
- it("should stringify object bodies for JSON content-type", async () => {
141
- const data = { name: "John" };
142
- await uiApiClient.post("/users", data);
143
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", expect.objectContaining({
144
- body: JSON.stringify(data),
145
- }));
146
- });
147
- it("should not stringify non-object bodies", async () => {
148
- const formData = new FormData();
149
- await uiApiClient.post("/upload", formData);
150
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/upload", expect.objectContaining({
151
- body: formData,
152
- }));
153
- });
154
- it("should not stringify when content-type is not JSON", async () => {
155
- const data = { name: "John" };
156
- await uiApiClient.post("/users", data, {
157
- headers: { "Content-Type": "multipart/form-data" },
158
- });
159
- // When content-type is not JSON and body is a plain object (not FormData/string),
160
- // processBody returns undefined since it can't serialize non-JSON content
161
- expect(mockFetch).toHaveBeenCalledWith("/services/data/v99.0/ui-api/users", expect.objectContaining({
162
- body: undefined,
163
- }));
164
- });
165
- });
166
- });
167
- });
@@ -1,44 +0,0 @@
1
- export var DataType;
2
- (function (DataType) {
3
- DataType["Address"] = "ADDRESS";
4
- DataType["Anytype"] = "ANYTYPE";
5
- DataType["Base64"] = "BASE64";
6
- DataType["Boolean"] = "BOOLEAN";
7
- DataType["Combobox"] = "COMBOBOX";
8
- DataType["Complexvalue"] = "COMPLEXVALUE";
9
- DataType["Currency"] = "CURRENCY";
10
- DataType["Date"] = "DATE";
11
- DataType["Datetime"] = "DATETIME";
12
- DataType["Double"] = "DOUBLE";
13
- DataType["Email"] = "EMAIL";
14
- DataType["Encryptedstring"] = "ENCRYPTEDSTRING";
15
- DataType["Int"] = "INT";
16
- DataType["Json"] = "JSON";
17
- DataType["Junctionidlist"] = "JUNCTIONIDLIST";
18
- DataType["Location"] = "LOCATION";
19
- DataType["Long"] = "LONG";
20
- DataType["Multipicklist"] = "MULTIPICKLIST";
21
- DataType["Percent"] = "PERCENT";
22
- DataType["Phone"] = "PHONE";
23
- DataType["Picklist"] = "PICKLIST";
24
- DataType["Reference"] = "REFERENCE";
25
- DataType["String"] = "STRING";
26
- DataType["Textarea"] = "TEXTAREA";
27
- DataType["Time"] = "TIME";
28
- DataType["Url"] = "URL";
29
- })(DataType || (DataType = {}));
30
- export var FieldExtraTypeInfo;
31
- (function (FieldExtraTypeInfo) {
32
- FieldExtraTypeInfo["ExternalLookup"] = "EXTERNAL_LOOKUP";
33
- FieldExtraTypeInfo["ImageUrl"] = "IMAGE_URL";
34
- FieldExtraTypeInfo["IndirectLookup"] = "INDIRECT_LOOKUP";
35
- FieldExtraTypeInfo["Personname"] = "PERSONNAME";
36
- FieldExtraTypeInfo["Plaintextarea"] = "PLAINTEXTAREA";
37
- FieldExtraTypeInfo["Richtextarea"] = "RICHTEXTAREA";
38
- FieldExtraTypeInfo["SwitchablePersonname"] = "SWITCHABLE_PERSONNAME";
39
- })(FieldExtraTypeInfo || (FieldExtraTypeInfo = {}));
40
- export var ResultOrder;
41
- (function (ResultOrder) {
42
- ResultOrder["Asc"] = "ASC";
43
- ResultOrder["Desc"] = "DESC";
44
- })(ResultOrder || (ResultOrder = {}));
@@ -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=records.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"records.test.d.ts","sourceRoot":"","sources":["../../../src/api/utils/records.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}