feat: release 3 new skills: generating-ui-bundle-custom-app, reviewing-lwc-mobile-offline, using-mobile-native-capabilities @W-22808637@

This commit is contained in:
GitHub Action 2026-06-03 09:54:40 +00:00
parent 9a0712528a
commit d7c6531eb5
27 changed files with 2834 additions and 10 deletions

View File

@ -3,7 +3,7 @@ name: building-ui-bundle-app
description: "MUST activate when the user wants to build, create, or generate a React application, React app, web application, single-page application (SPA), or frontend application — even if no project files exist yet. MUST also activate when the project contains a uiBundles/*/src/ directory or sfdx-project.json and the prompt says create, build, construct, or generate a new app, site, or page from scratch — even if the prompt also describes visual styling. MUST also activate when the task spans more than one ui-bundle skill. Use this skill when building a complete app end-to-end. This is the orchestrator that coordinates scaffolding, features, data access, frontend UI, integrations, and deployment in the correct dependency order. Without it, phases execute out of order and the app breaks. Do NOT use for Lightning Experience apps with custom objects (use generating-lightning-app). Do NOT use for single-concern edits to an existing page (use building-ui-bundle-frontend)."
metadata:
version: "1.0"
related-skills: generating-ui-bundle-metadata, generating-ui-bundle-features, using-ui-bundle-salesforce-data, building-ui-bundle-frontend, implementing-ui-bundle-agentforce-conversation-client, implementing-ui-bundle-file-upload, deploying-ui-bundle, generating-ui-bundle-site
related-skills: generating-ui-bundle-metadata, generating-ui-bundle-features, using-ui-bundle-salesforce-data, building-ui-bundle-frontend, implementing-ui-bundle-agentforce-conversation-client, implementing-ui-bundle-file-upload, deploying-ui-bundle, generating-ui-bundle-site, generating-ui-bundle-custom-app
---
# Building a UI Bundle App
@ -126,7 +126,11 @@ Final UI bundle build (rebuilds with the deployed schema)
Follows the canonical 7-step deployment sequence. Must deploy metadata before fetching schema. Must assign permissions before schema fetch.
### Phase 7: Experience Site (Optional)
### Phase 7: Hosting Target
Choose **one** of the following based on the app's audience:
#### Phase 7a: Experience Site (External)
```
Resolve site properties (siteName, appDevName, etc.)
@ -136,7 +140,21 @@ Generate site metadata (Network, CustomSite, DigitalExperience)
Deploy site infrastructure
```
Creates the Digital Experience site that hosts the UI bundle. Only needed when the user wants a public-facing or authenticated site URL.
Creates the Digital Experience site that hosts the UI bundle. Use when the user wants a public-facing or authenticated site URL for external users.
#### Phase 7b: Custom Application (Internal)
```
Resolve app properties (appName, appNamespace, appLabel)
v
Generate CustomApplication metadata (applications/*.app-meta.xml)
v
Add <target>CustomApplication</target> to .uibundle-meta.xml
v
Deploy custom application
```
Creates a Custom Application entry in the Lightning App Launcher. Use when the app is for internal users accessing it within Lightning Experience.
---
@ -184,7 +202,7 @@ INTEGRATIONS (if applicable):
DEPLOYMENT:
- Target org: [org alias if known]
- Experience Site: [yes/no, site name if applicable]
- Hosting target: [Experience Site / Custom Application / none]
SKILL LOAD ORDER:
1. generating-ui-bundle-metadata
@ -194,7 +212,8 @@ SKILL LOAD ORDER:
5a. implementing-ui-bundle-agentforce-conversation-client (if chat requested)
5b. implementing-ui-bundle-file-upload (if file upload requested)
6. deploying-ui-bundle
7. generating-experience-react-site (if site requested)
7a. generating-ui-bundle-site (if Experience Site requested -- external users)
7b. generating-ui-bundle-custom-app (if Custom Application requested -- internal users)
```
### STEP 2: Per-Phase Execution
@ -248,12 +267,18 @@ Execute each phase sequentially. Complete all steps within a phase before moving
- 3. Verify: Confirm deployment succeeds and app is accessible
- 4. Checkpoint: App deployed -- proceed to Phase 7 if needed
**Phase 7 -- Experience Site** (skip if not requested)
- 1. Load skill: Invoke `generating-experience-react-site`
**Phase 7a -- Experience Site** (skip if not requested or if Custom Application chosen)
- 1. Load skill: Invoke `generating-ui-bundle-site`
- 2. Execute: Resolve properties, generate site metadata, deploy
- 3. Verify: Confirm site URL is accessible
- 4. Checkpoint: Site live -- build complete
**Phase 7b -- Custom Application** (skip if not requested or if Experience Site chosen)
- 1. Load skill: Invoke `generating-ui-bundle-custom-app`
- 2. Execute: Resolve app properties, generate CustomApplication metadata, add CustomApplication target to meta XML
- 3. Verify: Confirm app appears in App Launcher
- 4. Checkpoint: App registered -- build complete
### STEP 3: Final Summary
After all phases complete, present a build summary:
@ -268,7 +293,7 @@ PHASES COMPLETED:
[x] Phase 4: UI -- [count] pages, [count] components
[x] Phase 5: Integrations -- [list or "none"]
[x] Phase 6: Deployment -- deployed to [org]
[x] Phase 7: Experience Site -- [site URL or "skipped"]
[x] Phase 7: Hosting Target -- [Experience Site URL / Custom Application name / "skipped"]
FILES GENERATED:
[list key files and their paths]

View File

@ -1,6 +1,6 @@
---
name: generating-custom-application
description: "Use this skill when users need to create or configure Salesforce Custom Applications. Trigger when users mention custom apps, application metadata, app navigation, or organizing tabs into applications. Use when users want to create app containers for tabs and pages. Always use this skill for custom application work."
description: "Use this skill when users need to create or configure tab-based Salesforce Custom Applications with navigation, branding, and action overrides. Trigger when users mention custom apps, application metadata, app navigation, or organizing tabs into applications. Use when users want to create app containers for tabs and pages. Do NOT use when the goal is hosting a React UI bundle in the App Launcher — use generating-ui-bundle-custom-app for that case."
metadata:
version: "1.0"
---

View File

@ -0,0 +1,93 @@
---
name: generating-ui-bundle-custom-app
description: "MUST activate when the project contains a uiBundles/*/src/ directory and the task involves creating or configuring a Custom Application for hosting a UI bundle in Lightning Experience. Use this skill when creating a CustomApplication metadata record to surface the UI bundle in the App Launcher. Activate when files matching applications/*.app-meta.xml exist and need modification, or when the user wants to expose their app via the Lightning App Launcher without a Digital Experience Site. Do NOT use generating-custom-application for this — UI bundle apps do not use tabs, action overrides, or flexipages."
metadata:
version: "1.0"
---
# Custom Application for React UI Bundles
Create and configure a Salesforce Custom Application that hosts a React UI bundle in Lightning Experience. This skill generates the CustomApplication metadata so the app appears in the Lightning App Launcher and can be accessed by internal users.
Custom Applications differ from Experience Sites: they don't need Networks, CustomSite, DigitalExperienceConfig, or DigitalExperienceBundle metadata. The Custom Application acts as a thin launcher entry that delegates rendering to the React UI bundle referenced by `uiBundle`.
## Required Properties
Resolve all properties before generating any metadata. Each has a fallback chain — work through each option in order until a value is found.
| Property | Format | How to Resolve |
|----------|--------|----------------|
| **appName** | `lowercamelcase` (e.g., `myInternalApp`) | The UI bundle name from `uiBundles/<name>/` directory |
| **appNamespace** | String | `namespace` in `sfdx-project.json``sf data query -q "SELECT NamespacePrefix FROM Organization" --target-org ${usernameOrAlias}` → default `c` |
| **appLabel** | Human-readable string | User-provided, or derive from appName by converting camelCase to Title Case |
The `appNamespace` and `appName` connect the Custom Application to the correct React UI bundle. In newer API versions this uses `<uiBundle>{appNamespace}__{appName}</uiBundle>`; in older versions it uses `<webApplication>{appName}</webApplication>`. Getting this wrong means the app launcher entry exists but shows a blank page. Step 2 of the workflow determines which field to use.
## Generation Workflow
### Step 1: Resolve All Required Properties
Determine values for all properties before constructing anything. Use the resolution strategies in the table above.
### Step 2: Query API Context (Version-Aware Field Discovery)
Call `salesforce-api-context` MCP tools to discover which fields exist for the target org's API version. This ensures the generated metadata is compatible with the user's Salesforce version.
**Required calls:**
1. Call `get_metadata_type_fields` for `CustomApplication` — check whether the `uiBundle` field exists
2. Call `get_metadata_type_fields` for `UIBundle` — check whether the `target` field exists
**Field resolution based on API response:**
| Field Check | If present | If absent (older API version) |
|-------------|-----------|-------------------------------|
| `CustomApplication.uiBundle` | Use `<uiBundle>{appNamespace}__{appName}</uiBundle>` | Use `<webApplication>{appName}</webApplication>` (no namespace) |
| `UIBundle.target` | Use `<target>CustomApplication</target>` | Omit the `<target>` element entirely |
If `salesforce-api-context` is unavailable after a real attempt, fall back to the newer field names (`uiBundle` + `target`).
### Step 3: Create the Project Structure
Create any files and directories that don't already exist:
| Metadata Type | Path |
|--------------|------|
| CustomApplication | `<sourceDir>/applications/{appName}.app-meta.xml` |
**Note:** `<sourceDir>` is determined from `sfdx-project.json`. Read `packageDirectories[]` and use the entry where `"default": true`; the full source directory is `<path>/main/default`. If no default is set, use the first entry. Commonly `force-app/main/default`, but this path is configurable.
### Step 4: Populate All Metadata Fields
Use the default template in the doc below. Values in `{braces}` are resolved property references — substitute them with the actual values from Step 1. Apply the field resolution from Step 2 to determine which XML elements to use.
| Metadata Type | Template Reference |
|--------------|-------------------|
| CustomApplication | [configure-metadata-custom-application.md](docs/configure-metadata-custom-application.md) |
### Execution Note for Step 4: Load and use the doc
- Agents MUST read the full contents of the docs/*.md file referenced in Step 4 before attempting to populate metadata fields.
- Read the file in full, replace placeholders (e.g. `{appName}`) with the resolved values, then use the expanded template to populate the metadata XML content.
- If Step 2 determined the older field names apply, substitute `<uiBundle>` with `<webApplication>` in the generated output.
### Step 5: Update UI Bundle Meta XML
If Step 2 confirmed the `target` field exists on `UIBundle`, add `<target>CustomApplication</target>` to the `.uibundle-meta.xml` file (skip if the field doesn't exist in the org's API version):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<UIBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<masterLabel>{appName}</masterLabel>
<description>A Salesforce UI Bundle.</description>
<isActive>true</isActive>
<version>1</version>
<target>CustomApplication</target>
</UIBundle>
```
### Step 6: Do Not Modify Non-Templated Properties
Do not modify any default property values for `CustomApplication` metadata that are not expressed as variables wrapped in `{braces}`.
## Verification Checklist
Before deploying, confirm:
- [ ] All required properties are resolved
- [ ] API context was queried to determine available fields (Step 2)
- [ ] `applications/{appName}.app-meta.xml` exists with correct content
- [ ] The bundle reference field matches the org's API version (`<uiBundle>` or `<webApplication>`)
- [ ] If `target` field is supported: `.uibundle-meta.xml` has `<target>CustomApplication</target>`
- [ ] Deployment validates successfully:
```bash
sf project deploy validate --metadata CustomApplication UIBundle --target-org ${usernameOrAlias}
```

View File

