Skip to content

[v4] Remove PnPjs dependency while retaining DynamicForm and taxonomy controls - #2171

Merged
AJIXuMuK merged 7 commits into
v4-devfrom
aterentiev-microsoft-pnpjs-dependency-strategy
Oct 10, 2026
Merged

AJIXuMuK merged 7 commits into
v4-devfrom
aterentiev-microsoft-pnpjs-dependency-strategy

Conversation

@AJIXuMuK

Copy link
Copy Markdown
Collaborator
Q A
Bug fix? [x]
New feature? [ ]
New sample? [ ]
Related issues? N/A

What's in this Pull Request?

Removes PnPjs from the controls library and controls-tests app, replacing SDK calls with direct SharePoint requests through SPFx HTTP clients. No controls are removed; DynamicForm and both taxonomy picker modes remain available.

Intended target branch: v4-dev.

Changes

  • Add shared REST handling for operation-aware retries, Retry-After, digest acquisition and caching, response normalization, and partial batch failures.
  • Migrate DynamicForm item operations, user resolution, folders/document sets, and chunked uploads to a focused REST service, retaining ETag handling and upload defaults.
  • Preserve ModernTaxonomyPicker behavior using the existing SharePoint v2.1 term-store endpoints. Keep classic TaxonomyPicker's existing implementation.
  • Replace remaining PnPjs usage in folder browsing, people search, field utilities, and Carousel; export library-owned response types.
  • Prevent stale form submissions and taxonomy requests from crossing web/list/item/term-set boundaries.
  • Update dependencies, the Rush lockfile, app examples, control documentation, and the v4 migration guide. Add regression coverage for retries, uploads, partial persistence, public contracts, and lifecycle changes.

Breaking changes

  • DynamicForm.onSubmitted now receives saved item data and an optional IDynamicFormItemReference instead of a live PnPjs IItem.
  • Rename returnListItemInstanceOnSubmit to returnListItemReferenceOnSubmit. It still defaults to true.
  • Import taxonomy and other exposed REST types from the controls library rather than PnPjs. Consumers can continue using their own PnPjs installation independently.

Bundle impact

Controlled gzip measurements decreased from 141,063 to 102,328 bytes for DynamicForm, 23,829 to 7,805 bytes for PeoplePicker, and 19,153 to 11,567 bytes for ModernTaxonomyPicker. Non-PnPjs dependencies and styles were externalized equally; these are not complete SPFx application download sizes.

Remaining compatibility gate

Live SharePoint verification is still required for taxonomy endpoints and write/upload flows. The retained undocumented taxonomy APIs have no public stability guarantee. No authorized test tenant was available, so this PR does not claim verified live feature parity.

PnP telemetry is separate from PnPjs and remains unchanged.

Guidance

  • You can delete this section when you are submitting the pull request.
  • Please update this PR information accordingly. We'll use this as part of our release notes in monthly communications.
  • Please target your PR to dev branch.

…rols

Replace SDK calls with SPFx REST services, preserve retry and upload behavior, migrate public contracts, and update tests and documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Submission concurrency, stale load isolation, and inconsistent public callback and ID contracts remain unresolved.

4 open findings
What changed in this PR

Removes PnPjs from the v4 controls library while retaining DynamicForm, taxonomy, people, folder, and carousel functionality through SPFx REST clients.

Changes:

  • Adds shared REST, retry, digest, batching, and persistence services.
  • Migrates affected controls and introduces SDK-independent public contracts.
  • Updates dependencies, documentation, examples, and regression tests.
