diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 82d2ad9e..9370c7d9 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -1,5 +1,5 @@
module.exports = {
extends: ['eslint-config-salesforce-typescript', 'eslint-config-salesforce-license', 'plugin:sf-plugin/library'],
// ignore eslint files in NUT test repos
- ignorePatterns: ['test/nuts/ebikes-lwc'],
+ ignorePatterns: ['test/nuts/ebikes-lwc', 'test/nuts/repros/reactinternalapp'],
};
diff --git a/package.json b/package.json
index 347954e8..a3572e00 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"dependencies": {
"@salesforce/core": "^8.28.1",
"@salesforce/kit": "^3.2.6",
- "@salesforce/source-deploy-retrieve": "^12.32.3",
+ "@salesforce/source-deploy-retrieve": "^12.32.4",
"@salesforce/ts-types": "^2.0.12",
"fast-xml-parser": "^5.5.7",
"graceful-fs": "^4.2.11",
diff --git a/src/shared/populateTypesAndNames.ts b/src/shared/populateTypesAndNames.ts
index 1c5ad5fe..428dd2cc 100644
--- a/src/shared/populateTypesAndNames.ts
+++ b/src/shared/populateTypesAndNames.ts
@@ -69,25 +69,34 @@ export const populateTypesAndNames =
resolveDeleted ? VirtualTreeContainer.fromFilePaths(filenames) : maybeGetTreeContainer(projectPath),
!!forceIgnore
);
- const sourceComponents = filenames
- .flatMap((filename) => {
- try {
- return resolver.getComponentsFromPath(filename);
- } catch (e) {
- logger.warn(`unable to resolve ${filename}`);
- return undefined;
- }
- })
- .filter(isDefined);
-
- logger.debug(` matching SourceComponents have ${sourceComponents.length} items from local`);
-
const elementMap = new Map(
elements.flatMap((e) => (e.filenames ?? []).map((f) => [ensureRelative(projectPath)(f), e]))
);
+ // Deduplicate by fullName+type: all files in the same bundle component (e.g. uiBundles)
+ // resolve to the same SourceComponent, so without dedup getAllFiles/walkContent is called
+ // once per input file rather than once per unique component (O(N) walks instead of O(1)).
+ const uniqueSourceComponents = [
+ ...new Map(
+ filenames
+ .flatMap((filename) => {
+ try {
+ return resolver.getComponentsFromPath(filename);
+ } catch (e) {
+ logger.warn(`unable to resolve ${filename}`);
+ return undefined;
+ }
+ })
+ .filter(isDefined)
+ .filter(sourceComponentHasFullNameAndType)
+ .map((sc) => [`${sc.fullName}:${sc.type.name}`, sc] as const)
+ ).values(),
+ ];
+
+ logger.debug(`populateTypesAndNames resolved ${uniqueSourceComponents.length} unique components`);
+
// iterates the local components and sets their filenames
- sourceComponents.filter(sourceComponentHasFullNameAndType).map((matchingComponent) => {
+ uniqueSourceComponents.map((matchingComponent) => {
const filenamesFromMatchingComponent = getAllFiles(matchingComponent);
const ignored = filenamesFromMatchingComponent
.filter(excludeLwcLocalOnlyTest)
diff --git a/test/nuts/local/populateTypesAndNames.nut.ts b/test/nuts/local/populateTypesAndNames.nut.ts
new file mode 100644
index 00000000..92609b85
--- /dev/null
+++ b/test/nuts/local/populateTypesAndNames.nut.ts
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2026, Salesforce, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import path from 'node:path';
+import fs from 'node:fs';
+import os from 'node:os';
+import { expect } from 'chai';
+import { ForceIgnore, RegistryAccess } from '@salesforce/source-deploy-retrieve';
+import { populateTypesAndNames } from '../../../src/shared/populateTypesAndNames';
+import { ChangeResult } from '../../../src/shared/types';
+
+// TestSession stubs process.cwd() to the project dir, which causes maybeGetTreeContainer
+// to return undefined and the resolver to use the real cwd (workspace root) for FS ops.
+// Use mkdtempSync so process.cwd() !== projectPath and the NodeFSTreeContainer(projectPath)
+// is used, making relative-path resolution work correctly.
+
+const registry = new RegistryAccess();
+
+// Relative paths matching what isogit/localShadowRepo returns
+const apexMeta = path.join('force-app', 'main', 'default', 'classes', 'OrderController.cls-meta.xml');
+const lwcDir = path.join('force-app', 'main', 'default', 'lwc');
+
+describe('populateTypesAndNames', () => {
+ let projectPath: string;
+
+ before(() => {
+ projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'populateTypesAndNames-'));
+ fs.cpSync(path.resolve(path.join('test', 'nuts', 'ebikes-lwc')), projectPath, { recursive: true });
+ });
+
+ after(() => {
+ fs.rmSync(projectPath, { recursive: true, force: true });
+ });
+
+ it('returns an empty array for empty input', () => {
+ expect(populateTypesAndNames({ projectPath, registry })([])).to.deep.equal([]);
+ });
+
+ it('resolves an Apex class to its type and name', () => {
+ const input: ChangeResult[] = [{ origin: 'local', filenames: [apexMeta] }];
+ const [result] = populateTypesAndNames({ projectPath, registry })(input);
+ expect(result.type).to.equal('ApexClass');
+ expect(result.name).to.equal('OrderController');
+ });
+
+ it('resolves multiple LWC bundle files to the same component type/name', () => {
+ const input: ChangeResult[] = [
+ { origin: 'local', filenames: [path.join(lwcDir, 'accountMap', 'accountMap.js')] },
+ { origin: 'local', filenames: [path.join(lwcDir, 'accountMap', 'accountMap.html')] },
+ ];
+ const results = populateTypesAndNames({ projectPath, registry })(input);
+ expect(results).to.have.length(2);
+ results.forEach((r) => {
+ expect(r.type).to.equal('LightningComponentBundle');
+ expect(r.name).to.equal('accountMap');
+ });
+ });
+
+ it('marks a component as ignored when a content file matches .forceignore', () => {
+ // **/jsconfig.json is in the ebikes .forceignore. Writing one inside the bundle
+ // means forceIgnoreDenies returns true for this component.
+ const createCaseDir = path.join(projectPath, lwcDir, 'createCase');
+ fs.writeFileSync(path.join(createCaseDir, 'jsconfig.json'), '{}');
+
+ const forceIgnore = ForceIgnore.findAndCreate(projectPath);
+ const input: ChangeResult[] = [
+ { origin: 'local', filenames: [path.join(lwcDir, 'createCase', 'createCase.js-meta.xml')] },
+ ];
+ const [result] = populateTypesAndNames({ projectPath, registry, forceIgnore })(input);
+ expect(result.ignored).to.equal(true);
+ });
+
+ it('excludes unresolvable filenames when excludeUnresolvable is true', () => {
+ const input: ChangeResult[] = [
+ { origin: 'local', filenames: ['force-app/main/default/classes/DoesNotExist.cls-meta.xml'] },
+ ];
+ expect(populateTypesAndNames({ projectPath, registry, excludeUnresolvable: true })(input)).to.deep.equal([]);
+ });
+
+ it('preserves unresolvable elements when excludeUnresolvable is false', () => {
+ const input: ChangeResult[] = [
+ { origin: 'local', filenames: ['force-app/main/default/classes/DoesNotExist.cls-meta.xml'] },
+ ];
+ const [result] = populateTypesAndNames({ projectPath, registry })(input);
+ expect(result.origin).to.equal('local');
+ expect(result.type).to.equal(undefined);
+ expect(result.name).to.equal(undefined);
+ });
+});
diff --git a/test/nuts/local/reactInternalApp.nut.ts b/test/nuts/local/reactInternalApp.nut.ts
new file mode 100644
index 00000000..9e3c9ea0
--- /dev/null
+++ b/test/nuts/local/reactInternalApp.nut.ts
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2026, Salesforce, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import path from 'node:path';
+import fs from 'node:fs';
+import { execSync } from 'node:child_process';
+import { TestSession } from '@salesforce/cli-plugins-testkit';
+import { expect } from 'chai';
+import { RegistryAccess } from '@salesforce/source-deploy-retrieve';
+import { ShadowRepo } from '../../../src/shared/local/localShadowRepo';
+import { getGroupedFiles, getComponentSets } from '../../../src/shared/localComponentSetArray';
+
+const findUiBundleDir = (projectDir: string): string => {
+ const uiBundlesRoot = path.join(projectDir, 'force-app', 'main', 'default', 'uiBundles');
+ const entries = fs.readdirSync(uiBundlesRoot, { withFileTypes: true });
+ const first = entries.find((e) => e.isDirectory() && !e.name.startsWith('.'));
+ if (!first) throw new Error(`No uiBundle directory found under ${uiBundlesRoot}`);
+ return path.join(uiBundlesRoot, first.name);
+};
+
+describe('reactinternalapp template: getComponentSets dedup check', () => {
+ let session: TestSession;
+ let projectPath: string;
+ const registry = new RegistryAccess();
+ const pkgDir = 'force-app';
+
+ before(async () => {
+ session = await TestSession.create({
+ project: {
+ sourceDir: path.join('test', 'nuts', 'repros', 'reactinternalapp'),
+ },
+ devhubAuthStrategy: 'NONE',
+ });
+ projectPath = session.project.dir;
+ execSync('npm install --registry https://registry.npmjs.org/', {
+ cwd: findUiBundleDir(projectPath),
+ stdio: 'inherit',
+ });
+ });
+
+ after(async () => {
+ await session?.clean();
+ });
+
+ it('single pkgDir: no duplicate filenames in groupings', async () => {
+ const repo = await ShadowRepo.getInstance({
+ orgId: 'fakeOrgId-reactapp-single',
+ projectPath,
+ packageDirs: [{ path: pkgDir, name: pkgDir, fullPath: path.join(projectPath, pkgDir) }],
+ registry,
+ });
+
+ const [nonDeletes, deletes] = await Promise.all([repo.getNonDeleteFilenames(), repo.getDeleteFilenames()]);
+
+ // All files are new (not committed), so deletes should be empty
+ expect(deletes).to.have.lengthOf(0);
+ expect(nonDeletes.length).to.be.greaterThan(0);
+
+ const groupings = getGroupedFiles(
+ {
+ packageDirs: [{ path: pkgDir, name: pkgDir, fullPath: path.join(projectPath, pkgDir) }],
+ nonDeletes,
+ deletes,
+ },
+ false
+ );
+
+ expect(groupings).to.have.lengthOf(1);
+ // No duplicates: grouping should have exactly the same count as the raw filenames
+ expect(groupings[0].nonDeletes.length).to.equal(nonDeletes.length);
+
+ // Calling getComponentSets triggers the instrumented lines
+ getComponentSets({ groupings, registry, projectPath });
+ });
+});
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.forceignore b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.forceignore
new file mode 100644
index 00000000..c90cdea6
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.forceignore
@@ -0,0 +1,15 @@
+# List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status
+# More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm
+#
+
+package.xml
+
+# LWC configuration files
+**/jsconfig.json
+**/.eslintrc.json
+
+# LWC Jest
+**/__tests__/**
+
+node_modules/
+.DS_Store
\ No newline at end of file
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.graphqlrc.yml b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.graphqlrc.yml
new file mode 100644
index 00000000..fdd2369e
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.graphqlrc.yml
@@ -0,0 +1,2 @@
+schema: '../../../../../schema.graphql'
+documents: 'src/**/*.{graphql,js,ts,jsx,tsx}'
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.prettierignore b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.prettierignore
new file mode 100644
index 00000000..cb5e78f1
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.prettierignore
@@ -0,0 +1,9 @@
+node_modules
+dist
+build
+.vite
+coverage
+*.min.js
+*.min.css
+*.map
+package-lock.json
\ No newline at end of file
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.prettierrc b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.prettierrc
new file mode 100644
index 00000000..b1c7fb5b
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/.prettierrc
@@ -0,0 +1,11 @@
+{
+ "semi": true,
+ "trailingComma": "es5",
+ "singleQuote": true,
+ "printWidth": 80,
+ "tabWidth": 2,
+ "useTabs": false,
+ "bracketSpacing": true,
+ "arrowParens": "avoid",
+ "endOfLine": "lf"
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/CHANGELOG.md b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/CHANGELOG.md
new file mode 100644
index 00000000..cfc9c85f
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/CHANGELOG.md
@@ -0,0 +1,10 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+# [1.59.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.58.2...v1.59.0) (2026-02-27)
+
+### Features
+
+- auto bump base react app versions and fix issue with base ui-bundle json ([#175](https://github.com/salesforce-experience-platform-emu/webapps/issues/175)) ([048b5a8](https://github.com/salesforce-experience-platform-emu/webapps/commit/048b5a8449c899fc923aeebc3c76bc5bf1c5e0d4))
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/README.md b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/README.md
new file mode 100644
index 00000000..6988b98c
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/README.md
@@ -0,0 +1,35 @@
+# React Internal App
+
+An internal React template for the Salesforce platform. Includes an Agentforce conversation client and global search; intended for internal (non-Experience Cloud) deployment. Built with React, Vite, TypeScript, and Tailwind/shadcn.
+
+For project-level details (metadata, deploy), see the [project README](../../../../../../README.md).
+
+## Prerequisites
+
+```bash
+npm install
+```
+
+## Run (development)
+
+```bash
+npm run dev
+```
+
+Starts the Vite dev server (default: http://localhost:5173).
+
+## Build
+
+```bash
+npm run build
+```
+
+Writes the production bundle to `dist/` inside the UI Bundle folder.
+
+## Test
+
+```bash
+npm test
+```
+
+Runs the unit test suite (Vitest).
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/codegen.yml b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/codegen.yml
new file mode 100644
index 00000000..df61fc7b
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/codegen.yml
@@ -0,0 +1,95 @@
+schema: '../../../../../schema.graphql'
+documents: 'src/**/*.{graphql,ts,tsx}'
+generates:
+ src/api/graphql-operations-types.ts:
+ plugins:
+ - 'graphql-codegen-typescript-operation-types'
+ - 'typescript-operations'
+ config:
+ onlyOperationTypes: true
+ skipTypename: true
+ preResolveTypes: true
+ scalars:
+ # String-serialized scalars
+ JSON:
+ input: 'string'
+ output: 'string'
+ Date:
+ input: 'string'
+ output: 'string'
+ DateTime:
+ input: 'string'
+ output: 'string'
+ Time:
+ input: 'string'
+ output: 'string'
+ Email:
+ input: 'string'
+ output: 'string'
+ Url:
+ input: 'string'
+ output: 'string'
+ PhoneNumber:
+ input: 'string'
+ output: 'string'
+ Picklist:
+ input: 'string'
+ output: 'string'
+ MultiPicklist:
+ input: 'string'
+ output: 'string'
+ TextArea:
+ input: 'string'
+ output: 'string'
+ LongTextArea:
+ input: 'string'
+ output: 'string'
+ RichTextArea:
+ input: 'string'
+ output: 'string'
+ EncryptedString:
+ input: 'string'
+ output: 'string'
+ Base64:
+ input: 'string'
+ output: 'string'
+ IdOrRef:
+ input: 'string'
+ output: 'string'
+ # BigDecimal-serialized scalars (accepts number or string, returns number)
+ Currency:
+ input: 'number | string'
+ output: 'number'
+ BigDecimal:
+ input: 'number | string'
+ output: 'number'
+ Double:
+ input: 'number | string'
+ output: 'number'
+ Percent:
+ input: 'number | string'
+ output: 'number'
+ Longitude:
+ input: 'number | string'
+ output: 'number'
+ Latitude:
+ input: 'number | string'
+ output: 'number'
+ # Integer-like scalars
+ Long:
+ input: 'number'
+ output: 'number'
+ BigInteger:
+ input: 'number'
+ output: 'number'
+ Short:
+ input: 'number'
+ output: 'number'
+ Byte:
+ input: 'number'
+ output: 'number'
+ Char:
+ input: 'number'
+ output: 'number'
+overwrite: true
+ignoreNoDocuments: true
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/components.json b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/components.json
new file mode 100644
index 00000000..25318625
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/components.json
@@ -0,0 +1,18 @@
+{
+ "style": "new-york",
+ "rsc": true,
+ "tailwind": {
+ "config": "",
+ "css": "styles/global.css",
+ "baseColor": "neutral",
+ "cssVariables": true
+ },
+ "iconLibrary": "lucide",
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ }
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/e2e/app.spec.ts b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/e2e/app.spec.ts
new file mode 100644
index 00000000..f8399ca0
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/e2e/app.spec.ts
@@ -0,0 +1,17 @@
+import { test, expect } from '@playwright/test';
+
+test.describe('base-react-app', () => {
+ test('home page loads and shows welcome content', async ({ page }) => {
+ await page.goto('/');
+ await expect(page.getByRole('heading', { name: 'Home' })).toBeVisible();
+ await expect(
+ page.getByText('Welcome to your React application.')
+ ).toBeVisible();
+ });
+
+ test('not found route shows 404', async ({ page }) => {
+ await page.goto('/non-existent-route');
+ await expect(page.getByRole('heading', { name: '404' })).toBeVisible();
+ await expect(page.getByText('Page not found')).toBeVisible();
+ });
+});
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/eslint.config.js b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/eslint.config.js
new file mode 100644
index 00000000..cd400d40
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/eslint.config.js
@@ -0,0 +1,169 @@
+import { existsSync } from 'node:fs';
+import { resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { dirname } from 'node:path';
+import js from '@eslint/js';
+import tseslint from '@typescript-eslint/eslint-plugin';
+import tsparser from '@typescript-eslint/parser';
+import react from 'eslint-plugin-react';
+import reactHooks from 'eslint-plugin-react-hooks';
+import reactRefresh from 'eslint-plugin-react-refresh';
+import globals from 'globals';
+import graphqlPlugin from '@graphql-eslint/eslint-plugin';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const schemaPath = resolve(__dirname, '../../../../../schema.graphql');
+const schemaExists = existsSync(schemaPath);
+
+const config = [
+ // Global ignores
+ {
+ ignores: [
+ 'build/**/*',
+ 'dist/**/*',
+ 'coverage/**/*',
+ 'src/api/graphql-operations-types.ts',
+ ],
+ },
+ // Config files and build tools (first to avoid inheritance)
+ {
+ files: ['*.config.{js,ts}', 'vite.config.ts'],
+ languageOptions: {
+ parser: tsparser,
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ },
+ globals: {
+ ...globals.node,
+ __dirname: 'readonly',
+ process: 'readonly',
+ },
+ },
+ plugins: {
+ '@typescript-eslint': tseslint,
+ },
+ rules: {
+ '@typescript-eslint/no-var-requires': 'off',
+ },
+ },
+ // Main TypeScript/React files
+ {
+ files: ['**/*.{ts,tsx}'],
+ ignores: [
+ 'coverage',
+ 'dist',
+ 'node_modules',
+ 'build',
+ '*.config.{js,ts}',
+ 'vite.config.ts',
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module',
+ parser: tsparser,
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: './tsconfig.json',
+ },
+ globals: {
+ ...globals.browser,
+ JSX: 'readonly',
+ React: 'readonly',
+ process: 'readonly',
+ },
+ },
+ plugins: {
+ react,
+ 'react-hooks': reactHooks,
+ 'react-refresh': reactRefresh,
+ '@typescript-eslint': tseslint,
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ ...tseslint.configs.recommended.rules,
+ ...react.configs.recommended.rules,
+ ...reactHooks.configs.recommended.rules,
+ 'react/react-in-jsx-scope': 'off',
+ 'react/prop-types': 'off',
+ 'react/jsx-no-comment-textnodes': 'off',
+ 'react/no-unescaped-entities': 'off',
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ varsIgnorePattern: '^_',
+ caughtErrorsIgnorePattern: '^_',
+ ignoreRestSiblings: true,
+ },
+ ],
+ '@typescript-eslint/explicit-function-return-type': 'off',
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ 'react-hooks/set-state-in-effect': 'warn',
+ },
+ settings: {
+ react: {
+ version: 'detect',
+ },
+ },
+ },
+ // Test files
+ {
+ files: [
+ '**/*.test.{ts,tsx}',
+ '**/test/**/*.{ts,tsx}',
+ 'src/test/**/*.{ts,tsx}',
+ ],
+ languageOptions: {
+ parser: tsparser,
+ globals: {
+ ...globals.browser,
+ ...globals.node,
+ global: 'writable',
+ JSX: 'readonly',
+ },
+ },
+ rules: {
+ '@typescript-eslint/no-explicit-any': 'off',
+ },
+ },
+];
+
+// Only add GraphQL rules when schema exists (e.g. after graphql:schema).
+// In CI or when schema is not checked in, skip so lint succeeds.
+if (schemaExists) {
+ config.push(
+ {
+ files: ['**/*.{ts,tsx}'],
+ processor: graphqlPlugin.processor,
+ },
+ {
+ files: ['**/*.graphql'],
+ languageOptions: {
+ parser: graphqlPlugin.parser,
+ parserOptions: {
+ graphQLConfig: {
+ schema: '../../../../../schema.graphql',
+ },
+ },
+ },
+ plugins: {
+ '@graphql-eslint': graphqlPlugin,
+ },
+ rules: {
+ '@graphql-eslint/no-anonymous-operations': 'error',
+ '@graphql-eslint/no-duplicate-fields': 'error',
+ '@graphql-eslint/known-fragment-names': 'error',
+ '@graphql-eslint/no-undefined-variables': 'error',
+ '@graphql-eslint/no-unused-variables': 'error',
+ },
+ }
+ );
+}
+
+export default config;
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/index.html b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/index.html
new file mode 100644
index 00000000..f62781f1
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Welcome to React App
+
+
+
+
+
+
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/localReact3.uibundle-meta.xml b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/localReact3.uibundle-meta.xml
new file mode 100644
index 00000000..7a80cbe9
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/localReact3.uibundle-meta.xml
@@ -0,0 +1,7 @@
+
+
+ localReact3
+ A Salesforce UI Bundle.
+ true
+ 1
+
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/package.json b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/package.json
new file mode 100644
index 00000000..3e0f8217
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/package.json
@@ -0,0 +1,75 @@
+{
+ "name": "base-react-app",
+ "private": true,
+ "version": "1.59.0",
+ "type": "module",
+ "engines": {
+ "node": ">=22"
+ },
+ "scripts": {
+ "dev": "vite",
+ "dev:design": "vite --mode design",
+ "build": "tsc -b && vite build",
+ "build:e2e": "npm run build && node scripts/rewrite-e2e-assets.mjs",
+ "lint": "eslint .",
+ "preview": "vite preview",
+ "test": "vitest",
+ "graphql:codegen": "graphql-codegen",
+ "graphql:schema": "node scripts/get-graphql-schema.mjs"
+ },
+ "dependencies": {
+ "@salesforce/sdk-data": "^1.120.6",
+ "@salesforce/ui-bundle": "^1.120.6",
+ "@tailwindcss/vite": "^4.1.17",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "date-fns": "^4.1.0",
+ "lucide-react": "^0.562.0",
+ "radix-ui": "^1.4.3",
+ "react": "^19.2.0",
+ "react-day-picker": "^9.14.0",
+ "react-dom": "^19.2.0",
+ "react-router": "^7.10.1",
+ "shadcn": "^3.8.5",
+ "sonner": "^1.7.0",
+ "tailwind-merge": "^3.5.0",
+ "tailwindcss": "^4.1.17",
+ "tw-animate-css": "^1.4.0",
+ "@salesforce/agentforce-conversation-client": "^1.116.9"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.39.1",
+ "@graphql-codegen/cli": "^6.1.0",
+ "@graphql-codegen/typescript": "^5.0.6",
+ "@graphql-codegen/typescript-operations": "^5.0.6",
+ "@graphql-eslint/eslint-plugin": "^4.1.0",
+ "@graphql-tools/utils": "^11.0.0",
+ "@playwright/test": "^1.49.0",
+ "@salesforce/vite-plugin-ui-bundle": "^1.120.6",
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/react": "^16.1.0",
+ "@testing-library/user-event": "^14.5.2",
+ "@types/node": "^24.10.1",
+ "@types/react": "^19.2.5",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^5.1.1",
+ "@vitest/ui": "^4.0.17",
+ "eslint": "^9.39.1",
+ "eslint-plugin-react": "^7.37.2",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "globals": "^16.5.0",
+ "graphql": "^16.11.0",
+ "graphql-codegen-typescript-operation-types": "^2.0.2",
+ "jsdom": "^25.0.1",
+ "serve": "^14.2.5",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "^8.46.4",
+ "vite": "^7.2.4",
+ "vite-plugin-graphql-codegen": "^3.6.3",
+ "vitest": "^4.0.17"
+ },
+ "overrides": {
+ "lodash": "^4.18.1"
+ }
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/playwright.config.ts b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/playwright.config.ts
new file mode 100644
index 00000000..c02ce683
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/playwright.config.ts
@@ -0,0 +1,24 @@
+import { defineConfig, devices } from '@playwright/test';
+
+const E2E_PORT = 5175;
+
+export default defineConfig({
+ testDir: './e2e',
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 2 : 0,
+ workers: process.env.CI ? 1 : undefined,
+ reporter: 'html',
+ use: {
+ baseURL: `http://localhost:${E2E_PORT}`,
+ trace: 'on-first-retry',
+ },
+ projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
+ webServer: {
+ // Serve built dist/ with static server so e2e works in CI without SF org (vite preview runs plugin and can fail)
+ command: `npx serve dist -l ${E2E_PORT}`,
+ url: `http://localhost:${E2E_PORT}`,
+ reuseExistingServer: !process.env.CI,
+ timeout: process.env.CI ? 120_000 : 60_000,
+ },
+});
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/scripts/get-graphql-schema.mjs b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/scripts/get-graphql-schema.mjs
new file mode 100644
index 00000000..76030050
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/scripts/get-graphql-schema.mjs
@@ -0,0 +1,68 @@
+/**
+ * Downloads the full GraphQL schema from a connected Salesforce org via introspection.
+ *
+ * Usage:
+ * npm run graphql:schema
+ * node scripts/get-graphql-schema.mjs [output-path]
+ *
+ * The default output path matches the schema location expected by codegen.yml
+ * and .graphqlrc.yml so that codegen and IDE tooling resolve it automatically.
+ */
+import { writeFileSync } from 'node:fs';
+import { resolve } from 'node:path';
+import { getOrgInfo } from '@salesforce/ui-bundle/app';
+import { buildClientSchema, getIntrospectionQuery, printSchema } from 'graphql';
+import { pruneSchema } from '@graphql-tools/utils';
+
+const DEFAULT_SCHEMA_PATH = '../../../../../schema.graphql';
+
+async function executeSalesforceGraphQLQuery(query, variables, operationName) {
+ const {
+ rawInstanceUrl: instanceUrl,
+ apiVersion,
+ accessToken,
+ } = await getOrgInfo();
+
+ const targetUrl = `${instanceUrl}/services/data/v${apiVersion}/graphql`;
+
+ console.log(`Executing introspection query against ${targetUrl}`);
+ const response = await fetch(targetUrl, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ 'Content-Type': 'application/json',
+ 'X-Chatter-Entity-Encoding': 'false',
+ },
+ body: JSON.stringify({ query, variables, operationName }),
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(
+ `Salesforce GraphQL request failed: ${response.status} ${response.statusText} - ${errorText}`
+ );
+ }
+
+ return response.json();
+}
+
+try {
+ const outputPath = resolve(process.argv[2] || DEFAULT_SCHEMA_PATH);
+
+ const introspectionResult = await executeSalesforceGraphQLQuery(
+ getIntrospectionQuery(),
+ {},
+ 'IntrospectionQuery'
+ );
+
+ const schema = buildClientSchema(introspectionResult.data);
+ const prunedSchema = pruneSchema(schema);
+ const sdl = printSchema(prunedSchema);
+
+ writeFileSync(outputPath, sdl);
+
+ console.log(`Schema saved to ${outputPath}`);
+} catch (error) {
+ console.error('Error:', error.message);
+ process.exit(1);
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/scripts/rewrite-e2e-assets.mjs b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/scripts/rewrite-e2e-assets.mjs
new file mode 100644
index 00000000..45e7ba70
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/scripts/rewrite-e2e-assets.mjs
@@ -0,0 +1,23 @@
+/**
+ * Prepares dist/ for e2e: root-relative asset paths + SPA fallback for serve.
+ */
+import { readFileSync, writeFileSync } from 'node:fs';
+import { join, dirname } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const distDir = join(__dirname, '..', 'dist');
+
+// Rewrite index.html so asset paths are root-relative (/assets/...)
+const indexPath = join(distDir, 'index.html');
+let html = readFileSync(indexPath, 'utf8');
+html = html.replace(/(src|href)="[^"]*\/assets\//g, '$1="/assets/');
+writeFileSync(indexPath, html);
+
+// SPA fallback so /about, /non-existent-route etc. serve index.html
+writeFileSync(
+ join(distDir, 'serve.json'),
+ JSON.stringify({
+ rewrites: [{ source: '**', destination: '/index.html' }],
+ })
+);
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/accountSearchService.ts b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/accountSearchService.ts
new file mode 100644
index 00000000..9fe2dbb1
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/accountSearchService.ts
@@ -0,0 +1,52 @@
+import SEARCH_ACCOUNTS_QUERY from './query/searchAccounts.graphql?raw';
+import DISTINCT_INDUSTRIES_QUERY from './query/distinctAccountIndustries.graphql?raw';
+import DISTINCT_TYPES_QUERY from './query/distinctAccountTypes.graphql?raw';
+import {
+ searchObjects,
+ fetchDistinctValues,
+ type ObjectSearchOptions,
+ type PicklistOption,
+} from '../../features/object-search/api/objectSearchService';
+import type {
+ SearchAccountsQuery,
+ SearchAccountsQueryVariables,
+ DistinctAccountIndustriesQuery,
+ DistinctAccountTypesQuery,
+} from '../graphql-operations-types';
+
+export type AccountSearchResult = NonNullable<
+ SearchAccountsQuery['uiapi']['query']['Account']
+>;
+
+export type AccountSearchOptions = ObjectSearchOptions<
+ SearchAccountsQueryVariables['where'],
+ SearchAccountsQueryVariables['orderBy']
+>;
+
+export type { PicklistOption };
+
+export async function searchAccounts(
+ options: AccountSearchOptions = {}
+): Promise {
+ return searchObjects<
+ AccountSearchResult,
+ SearchAccountsQuery,
+ SearchAccountsQueryVariables
+ >(SEARCH_ACCOUNTS_QUERY, 'Account', options);
+}
+
+export async function fetchDistinctIndustries(): Promise {
+ return fetchDistinctValues(
+ DISTINCT_INDUSTRIES_QUERY,
+ 'Account',
+ 'Industry'
+ );
+}
+
+export async function fetchDistinctTypes(): Promise {
+ return fetchDistinctValues(
+ DISTINCT_TYPES_QUERY,
+ 'Account',
+ 'Type'
+ );
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/distinctAccountIndustries.graphql b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/distinctAccountIndustries.graphql
new file mode 100644
index 00000000..fef419bd
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/distinctAccountIndustries.graphql
@@ -0,0 +1,19 @@
+query DistinctAccountIndustries {
+ uiapi {
+ aggregate {
+ Account(groupBy: { Industry: { group: true } }) {
+ edges {
+ node {
+ aggregate @optional {
+ Industry @optional {
+ value
+ displayValue
+ label
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/distinctAccountTypes.graphql b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/distinctAccountTypes.graphql
new file mode 100644
index 00000000..0023d997
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/distinctAccountTypes.graphql
@@ -0,0 +1,19 @@
+query DistinctAccountTypes {
+ uiapi {
+ aggregate {
+ Account(groupBy: { Type: { group: true } }) {
+ edges {
+ node {
+ aggregate @optional {
+ Type @optional {
+ value
+ displayValue
+ label
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/getAccountDetail.graphql b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/getAccountDetail.graphql
new file mode 100644
index 00000000..1af070cf
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/getAccountDetail.graphql
@@ -0,0 +1,121 @@
+query GetAccountDetail($id: ID!) {
+ uiapi {
+ query {
+ Account(where: { Id: { eq: $id } }) {
+ edges {
+ node {
+ Id
+ Name @optional {
+ value
+ displayValue
+ }
+ Owner @optional {
+ Name @optional {
+ value
+ displayValue
+ }
+ }
+ Phone @optional {
+ value
+ displayValue
+ }
+ Fax @optional {
+ value
+ displayValue
+ }
+ Parent @optional {
+ Name @optional {
+ value
+ displayValue
+ }
+ }
+ Website @optional {
+ value
+ displayValue
+ }
+ Type @optional {
+ value
+ displayValue
+ }
+ NumberOfEmployees @optional {
+ value
+ displayValue
+ }
+ Industry @optional {
+ value
+ displayValue
+ }
+ AnnualRevenue @optional {
+ value
+ displayValue
+ }
+ Description @optional {
+ value
+ displayValue
+ }
+ BillingStreet @optional {
+ value
+ displayValue
+ }
+ BillingCity @optional {
+ value
+ displayValue
+ }
+ BillingState @optional {
+ value
+ displayValue
+ }
+ BillingPostalCode @optional {
+ value
+ displayValue
+ }
+ BillingCountry @optional {
+ value
+ displayValue
+ }
+ ShippingStreet @optional {
+ value
+ displayValue
+ }
+ ShippingCity @optional {
+ value
+ displayValue
+ }
+ ShippingState @optional {
+ value
+ displayValue
+ }
+ ShippingPostalCode @optional {
+ value
+ displayValue
+ }
+ ShippingCountry @optional {
+ value
+ displayValue
+ }
+ CreatedBy @optional {
+ Name @optional {
+ value
+ displayValue
+ }
+ }
+ CreatedDate @optional {
+ value
+ displayValue
+ }
+ LastModifiedBy @optional {
+ Name @optional {
+ value
+ displayValue
+ }
+ }
+ LastModifiedDate @optional {
+ value
+ displayValue
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/searchAccounts.graphql b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/searchAccounts.graphql
new file mode 100644
index 00000000..840df2c8
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/account/query/searchAccounts.graphql
@@ -0,0 +1,51 @@
+query SearchAccounts(
+ $first: Int
+ $after: String
+ $where: Account_Filter
+ $orderBy: Account_OrderBy
+) {
+ uiapi {
+ query {
+ Account(first: $first, after: $after, where: $where, orderBy: $orderBy) {
+ edges {
+ node {
+ Id
+ Name @optional {
+ value
+ displayValue
+ }
+ Industry @optional {
+ value
+ displayValue
+ }
+ Type @optional {
+ value
+ displayValue
+ }
+ Phone @optional {
+ value
+ displayValue
+ }
+ Owner @optional {
+ Name @optional {
+ value
+ displayValue
+ }
+ }
+ AnnualRevenue @optional {
+ value
+ displayValue
+ }
+ }
+ }
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ endCursor
+ startCursor
+ }
+ totalCount
+ }
+ }
+ }
+}
diff --git a/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/graphql-operations-types.ts b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/graphql-operations-types.ts
new file mode 100644
index 00000000..7f58dffe
--- /dev/null
+++ b/test/nuts/repros/reactinternalapp/force-app/main/default/uiBundles/localReact3/src/api/graphql-operations-types.ts
@@ -0,0 +1,11378 @@
+export type Maybe = T | null;
+export type InputMaybe = Maybe;
+export type Exact = {
+ [K in keyof T]: T[K];
+};
+export type MakeOptional = Omit & {
+ [SubKey in K]?: Maybe;
+};
+export type MakeMaybe = Omit & {
+ [SubKey in K]: Maybe;
+};
+export type MakeEmpty<
+ T extends { [key: string]: unknown },
+ K extends keyof T
+> = {
+ [_ in K]?: never;
+};
+export type Incremental =
+ | T
+ | {
+ [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never;
+ };
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+ ID: { input: string; output: string };
+ String: { input: string; output: string };
+ Boolean: { input: boolean; output: boolean };
+ Int: { input: number; output: number };
+ Float: { input: number; output: number };
+ Base64: { input: string; output: string };
+ Currency: { input: number | string; output: number };
+ Date: { input: string; output: string };
+ DateTime: { input: string; output: string };
+ Double: { input: number | string; output: number };
+ Email: { input: string; output: string };
+ /** Can be set to an ID or a Reference to the result of another mutation operation. */
+ IdOrRef: { input: string; output: string };
+ Latitude: { input: number | string; output: number };
+ /** A 64-bit signed integer */
+ Long: { input: number; output: number };
+ LongTextArea: { input: string; output: string };
+ Longitude: { input: number | string; output: number };
+ MultiPicklist: { input: string; output: string };
+ Percent: { input: number | string; output: number };
+ PhoneNumber: { input: string; output: string };
+ Picklist: { input: string; output: string };
+ RichTextArea: { input: string; output: string };
+ TextArea: { input: string; output: string };
+ Time: { input: string; output: string };
+ Url: { input: string; output: string };
+};
+
+export type AccountHistory_Filter = {
+ Account?: InputMaybe;
+ AccountId?: InputMaybe;
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ DataType?: InputMaybe;
+ Field?: InputMaybe;
+ Id?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ NewvalNumber?: InputMaybe;
+ NewvalString?: InputMaybe;
+ OldvalNumber?: InputMaybe;
+ OldvalString?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type AccountPartner_Filter = {
+ AccountFrom?: InputMaybe;
+ AccountFromId?: InputMaybe;
+ AccountTo?: InputMaybe;
+ AccountToId?: InputMaybe;
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ Id?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ IsPrimary?: InputMaybe;
+ LastModifiedBy?: InputMaybe;
+ LastModifiedById?: InputMaybe;
+ LastModifiedDate?: InputMaybe;
+ Opportunity?: InputMaybe;
+ OpportunityId?: InputMaybe;
+ ReversePartnerId?: InputMaybe;
+ Role?: InputMaybe;
+ SystemModstamp?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type Account_Filter = {
+ AccountSource?: InputMaybe;
+ AnnualRevenue?: InputMaybe;
+ BillingCity?: InputMaybe;
+ BillingCountry?: InputMaybe;
+ BillingGeocodeAccuracy?: InputMaybe;
+ BillingLatitude?: InputMaybe;
+ BillingLongitude?: InputMaybe;
+ BillingPostalCode?: InputMaybe;
+ BillingState?: InputMaybe;
+ BillingStreet?: InputMaybe;
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ Description?: InputMaybe;
+ Fax?: InputMaybe;
+ Id?: InputMaybe;
+ Industry?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ Jigsaw?: InputMaybe;
+ JigsawCompanyId?: InputMaybe;
+ LastActivityDate?: InputMaybe;
+ LastModifiedBy?: InputMaybe;
+ LastModifiedById?: InputMaybe;
+ LastModifiedDate?: InputMaybe;
+ LastReferencedDate?: InputMaybe;
+ LastViewedDate?: InputMaybe;
+ MasterRecord?: InputMaybe;
+ MasterRecordId?: InputMaybe;
+ Name?: InputMaybe;
+ NumberOfEmployees?: InputMaybe;
+ Owner?: InputMaybe;
+ OwnerId?: InputMaybe;
+ Parent?: InputMaybe;
+ ParentId?: InputMaybe;
+ Phone?: InputMaybe;
+ PhotoUrl?: InputMaybe;
+ ShippingCity?: InputMaybe;
+ ShippingCountry?: InputMaybe;
+ ShippingGeocodeAccuracy?: InputMaybe;
+ ShippingLatitude?: InputMaybe;
+ ShippingLongitude?: InputMaybe;
+ ShippingPostalCode?: InputMaybe;
+ ShippingState?: InputMaybe;
+ ShippingStreet?: InputMaybe;
+ SicDesc?: InputMaybe;
+ SystemModstamp?: InputMaybe;
+ Type?: InputMaybe;
+ Website?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type Account_OrderBy = {
+ AccountSource?: InputMaybe;
+ AnnualRevenue?: InputMaybe;
+ BillingCity?: InputMaybe;
+ BillingCountry?: InputMaybe;
+ BillingGeocodeAccuracy?: InputMaybe;
+ BillingLatitude?: InputMaybe;
+ BillingLongitude?: InputMaybe;
+ BillingPostalCode?: InputMaybe;
+ BillingState?: InputMaybe;
+ BillingStreet?: InputMaybe;
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ Description?: InputMaybe;
+ Fax?: InputMaybe;
+ Id?: InputMaybe;
+ Industry?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ Jigsaw?: InputMaybe;
+ JigsawCompanyId?: InputMaybe;
+ LastActivityDate?: InputMaybe;
+ LastModifiedBy?: InputMaybe;
+ LastModifiedById?: InputMaybe;
+ LastModifiedDate?: InputMaybe;
+ LastReferencedDate?: InputMaybe;
+ LastViewedDate?: InputMaybe;
+ MasterRecord?: InputMaybe;
+ MasterRecordId?: InputMaybe;
+ Name?: InputMaybe;
+ NumberOfEmployees?: InputMaybe;
+ Owner?: InputMaybe;
+ OwnerId?: InputMaybe;
+ Parent?: InputMaybe;
+ ParentId?: InputMaybe;
+ Phone?: InputMaybe;
+ PhotoUrl?: InputMaybe;
+ ShippingCity?: InputMaybe;
+ ShippingCountry?: InputMaybe;
+ ShippingGeocodeAccuracy?: InputMaybe;
+ ShippingLatitude?: InputMaybe;
+ ShippingLongitude?: InputMaybe;
+ ShippingPostalCode?: InputMaybe;
+ ShippingState?: InputMaybe;
+ ShippingStreet?: InputMaybe;
+ SicDesc?: InputMaybe;
+ SystemModstamp?: InputMaybe;
+ Type?: InputMaybe;
+ Website?: InputMaybe;
+};
+
+export type Agent__History_Filter = {
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ DataType?: InputMaybe;
+ Field?: InputMaybe;
+ Id?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ NewvalNumber?: InputMaybe;
+ NewvalString?: InputMaybe;
+ OldvalNumber?: InputMaybe;
+ OldvalString?: InputMaybe;
+ Parent?: InputMaybe;
+ ParentId?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type Agent__C_Filter = {
+ Agent_Type__c?: InputMaybe;
+ Availability__c?: InputMaybe;
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ Emergency_Alt__c?: InputMaybe;
+ Id?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ Language__c?: InputMaybe;
+ LastActivityDate?: InputMaybe;
+ LastModifiedBy?: InputMaybe;
+ LastModifiedById?: InputMaybe;
+ LastModifiedDate?: InputMaybe;
+ License_Expiry__c?: InputMaybe;
+ License_Number__c?: InputMaybe;
+ Name?: InputMaybe;
+ Office_Location__c?: InputMaybe;
+ Owner?: InputMaybe;
+ OwnerId?: InputMaybe;
+ SystemModstamp?: InputMaybe;
+ Territory__c?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type Agent__C_Owner_Filters = {
+ Group?: InputMaybe;
+ Name?: InputMaybe;
+ User?: InputMaybe;
+};
+
+export type AggregateOrderByStringClause = {
+ function?: InputMaybe;
+ nulls?: InputMaybe;
+ order?: InputMaybe;
+};
+
+export enum AggregateOrderByStringFunction {
+ Count = 'COUNT',
+ CountDistinct = 'COUNT_DISTINCT',
+ Max = 'MAX',
+ Min = 'MIN',
+}
+
+export type AnalyticsUserAttrFuncTkn_Filter = {
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ DefinitionName?: InputMaybe;
+ Id?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ LastModifiedBy?: InputMaybe;
+ LastModifiedById?: InputMaybe;
+ LastModifiedDate?: InputMaybe;
+ Name?: InputMaybe;
+ Owner?: InputMaybe;
+ OwnerId?: InputMaybe;
+ SystemModstamp?: InputMaybe;
+ TargetObject?: InputMaybe;
+ TargetObjectField?: InputMaybe;
+ TokenKey?: InputMaybe;
+ ViewerTgtObjRelDesc?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type AnalyticsUserAttrFuncTkn_Owner_Filters = {
+ Group?: InputMaybe;
+ Name?: InputMaybe;
+ User?: InputMaybe;
+};
+
+export type AppAnalyticsQueryRequest_Filter = {
+ AvailableSince?: InputMaybe;
+ CreatedBy?: InputMaybe;
+ CreatedById?: InputMaybe;
+ CreatedDate?: InputMaybe;
+ DataType?: InputMaybe;
+ DownloadExpirationTime?: InputMaybe;
+ DownloadSize?: InputMaybe;
+ DownloadUrl?: InputMaybe;
+ EndTime?: InputMaybe;
+ ErrorMessage?: InputMaybe;
+ FileCompression?: InputMaybe;
+ FileType?: InputMaybe;
+ Id?: InputMaybe;
+ IsDeleted?: InputMaybe;
+ LastModifiedBy?: InputMaybe;
+ LastModifiedById?: InputMaybe;
+ LastModifiedDate?: InputMaybe;
+ LastReferencedDate?: InputMaybe;
+ LastViewedDate?: InputMaybe;
+ Name?: InputMaybe;
+ OrganizationIds?: InputMaybe;
+ PackageIds?: InputMaybe;
+ QuerySubmittedTime?: InputMaybe;
+ RequestState?: InputMaybe;
+ StartTime?: InputMaybe;
+ SystemModstamp?: InputMaybe;
+ and?: InputMaybe>>;
+ not?: InputMaybe;
+ or?: InputMaybe>>;
+};
+
+export type AppMenuItem_Filter = {
+ ApplicationId?: InputMaybe;
+ CanvasAccessMethod?: InputMaybe;
+ CanvasEnabled?: InputMaybe;
+ CanvasOptions?: InputMaybe