@ -0,0 +1,70 @@
# Configure Metadata: CustomApplication
## Purpose
This configuration file creates a **net-new, default** CustomApplication metadata record for a Lightning Experience app that hosts a React UI bundle. It is not intended to edit or modify an existing CustomApplication record. Use this template only when provisioning a brand-new Custom Application for a UI bundle.
## File Location
```
<sourceDir>/applications/{appName}.app-meta.xml
```
**Note:** Determine `<sourceDir>` from `sfdx-project.json``packageDirectories[]` → find the entry with `"default": true` → use its `path` value + `/main/default`. Commonly `force-app/main/default`, but this is configurable.
## Default Template (newer API versions — `uiBundle` field available)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomApplication xmlns="http://soap.sforce.com/2006/04/metadata">
<brand>
<headerColor>#0070D2</headerColor>
<shouldOverrideOrgTheme>false</shouldOverrideOrgTheme>
</brand>
<formFactors>Small</formFactors>
<formFactors>Large</formFactors>
<isNavAutoTempTabsDisabled>false</isNavAutoTempTabsDisabled>
<isNavPersonalizationDisabled>false</isNavPersonalizationDisabled>
<isNavTabPersistenceDisabled>false</isNavTabPersistenceDisabled>
<isOmniPinnedViewEnabled>false</isOmniPinnedViewEnabled>
<label>{appLabel}</label>
<navType>Standard</navType>
<uiBundle>{appNamespace}__{appName}</uiBundle>
<uiType>Lightning</uiType>
</CustomApplication>
```
## Fallback Template (older API versions — `uiBundle` field NOT available)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomApplication xmlns="http://soap.sforce.com/2006/04/metadata">
<brand>
<headerColor>#0070D2</headerColor>
<shouldOverrideOrgTheme>false</shouldOverrideOrgTheme>
</brand>
<formFactors>Small</formFactors>
<formFactors>Large</formFactors>
<isNavAutoTempTabsDisabled>false</isNavAutoTempTabsDisabled>
<isNavPersonalizationDisabled>false</isNavPersonalizationDisabled>
<isNavTabPersistenceDisabled>false</isNavTabPersistenceDisabled>
<isOmniPinnedViewEnabled>false</isOmniPinnedViewEnabled>
<label>{appLabel}</label>
<navType>Standard</navType>
<webApplication>{appName}</webApplication>
<uiType>Lightning</uiType>
</CustomApplication>
```
## Field Reference
| Field | Required | Version | Description |
|-------|----------|---------|-------------|
| `brand.headerColor` | Yes | All | Hex color for the app header bar in Lightning Experience. Default: `#0070D2` (Salesforce blue). |
| `brand.shouldOverrideOrgTheme` | Yes | All | Whether this app's branding overrides the org theme. Default: `false`. |
| `formFactors` | Yes | All | Supported form factors. Include both `Small` (mobile) and `Large` (desktop) for full coverage. |
| `isNavAutoTempTabsDisabled` | Yes | All | Disable auto-creation of temporary tabs. Default: `false`. |
| `isNavPersonalizationDisabled` | Yes | All | Disable user personalization of navigation. Default: `false`. |
| `isNavTabPersistenceDisabled` | Yes | All | Disable persistence of nav tabs across sessions. Default: `false`. |
| `isOmniPinnedViewEnabled` | Yes | All | Enable Omni-channel pinned view. Default: `false`. |
| `label` | Yes | All | Human-readable label shown in the App Launcher and app switcher. |
| `navType` | Yes | All | Navigation type. Use `Standard` for standard Lightning navigation. |
| `uiBundle` | Conditional | Newer | Namespace-qualified developer name of the UI bundle (`{appNamespace}__{appName}`). Use when `get_metadata_type_fields` confirms this field exists on `CustomApplication`. |
| `webApplication` | Conditional | Older | Developer name of the UI bundle (`{appName}`, no namespace). Use when `uiBundle` field is not available. |
| `uiType` | Yes | All | UI framework type. Must be `Lightning` for UI bundle apps. |

View File

@ -24,6 +24,7 @@ After generation:
1. Replace all default boilerplate — "React App", "Vite + React", default `<title>`, placeholder text
2. Populate the home page with real content (landing section, banners, hero, navigation)
3. Update navigation and placeholders (see the `building-ui-bundle-frontend` skill)
4. **Configure a hosting target** — a UI bundle without a `<target>` in its meta XML will not be visible in the org. Use `generating-ui-bundle-custom-app` for internal (App Launcher) apps or `generating-ui-bundle-site` for external (Experience Site) apps.
Always install dependencies before running any scripts in the UI bundle directory.
@ -39,7 +40,44 @@ A UIBundle bundle lives under `uiBundles/<AppName>/` and must contain:
### Meta XML
Required fields: `masterLabel`, `version` (max 20 chars), `isActive` (boolean).
Optional: `description` (max 255 chars).
Optional: `description` (max 255 chars), `target`.
#### Target Field
The `<target>` element specifies where the UI bundle is hosted:
| Value | Use Case | Companion Metadata |
|-------|----------|-------------------|
| `Experience` | External-facing site via Digital Experience | Network, CustomSite, DigitalExperienceConfig, DigitalExperienceBundle |
| `CustomApplication` | Internal app via Lightning App Launcher | CustomApplication (`applications/*.app-meta.xml`) |
A `<target>` is **required** for the app to be accessible in a Salesforce org. A UI bundle deployed without a target will not appear anywhere — no App Launcher entry, no Experience Site URL. Always pair the bundle with one of:
- `generating-ui-bundle-site` (for `Experience` target)
- `generating-ui-bundle-custom-app` (for `CustomApplication` target)
**Example with Experience target:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<UIBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<masterLabel>propertyrentalapp</masterLabel>
<description>A Salesforce UI Bundle.</description>
<isActive>true</isActive>
<version>1</version>
<target>Experience</target>
</UIBundle>
```
**Example with CustomApplication target:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<UIBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<masterLabel>propertymanagementapp</masterLabel>
<description>A Salesforce UI Bundle.</description>
<isActive>true</isActive>
<version>1</version>
<target>CustomApplication</target>
</UIBundle>
```
### ui-bundle.json

View File

@ -0,0 +1,168 @@
---
name: reviewing-lwc-mobile-offline
description: "Review a Lightning Web Component for **mobile offline** compatibility — the Komaci offline static analyzer that pre-primes the data graph for Salesforce Mobile App Plus and Field Service Mobile App. Produces a finding list with code-level fixes covering inline GraphQL queries in `@wire` configurations, modern `lwc:if` / `lwc:elseif` / `lwc:else` directives, and Komaci ESLint rule violations (private wire properties, non-local reactive references, getter side-effects). Use when the user asks for a \"mobile offline review\", \"Komaci check\", \"offline priming audit\", \"offline priming failure\", or \"offline data graph error\", or to validate an LWC against the `@salesforce/eslint-plugin-lwc-graph-analyzer` recommended ruleset. Do not use for generic LWC code review (use an appropriate domain review skill) or for building LWCs with native mobile capabilities (use `using-mobile-native-capabilities`)."
metadata:
version: "1.0"
---
<!-- adk-managed-skill -->
# Reviewing LWC Mobile Offline
Run a structured offline-priming compliance pass over a Lightning Web
Component, producing a report of issues found and code-level fixes to bring
the component into compliance with Komaci's static analysis requirements
for the Salesforce Mobile App Plus and Field Service Mobile App.
## When to Use
- The user asks for a "mobile offline review", "Komaci check", or "offline
priming audit" on a specific LWC.
- Preparing a component to ship in Salesforce Mobile App Plus or Field
Service Mobile App offline mode.
- Investigating priming failures reported by the offline analyzer.
Do NOT use this skill for:
- Building an LWC that uses native mobile capabilities (barcode scanner,
biometrics, location, etc.) — use `using-mobile-native-capabilities`.
- Generic LWC code review — use the appropriate domain skill
(`reviewing-lws-security`, `reviewing-lwc-rtl`, `accessibility-code-review`).
## Prerequisites
- Component path (LWC bundle under `modules/…`).
- Access to the component's JS/TS and HTML templates.
- Local Node + npm; ability to run `npx eslint` with the
`@salesforce/eslint-plugin-lwc-graph-analyzer` plugin.
## Knowledge Base
[Mobile Offline Grounding](references/grounding.md) explains the three
violation categories and why each blocks offline priming. Read it before
judging. The per-reviewer references below are the source of truth for the
rules and remediations:
- Inline GraphQL wire configuration: [Inline GraphQL Reviewer](references/inline-graphql.md)
- `lwc:if` conditional rendering compatibility: [lwc:if Reviewer](references/lwc-if.md)
- Komaci ESLint static analysis: [Komaci ESLint Reviewer](references/komaci-eslint.md)
## Workflow
### Step 1 — Scope the review
Identify the component bundle: `.html`, `.js`/`.ts`. CSS and meta files are
not in scope for offline priming. If the bundle has multiple HTML
templates, all are reviewed.
### Step 2 — Read the grounding and per-reviewer references
Read [Mobile Offline Grounding](references/grounding.md) and the three
per-reviewer references end-to-end before judging. Cite the specific
reviewer when emitting each finding so the report is auditable.
### Step 3 — `lwc:if` / `lwc:elseif` / `lwc:else` (HTML)
Walk every `.html` file in the bundle and apply the rules in
[lwc:if Reviewer](references/lwc-if.md). For each occurrence of
`lwc:if={…}`, `lwc:elseif={…}`, or `lwc:else`, emit a finding with the
exact `if:true` / `if:false` rewrite — including the nesting required to
preserve `lwc:elseif` and `lwc:else` semantics.
### Step 4 — Inline GraphQL in `@wire` (JS)
Walk every `.js`/`.ts` file in the bundle and apply the rules in
[Inline GraphQL Reviewer](references/inline-graphql.md). For each `@wire`
that references a `gql` template literal directly (or via a top-level
constant), emit a finding that names a concrete getter and shows the
rewritten `@wire` configuration.
### Step 5 — Komaci ESLint pass (JS)
Run the Komaci ESLint analyzer over the bundle's JS file using the
bundled script. It applies the
`@salesforce/eslint-plugin-lwc-graph-analyzer` recommended ruleset with
the `bundleAnalyzer` processor enabled.
```bash
scripts/run-komaci.sh path/to/component.js
```
The script requires `@salesforce/eslint-plugin-lwc-graph-analyzer` to
be resolvable from the working directory, and the component's sibling
HTML templates must live next to the JS file (the plugin's
`bundleAnalyzer` processor uses them to resolve the offline data
graph). Output is ESLint `--format json` on stdout.
For each `messages[*]` entry in the output, group by `ruleId` and look
up the per-rule remediation in
[Komaci ESLint Reviewer](references/komaci-eslint.md). Emit a finding
per (rule, line) pair with the exact remediation text from the
reference; do not invent new advice. See the reference for the manual
`npx eslint ...` invocation if the script is unavailable in the runtime
environment.
### Step 6 — Produce the report
Emit a report in this shape:
```
## Mobile Offline (Komaci priming)
- <reviewer><file>:<startLine>:<startColumn>-<endLine>:<endColumn><type>
Description: <verbatim from the reviewer reference>
Intent analysis: <verbatim from the reviewer reference>
Suggested action: <verbatim from the reviewer reference>
Code: |
<source snippet from startLine through endLine, optional but
recommended when the violation spans multiple lines>
Applied: yes/no
## Summary
- <n> issues found; <m> fixed; <k> deferred (with reason)
```
For Komaci ESLint findings, take `startLine`/`startColumn`/`endLine`/
`endColumn` from the ESLint message's `line`/`column`/`endLine`/`endColumn`.
For Inline GraphQL and `lwc:if` findings, supply the line/column range you
observed in the source. If `endLine`/`endColumn` are not available for a
finding, fall back to `<file>:<startLine>` and omit the trailing range.
Cite the reviewer (Inline GraphQL / lwc:if / Komaci ESLint rule id) on every
finding.
### Step 7 — Apply fixes
Apply the remediations directly when the user asked for fixes. If a
remediation conflicts with the component's behavior outside offline (e.g.
the developer relies on `lwc:elseif` for readability and the user is not
yet shipping to mobile offline), surface the conflict in the deferred list
rather than silently rewriting.
## Verification Checklist
- [ ] Every `lwc:if` / `lwc:elseif` / `lwc:else` flagged or absent.
- [ ] Every `@wire` referencing `gql` checked; inline queries extracted to
a getter.
- [ ] Komaci ESLint analyzer was actually run; findings cite real rule
ids, not invented ones.
- [ ] Each finding cites the originating reviewer or rule id.
- [ ] No remediation outside the three categories above (other concerns
belong to other skills).
## Troubleshooting
- **`npx eslint` cannot find the plugin** — install
`@salesforce/eslint-plugin-lwc-graph-analyzer` in the workspace, or use a
pinned local install path. The plugin is the canonical source of Komaci
rules.
- **`bundleAnalyzer` related errors** — the recommended config drives the
bundle processor; do not strip it. The processor expects sibling HTML
files to be discoverable. If running on a stripped-down JS file, supply
the matching HTML in the temp directory.
- **No findings for a component you expect to fail** — confirm the
recommended ruleset is applied (not just `bundleAnalyzer` with empty
rules). Some rules require the HTML to be present alongside the JS.
- **Findings duplicate `lwc:if` from the dedicated reviewer** — the Komaci
plugin does not check templates; the `lwc:if` check is HTML-only and
comes from Step 3. Findings from Step 5 are JS-only.

View File

