Agent Skillsforcedotcom/sf-skills › experience-ui-bundle-salesforce-data-access

experience-ui-bundle-salesforce-data-access

GitHub

指导在UI Bundle中通过@salesforce/platform-sdk进行Salesforce数据读写、缓存及GraphQL操作。涵盖查询、变更、刷新及旧版迁移,排除非数据访问场景。

skills/experience-ui-bundle-salesforce-data-access/SKILL.md forcedotcom/sf-skills

Trigger Scenarios

代码导入 @salesforce/platform-sdk 调用 sdk.graphql.query/mutate 或 sdk.fetch 存在 .graphql 文件 需要强制刷新缓存数据 为UI bundle配置数据层以读写Salesforce记录

Install

npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-salesforce-data-access -g -y
More Options

Use without installing

npx skills use forcedotcom/sf-skills@experience-ui-bundle-salesforce-data-access

指定 Agent (Claude Code)

npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-salesforce-data-access -a claude-code -g -y

安装 repo 全部 skill

npx skills add forcedotcom/sf-skills --all -g -y

预览 repo 内 skill

npx skills add forcedotcom/sf-skills --list

SKILL.md

Frontmatter
{
    "name": "experience-ui-bundle-salesforce-data-access",
    "metadata": {
        "version": "2.1"
    },
    "description": "MUST activate when a uiBundles\/*\/src\/ project does ANY Salesforce record operation — reading, creating, updating, deleting, or caching\/refreshing query results. Triggers: code importing @salesforce\/platform-sdk, calls to sdk.graphql.query \/ sdk.graphql.mutate \/ sdk.fetch, *.graphql files, stale data needing a force-refresh, or wiring up a UI bundle's data layer to read, write, or refresh Salesforce records. The default for new read\/write work is the Read\/Write workflow with the current @salesforce\/platform-sdk API; only follow the migration path when EXISTING code already uses the old @salesforce\/sdk-data callable form. Not for building app shell\/UI, styling, file upload, or auth\/search scaffolding — use the other ui-bundle-* skills. DO NOT TRIGGER when: OAuth setup, schema changes, Bulk\/Tooling\/Metadata API, or declarative automation."
}

Salesforce Data Access (UI bundles)

All Salesforce data access in a UI bundle goes through the @salesforce/platform-sdk data SDK. The SDK handles auth, CSRF, and base-URL resolution, and — on the WebApp surface — caches every GraphQL query by default.

This file is the workflow + guardrail spine. Depth lives in linked docs:

  • references/graphiti-cli.md — the graphiti CLI (sf-gql-* commands) that compiles a small JSON spec into a schema-correct, guardrail-applied query + variables + types. The preferred way to author the GraphQL in steps below; falls back to the schema-grep script when unavailable.
  • references/sdk-api.md — the new call API: query/mutate, QueryResult, typing, error-handling stances.
  • references/caching.md — on-by-default cache + the two refresh modes (result.refresh/subscribe vs per-call cacheControl).
  • references/graphql-hand-authoring.md — schema lookup, read / mutation templates, every platform guardrail (@optional, pagination, limits, semi-join, wrappers, error table…).
  • references/rest-and-integration.mdsdk.fetch, the supported-API allowlist, and the reactive/lifecycle integration patterns.
  • references/migration.md — old @salesforce/sdk-data callable code → new namespace. The only place the dead API appears as usable code.

The one-paragraph mental model

const sdk = await createDataSDK(). Then sdk.graphql is a namespace, not a function: sdk.graphql!.query({...}) for reads, sdk.graphql!.mutate({...}) for writes. On WebApp, every query() is cached by default (300s). HTTP 200 never means success — always check result.errors. Verify every entity and field against the schema before you query it: one unverified field fails the whole query at runtime, and schema.graphql is too large to eyeball — look it up.

import { createDataSDK, gql } from "@salesforce/platform-sdk"; // gql tags the query string so codegen + eslint validate it

const sdk = await createDataSDK();
const result = await sdk.graphql!.query({ query: GET_ACCOUNTS, variables });
if (result.errors?.length) throw new Error(result.errors.map((e) => e.message).join("; "));
const rows = result.data?.uiapi?.query?.Account?.edges?.map((e) => e.node) ?? []; // unwrap edges/node; read field values via .value