File Description
README.md Documents PnPjs-free v4 development.
tests/​utils/​SPHelper.test.ts Tests migrated field and user requests.
tests/​services/​SPTaxonomyService.test.ts Tests taxonomy REST compatibility.
tests/​services/​SPRestClient.test.ts Tests retries, digests, batching, and URLs.
tests/​services/​restTestHelpers.ts Adds shared REST test mocks.
tests/​services/​PeopleSearchService.test.ts Tests people resolution behavior.
tests/​services/​FolderExplorerService.test.ts Tests folder and file REST requests.
tests/​services/​DynamicFormService.test.ts Tests saves, uploads, and partial commits.
tests/​controls/​modernTaxonomyPicker/​ModernTaxonomyPicker.lifecycle.test.tsx Tests taxonomy target isolation.
tests/​controls/​dynamicForm/​DynamicForm.lifecycle.test.tsx Tests stale submission invalidation.
tests/​__mocks__/​sp-http.js Expands the SPHttpClient mock.
src/​services/​SPTaxonomyService.types.ts Defines library-owned taxonomy contracts.
src/​services/​SPTaxonomyService.ts Replaces PnPjs taxonomy requests.
src/​services/​SPRestClient.ts Adds shared SharePoint REST transport.
src/​services/​PeopleSearchService.ts Migrates user resolution from PnPjs.
src/​services/​IFolderExplorerService.ts Uses the owned file contract.
src/​services/​FolderExplorerService.ts Migrates folder browsing and creation.
src/​services/​DynamicFormService.ts Adds DynamicForm persistence and upload REST operations.
src/​controls/​modernTaxonomyPicker/​termItem/​TermItemSuggestion.tsx Uses owned taxonomy types.
src/​controls/​modernTaxonomyPicker/​taxonomyTree/​TaxonomyTree.tsx Uses owned taxonomy types.
src/​controls/​modernTaxonomyPicker/​taxonomyPanelContents/​TaxonomyPanelContents.tsx Uses owned taxonomy types.
src/​controls/​modernTaxonomyPicker/​modernTermPicker/​ModernTermPicker.types.ts Migrates picker type imports.
src/​controls/​modernTaxonomyPicker/​modernTermPicker/​ModernTermPicker.tsx Migrates term type imports.
src/​controls/​modernTaxonomyPicker/​ModernTaxonomyPicker.tsx Adds REST lifecycle isolation and error reporting.
src/​controls/​folderExplorer/​FolderExplorer/​IFolderExplorerState.ts Uses the owned file type.
src/​controls/​folderExplorer/​FolderExplorer/​IFolderExplorerProps.ts Updates the file callback contract.
src/​controls/​folderExplorer/​FolderExplorer/​FolderExplorer.tsx Removes the PnPjs file import.
src/​controls/​dynamicForm/​index.ts Exports new save-error contracts.
src/​controls/​dynamicForm/​IDynamicFormState.ts Uses owned language information.
src/​controls/​dynamicForm/​IDynamicFormProps.ts Replaces the PnPjs submission reference.
src/​controls/​dynamicForm/​DynamicForm.tsx Migrates form loading and persistence.
src/​controls/​dynamicForm/​dynamicField/​IDynamicFieldProps.ts Adds target-web support and owned types.
src/​controls/​dynamicForm/​dynamicField/​DynamicField.tsx Removes PnPjs setup and propagates target web.
src/​controls/​carousel/​Carousel.tsx Replaces PnP array detection.
src/​common/​utilities/​SPHelper.ts Migrates field, lookup, and user utilities.
src/​common/​SPRestTypes.ts Adds library-owned SharePoint response types.
src/​common/​Interfaces.ts Uses the owned navigation type.
src/​common/​index.ts Exports REST response contracts.
package.json Removes PnPjs and adds renderer typings.
config/​jest.config.json Removes obsolete PnPjs mappings.
common/​docs/​documentation/​mkdocs.yml Adds the v4 migration guide.
common/​docs/​documentation/​docs/​index.md Advertises the v4 migration.
common/​docs/​documentation/​docs/​guides/​rush.md Documents dependency and validation rules.
common/​docs/​documentation/​docs/​guides/​migrate-to-v4.md Provides migration and compatibility guidance.
common/​docs/​documentation/​docs/​guides/​index.md Links the migration guide.
common/​docs/​documentation/​docs/​controls/​TaxonomyPicker.md Documents retained classic taxonomy behavior.
common/​docs/​documentation/​docs/​controls/​PeoplePicker.md Documents migrated user resolution.
common/​docs/​documentation/​docs/​controls/​ModernTaxonomyPicker.md Rewrites usage and endpoint documentation.
common/​docs/​documentation/​docs/​controls/​ListItemComments.md Notes shared people-search migration.
common/​docs/​documentation/​docs/​controls/​FolderExplorer.md Documents the owned file contract.
common/​docs/​documentation/​docs/​controls/​DynamicForm.md Documents the new submission contract.
common/​docs/​documentation/​docs/​controls/​ComboBoxListItemPicker.md Corrects the HTTP client documentation.
common/​config/​rush/​pnpm-lock.yaml Removes locked PnPjs packages.
common/​changes/​@pnp/​spfx-controls-react/​pnpjs-removal.json Records the major breaking change.
apps/​controls-tests/​src/​webparts/​controlsTest/​components/​IControlsTestState.ts Uses exported taxonomy types.
apps/​controls-tests/​src/​webparts/​controlsTest/​components/​ControlsTest.tsx Updates examples to SDK-free contracts.
apps/​controls-tests/​package.json Removes app-level PnPjs dependencies.
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread libraries/spfx-controls-react/src/controls/dynamicForm/DynamicForm.tsx Outdated
Comment thread libraries/spfx-controls-react/src/services/PeopleSearchService.ts
Lock submissions before validation, isolate asynchronous form loads, share the taxonomy tree callback contract, and normalize people picker IDs. Add regression tests and migration guidance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The REST client uses an unsupported ES2020 API, and upload errors regress the DynamicForm callback contract.