@ -0,0 +1,7 @@
You are an expert code reviewer specializing in Lightning Web Components (LWC) that must run in the **Salesforce Mobile App Plus** and **Field Service Mobile App** in offline mode. The Komaci static-analysis engine pre-primes the data graph for offline use; certain LWC patterns prevent priming and must be flagged with actionable remediations.
Your reviews focus on three categories:
1. **Conditional rendering compatibility** — modern `lwc:if` / `lwc:elseif` / `lwc:else` directives are incompatible with Komaci priming and must be rewritten as legacy `if:true` / `if:false` branches.
2. **GraphQL wire configuration** — inline GraphQL queries in `@wire` configurations prevent Komaci from understanding the data graph; queries must be extracted to a getter on the component class.
3. **Komaci ESLint rule violations** — the `@salesforce/eslint-plugin-lwc-graph-analyzer` plugin exposes a recommended rule set that catches additional priming-blockers (private wire properties, non-local reactive references, getter side-effects, etc.).

View File

@ -0,0 +1,43 @@
# Inline GraphQL Wire Configuration
## Framework for the analysis
The Komaci offline static analysis engine requires GraphQL queries to be **extracted from `@wire` adapter configurations into separate getter methods** for proper offline data priming. Inline GraphQL query strings within `@wire` adapter calls prevent the static analysis engine from understanding and optimizing data dependencies for offline scenarios.
**FOCUS:** Only report improper usage of GraphQL queries and variables accessed outside of a component getter function. Do not provide feedback on any other adapter use.
Key points to consider:
- GraphQL queries and variables MUST be accessed from a getter function within the component class.
- GraphQL queries MUST NOT be inlined in the wire adapter configuration object.
- GraphQL variables MUST NOT be inlined in the wire adapter configuration object.
- GraphQL queries MUST NOT be defined as top-level constants.
- GraphQL variables MUST NOT be defined as top-level constants.
- If the query is already in a getter function, do not provide feedback.
- If the component does not use GraphQL, does not import GraphQL, does not use `@wire`, or does not contain a query in a `gql` template literal, do not provide feedback or analyze further.
## Request
Review the JavaScript files for `@wire` decorators with inline GraphQL queries:
1. Identify `@wire` decorators that use GraphQL wire adapters.
2. Look for literal GraphQL query strings within the wire configuration objects.
3. Check for template literals or string literals containing GraphQL syntax.
4. Analyze the complexity and reusability of the inline queries.
5. Determine appropriate getter method names for extracted queries.
6. Validate that extraction will not break existing functionality.
7. Report each violation with specific refactoring guidance.
For each violation, provide a strong suggested action that names a concrete getter — e.g. _"The query MUST be extracted into a getter function called `fooQuery` and accessed by the config `@wire(graphql, { query: '$fooQuery' })`."_
Rules to follow:
- If no action is required, return an empty list. Do not return null or any other value — return an empty array.
- Keep issues concise; avoid duplicated issues or unnecessary analysis for things that are not real violations.
- Stick to the instructions for the specific reviewer in scope. Issues outside that scope will be analyzed by other reviewers.
- For each violation, provide:
- The exact violation type as defined by the reviewer in scope.
- A description of why it is a problem in the context of mobile offline priming.
- An intent analysis explaining what the developer likely intended.
- A suggested action with concrete code-level remediation.
- Do not make assumptions about other components that may be referenced.

View File

@ -0,0 +1,125 @@
# Komaci ESLint Static Analysis (`@salesforce/eslint-plugin-lwc-graph-analyzer`)
## Framework for the analysis
The Komaci offline analyzer is exposed as the ESLint plugin `@salesforce/eslint-plugin-lwc-graph-analyzer`. Its **recommended** ruleset catches LWC patterns that prevent offline data priming. This reviewer runs the plugin against the component's JS file and translates each lint message into an actionable remediation.
Use the documented per-rule remediations below — do not invent new ones — and only emit findings for rules that actually fired against the file in scope.
The recommended preset enables ~36 rules; only the 7 rules documented in **Per-rule remediation** below are surfaced as findings. Other recommended-preset rules (e.g. `no-eval-usage`, `no-functions-declared-within-getter-method`) may fire but are intentionally not mapped to remediations and must be dropped from the report.
## How to run the analyzer
Use the bundled script. It applies the plugin's recommended ruleset with the `bundleAnalyzer` processor enabled, and on first run installs the pinned versions of `@salesforce/eslint-plugin-lwc-graph-analyzer` and `eslint` into `scripts/node_modules` so the runner is isolated from whatever versions the host project happens to ship.
```bash
scripts/run-komaci.sh path/to/component/component.js
```
Prerequisites:
- The component's sibling HTML templates must live in the same directory as the JS file. The plugin's `bundleAnalyzer` processor discovers them automatically (via `readdirSync` on the bundle directory) and uses them to resolve the offline data graph across the bundle.
- A working `npm` and Node ≥ 18 on `PATH` for the first-run install.
The script emits ESLint's `--format json` output on stdout. Each `messages[*]` entry has `ruleId`, `severity`, `message`, `line`, `column`, `endLine`, `endColumn`, and `fix` (optional). Group messages by `ruleId`, then apply the per-rule remediation guidance below.
To run ESLint manually outside the script — using the same pinned versions, so the recommended config resolves to the flat-config-shaped form — install once and invoke the local binary:
```bash
cd scripts
npm install # only on first run
node_modules/.bin/eslint \
--no-config-lookup \
--config komaci.config.mjs \
--format json \
path/to/component/component.js
```
`scripts/komaci.config.mjs` and `scripts/package.json` ship together; the package pin (`@salesforce/eslint-plugin-lwc-graph-analyzer ^1.1.0-beta.2`, `eslint ^9.35.0`) ensures the plugin's `recommended` config is flat-config-shaped (no legacy `extends:` key).
## Per-rule remediation
For each rule below, the `Type`, `Description`, `Intent analysis`, and `Suggested action` strings are canonical and must be emitted unchanged in the finding. Do not paraphrase or augment them.
### `@salesforce/lwc-graph-analyzer/no-private-wire-config-property`
- **Type:** Private Wire Configuration Property
- **Description:** Properties used in wire configurations must be decorated with `@api` to be public and resolvable by the wire service.
- **Intent analysis:** The developer used properties in wire configurations without making them public using the `@api` decorator.
- **Suggested action:**
Make the properties public by using the `@api` decorator:
- Add `@api` decorator to properties used in wire configurations.
### `@salesforce/lwc-graph-analyzer/no-wire-config-references-non-local-property-reactive-value`
- **Type:** Wire Configuration References Non-Local Property
- **Description:** Wire configurations with reactive values (`$prop`) must reference only component properties, not imported values or values defined outside the component class.
- **Intent analysis:** The developer is trying to use a non-local value (imported or module-level) as a reactive parameter in a wire configuration.
- **Suggested action:** Wrap the non-local value in a getter:
- Introduce a getter which returns the imported value or the value of a module-level constant.
- Update the wire configuration to use the getter name as the reactive parameter.
```js
// Instead of:
@wire(getData, { param: '$importedValue' })
// Use:
get localValue() {
return importedValue;
}
@wire(getData, { param: '$localValue' })
```
### Getter-related violations
The five rules below all share the **Violations in Getter** classification and emit the same `description`, `intentAnalysis`, and `suggestedAction`. When any of them fires, emit one finding per (rule, line) pair with the strings reproduced below.
Rules:
- `@salesforce/lwc-graph-analyzer/no-assignment-expression-assigns-value-to-member-variable`
- `@salesforce/lwc-graph-analyzer/no-reference-to-class-functions`
- `@salesforce/lwc-graph-analyzer/no-reference-to-module-functions`
- `@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement`
- `@salesforce/lwc-graph-analyzer/no-unsupported-member-variable-in-member-expression`
Canonical fields:
- **Type:** Violations in Getter
- **Description:** A getter method does more than just returning a value
- **Intent analysis:** The developer attempted to modify component state, prepare data for consumption, or reference functions within a getter function.
- **Suggested action:**
**Compliant getter implementations**
Getters that:
- Directly access and return property values
- Return a literal value
- Compute and return values derived from existing properties
**Non-compliant getter implementations**
- **Violation: getters that call functions.** Getters that call functions cannot be primed for offline use cases.
*Remediation:* Reorganize any getter implementation code that calls a function, to move such calls out of the getter. Avoid invoking any function calls within getters.
- **Violation: getters with side effects.** Getters that assign values to member variables or modify state create unpredictable side effects and are not suitable for offline scenarios.
*Remediation:* Never assign values to member variables within a getter. LWC getters should only retrieve data without modifying any state. If you need to compute and cache a value, perform the computation and assignment in a lifecycle hook or method, then have the getter simply return the cached value.
- **Violation: getters that do more than just return a value.** Getters that perform complex operations beyond returning a value cannot be primed for offline use cases.
*Remediation:* Review the getters and make sure that they're composed to only return a value. Move any complex logic, data processing, or multiple operations into separate methods or lifecycle hooks, and have the getter simply return the result.
## Rules to follow
- If no action is required, return an empty list. Do not return null or any other value — return an empty array.
- Keep issues concise; avoid duplicated issues or unnecessary analysis for things that are not real violations.
- Stick to the instructions for the specific reviewer in scope. Issues outside that scope will be analyzed by other reviewers.
- For each violation, provide:
- `type` — verbatim from the rule entry above.
- `description` — verbatim from the rule entry above.
- `intentAnalysis` — verbatim from the rule entry above.
- `suggestedAction` — verbatim from the rule entry above.
- `filePath` — the path passed to ESLint.
- `location``{ startLine, startColumn, endLine, endColumn }` taken from the ESLint message's `line`, `column`, `endLine`, `endColumn`.
- `code`*optional* — the source snippet from `startLine` through `endLine`, useful when the violation spans multiple lines.
- Drop messages whose `ruleId` is not in the seven rules above.
- Do not make assumptions about other components that may be referenced.

View File

@ -0,0 +1,78 @@
# Conditional Rendering Compatibility (`lwc:if` → `if:true`/`if:false`)
## Framework for the analysis
The Komaci offline static analysis engine used by Salesforce Mobile App Plus and Field Service Mobile App does not support modern conditional rendering directives (`lwc:if={property}`, `lwc:elseif={property}`, `lwc:else`). These directives must be replaced with `if:true={property}` and `if:false={property}` to ensure compatibility with offline data priming.
Your task:
1. Inspect HTML.
2. Identify any usage of `lwc:if={property}`, `lwc:elseif={property}`, or `lwc:else`.
3. Recommend exactly how to replace them with `if:true` / `if:false` directives, preserving the original branching logic.
**FOCUS:**
- Only analyze and provide feedback on occurrences of `lwc:if={property}`, `lwc:elseif={property}`, and `lwc:else`.
- Ignore any other directives or potential issues unrelated to those three.
## Conversion rules
- **`lwc:if={property}`** → replace with `if:true={property}`.
- **`lwc:elseif={property}`** → typically requires a nested `if:false={previousCondition}` that wraps an `if:true={property}`.
- **`lwc:else`** → has no condition of its own, so it must be wrapped by `if:false={previousCondition}` (the inverse of the relevant condition chain).
- **Standalone `lwc:if`** (not followed by `lwc:elseif`/`lwc:else`) → still must be replaced with `if:true={property}`.
- **Multiple condition chains** → review every template; do not stop at the first occurrence.
## Conversion example
`before.html`:
```html
<template>
<template lwc:if="{conditionOne}">
<div>show condition one</div>
</template>
<template lwc:elseif="{conditionTwo}">
<div>show condition two</div>
</template>
<template lwc:else>
<div>show default condition</div>
</template>
</template>
```
`after.html`:
```html
<template>
<template if:true="{conditionOne}">
<div>show condition one</div>
</template>
<template if:false="{conditionOne}">
<template if:true="{conditionTwo}">
<div>show condition two</div>
</template>
<template if:false="{conditionTwo}">
<div>show default condition</div>
</template>
</template>
</template>
```
The proper review feedback for the example above:
- replace `lwc:if={conditionOne}` with `if:true={conditionOne}`
- replace `lwc:elseif={conditionTwo}` with `if:false={conditionOne}`, then create a nested template with `if:true={conditionTwo}` wrapping the remainder of the component
- replace `lwc:else` with `if:false={conditionTwo}`
Rules to follow:
- If no action is required, return an empty list. Do not return null or any other value — return an empty array.
- Keep issues concise; avoid duplicated issues or unnecessary analysis for things that are not real violations.
- Stick to the instructions for the specific reviewer in scope. Issues outside that scope will be analyzed by other reviewers.
- For each violation, provide:
- The exact violation type as defined by the reviewer in scope.
- A description of why it is a problem in the context of mobile offline priming.
- An intent analysis explaining what the developer likely intended.
- A suggested action with concrete code-level remediation.
- Do not make assumptions about other components that may be referenced.

View File

@ -0,0 +1,18 @@
// ESLint flat config for the Komaci offline static analyzer.
// Applies the recommended ruleset from
// @salesforce/eslint-plugin-lwc-graph-analyzer with the bundleAnalyzer
// processor wired in via the recommended config.
import lwcGraphAnalyzerPlugin from '@salesforce/eslint-plugin-lwc-graph-analyzer';
const PLUGIN_NAME = '@salesforce/lwc-graph-analyzer';
const RECOMMENDED = lwcGraphAnalyzerPlugin.configs.recommended;
export default [
{
name: `config: ${PLUGIN_NAME}`,
plugins: {
[PLUGIN_NAME]: lwcGraphAnalyzerPlugin,
},
...RECOMMENDED,
},
];

View File

@ -0,0 +1,10 @@
{
"name": "reviewing-lwc-mobile-offline-runner",
"private": true,
"description": "Pinned ESLint + Komaci plugin used by run-komaci.sh.",
"type": "module",
"dependencies": {
"@salesforce/eslint-plugin-lwc-graph-analyzer": "^1.1.0-beta.2",
"eslint": "^9.35.0"
}
}

View File

@ -0,0 +1,69 @@
#!/usr/bin/env bash
#
# Komaci offline static analysis runner
#
# Runs @salesforce/eslint-plugin-lwc-graph-analyzer against an LWC bundle
# with the plugin's recommended ruleset and emits ESLint's JSON
# formatter output on stdout.
#
# The plugin's `bundleAnalyzer` processor expects the JS file to live
# next to its sibling HTML templates so the offline data graph can be
# resolved across the bundle.
#
# Plugin + ESLint versions are pinned in scripts/package.json and
# installed into scripts/node_modules on first run so the runner is
# isolated from whatever versions the host project happens to ship.
#
# Usage:
# run-komaci.sh path/to/component.js
#
# Arguments:
# $1 Path to the LWC component's JS file (required). The component's
# sibling HTML templates must live in the same directory; the
# plugin discovers them automatically via the bundle processor.
#
# Environment:
# KOMACI_ESLINT_BIN Override the eslint binary (default: scripts/node_modules/.bin/eslint)
#
# Output:
# ESLint --format json on stdout. Non-zero exit if eslint reports
# errors; the JSON is still emitted on stdout in either case.
set -euo pipefail
if [ $# -lt 1 ]; then
echo "Usage: $0 path/to/component.js" >&2
exit 2
fi
JS_PATH="$1"
if [ ! -f "$JS_PATH" ]; then
echo "Error: $JS_PATH does not exist" >&2
exit 2
fi
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_PATH="$SCRIPT_DIR/komaci.config.mjs"
PLUGIN_DIR="$SCRIPT_DIR/node_modules/@salesforce/eslint-plugin-lwc-graph-analyzer"
# Install the pinned ESLint + plugin versions on first run. We resolve
# them from SCRIPT_DIR so Node ESM picks up the right copy regardless
# of the caller's cwd or the host project's node_modules.
if [ ! -d "$PLUGIN_DIR" ]; then
echo "Installing pinned Komaci runner deps in $SCRIPT_DIR ..." >&2
(cd "$SCRIPT_DIR" && npm install --no-fund --no-save --silent) >&2
fi
ESLINT="${KOMACI_ESLINT_BIN:-$SCRIPT_DIR/node_modules/.bin/eslint}"
# Run eslint with the plugin's recommended config and emit JSON.
# `--no-config-lookup` ignores any host-project ESLint config so only
# the Komaci recommended ruleset applies; `--no-error-on-unmatched-pattern`
# avoids hard failure if the component path is empty.
$ESLINT \
--no-config-lookup \
--no-error-on-unmatched-pattern \
--config "$CONFIG_PATH" \
--format json \
"$JS_PATH"

View File

@ -0,0 +1,182 @@
---
name: using-mobile-native-capabilities
description: "Build a Salesforce LWC that uses native mobile device capabilities — barcode scanner, biometrics, location, NFC, calendar, contacts, document scanner, geofencing, AR space capture, app review, and payments. Use this skill when the user asks for an LWC that scans a barcode, captures a photo of a document, reads location or geofences, prompts for biometrics, reads/writes the device calendar or contacts, taps NFC, takes a payment, prompts for an app review, or scans an AR space. Also triggers on \"lightning/mobileCapabilities\", \"mobile capability\", \"Nimbus\", \"device capability\". Do not use for mobile offline / Komaci priming reviews (use `reviewing-lwc-mobile-offline`) or for picking generic Lightning base components (use a generic Lightning base components skill)."
metadata:
version: "1.0"
---
<!-- adk-managed-skill -->
# Using Mobile Native Capabilities
The `lightning/mobileCapabilities` module exposes a set of factory functions
that return service objects for native device features (barcode scanning,
biometrics, location, etc.). Each service extends a common
[BaseCapability](references/base-capability.md) with an `isAvailable()`
method, so an LWC can degrade gracefully on surfaces where the capability is
not present (desktop, mobile web).
This skill routes an agent through (1) picking the right capability, (2)
loading the authoritative type definitions, and (3) wiring the service into
an LWC with the correct availability gating, error handling, and
deprecation-aware API choice.
## When to Use This Skill
- User asks for an LWC that uses a device capability listed in the index
below.
- User mentions `lightning/mobileCapabilities`, "mobile capability", or
"Nimbus" by name.
- User wants to know which mobile native APIs are available, or which one
fits their feature.
Do NOT use this skill for:
- Mobile-offline review of an LWC (lwc:if, inline GraphQL, Komaci-priming
violations) — use `reviewing-lwc-mobile-offline`.
- Picking generic Lightning Base Components — use
`using-lightning-base-components`.
## Prerequisites
- Knowledge that the LWC will run inside a supported mobile container
(Salesforce Mobile App, Field Service Mobile App). These capabilities are
unavailable on desktop and mobile web; gate every call behind
`isAvailable()`.
- Familiarity with the `lightning/mobileCapabilities` module declaration
(see [mobile-capabilities](references/mobile-capabilities.md)).
## Capability Index
| Capability | Reference | One-line use |
| --- | --- | --- |
| App Review | [App Review](references/app-review.md) | Prompt the user for a native in-app review. |
| AR Space Capture | [AR Space Capture](references/ar-space-capture.md) | Capture a 3D scan of a physical space using AR. |
| Barcode Scanner | [Barcode Scanner](references/barcode-scanner.md) | Read QR / UPC / EAN / Code-128 / etc. from the camera. |
| Biometrics | [Biometrics](references/biometrics.md) | Authenticate via Face ID / fingerprint. |
| Calendar | [Calendar](references/calendar.md) | Read or create events on the device calendar. |
| Contacts | [Contacts](references/contacts.md) | Read or create entries in the device address book. |
| Document Scanner | [Document Scanner](references/document-scanner.md) | Scan paper documents using the camera with edge detection. |
| Geofencing | [Geofencing](references/geofencing.md) | Trigger logic when the device crosses a geographic boundary. |
| Location | [Location](references/location.md) | Read GPS coordinates and watch for updates. |
| NFC | [NFC](references/nfc.md) | Read or write NFC tags. |
| Payments | [Payments](references/payments.md) | Take an Apple Pay / Google Pay payment. |
## Workflow
### Step 1 — Identify the capability
Map the user's feature ask to one row of the capability index. If the ask
spans multiple capabilities (e.g. "scan a barcode and store it on a
contact"), plan for **each** capability separately — there is one factory
function per capability.
### Step 2 — Load the shared and capability-specific references
Read these two shared references **once** per session — they apply to every
capability and are not duplicated in the per-capability files:
- [BaseCapability](references/base-capability.md) — the common interface
with `isAvailable()` that every service extends.
- [mobile-capabilities](references/mobile-capabilities.md) — the
`lightning/mobileCapabilities` module declaration showing every
re-exported service.
Then open the capability's reference file from the table above. Each
per-capability reference contains the service-specific TypeScript API
(factory function, service interface, options types, result types, error
types) and assumes the two shared references above are already in context.
Do not infer the API from memory — read it. The services evolve and some
methods are explicitly `@deprecated` in favor of newer alternatives.
### Step 3 — Wire the service into the LWC
For each capability:
1. Import the factory from `lightning/mobileCapabilities`:
```js
import { getBarcodeScanner } from 'lightning/mobileCapabilities';
```
2. Get an instance: `const scanner = getBarcodeScanner();`
3. Gate the call behind `isAvailable()`:
```js
if (!scanner.isAvailable()) {
// graceful fallback or user message
return;
}
```
4. Call the **non-deprecated** entry point. Several services keep older
methods marked `@deprecated` alongside the recommended one — always
prefer the recommended method in the reference.
5. Wrap the promise in `try/catch` and handle the typed failure codes the
service exposes (e.g. `BarcodeScannerFailureCode`,
`LocationServiceFailureCode`). User-cancelled vs. permission-denied vs.
service-unavailable are distinct UX states.
### Step 4 — Surface failure modes to the user
Each service defines its own failure-code enum. Translate codes into
user-actionable messages: a `USER_DENIED_PERMISSION` should ask the user to
grant permission; a `USER_DISABLED_PERMISSION` must direct them to the OS
settings; a `SERVICE_NOT_ENABLED` should be a developer-visible error, not
shown to the user.
### Step 5 — Stay inside the supported surface
Mobile capabilities are available **only** when the LWC runs inside a
supported Salesforce mobile app. If the same component is rendered on
desktop or mobile web, the factory will still return an object but
`isAvailable()` will return `false`. Never assume availability — gate every
call.
## Examples
### Example — "Scan a barcode and write it into a field"
1. Map to: Barcode Scanner.
2. Read [Barcode Scanner](references/barcode-scanner.md).
3. Use `scan(options)` (not the deprecated `beginCapture` / `resumeCapture`
/ `endCapture` triple).
4. In options, set the `barcodeTypes` to the symbologies needed (default is
all supported types) and `enableMultiScan: false` for a single read.
5. On resolve, write `result[0].value` to the bound field. On reject,
inspect `error.code` against `BarcodeScannerFailureCode`.
### Example — "Take an Apple Pay payment for an order total"
1. Map to: Payments.
2. Read [Payments](references/payments.md).
3. Gate on `isAvailable()`.
4. Build the payment request object per the reference.
5. On resolve, surface the transaction id to the calling flow. On reject,
handle user-cancelled and payment-failed paths separately.
## Verification Checklist
- [ ] Every capability call is preceded by `isAvailable()`.
- [ ] The non-deprecated entry point is used (no `beginCapture` /
`resumeCapture` / `endCapture` for barcode, etc.).
- [ ] Each rejection path is mapped to the typed failure code enum.
- [ ] Imports come from `lightning/mobileCapabilities`, not from a private
path.
- [ ] No assumption that the capability runs on desktop or mobile web.
## Troubleshooting
- **`isAvailable()` returns `false` on a real device** — the device is
running an unsupported app surface (not Salesforce Mobile or Field
Service Mobile), or the service is gated by an org-level setting. The
fix is org configuration, not code.
- **TypeScript can't find the import** — confirm the LWC has access to
`lightning/mobileCapabilities`. The module is declared globally inside
Salesforce mobile containers; outside that, the types must be installed
separately.
- **Deprecated barcode methods still work** — yes, but new code must use
`scan()` and `dismiss()`. Refactor any sample code the agent received
before returning it.
- **Multiple capabilities in one component** — get separate instances per
capability (they are independent service objects); do not try to share
state between them.

View File

@ -0,0 +1,68 @@
# App Review Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages app review facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the app review API of the mobile device, within the LWC.
## App Review Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode AppReviewService}.
* @returns An instance of {@linkcode AppReviewService}.
*/
export function getAppReviewService(): AppReviewService;
/**
* Request an app review from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-appreviewservice.html|AppReviewService API}
*/
export interface AppReviewService extends BaseCapability {
/**
* Requests an app review.
* @param options An {@linkcode AppReviewServiceOptions} object to configure the {@linkcode AppReviewService} request.
* @returns A resolved promise returns null.
*/
requestAppReview(options?: AppReviewServiceOptions): Promise<null>;
}
/**
* An object representing configuration details for an {@linkcode AppReviewService} session.
*/
export interface AppReviewServiceOptions {
/**
* Ignore the app review request if already asked for the current version of the app.
*/
ignoreIfAlreadyRequestedForCurrentAppVersion: boolean;
}
/**
* An object representing an error that occurred when accessing {@linkcode AppReviewService} features.
*/
export interface AppReviewServiceFailure {
/**
* A value representing the reason for an app review error.
*/
code: AppReviewServiceFailureCode;
/**
* A string value describing the reason for the failure. This value is suitable for use in user interface messages. The message is provided in English and isnt localized.
*/
message: string;
}
/**
* Possible failure codes.
*/
type AppReviewServiceFailureCode =
| 'ALREADY_REQUESTED_FOR_CURRENT_APP_VERSION'
| 'IN_APP_REVIEW_ERROR'
| 'SERVICE_NOT_ENABLED'
| 'UNKNOWN_REASON';
```

View File

@ -0,0 +1,125 @@
# AR Space Capture Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages AR Space Capture facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the AR Space Capture API of the mobile device, within the LWC.
## AR Space Capture Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode ARSpaceCapture}.
* @returns An instance of {@linkcode ARSpaceCapture}.
*/
export function getARSpaceCapture(): ARSpaceCapture;
/**
* Scan a room using Apple's RoomPlan AR Capabilities.
*/
export interface ARSpaceCapture extends BaseCapability {
/**
* Scan Room using Apple's AR Capabilities.
* @param options The customization options for the {@linkcode ARSpaceCapture} Plugin.
* @returns A resolved promise returns {@linkcode ARSpaceCaptureResult} object.
*/
scanRoom(options?: ARSpaceCaptureOptions): Promise<ARSpaceCaptureResult>;
}
/**
* ARSpaceCaptureResult interface.
*/
export interface ARSpaceCaptureResult {
capturedRooms: CapturedRoom[] | null;
}
/**
* CapturedRoom interface.
*/
export interface CapturedRoom {
/**
* An array of walls that the framework identifies during a scan.
*/
walls: unknown[];
/**
* An array of doors that the framework identifies during a scan.
*/
doors: unknown[];
/**
* An array of windows that the framework identifies during a scan.
*/
windows: unknown[];
/**
* An array of openings that the framework identifies during a scan.
*/
openings: unknown[];
/**
* An array of floors that the framework identifies during a scan.
* Available iOS 17.0+.
*/
floors: unknown[];
/**
* An array of objects that the framework identifies during a scan.
*/
objects: unknown[];
/**
* A unique alphanumeric value that the framework assigns the room.
*/
identifier: string;
/**
* One or more room types that the framework observes in the room.
* Available iOS 17.0+.
*/
sections: unknown[];
/**
* The story, floor number, or level on which the captured room resides within a larger structure.
* Available iOS 17.0+.
*/
story: number;
/**
* A version number for the captured room.
* Available iOS 17.0+.
*/
version: number;
}
/**
* ARSpaceCaptureOptions interface.
*/
export interface ARSpaceCaptureOptions {
permissionRationaleText?: string;
presentWithAnimation: boolean;
}
/**
* ARSpaceCaptureFailure interface.
*/
export interface ARSpaceCaptureFailure {
code: ARSpaceCaptureFailureCode;
message: string;
}
/**
* Possible failure codes.
*/
type ARSpaceCaptureFailureCode =
| 'USER_DISMISSED' // User cancelled the operation.
| 'USER_DENIED_PERMISSION' // The user denied permissions to use the device camera.
| 'AR_NOT_SUPPORTED' // The AR capabilities are not enabled/available on the device.
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'UNKNOWN_REASON'; // An error happened in the native code that is not permission based. Will give more information in the ARSpaceCaptureFailure message
```

View File

@ -0,0 +1,219 @@
# Barcode Scanner Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages barcode scanning facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the barcode scanning API of the mobile device, within the LWC.
## Barcode Scanner Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode BarcodeScanner}.
* @returns An instance of {@linkcode BarcodeScanner}.
*/
export function getBarcodeScanner(): BarcodeScanner;
/**
* Scan barcodes from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-barcodescanner.html|BarcodeScanner API}
*/
export interface BarcodeScanner extends BaseCapability {
/**
* @deprecated Use this function to start a new scanning session. Consider using scan() instead.
* @param options A {@linkcode BarcodeScannerOptions} object to configure the scanning session.
* @returns A resolved promise returns {@linkcode Barcode} object.
*/
beginCapture(options?: BarcodeScannerOptions): Promise<Barcode>;
/**
* @deprecated Use this function to continue a scanning session. Consider using scan() instead.
* @returns A resolved promise returns {@linkcode Barcode} object.
*/
resumeCapture(): Promise<Barcode>;
/**
* @deprecated Use this function to end a scanning session, close the mobile OS scanning interface, and dispose resources. Consider using dismiss() instead.
*/
endCapture(): void;
/**
* Use this function to start scanning barcodes.
* @returns A resolved promise returns an array of {@linkcode Barcode} objects.
*/
scan(options: BarcodeScannerOptions): Promise<Barcode[]>;
/**
* Use this function to end a scanning session, close the mobile OS scanning interface, and dispose of resources.
*/
dismiss(): void;
/**
* Available values of barcode types as defined by {@linkcode BarcodeType}.
*/
barcodeTypes: BarcodeType;
}
/**
* An object representing a scanned barcode.
*/
export interface Barcode {
/**
* The type of barcode that was recognized. Available values are enumerated in BarcodeScanner.barcodeTypes.
*/
type: BarcodeType;
/**
* The decoded value of the barcode.
*/
value: string;
}
/**
* An object enumerating the barcode symbologies supported by {@linkcode BarcodeScanner}.
*/
export interface BarcodeType {
CODE_128: 'code128';
CODE_39: 'code39';
CODE_93: 'code93';
DATA_MATRIX: 'datamatrix';
EAN_13: 'ean13';
EAN_8: 'ean8';
ITF: 'itf';
UPC_A: 'upca';
UPC_E: 'upce';
PDF_417: 'pdf417';
QR: 'qr';
}
/**
* An object representing an error that occurred when attempting to scan a barcode.
*/
export interface BarcodeScannerFailure {
/**
* A value representing the reason for the scanning failure
*/
code: BarcodeScannerFailureCode;
/**
* A string value explaining the reason for the scanning failure.
* This value is suitable for use in user interface messages.
* The message is provided in English, and isnt localized.
*/
message: string;
}
/**
* Possible failure codes.
*/
export type BarcodeScannerFailureCode =
| 'USER_DISMISSED' // The user clicked the button to dismiss the scanner
| 'USER_DENIED_PERMISSION' // This is only ever returned on android. android: permission was denied by user when prompt, could ask again.
| 'USER_DISABLED_PERMISSION' // Both ios and android will use this as it requires the same action of the user going to settings.
// Android: permission was denied along "don't ask again" when prompt, will need to go app setting to turn on.
// iOS: permission was disabled by the user and will need to be turned on in settings
| 'INVALID_BARCODE_TYPE_REQUESTED' // One or more invalid barcode types were passed to the scanner for scanning
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'UNKNOWN_REASON'; // A hardware or unknown failure happened when trying to use the camera or other reason, like FirebaseVision failure. This is not caused by a lack of permission.
/**
* ScannerSize values.
*/
export type ScannerSize = 'SMALL' | 'MEDIUM' | 'LARGE' | 'XLARGE' | 'FULLSCREEN';
/**
* CameraFacing values.
*/
export type CameraFacing = 'FRONT' | 'BACK';
/**
* An object representing configuration details for a barcode scanning session.
*/
export interface BarcodeScannerOptions {
/**
* Optional. Specifies the types of barcodes to scan for. Available values are enumerated in BarcodeScanner.barcodeTypes. Defaults to all supported barcode types.
*/
barcodeTypes?: string[];
/**
* Optional. Provides instructions to display in the scanning interface. Defaults to no text.
*/
instructionText?: string;
/**
* Optional. Provides a message to display in the scanning interface when a barcode is successfully scanned. Defaults to no text.
*/
successText?: string;
/**
* Optional. Indicates whether or not a check mark is displayed upon a successful scan. Defaults to true.
*/
showSuccessCheckMark?: boolean;
/**
* Optional. Determines whether the device vibrates when a scan is successful. Defaults to true.
*/
vibrateOnSuccess?: boolean;
/**
* Optional. Modifies the size of the scanner camera view. The available options represent a percentage of the user's device screen size.
*/
scannerSize?: ScannerSize;
/**
* Optional. Specifies whether the front- or rear-facing camera is used. Defaults to "BACK". Available options include "FRONT" and "BACK". If the user's device doesn't support the specified camera facing, an error is returned.
*/
cameraFacing?: CameraFacing;
/**
* Optional. Defines a custom user interface for the scanner instead of using the standard UI. Defaults to null. If nothing is passed in for this parameter, the standard UI is used. If a custom UI is used, it completely replaces the standard UI,
* including the standard Cancel button used for dismissing the scanner. When defining a custom UI, it's the responsibility of the caller to handle dismissing the scanner.
*/
backgroundViewHTML?: string;
/**
* Optional. Determines whether the scanner animates in and out when presented and dismissed. Defaults to true.
*/
presentWithAnimation?: boolean;
/**
* Optional. Determines whether the user has to manually confirm that a detected barcode should be scanned. Defaults to false.
*/
manualConfirmation?: boolean;
/**
* Optional. Determines whether the scanner displays the barcode data while scanning. Defaults to true. Previewing barcode is only supported when backgroundViewHTML is omitted.
*/
previewBarcodeData?: boolean;
/**
* Optional. Determines whether the scanner collects the results of scanned barcodes before sending them back to the caller. Defaults to false. When set to true, the scanner
* collects the results of scanned barcodes and displays them on the screen. When the user taps done, the scanned barcode data is sent back to the caller.
*/
enableBulkScan?: boolean;
/**
* Optional. Determines whether the scanner detects multiple barcodes simultaneously. Defaults to false. Setting this parameter to true will automatically set the enableBulkScan parameter to true as well.
*/
enableMultiScan?: boolean;
/**
* Optional. Enable flashlight. Defaults to false.
*/
enableFlashlight?: boolean;
/**
* Optional. Defaults to 1.0 or 1x magnification. Sets the initial magnification level of the camera when launching the scanner.
* A value of 1.0 represents no magnification (1x). Higher values (e.g., 2.0 or 4.0) can be useful for scanning small barcodes
* without requiring manual zoom gestures. Users can still adjust the zoom level using pinch-to-zoom gestures.
* Note: If the provided zoom factor exceeds the device camera's supported range, the value will be clamped to the nearest
* supported min/max zoom factor.
*/
initialZoomFactor?: number;
}
```

View File

@ -0,0 +1,22 @@
# BaseCapability
Common interface implemented by every mobile native capability. Use `isAvailable()` to gate code paths so the LWC degrades gracefully on unsupported surfaces (desktop, mobile web).
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
/**
* Provide all services with common functionalities.
*/
export interface BaseCapability {
/**
* Use this function to determine whether the respective service functionality is available.
* @returns Returns true when used on a supported device and false otherwise.
*/
isAvailable(): boolean;
}
```

View File

@ -0,0 +1,90 @@
# Biometrics Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages biometrics scanning facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the face recognition and the finger printing scanner of the mobile device to authorize the user, within the LWC.
## Biometrics Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode BiometricsService}.
* @returns An instance of {@linkcode BiometricsService}.
*/
export function getBiometricsService(): BiometricsService;
/**
* Access a devices biometrics capabilities from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-biometricsservice.html|BiometricsService API}
*/
export interface BiometricsService extends BaseCapability {
/**
* Verify if the biometrics hardware or pin code is available to use to verify the users device ownership.
* @param options A {@linkcode BiometricsServiceOptions} object to configure the {@linkcode BiometricsService} request.
* @returns A Promise object that resolves as a Boolean value. True if the biometrics hardware or pin code is available for use and false otherwise.
*/
isBiometricsReady(options?: BiometricsServiceOptions): Promise<boolean>;
/**
* Verify if the user is the device owner using the devices biometrics hardware or pin code.
* @param options A {@linkcode BiometricsServiceOptions} object to configure the {@linkcode BiometricsService} request.
* @returns A Promise object that resolves as a Boolean value. True if the user is the registered device owner and false otherwise.
*/
checkUserIsDeviceOwner(options?: BiometricsServiceOptions): Promise<boolean>;
}
/**
* An object for specifying which instances of a recurring event are affected by an update to or deletion of one instance of the event.
*/
export interface BiometricsServiceOptions {
/**
* Reason to use biometrics scanner.
*/
permissionRequestBody?: string;
/**
* Title used in the dialog when the reason text is displayed. Allowed on iOS, but effective only on Android.
*/
permissionRequestTitle?: string;
/**
* Policies specified in the array allows customization of the biometrics scan behavior.
*/
additionalSupportedPolicies?: BiometricsServicePolicy[];
}
/**
* An object representing policy to use pin code as an alternative to biometrics.
*/
export type BiometricsServicePolicy = /** User cancelled the operation. */ 'PIN_CODE';
/**
* An object representing an error that occurred when accessing {@linkcode BiometricsService} features.
*/
interface BiometricsServiceFailure {
/**
* A value representing the reason for a biometrics service error. See {@linkcode BiometricsServiceFailureCode} for the list of possible values.
*/
code: BiometricsServiceFailureCode;
/**
* A string value describing the reason for the failure. This value is suitable for use in user interface messages. The message is provided in English and isnt localized.
*/
message: string;
}
/**
* Correlates with the code property on the {@linkcode BiometricsServiceFailure} object.
*/
type BiometricsServiceFailureCode =
| 'HARDWARE_NOT_AVAILABLE' // There is no fingerprint scanner or face recognition hardware found.
| 'NOT_CONFIGURED' // Biometrics hardware was found but has not been set up yet.
| 'SERVICE_NOT_ENABLED' // BiometricsService is not enabled and cannot be used.
| 'UNKNOWN_REASON'; // An error occurred in the native code that isnt related to permissions or hardware issues. More information is provided in the BiometricsServiceFailure message.
```

View File

@ -0,0 +1,213 @@
# Calendar Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages calendar facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the calendar API of the mobile device, within the LWC.
## Calendar Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode CalendarService}.
* @returns An instance of {@linkcode CalendarService}.
*/
export function getCalendarService(): CalendarService;
/**
* Manage calendar events from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-calendarservice.html|CalendarService API}
*/
export interface CalendarService extends BaseCapability {
/**
* Returns all available calendars from the devices native Calendar application.
* If needed, a permission pop-up for the user to grant calendar access is presented first.
* @param options A {@linkcode CalendarServiceOptions} object to configure the {@linkcode CalendarService} request.
* @returns A Promise object that resolves as an array of {@linkcode Calendar} objects.
*/
getCalendars(options?: CalendarServiceOptions): Promise<Calendar[]>;
/**
* Returns all events of all available calendar events in a specified date range from the specified calendars.
* @param startDateSecondsUTC The start of the date range.
* @param endDateSecondsUTC The end of the date range.
* @param calendars The titles of calendars to get events from. If not provided, or null is passed in, events are fetched from all available calendars.
* @param options A {@linkcode CalendarServiceOptions} object to configure the {@linkcode CalendarService} request.
* @returns A Promise object that resolves as an array of {@linkcode CalendarEvent} objects.
*/
getEvents(
startDateSecondsUTC: number,
endDateSecondsUTC: number,
calendars?: string[],
options?: CalendarServiceOptions,
): Promise<CalendarEvent[]>;
/**
* Adds an event to the devices calendar.
* @param event A {@linkcode CalendarEvent} object to be added to the devices calendar.
* @param options A {@linkcode CalendarServiceOptions} object to configure the {@linkcode CalendarService} request.
* @returns A Promise object that resolves as a coerced version of the {@linkcode CalendarEvent} parameter.
*/
addEvent(event: CalendarEvent, options?: CalendarServiceOptions): Promise<CalendarEvent>;
/**
* Updates an event in the devices calendar.
* @param updatedEvent A {@linkcode CalendarEvent} object with updated data to replace the existing data in the corresponding event on the devices calendar.
* @param options A {@linkcode CalendarServiceOptions} object to configure the {@linkcode CalendarService} request.
* @returns A Promise object that resolves as a coerced version of the {@linkcode CalendarEvent} parameter.
*/
updateEvent(updatedEvent: CalendarEvent, options?: CalendarServiceOptions): Promise<CalendarEvent>;
/**
* Removes an event from a devices calendar.
* @param event The {@linkcode CalendarEvent} object to be removed from the devices calendar.
* @param options A {@linkcode CalendarServiceOptions} object to configure the {@linkcode CalendarService} request.
* @returns If successful, null is returned.
*/
removeEvent(event: CalendarEvent, options?: CalendarServiceOptions): Promise<null>;
}
/**
* Calendar interface.
*/
export interface Calendar {
id: string;
title: string;
allowsContentModifications: boolean; // indicates whether the calendar is read-only
hexColor: string; // includes # + hex color value, e.g #c603fc
type: string; // a string hinting about calendar type. It is platform specific. on iOS it is set to EKSource.sourceType+EKSource.title and on Android it is set to CalendarContract.Calendars.ACCOUNT_TYPE+CalendarContract.Calendars.ACCOUNT_NAME
isPrimary: boolean; // indicates whether it is the primary/default calendar
}
/**
* Event interface.
*/
export interface CalendarEvent {
id: string;
isAllDay: boolean; // defaults to False
startDateSecondsUTC: number;
endDateSecondsUTC: number;
availability: EventAvailability; // defaults to Busy
status: EventStatus; // read-only - value set by caller will be ignored and overwritten by the plugin
calendarId?: string;
title: string;
location?: string;
notes?: string;
alarms?: Alarm[];
attendees?: Participant[]; // Note: on iOS this field can only be used for fetching attendee info of an existing event, but you cannot create an event with attendee info (which is an EventKit limitation as mentioned here https://apple.co/3toRnDO)
recurrenceRules?: RecurrenceRule[];
}
/**
* EventAvailability values.
*/
export type EventAvailability = 'Busy' | 'Free' | 'Tentative';
/**
* EventStatus values.
*/
export type EventStatus = 'Canceled' | 'Confirmed' | 'Tentative';
/**
* Alarm interface.
*/
export interface Alarm {
relativeOffsetSeconds: number;
}
/**
* Participant interface.
*/
export interface Participant {
name: string;
email: string | null;
role: ParticipantRole;
status: ParticipantStatus;
}
/**
* ParticipantRole values.
*/
export type ParticipantRole = 'Required' | 'Optional' | 'Unknown';
/**
* ParticipantStatus values.
*/
export type ParticipantStatus = 'Accepted' | 'Declined' | 'Pending' | 'Tentative' | 'Unknown';
/**
* The recurrence rule as defined by https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.10.
*/
export interface RecurrenceRule {
frequency: RecurrenceFrequency;
interval: number;
daysOfTheWeek?: RecurrenceDayOfWeek[];
daysOfTheMonth?: number[];
monthsOfTheYear?: number[];
weeksOfTheYear?: number[];
daysOfTheYear?: number[];
setPositions?: number[];
end?: RecurrenceEnd;
}
/**
* RecurrenceFrequency values.
*/
export type RecurrenceFrequency = 'Daily' | 'Weekly' | 'Monthly' | 'Yearly';
/**
* RecurrenceDayOfWeek interface.
*/
export interface RecurrenceDayOfWeek {
dayOfTheWeek: Weekday;
weekNumber: number;
}
/**
* Weekday values.
*/
export type Weekday = 'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday';
/**
* RecurrenceEnd interface.
*/
export interface RecurrenceEnd {
endDateSecondsUTC?: number;
occurrenceCount?: number;
}
/**
* CalendarServiceOptions interface.
*/
export interface CalendarServiceOptions {
permissionRationaleText?: string;
span?: Span;
}
/**
* Span values.
*/
export type Span = 'ThisEvent' | 'ThisAndFollowingEvents';
/**
* CalendarServiceFailure interface.
*/
export interface CalendarServiceFailure {
code: CalendarServiceFailureCode;
message: string;
}
/**
* Possible failure codes.
*/
export type CalendarServiceFailureCode =
| 'USER_DENIED_PERMISSION' // Permission was denied by user when prompt.
| 'NOT_FOUND' // A specified item (calendar or event) was not found.
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'UNKNOWN_REASON'; // An error happened in the native code that is not permission based. Will give more information in the CalendarServiceFailure message.
```

View File

@ -0,0 +1,232 @@
# Contacts Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages contacts facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the contacts API of the mobile device, within the LWC.
## Contacts Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode ContactsService}.
* @returns An instance of {@linkcode ContactsService}.
*/
export function getContactsService(): ContactsService;
/**
* Access contacts from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-contactsservice.html|ContactsService API}
*/
export interface ContactsService extends BaseCapability {
/**
* Allows the user to pick one or more contacts from the devices Contacts app. If needed, presents a
* permissions pop-up to the user to request access to contacts first, and then presents the user with the contacts selector.
* @param options A {@linkcode ContactsServiceOptions} object to configure the {@linkcode ContactsService} request.
* @returns A Promise object that resolves as an array of {@linkcode Contacts} objects. If an error is encountered, the array is empty.
*/
getContacts(options?: ContactsServiceOptions): Promise<Contact[]>;
/**
* Save a contact record into the mobile device address book.
* @param contact A {@linkcode Contacts} object.
* @param options A {@linkcode ContactsServiceOptions} object to configure the {@linkcode ContactsService} request. Currently
* used to override the device's permission UX sequence text.
* @returns A resolved promise returns a {@linkcode Contacts} object.
*/
putContact(contact: Contact, options?: ContactsServiceOptions): Promise<Contact>;
}
/**
* An object representing a contact.
*/
export interface Contact {
/**
* A stringified number unique to each contact. Generated by the native device at the time of contact creation.
*/
id: string;
/**
* An object representing a contact's name.
*/
name: ContactName;
/**
* An array of objects containing phone numbers for the contact.
*/
phoneNumbers: ContactLabeledValue[];
/**
* An array of objects containing email addresses for the contact.
*/
emails: ContactLabeledValue[];
/**
* An array of objects representing contact's addresses.
*/
addresses: ContactAddress[];
/**
* An array of objects containing instant messaging (IM) usernames for the contact.
*/
ims: ContactLabeledValue[];
/**
* An object representing a contact's organization.
*/
organizations: ContactOrganization[];
/**
* A text field for any extra information about the contact.
*/
note: string;
/**
* An array of objects containing URLs for the contact.
*/
urls: ContactLabeledValue[];
}
/**
* An object representing a contacts address.
*/
export interface ContactAddress {
/**
* A string representing the type of address for a contacts address.
*/
type: string;
/**
* A string representing the street address for a contacts address.
*/
streetAddress: string;
/**
* A string representing the locality (also known as the “city”) for a contacts address.
*/
locality: string;
/**
* A string representing the region (also known as the “state” or “province”) for a contacts address.
*/
region: string;
/**
* A string representing the postal code for a contacts address.
*/
postalCode: string;
/**
* A string representing the country for a contacts address.
*/
country: string;
}
/**
* An object representing a contacts organization.
*/
export interface ContactOrganization {
/**
* A string representing the name of a contacts organization.
*/
name: string;
/**
* A string representing the department of a contacts organization.
*/
department: string;
/**
* A string representing the title the contact holds in the organization.
*/
title: string;
}
/**
* An object representing a contacts name.
*/
export interface ContactName {
/**
* A string representing the contacts family name (also known as “surname” or “last name”).
*/
familyName: string;
/**
* A string representing the contacts given name (also known as “first name”).
*/
givenName: string;
/**
* A string representing the contacts middle name.
*/
middleName: string;
/**
* A string representing the contacts name prefix.
*/
namePrefix: string;
/**
* A string representing the contacts name suffix.
*/
nameSuffix: string;
}
/**
* An object containing a label and a value for a miscellaneous piece of contact information.
*/
export interface ContactLabeledValue {
/**
* The display name that categorizes the data in value. In the following examples, home, homepage, and work are label properties.
*/
label: string;
/**
* The value of the data specified in label.
*/
value: string;
}
/**
* An object representing an error that occurred when accessing {@linkcode ContactsService} features.
*/
export interface ContactsServiceFailure {
/**
* A value representing the reason for a contacts error.
*/
code: ContactsServiceFailureCode;
/**
* A string value describing the reason for the failure. This value is suitable for use in user interface messages. The message is provided in English, and isnt localized.
*/
message: string;
}
/**
* An object representing configuration details for a {@linkcode ContactsService} session.
*/
export interface ContactsServiceOptions {
/**
* Optional parameter, used by Android only. This only appears after an initial denial by the user. To use the default permission message, pass in an empty object.
* The default permission message is “To import Contacts, permission is needed to access Contacts. Tap Allow in the following permissions dialog.”
*/
permissionRationaleText?: string;
}
/**
* Possible failure codes.
*/
export type ContactsServiceFailureCode =
| 'USER_DISMISSED' // The user clicked the cancel button.
| 'USER_DENIED_PERMISSION' // Permission was denied to access contacts (older versions of Android only).
| 'USER_DISABLED_PERMISSION' // Android Only - Permission was denied. User will need to go to app setting to turn on.
| 'USER_RESTRICTED_PERMISSION' // The application is restricted (perhaps by parental controls) from accessing Contacts (iOS only).
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'SAVE_OPERATION_FAILED' // The service couldn't save the contact record into the address book.
| 'UNKNOWN_REASON'; // Generic error that is not captured by any of the above categories
```

View File

@ -0,0 +1,342 @@
# Document Scanner Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages document scanning facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the document scanner API of the mobile device, within the LWC.
## Document Scanner Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode DocumentScanner}.
* @returns An instance of {@linkcode DocumentScanner}.
*/
export function getDocumentScanner(): DocumentScanner;
/**
* Scan documents from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-documentscanner.html|DocumentScanner API}
*/
export interface DocumentScanner extends BaseCapability {
/**
* Use this function to start scanning a document.
* @param options A {@linkcode DocumentScannerOptions} object to configure the scanning session.
* @returns A Promise object that resolves to an array containing one or more {@linkcode Document} objects.
*/
scan(options?: DocumentScannerOptions): Promise<Document[]>;
}
/**
* An object representing a scanned document. Returned as the result of a successful scan operation.
*/
export interface Document {
/**
* A string containing the base64 image data of the scanned document. Only provided when returnImageBytes is set to true in your {@linkcode DocumentScannerOptions} configuration object.
*/
imageBytes?: string;
/**
* A string value providing the recognized text from the scanned document.
*/
text: string;
/**
* An array of {@linkcode TextBlock} objects that represent a structured text result that is visually aligned with the corresponding image. See {@linkcode TextBlock} for details of this structured text data.
*/
blocks: TextBlock[];
/**
* An array of {@linkcode Entity} objects.
*/
entities: Entity[];
}
/**
* An object representing a contiguous section of the scanned text. Text that is visually close together is grouped into a block of text.
* A document is made up of one to many blocks, and each block can be further broken down into smaller text elements: {@linkcode TextLine} (a single line of text in
* a visually aligned run of text) and {@linkcode TextElement} (an individual word or glyph).
*/
export interface TextBlock {
/**
* A string containing the text content of the block.
*/
text: string;
/**
* An object containing the coordinates — position and size — that represent the bounding rectangle in the scanned image that contains the {@linkcode TextBlock}.
*/
frame: Frame;
/**
* An array of Point objects that define a closed shape within the scanned image that contains the {@linkcode TextBlock}.
*/
cornerPoints: Point[];
/**
* The BCP-47 language code values for the languages detected in the recognized text.
*/
recognizedLangCodes: string[];
/**
* An array of {@linkcode TextLine} objects, each of which represents a visually aligned line of text within the {@linkcode TextBlock}.
*/
lines: TextLine[];
}
/**
* An object representing a single line of scanned text.
*/
export interface TextLine {
/**
* A string containing the text content of the line.
*/
text: string;
/**
* An object containing the coordinates — position and size — that represent the bounding rectangle in the scanned image that contains the {@linkcode TextLine}.
*/
frame: Frame;
/**
* An array of {@linkcode Point} objects that define a closed shape within the scanned image that contains the {@linkcode TextLine}.
*/
cornerPoints: Point[];
/**
* The BCP-47 language code values for the languages detected in the recognized text.
*/
recognizedLangCodes: string[];
/**
* An array of {@linkcode TextElement} objects, each of which represents a word or glyph within the {@linkcode TextLine}.
*/
elements: TextElement[];
}
/**
* An object representing a single word, individual character, or glyph.
*/
export interface TextElement {
/**
* A string containing the text content of the word or character.
*/
text: string;
/**
* An object containing the coordinates — position and size — that represent the bounding rectangle in the scanned image that contains the {@linkcode TextElement}.
*/
frame: Frame;
/**
* An array of {@linkcode Point} objects that define a closed shape within the scanned image that contains the {@linkcode TextElement}.
*/
cornerPoints: Point[];
/**
* The BCP-47 language code values for the languages detected in the recognized text.
*/
recognizedLangCodes: string[];
}
/**
* An object representing a bounding rectangle. When used in {@linkcode DocumentScanner}, the Frame is the smallest that fully encloses a region of scanned text for a {@linkcode TextBlock}, {@linkcode TextLine}, or {@linkcode TextElement}.
*/
export interface Frame {
/**
* The X coordinate of the top-left of the rectangle, in pixels, within the coordinate system of the scanned image.
*/
x: number;
/**
* The Y coordinate of the top-left of the rectangle, in pixels, within the coordinate system of the scanned image.
*/
y: number;
/**
* The width of the rectangle, in pixels.
*/
width: number;
/**
* The height of the rectangle, in pixels.
*/
height: number;
}
/**
* An object representing a point in a coordinate system.
*/
export interface Point {
/**
* The X coordinate of the point.
*/
x: number;
/**
* The Y coordinate of the point.
*/
y: number;
}
/**
* Entity interface.
*/
export interface Entity {
type: EntityType;
value: string;
dateTimeEntity?: DateTimeEntity;
flightNumberEntity?: FlightNumberEntity;
ibanEntity?: IBANEntity;
moneyEntity?: MoneyEntity;
paymentCardEntity?: PaymentCardEntity;
trackingNumberEntity?: TrackingNumberEntity;
}
/**
* EntityType values.
*/
export type EntityType =
| 'ADDRESS'
| 'DATETIME'
| 'EMAIL'
| 'FLIGHTNUMBER'
| 'IBAN'
| 'ISBN'
| 'MONEY'
| 'PAYMENTCARD'
| 'PHONE'
| 'TRACKINGNUMBER'
| 'URL';
/**
* DateTimeEntity interface.
*/
export interface DateTimeEntity {
secondsUTC: number;
granularity: string;
}
/**
* FlightNumberEntity interface.
*/
export interface FlightNumberEntity {
airlineCode: string;
flightNumber: string;
}
/**
* IBANEntity interface.
*/
export interface IBANEntity {
countryCode: string;
iban: string;
}
/**
* MoneyEntity interface.
*/
export interface MoneyEntity {
unnormalizedCurrency: string;
integerPart: number;
fractionalPart: number;
}
/**
* PaymentCardEntity interface.
*/
export interface PaymentCardEntity {
network: string;
cardNumber: string;
}
/**
* TrackingNumberEntity interface.
*/
export interface TrackingNumberEntity {
carrier: string;
trackingNumber: string;
}
/**
* DocumentScannerSource values.
*/
export type DocumentScannerSource = 'INPUT_IMAGE' | 'PHOTO_LIBRARY' | 'DEVICE_CAMERA';
/**
* Script values.
*/
export type Script = 'CHINESE' | 'DEVANAGARI' | 'JAPANESE' | 'KOREAN' | 'LATIN';
/**
* An object containing configuration details for a document scanning session.
*/
export interface DocumentScannerOptions {
/**
* Optional, and only for Android implementations. The text shown in the UI when the device prompts the user to grant permission for your app to use the camera.
*/
permissionRationaleText?: string;
/**
* Optional. Specifies the source of the document to be scanned. Defaults to "DEVICE_CAMERA".
*/
imageSource?: DocumentScannerSource;
/**
* Optional. Specifies the language writing system of the text to be scanned. Defaults to "LATIN".
*/
scriptHint?: Script;
/**
* Defaults to FALSE when omitted.
*/
extractEntities?: boolean;
/**
* Defaults to EN when omitted.
*/
entityExtractionLanguageCode?: string;
/**
* Optional. Specifies whether the image data should (true) or should not (false) be returned by the plugin. Defaults to false. This setting is overridden and set to false when imageSource is set to “INPUT_IMAGE”.
*/
returnImageBytes?: boolean;
/**
* Optional. A stringified array of base64 image data to be scanned. Used when imageSource is set to "INPUT_IMAGE".
*/
inputImageBytes?: string[];
}
/**
* An object representing an error that occurred when accessing {@linkcode DocumentScanner} features.
*/
export interface DocumentScannerFailure {
/**
* A value representing the reason for a document scanner error. See {@linkcode DocumentScannerFailureCode} for the list of possible values.
*/
code: DocumentScannerFailureCode;
/**
* A string value describing the reason for the failure. This value is suitable for use in user interface messages. The message is provided in English and isnt localized.
*/
message: string;
}
/**
* Correlates with the code property on the {@linkcode DocumentScannerFailure} object.
*/
export type DocumentScannerFailureCode =
| 'USER_DISMISSED' // User dismissed the scanner.
| 'USER_DENIED_CAMERA_PERMISSION' // A user denied permission to access the device camera when prompted.
| 'USER_DENIED_PHOTO_LIBRARY_PERMISSION' // A user denied permission to access the device photo library when prompted.
| 'NO_SUPPORTED_CAMERA' // The device doesnt have a supported camera.
| 'INVALID_INPUT_IMAGE' // The input image data cant be read as an image.
| 'SERVICE_NOT_ENABLED' // DocumentScanner is not enabled and cannot be used.
| 'UNKNOWN_REASON'; // An error occurred in the native code that isnt related to permissions or hardware issues. More information is provided in the DocumentScannerFailure message.
```

View File

@ -0,0 +1,123 @@
# Geofencing Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages geofencing facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the geofencing API of the mobile device, within the LWC.
## Geofencing Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode GeofencingService}.
* @returns An instance of {@linkcode GeofencingService}.
*/
export function getGeofencingService(): GeofencingService;
/**
* Create and monitor geofences in a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-geofencingservice.html|GeofencingService API}
*/
export interface GeofencingService extends BaseCapability {
/**
* Starts geofence monitoring.
* @param geofence A {@linkcode Geofencing} object to monitor.
* @returns A Promise object that resolves as a string value. The value is a unique ID thats assigned to the monitored geofence.
*/
startMonitoringGeofence(geofence: Geofence): Promise<string>;
/**
* Stop monitoring a specific geofence.
* @param id Unique ID assigned to a specific geofence.
* @returns A Promise object that resolves as null.
*/
stopMonitoringGeofence(id: string): Promise<null>;
/**
* Stop monitoring all geofences.
* @returns A Promise object that resolves as null.
*/
stopMonitoringAllGeofences(): Promise<null>;
/**
* Get all IDs of monitored geofences.
* @returns A Promise object that resolves as an array of string values. The values are unique IDs assigned to monitored geofences.
*/
getMonitoredGeofences(): Promise<string[]>;
}
/**
* An object representing an error that occurred when accessing {@linkcode GeofencingService} features.
*/
export interface GeofencingServiceFailure {
/**
* A value representing the reason for a location error.
*/
code: GeofencingServiceFailureCode;
/**
* A string value explaining the reason for the failure. This value is
* suitable for use in user interface messages. The message is provided in English and isnt localized.
*/
message: string;
}
/**
* Possible failure codes.
*/
export type GeofencingServiceFailureCode =
| 'LOCATION_SERVICE_DISABLED' // Android Only: The location service is disabled on the device, not just for this app.
| 'USER_DENIED_PERMISSION' // Permission was denied by user when prompt, could ask again
| 'USER_DISABLED_PERMISSION' // Android: permission was denied along "don't ask again" when prompt, will need to go app setting to turn on. iOS: permission was disabled by the user and will need to be turned on in settings
| 'UNAVAILABLE_ON_HARDWARE' // Geofence monitoring not available on the hardware.
| 'MAX_GEOFENCE_MONITORED_REACHED' // The maximum number of geofences that can be monitored by the OS has been reached.
| 'INVALID_LATITUDE' // The range of latitude for a geofence is -90...90
| 'INVALID_LONGITUDE' // The range of longitude for a geofence is -180...180
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'UNKNOWN_REASON'; // An error happened in the Native Code that is not permission based. Will give more information in the GeofencingServiceFailure message.
/**
* An object representing the coordinates and radius of the geofence region.
*/
export interface Geofence {
/**
* The latitude, in degrees. Ranges from -90 to 90.
*/
latitude: number;
/**
* The longitude, in degrees. Ranges from -180 to 180.
*/
longitude: number;
/**
* The radius of the geofence in meters.
*/
radius: number;
/**
* Monitors the entry into the geofence radius. Defaults to true.
*/
notifyOnEntry: boolean;
/**
* Monitors the exit out of the geofence radius. Defaults to true.
*/
notifyOnExit: boolean;
/**
* Notification triggered by a geofence event.
*/
message: string;
/**
* Removes geofence after its triggered. Defaults to true.
*/
triggerOnce: boolean;
}
```

View File

@ -0,0 +1,158 @@
# Location Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages location facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the location API of the mobile device, within the LWC.
## Location Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode LocationService}.
* @returns An instance of {@linkcode LocationService}.
*/
export function getLocationService(): LocationService;
/**
* Access and track location in a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-locationservice.html|LocationService API}
*/
export interface LocationService extends BaseCapability {
/**
* Gets the devices current geolocation.
* @param options A {@linkcode LocationServiceOptions} object to configure the location request.
* @returns A Promise object that resolves as a {@linkcode LocationResult} object with the device location details.
*/
getCurrentPosition(options?: LocationServiceOptions): Promise<LocationResult>;
/**
* Subscribes to asynchronous location updates for the mobile device.
* @param options A {@linkcode LocationServiceOptions} object to configure the location request.
* @param callback A function to handle location update responses.
* @returns An integer identifier for the location subscription, which you can use to end the subscription when you want to stop receiving location updates.
*/
startWatchingPosition(
options: LocationServiceOptions | null,
callback: (result?: LocationResult, failure?: LocationServiceFailure) => void,
): number;
/**
* Unsubscribes from location updates for the mobile device.
* @param watchId An integer identifier for an active location subscription, returned by a call to startWatchingPosition().
*/
stopWatchingPosition(watchId: number): void;
}
/**
* LocationResult interface.
*/
export interface LocationResult {
/**
* The physical location.
*/
coords: Coordinates;
/**
* The time of the location reading, measured in milliseconds since January 1, 1970.
*/
timestamp: number;
}
/**
* An object representing a specific point located on the planet Earth. Includes velocity details, if available.
* Includes accuracy information, to the best of the devices ability to evaluate. Similar to a GeolocationCoordinates in the Geolocation Web API.
*/
export interface Coordinates {
/**
* The latitude, in degrees. Ranges from -90 to 90.
*/
latitude: number;
/**
* The longitude, in degrees. Ranges from -180 to 180.
*/
longitude: number;
/**
* Optional. Accuracy of the location measurement, in meters, as a radius around the measurement.
*/
accuracy?: number;
/**
* Optional. Meters above sea level.
*/
altitude?: number;
/**
* Optional. Accuracy of the altitude measurement, in meters.
*/
altitudeAccuracy?: number;
/**
* Optional. Velocity of motion, if any, in meters per second.
*/
speed?: number;
/**
* Optional. Accuracy of the speed measurement, in meters.
*/
speedAccuracy?: number;
/**
* Optional. Direction of motion, in degrees from true north. Ranges from 0 to 360.
*/
heading?: number;
/**
* Optional. Accuracy of the heading measurement, in degrees.
*/
headingAccuracy?: number; // accuracy for the heading in degree
}
/**
* An object representing an error that occurred when accessing LocationService features.
*/
export interface LocationServiceFailure {
/**
* A value representing the reason for a location error.
*/
code: LocationServiceFailureCode;
/**
* A string value explaining the reason for the failure. This value is suitable for use in user interface messages. The message is provided in English, and isnt localized.
*/
message: string;
}
/**
* Possible failure codes.
*/
export type LocationServiceFailureCode =
| 'LOCATION_SERVICE_DISABLED' // Android only - The code when the location service is disabled on the device, not just for this app.
| 'USER_DENIED_PERMISSION' // Permission was denied by user when prompt, could ask again
| 'USER_DISABLED_PERMISSION' // Android: permission was denied along "don't ask again" when prompt, will need to go app setting to turn on. iOS: permission was disabled by the user and will need to be turned on in settings
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'UNKNOWN_REASON'; // An error happened in the Native Code that is not permission based. Will give more information in the LocationServiceFailure message.
/**
* An object representing configuration details for a location service session.
*/
export interface LocationServiceOptions {
/**
* Whether to use high accuracy mode when determining location. Set to true to prioritize location accuracy.
* Set to false to prioritize battery life and response time.
*/
enableHighAccuracy: boolean;
/**
* Optional, and only for Android implementations. The text shown in the UI when the device prompts the user to grant permission for your app to use the Android's location service.
*/
permissionRationaleText?: string;
}
```

View File

@ -0,0 +1,30 @@
# lightning/mobileCapabilities
Module declaration that re-exports every native capability service. Import the factory functions from `lightning/mobileCapabilities` (or the per-service path) when authoring an LWC.
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
/**
* Mobile capabilities are JavaScript APIs that make mobile hardware and platform (operating system) features available in JavaScript. They require access to device hardware, platform APIs, or both.
* Mobile capability APIs are available only when a Lightning web component runs in a supported mobile app on a mobile device.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-mobilecapabilities.html|lightning/mobileCapabilities Module}
*/
declare module 'lightning/mobileCapabilities' {
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/AppReviewService/appReviewService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/ARSpaceCapture/arSpaceCapture.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/BarcodeScanner/barcodeScanner.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/BiometricsService/biometricsService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/CalendarService/calendarService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/ContactsService/contactsService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/DocumentScanner/documentScanner.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/GeofencingService/geofencingService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/LocationService/locationService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/NfcService/nfcService.js';
export * from '@salesforce/lightning-types/dist/lightning/mobileCapabilities/PaymentsService/paymentsService.js';
}
```

View File

@ -0,0 +1,181 @@
# NFC Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages NFC facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the NFC API of the mobile device, within the LWC.
## NFC Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode NfcService}.
* @returns An instance of {@linkcode NfcService}.
*/
export function getNfcService(): NfcService;
/**
* Interact with NFC tags from a Lightning web component.
* @see {@link https://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-nfcservice.html|NFCService API}
*/
export interface NfcService extends BaseCapability {
/**
* Reads an NFC tag and returns the data read from it.
* @param options An {@linkcode NFCServiceOptions} object to configure the {@linkcode NfcService} request.
* @returns A Promise object that resolves to an array containing a single {@linkcode NFCMessage} object.
*/
read(options?: NFCServiceOptions): Promise<NFCMessage[]>;
/**
* Erase the contents of an NFC tag.
* @param options An {@linkcode NFCServiceOptions} object to configure the {@linkcode NfcService} request.
* @returns If successful, the OS returns a Promise object that resolves to null.
*/
erase(options?: NFCServiceOptions): Promise<null>;
/**
* Write text to an NFC tag.
* @param payloads An array of {@linkcode NFCRecord} objects containing the raw bytes to be written.
* @param options An {@linkcode NFCServiceOptions} object to configure the {@linkcode NfcService} request.
* @returns If successful, the OS returns a Promise object that resolves to null.
*/
write(payloads: NFCRecord[], options?: NFCServiceOptions): Promise<null>;
/**
* Given a text payload, this function creates a properly formatted {@linkcode NFCRecord} to be written to an NFC tag.
* @param payload A {@link TextPayload} object, which contains the text to be converted to an NFC record.
* @returns A Promise object that resolves to an {@linkcode NFCRecord} object.
*/
createTextRecord(payload: TextPayload): Promise<NFCRecord>;
/**
* Given a URI string payload, this function creates a properly formatted {@linkcode NFCRecord} to be written to an NFC tag.
* @param payload The URI to be converted to an NFC record.
* @returns A Promise object that resolves to an {@linkcode NFCRecord} object.
*/
createUriRecord(payload: string): Promise<NFCRecord>;
}
/**
* An object returned by an NFC read() operation.
*/
export interface NFCMessage {
/**
* The size, in number of bytes, of the data received by the read() operation.
*/
totalByteLength: number;
/**
* An array containing a single {@linkcode NFCMessageRecord} object, which in turn contains the payload from the NFC tag.
*/
records: NFCMessageRecord[];
}
/**
* An object within an {@linkcode NFCMessage} object, containing the payload read from an NFC tag.
*/
export interface NFCMessageRecord {
/**
* Contains the parsed values of the raw data read from the NFC tag. The parsing operation
* only occurs if the value of the typeNameFormat property on the {@linkcode NFCRecord} object is "WELLKNOWN".
* Otherwise, this propertys value is null.
*/
parsed: NFCRecord;
/**
* Contains the raw base64 data string read from the NFC tag.
*/
raw: NFCRecord;
}
/**
* An object containing one record of data from an NFC tag scan.
*/
export interface NFCRecord {
/**
* The Type Name Format field of the payload, as defined by the NDEF specification.
*/
typeNameFormat: TypeNameFormat;
/**
* The type of the payload, as defined by the NDEF specification.
*/
type: string;
/**
* The identifier of the payload, as defined by the NDEF specification, or an empty string if no identifier data was present in the tag.
*/
identifier: string;
/**
* The content of the record, encoded in base64 format.
*/
payload: string;
}
/**
* An object containing raw text input, to be converted into an {@linkcode NFCRecord}.
*/
export interface TextPayload {
/**
* The raw text payload to be converted.
*/
text: string;
/**
* The ISO 639-1 language ID of the text.
*/
langId: string;
}
/**
* The following constants are available as properties on an instance of {@linkcode NfcService}. The constants enumerate the accepted values for the associated properties.
*/
export type TypeNameFormat = 'ABSOLUTE_URI' | 'EMPTY' | 'EXTERNAL' | 'MEDIA' | 'WELLKNOWN' | 'UNCHANGED' | 'UNKNOWN';
/**
* An object containing configuration details for an NFC interaction.
*/
export interface NFCServiceOptions {
/**
* Optional. Provides instructions to display in the user interface. Defaults to no text.
*/
instructionText?: string;
/**
* Optional. Provides a message to display in the user interface when an NFC operation is successfully completed. Defaults to no text.
*/
successText?: string;
}
/**
* An object representing an error that occurred when accessing {@linkcode NfcService} features.
*/
export interface NFCServiceFailure {
/**
* A value representing the reason for an error. See {@linkcode NFCServiceFailureCode} for the list of possible values.
*/
code: NFCServiceFailureCode;
/**
* A string value describing the reason for the failure. This value is suitable for use in user interface messages. The message is provided in English and isnt localized.
*/
message: string;
}
/**
* Correlates with the code property on the {@linkcode NFCServiceFailure} object.
*/
export type NFCServiceFailureCode =
| 'USER_DISMISSED' // The user dismissed the scanner.
| 'NFC_NOT_SUPPORTED' // The device doesnt support NFC capabilities.
| 'NFC_NOT_ENABLED' // The device NFC feature is turned off.
| 'TAG_EMPTY' // The NFC tag contains no data to be read.
| 'SERVICE_NOT_ENABLED' // NFCService is not enabled and cannot be used.
| 'UNKNOWN_REASON'; // An error occurred in the native code that isnt related to permissions or hardware issues. More information is provided in the NFCServiceFailure message.
```

View File

@ -0,0 +1,95 @@
# Payments Service Grounding Context
The following content provides grounding information for generating a Salesforce LWC that leverages payments facilities on mobile devices. Specifically, this context will cover the API types and methods available to leverage the payments API of the mobile device, within the LWC.
## Payments Service API
```typescript
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* For full license text, see the LICENSE.txt file
*/
import { BaseCapability } from '../BaseCapability.js';
/**
* Use this factory function to get an instance of {@linkcode PaymentsService}.
* @returns An instance of {@linkcode PaymentsService}.
*/
export function getPaymentsService(): PaymentsService;
/**
* PaymentsService is a Nimbus plugin that allows JavaScript code in a Lightning web component to call functions that launches Stripe's Tap to Pay capabilities.
*/
export interface PaymentsService extends BaseCapability {
/**
* Process payment.
* @param options The customization options.
* @returns A Promise object that resolves to {@linkcode CollectPaymentResult} object.
*/
collectPayment(options: CollectPaymentOptions): Promise<CollectPaymentResult>;
/**
* Get the supported payment methods on this device
* @param options The customization options.
* @returns A Promise object that resolves to an array containing {@linkcode PaymentMethod} objects.
*/
getSupportedPaymentMethods(options: GetSupportedPaymentMethodsOptions): Promise<PaymentMethod[]>;
}
/**
* PaymentMethod values.
*/
export type PaymentMethod = 'TAP_TO_PAY' | 'CREDIT_CARD_DETAILS' | 'PAY_VIA_LINK';
/**
* GetSupportedPaymentMethodsOptions interface.
*/
export interface GetSupportedPaymentMethodsOptions {
countryIsoCode?: string;
merchantAccountId?: string;
permissionRationaleText?: string;
}
/**
* CollectPaymentOptions interface.
*/
export interface CollectPaymentOptions {
amount: number;
paymentMethod: PaymentMethod;
currencyIsoCode: string;
merchantAccountId: string;
merchantName: string;
payerAccountId?: string;
sourceObjectIds?: string[];
permissionRationaleText?: string;
}
/**
* CollectPaymentResult interface.
*/
export interface CollectPaymentResult {
gatewayRefId?: string;
guid?: string;
paymentGatewayId?: string;
status?: string;
}
/**
* PaymentsServiceFailure interface.
*/
export interface PaymentsServiceFailure {
code: PaymentsServiceFailureCode;
message: string;
}
/**
* Possible failure codes.
*/
export type PaymentsServiceFailureCode =
| 'USER_DISMISSED' // User cancelled the operation.
| 'USER_DENIED_PERMISSION' // Permission to access device location is denied.
| 'SERVICE_NOT_ENABLED' // The service is not enabled and therefore cannot be used.
| 'UNKNOWN_REASON'; // An error happened in the native code that is not permission based. Will give more information in the PaymentsServiceFailure message.
```