Typed call params (query<GetAccountsQuery, GetAccountsQueryVariables>), the CacheControl type, and NodeOfConnection<T> (extracts a node type from a Connection for clean typing) all live in references/sdk-api.md.

This changed (breaking — PR #502). The previous callable sdk.graphql(...) form and the previous package name are dead — the code above is the only correct form. If you encounter the old API in existing code (or a stale dist/ artifact), don't copy it; convert it per Working on existing code.

sdk.graphql! is WebApp-only. The non-null assertion above is correct only if the bundle runs solely on WebApp. On other surfaces it can crash — decide before you write it. See Surfaces — ! vs guard below.


Surfaces — sdk.graphql! vs guard

createDataSDK() runs on multiple surfaces, and sdk.graphql / sdk.fetch are genuinely optional (typed graphql?: …). Whether you may assert them with ! depends entirely on where the bundle runs — this is the one surface decision that turns into a runtime crash if you get it wrong, so make it explicitly before writing any query/mutate call:

Surface(s) sdk.graphql Write
WebApp only always present sdk.graphql!.query({...})! is safe; every shipped WebApp consumer uses it
Mosaic / OpenAI / MCPApps (or any bundle that might run off-WebApp) can be undefined guard first (if (!sdk.graphql) return …), then call

Rule of thumb: if you cannot prove the bundle is WebApp-only, guard. A bare sdk.graphql! that later ships to another surface throws Cannot read properties of undefined at runtime — TypeScript won't catch it because ! silences exactly that check (same applies to sdk.fetch!). The portable guard snippet lives in references/sdk-api.md.


Step 0 — Route the task

The task is… Go to
Read records Read workflow below
Create / update / delete records Write workflow below
Object/field metadata, picklist values, related-list metadata, aggregations Beyond record CRUD below
Data is stale / "add a refresh button" / "cache it longer" Freshness & caching below
Something GraphQL can't express (Apex REST, file upload, Einstein) references/rest-and-integration.md
Migrating old sdk.graphql?.(query, vars) code Working on existing code below

GraphQL covers far more than record reads and writes — prefer it for anything the uiapi namespace exposes (see Beyond record CRUD). Reach for REST only when the data genuinely lives outside uiapi (Apex REST, file upload, Einstein) — see references/rest-and-integration.md.


Preconditions — verify before writing any query

<skill-dir> below is wherever this skill is installed (the directory this SKILL.md loaded from). The schema-lookup script ships inside it. The script does not hunt for schema.graphql by walking up the tree — an ancestor schema can belong to a different org and would validate fields against the wrong one. Resolve the schema explicitly: run from the SFDX project root (where schema.graphql lives), or pass --schema <path> / set GRAPHQL_SCHEMA=<path>. The script echoes the schema it resolved ([graphql-search] using schema: … on stderr) — glance at it to confirm you grounded against the right file.

# Requirement Verify If missing
1 @salesforce/platform-sdk installed package.json in the UI bundle dir Tell user to install it; cannot proceed
2 A grounding tool resolves Preferred: npx graphiti sf-gql-discover '{"org":"<alias>","mode":"list_objects"}' from the UI bundle dir returns objects. Fallback: bash <skill-dir>/scripts/graphql-search.sh <Entity> from the project root prints a lookup, not "schema.graphql not found" No graphiti dep / org won't prime → use the script. Script can't find schema.graphql → pass --schema <path>, or npm run graphql:schema from the UI bundle dir. (references/graphiti-cli.md covers CLI setup)
3 Target objects/fields deployed The object appears in sf-gql-discover (or graphql-search.sh <Entity> returns output) Entity absent usually means it isn't deployed (or the cache/schema is stale). Refresh: npx graphiti sf-gql-connect '{"org":"<alias>","forceRefresh":true}' (CLI) or npm run graphql:schema (script). If still absent, deploy the metadata (the platform-metadata-deploy skill handles this) and assign the permission sets, then re-check

If preconditions aren't met you may still scaffold components, routes, and layout — but use empty arrays / null for data, mark query sites with // TODO: add query after schema verification, and add a plan item to return. Do not write GraphQL strings until the schema workflow is complete.


Read workflow

  1. Look up the schema first — never guess a name. Preferred (graphiti): when the exact API name is at all uncertain, list before you describenpx graphiti sf-gql-discover '{"org":"<alias>","mode":"list_objects","search":"<intent>"}' to find the real name, then npx graphiti sf-gql-discover '{"org":"<alias>","mode":"describe_object","object":"<Entity>"}' for exact field/type names, picklist values, filterable/sortable. An empty list or missing object is a fact about the org (wrong name or not deployed), not a tool failure — re-list or forceRefresh; do not fall back to the script for this (see guardrail 2). Fallback is only for a CLI that genuinely can't run (no graphiti dep / org won't prime): bash <skill-dir>/scripts/graphql-search.sh <Entity> from the SFDX project root. (Full rules: references/graphql-hand-authoring.md.)

  2. Write the query. Preferred — compile it with graphiti: npx graphiti sf-gql-list '{"org":"<alias>","object":"<Entity>","fields":[…],"first":N}' returns a { query, variables, types, warnings } envelope with @optional, value/displayValue, edges/node, and first:/pageInfo already applied. Confirm warnings: [] (a non-empty array means the object wasn't in the primed schema — the query is degraded; don't ship it), then paste the query verbatim into inline gql (simple) or an external .graphql file (one operation per file, imported with the bundler's ?raw suffix — import Q from "./q.graphql?raw" brings the file in as a plain string). Fallback — hand-author: apply @optional to every selectable FLS-gated field — scalar leaf fields (Name @optional { value }) and parent/child relationships and the fields inside them — but NOT on Id, on connection plumbing (edges, node, the connection field itself), or on pageInfo; the graphiti output leaves those bare and is the canonical placement. Always set first:, include pageInfo if it may page. Either way, full mechanics and the primed-vs-degraded behavior: references/graphiti-cli.md.

  3. Generate typesnpm run graphql:codegen (from the UI bundle dir) → src/api/graphql-operations-types.ts.

  4. Call query() with the generated types:

    import type { GetAccountsQuery, GetAccountsQueryVariables } from "../graphql-operations-types";
    
    const result = await sdk.graphql!.query<GetAccountsQuery, GetAccountsQueryVariables>({
      query: GET_ACCOUNTS,
      variables: { first: 20 },
      // cacheControl,            // optional — see Freshness & caching
    });
    
  5. Handle the result. result.data + result.errors are the initial snapshot; result.subscribe / result.refresh are the reactive handles. Always check errors before reading data:

    if (result.errors?.length) throw new Error(result.errors.map((e) => e.message).join("; "));
    const rows = result.data?.uiapi?.query?.Account?.edges?.map((e) => e.node) ?? [];
    

Defend consuming code with ?./?? (because @optional can omit fields). Error-handling stances (strict / tolerant / discriminated) and NodeOfConnection typing: references/sdk-api.md.


Write workflow

1–3 as above (schema lookup → write the mutation → codegen). To compile the mutation with graphiti, use sf-gql-create / sf-gql-update / sf-gql-delete — they emit the uiapi { <Object>Create(input: $input) { Record {…} } } shape; the types field tells you the input shape. Details: references/graphiti-cli.md. 4. Call mutate() — note the option key is mutation, not query, and that mutations are never cached. The runtime variables shape differs per operation — values are raw (never {value}-wrapped; that wrapper is a read-shape thing and breaks writes) and nest under the entity key:

// create — input.<Entity> holds the new field values
variables: { input: { Account: { Name: "Acme", Industry: "Technology" } } }
// update — sibling Id alongside the entity key
variables: { input: { Id: "001…", Account: { Industry: "Finance" } } }
// delete — Id only, no entity key (generic RecordDeleteInput)
variables: { input: { Id: "001…" } }

const { data, errors } = await sdk.graphql!.mutate<CreateAccountMutation, CreateAccountMutationVariables>({
  mutation: CREATE_ACCOUNT,
  variables: { input: { Account: { Name: "Acme" } } },
});
if (errors?.length) throw new Error(errors.map((e) => e.message).join("; "));

This is the variables shape the spine owns; the CLI types-field interpretation is in references/graphiti-cli.md and the GraphQL-document field constraints (createable/updateable, ApiName references, @{alias} chaining) in references/graphql-hand-authoring.md. 5. Re-freshen affected reads. mutate() has no refresh. To update a live list after a write, hold the QueryResult from your earlier query() call (e.g. accountsResult) and call await accountsResult.refresh() (forced re-fetch, pushes to subscribers) — note this is the read's handle, not anything mutate() returns. See Freshness & caching.

Mutation syntax is exacting: wrap under uiapi(input: { allOrNone: ... }), only createable/updateable fields, Create/Update output is always Record but Delete has no Record field — select Id only. Full template + chaining + constraints: references/graphql-hand-authoring.md.


Beyond record CRUD

The uiapi namespace is not just record reads/writes. Before reaching for REST, check whether GraphQL already covers it — the same sdk.graphql!.query() call, different sub-selection. The top-level uiapi fields:

Need Use Returns
Query records uiapi { query { <Entity>(...) } } records (the Read workflow)
Counts / sums / grouped rollups without pulling rows uiapi { aggregate { <Entity>(groupBy: …) } } aggregated buckets
Object/field metadata — labels, data types, createable/updateable, record types uiapi { objectInfos(apiNames: […]) } ObjectInfo[]
Picklist values (per record type) uiapi { objectInfos(objectInfoInputs: […]) { fields … on PicklistField { … } } } picklist values
Related-list metadata — display columns, ordering for a parent's related list uiapi { relatedListByName(parentApiName, relatedListName) } RelatedListInfo

Same rules as record reads: verify every type/field first, @optional where FLS applies, check result.errors. Aggregations can be compiled with npx graphiti sf-gql-aggregate (pass groupBy + aggregations); object metadata / picklists / related lists are hand-authored — templates: references/graphql-hand-authoring.md.

Two related capabilities (the current-user record and layout delivery) need confirmation against a current org schema before this skill documents a query shape — tracked as a follow-up, not yet covered here.


Freshness & caching

Caching is ON by default on WebApp. Every sdk.graphql!.query() is cached with a 300-second max-age TTL — no opt-in flag, no factory, no import subpath. Do not build your own cache (no React Query, SWR, localStorage, or hand-rolled Map). The cache is shared across SDK instances by baseUrl: the same query+variables from a different createDataSDK() targeting the same host is a cache hit. Only non-empty, error-free data is cached. mutate() is never cached.

There are two distinct freshness tools — keep them separate:

  1. Per-call cacheControl — a one-shot policy override on the query options bag ("no-cache" / "only-if-cached" / { type: "max-age", maxAge: <seconds> }). The type and exact per-value behavior live in references/sdk-api.md. Take cacheControl as an optional param on the read function and expose each distinct policy as a thin named export in the same data-layer file — a "call site" is a named export, not a new React component. For getAccounts(first, after?, cacheControl?): export const refreshAccounts = () => getAccounts(20, undefined, "no-cache") (and likewise offlineAccounts"only-if-cached", shortLivedAccounts{ type: "max-age", maxAge: 10 }). Keep the policy in the data layer.
  2. Reactive subscribe / refresh — a stateful handle on a live QueryResult: result.subscribe(cb) fires on every later snapshot, result.refresh() re-fetches bypassing the cache and pushes to subscribers. Shape in references/sdk-api.md; subscription lifecycle (always unsubscribe on teardown) in references/caching.md.
Want Reach for
Freshness within ~5 min is fine nothing (default cache)
This one read must bypass the cache (refresh button) cacheControl: "no-cache"
Read only cached data, tolerate misses (offline-first) cacheControl: "only-if-cached" — a miss is expected, not an error: it surfaces a DataNotFoundError on result.errors (no network, no throw). Check result.errors, render empty state, do not throw and do not fall back to the network — that defeats offline-first.
Tighter/looser TTL for this query cacheControl: { type: "max-age", maxAge: 60 } (maxAge is in seconds)
Mounted component reflects updates over time result.subscribe(cb)
Re-fetch now + notify all subscribers (e.g. after a mutation) result.refresh()

cacheControl is fire-and-forget at call time; subscribe/refresh is a live handle. Different mechanisms, different jobs — don't conflate "refresh" with "no-cache". Full behavior, the reactive-subscription lifecycle, and uncached-surface caveats: references/caching.md.


Working on existing code (migration)

Only enter this path if the existing code actually uses the old API — i.e. it imports @salesforce/sdk-data or calls the callable sdk.graphql(query, vars) form. For any new read/write, ignore migration entirely and use the Read workflow / Write workflow — those already show the only correct API.

When you do have old code to convert, see references/migration.md for the before→after diff (imports, query/mutate calls, optional-chaining → non-null assertion, codegen type placement) and a checklist. The target API is exactly what the Read/Write workflows above prescribe — migrating is just swapping the old form for that.


Platform guardrails — never regress these

These are Salesforce GraphQL platform behaviors, independent of the SDK. Violations cause silent runtime failures. (Details + templates: references/graphql-hand-authoring.md.)

  1. HTTP 200 ≠ success — always parse result.errors; the Promise resolves even on failure.
  2. Schema is the only source of truth — verify, never invent. Verify every entity/field/type via graphiti sf-gql-discover (preferred) or bash <skill-dir>/scripts/graphql-search.sh <Entity> before use. Case-sensitive; __c/__e; _Record entity suffix (v60+). When graphiti is primed, a "not found"/empty/Cannot query field answer (including from graphql-codegen/@graphql-eslint, even when the message points at schema.graphql) is a fact about the org — wrong name or undeployed/inaccessible metadata, not a tool failure: fix the operation, or deploy the metadata (the platform-metadata-deploy skill)
    • assign perms + refresh (sf-gql-connect --forceRefresh / npm run graphql:schema). Do not fall back to the script, hand-author around it, or guess a name — a guessed entity or field silently fails the whole query at runtime; if lookups aren't converging, ask the user rather than keep spiraling. schema.graphql and the codegen output (src/api/graphql-operations-types.ts) are read-only generated mirrors — never open or edit them (honor any # DO NOT EDIT marker). Hand-adding a missing type satisfies codegen/lint but grants no org access; it just hides the failure until runtime. Fall back to the script only when the CLI can't run at all (no dep / SCHEMA_PRIME_FAILED).
  3. @optional on every FLS-gated field at each nesting level — scalar leaf fields plus each parent/child relationship and the fields inside it (FLS fails the whole query otherwise, v65+). Do NOT decorate Id, the connection plumbing (edges, node, the connection field), or pageInfo — those are not FLS-gated and the graphiti output leaves them bare. Consume with ?./??. Placement rules: references/graphql-hand-authoring.md.
  4. Mutations wrap under uiapi(input: { allOrNone: ... }); set allOrNone explicitly; output excludes child/navigated-reference fields; the output field is literally named Record (unrelated to the _Record entity suffix in rule 2) — Delete → Id only. GA v66+.
  5. Explicit pagination — always set first:, because the server silently caps at 10 and you'll drop rows with no error; forward-only (first/after, no last/before); upperBound (v59+) raises the per-request ceiling for large sets (when set, first must be 200–2000).
  6. SOQL governor limits applyuiapi queries compile to SOQL, so the same governor limits are inherited: ≤10 subqueries, ≤5 child→parent levels, ≤1 parent→child level, ≤2,000 records/subquery. Split into multiple requests if you'd exceed them.
  7. Field value wrappers — read the raw value via .value; displayValue is the server-formatted string for UI. When a field is both shown and operated on (currency, dates, picklists), select both value and displayValue so you don't reformat on the client. Display-only fields can take just displayValue.
  8. Compound fields — filter/order on constituents (BillingCity), not the wrapper (BillingAddress).
  9. Supported APIs only — GraphQL (uiapi), UI API REST, Apex REST, Connect REST, Einstein LLM via sdk.fetch. NOT: Enterprise SOQL /query, Aura-enabled Apex, Chatter (use uiapi.currentUser). See references/rest-and-integration.md.

One SDK convention lives in the workflows, not this list (it's not a platform behavior): always run npm run graphql:codegen and use the generated types after writing an operation (Read workflow step 3). Also in the Pre-flight checklist.

graphiti applies most of these for you. When you compile a query with sf-gql-* against an object that's in the primed schema, rules 3 (@optional), 4 (mutation Record output envelope and entity-keyed input — not allOrNone, which you still add yourself), 5 (first:/pageInfo), and 7 (value/displayValue wrappers) come out already satisfied — which is exactly why you paste the query verbatim rather than re-deriving it. Rules 1 (check result.errors), 6 (governor limits), 8 (compound fields), and 9 (supported APIs) are still on you. And the automation only fires when the object is primed: a non-empty warnings array means it isn't, and the emitted query is degraded (bare fields, no guardrails) — see references/graphiti-cli.md.


Commands & layout

<skill-dir>/                            ← wherever this skill is installed
└── scripts/graphql-search.sh           ← schema lookup (ships with the skill)

<project-root>/                         ← SFDX project root; run the script from here
├── schema.graphql                      ← generated mirror; grep target (never open or edit; script reads ./schema.graphql)
└── force-app/main/default/uiBundles/<app>/   ← UI bundle dir
    ├── package.json                    ← npm scripts
    └── src/api/                        ← queries, generated types, SDK calls
Command Run from Purpose
npx graphiti sf-gql-discover '{…}' UI bundle dir Discover objects/fields against the live org (preferred grounding)
npx graphiti sf-gql-<list|detail|aggregate|create|update|delete|raw> '{…}' UI bundle dir Compile a guardrail-applied query/mutation (references/graphiti-cli.md)
npx graphiti sf-gql-connect '{"org":"<alias>","forceRefresh":true}' UI bundle dir Refresh graphiti's schema cache after a deploy
bash <skill-dir>/scripts/graphql-search.sh <Entity> project root (or pass --schema <path>; no tree walk-up) Schema lookup fallback (grep over local schema.graphql)
npm run graphql:schema UI bundle dir Fetch/refresh schema.graphql (for the fallback script)
npm run graphql:codegen UI bundle dir Generate operation types
npx eslint <file> UI bundle dir Lint (catches gql schema violations)

Pre-flight checklist

  • Surface decided: sdk.graphql! only if WebApp-only; otherwise guard with if (!sdk.graphql) … (Surfaces)
  • Every field/entity verified — sf-gql-discover (preferred) or graphql-search.sh (fallback, against the right schema)
  • If compiled with graphiti: warnings: [] confirmed (non-empty = degraded query, don't ship); query pasted verbatim
  • @optional on FLS-gated fields + relationships (NOT Id/edges/node/pageInfo); ?./?? in consuming code
  • result.errors checked before reading result.data
  • Caching considered: default 300s OK, or cacheControl / refresh chosen deliberately
  • npm run graphql:codegen run; generated types used; npx eslint passes

Version History

  • 1.29.0 Current 2026-07-05 18:50

Same Skill Collection

skills/automation-flow-generate/SKILL.md
skills/commerce-b2b-open-code-components-integrate/SKILL.md
skills/commerce-b2b-store-create/SKILL.md
skills/data360-activate/SKILL.md
skills/data360-code-extension-generate/SKILL.md
skills/data360-prepare/SKILL.md
skills/data360-schema-get/SKILL.md
skills/design-systems-slds-apply/SKILL.md
skills/dx-org-permission-set-assign/SKILL.md
skills/dx-org-switch/SKILL.md
skills/experience-lwc-generate/SKILL.md
skills/experience-ui-bundle-features-generate/SKILL.md
skills/experience-ui-bundle-file-upload-generate/SKILL.md
skills/experience-ui-bundle-metadata-generate/SKILL.md
skills/experience-ui-bundle-site-generate/SKILL.md
skills/external-diagram-visual-generate/SKILL.md
skills/platform-apex-logs-debug/SKILL.md
skills/platform-custom-application-generate/SKILL.md
skills/platform-custom-tab-generate/SKILL.md
skills/platform-lightning-app-coordinate/SKILL.md
skills/platform-list-view-generate/SKILL.md
skills/platform-metadata-deploy/SKILL.md
skills/platform-permission-set-generate/SKILL.md
skills/platform-validation-rule-generate/SKILL.md
skills/agentforce-architecture-analyze/SKILL.md
skills/agentforce-d360-analyze/SKILL.md
skills/agentforce-generate/SKILL.md
skills/agentforce-observe/SKILL.md
skills/agentforce-test/SKILL.md
skills/commerce-b2b-open-code-components-replace/SKILL.md
skills/data360-connect/SKILL.md
skills/data360-harmonize/SKILL.md
skills/data360-orchestrate/SKILL.md
skills/data360-query/SKILL.md
skills/data360-segment/SKILL.md
skills/design-systems-slds-validate/SKILL.md
skills/design-systems-slds2-migrate/SKILL.md
skills/dx-app-analytics-query/SKILL.md
skills/dx-code-analyzer-configure/SKILL.md
skills/dx-code-analyzer-custom-rule-create/SKILL.md
skills/dx-code-analyzer-run/SKILL.md
skills/dx-devops-test-failures-analyze/SKILL.md
skills/dx-devops-test-pipeline-configure/SKILL.md
skills/dx-devops-test-suite-assignments-configure/SKILL.md
skills/dx-devops-test-suite-run/SKILL.md
skills/dx-org-manage/SKILL.md
skills/experience-cms-brand-apply/SKILL.md
skills/experience-content-media-search/SKILL.md
skills/experience-ui-bundle-agentforce-client-generate/SKILL.md
skills/experience-ui-bundle-app-coordinate/SKILL.md
skills/experience-ui-bundle-custom-app-generate/SKILL.md
skills/experience-ui-bundle-deploy/SKILL.md
skills/experience-ui-bundle-frontend-generate/SKILL.md
skills/external-diagram-mermaid-generate/SKILL.md
skills/integration-connectivity-connected-app-configure/SKILL.md
skills/integration-connectivity-generate/SKILL.md
skills/integration-eventing-cdc-configure/SKILL.md
skills/integration-eventing-subscription-configure/SKILL.md
skills/mobile-apps-create/SKILL.md
skills/mobile-platform-native-capabilities-integrate/SKILL.md
skills/mobile-platform-offline-validate/SKILL.md
skills/omnistudio-callable-apex-generate/SKILL.md
skills/omnistudio-datamapper-generate/SKILL.md
skills/omnistudio-datapacks-deploy/SKILL.md
skills/omnistudio-dependencies-analyze/SKILL.md
skills/omnistudio-epc-catalog-generate/SKILL.md
skills/omnistudio-flexcard-generate/SKILL.md
skills/omnistudio-integration-procedure-generate/SKILL.md
skills/omnistudio-omniscript-generate/SKILL.md
skills/platform-agentexchange-partner-offers-configure/SKILL.md
skills/platform-agentsetup-categories-fetch/SKILL.md
skills/platform-apex-generate/SKILL.md
skills/platform-apex-test-generate/SKILL.md
skills/platform-apex-test-run/SKILL.md
skills/platform-custom-field-generate/SKILL.md
skills/platform-custom-lightning-type-generate/SKILL.md
skills/platform-custom-object-generate/SKILL.md
skills/platform-data-manage/SKILL.md
skills/platform-docs-get/SKILL.md
skills/platform-flexipage-generate/SKILL.md
skills/platform-metadata-api-context-get/SKILL.md
skills/platform-metadata-retrieve/SKILL.md
skills/platform-sharing-rules-generate/SKILL.md
skills/platform-soql-query/SKILL.md
skills/platform-tracing-agentforce-configure/SKILL.md
skills/platform-tracing-configure/SKILL.md
skills/platform-trust-archive-manage/SKILL.md
skills/platform-value-set-generate/SKILL.md

Metadata

Files
0
Version
1.29.0
Hash
a171f444
Indexed
2026-07-05 18:50

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-09 00:41
浙ICP备14020137号-1 $bản đồ khách truy cập$