2 open findings
4 resolved since last review
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file

🧠 Review effort: Balanced

Comment thread libraries/spfx-controls-react/src/services/SPRestClient.ts Outdated
Comment thread libraries/spfx-controls-react/src/controls/dynamicForm/DynamicForm.tsx Outdated
Address PR review by replacing matchAll with RegExp.exec and retaining submitted values for document upload failures. Add emitted-runtime and callback regressions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Folder creation, target transitions, and taxonomy request failures currently contain user-facing correctness issues.

2 open findings
2 resolved since last review
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file
Previously missed (1)

In code that hasn't changed since last review

Medium severity Clear loading state when taxonomy tree requests fail

libraries/​spfx-controls-react/​src/​controls/​modernTaxonomyPicker/​ModernTaxonomyPicker.tsx:384

Re-throwing here leaves the tree permanently loading after a failed initial, expansion, or “load more” request. TaxonomyTree adds the group key to groupsLoading, but all three rejection handlers are no-ops and only the success paths remove it, so the new visible error is accompanied by a spinner that never clears and no retry link. Update those rejection paths to clear the loading key (and group.data.isLoading) while preserving hasMoreData for retry.

🧠 Review effort: Balanced

Comment thread libraries/spfx-controls-react/src/controls/dynamicForm/DynamicForm.tsx Outdated
Comment thread libraries/spfx-controls-react/src/services/DynamicFormService.ts Outdated
Clear target-bound form state before reloading, handle empty folder creation responses, and restore retryable taxonomy loading state while preserving descendant restrictions. Add regression coverage and documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Async submission callback failures are misreported as uncommitted saves, and taxonomy errors remain visible after successful retries.

1 open finding
2 resolved since last review
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file
Previously missed (1)

In code that hasn't changed since last review

Medium severity Stale search error persists after successful retry

libraries/​spfx-controls-react/​src/​controls/​modernTaxonomyPicker/​ModernTaxonomyPicker.tsx:92

errorMessage is only cleared when the target changes, so a transient search/tree/path failure remains displayed after a successful retry on the same term set. Track the failing operation and clear its error when that operation subsequently succeeds; otherwise the picker continues to report a failure while showing successfully loaded data.

🧠 Review effort: Balanced

Comment thread libraries/spfx-controls-react/src/controls/dynamicForm/DynamicForm.tsx Outdated
Wrap submission callback failures with saved item identity and phase information. Track taxonomy errors by operation so successful retries clear only the recovered failure. Add regression coverage and migration guidance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Batch responses are correlated unsafely and a taxonomy API return type excludes an actual runtime result.

1 open finding
1 resolved since last review
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file
Previously missed (1)

In code that hasn't changed since last review

Medium severity Include undefined in the method's return type

libraries/​spfx-controls-react/​src/​services/​SPTaxonomyService.ts:40

The declared return type excludes a value that this method explicitly returns on the next line. Consumers compiled with strict null checks can therefore dereference the result even when Guid.empty produced undefined; this also narrows the previous public contract without documenting it. Keep undefined in the return type.

🧠 Review effort: Balanced

Comment thread libraries/spfx-controls-react/src/services/SPRestClient.ts Outdated
Preserve request identity and input order across reordered batch responses and retries. Reject ambiguous response IDs, expose undefined taxonomy results, and add regression coverage and documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The replacement ISiteUserInfo contract omits a valid previously exposed SharePoint user property.

1 open finding
1 resolved since last review
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file

🧠 Review effort: Balanced

Comment thread libraries/spfx-controls-react/src/common/SPRestTypes.ts
Preserve IsShareByEmailGuestUser from the previous PnPjs user type, with public contract regression coverage and migration guidance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Live SharePoint validation remains outstanding for undocumented taxonomy endpoints and write/upload flows.

0 open findings

1 resolved since last review
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Generated file

🧠 Review effort: Balanced

@AJIXuMuK
AJIXuMuK merged commit ce1e9cf into v4-dev Oct 10, 2026
3 checks passed
@AJIXuMuK
AJIXuMuK deleted the aterentiev-microsoft-pnpjs-dependency-strategy branch October 10, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants