Skip to content

refactor(types): adopt official beta Graph types for container-type control-plane contracts - #36

Merged
Gregory Joseph (gnjoseph) merged 2 commits into
feat/spe-mcp-serverfrom
agents/pr3-graphC
Jul 9, 2026
Merged

refactor(types): adopt official beta Graph types for container-type control-plane contracts#36
Gregory Joseph (gnjoseph) merged 2 commits into
feat/spe-mcp-serverfrom
agents/pr3-graphC

Conversation

@gnjoseph

Copy link
Copy Markdown
Collaborator

Batch C — official beta Graph types for the container-type control plane

Types-only refactor in the Graph-SDK type-adoption series (follows the Batch A POC and Batch B). Replaces the remaining hand-maintained control-plane (container-type) Microsoft Graph interfaces with types derived from the official @microsoft/microsoft-graph-types-beta package. The SPE container-type control-plane APIs (/storage/fileStorage/containerTypes*) are /beta, so the official types come from the beta package (Batch A/B used the stable @microsoft/microsoft-graph-types for the content plane).

No runtime, behavior, or wire-format change — only type annotations and generic arguments change.

Local type → official beta type

Local type (file) Derives from (beta) Required keys Optional keys (Pick) Null handling / narrowing kept
RawContainerType (graph-client.ts) FileStorageContainerType id, name, owningAppId, createdDateTime, expirationDateTime, etag + local extras containerTypeId?, displayName?, azureSubscriptionId?; billingClassification? kept as local BillingClassification union. All optional so normalizeContainerType({}) still type-checks.
ContainerTypePermission (types.ts) Permission (beta) roles = NonNullable<Permission["roles"]> id roles un-nullabled (official NullableOption<string[]>); grantedToV2.user kept as narrowed local shape to retain userPrincipalName (official identity omits it).
ContainerTypeRegistrationRecord (types.ts) FileStorageContainerTypeRegistration id, owningAppId, registeredDateTime + billingClassification? (local union) + applicationPermissionGrants?: ApplicationPermissionGrant[] (our non-null-element array).
ContainerTypeRegistration (types.ts) FileStorageContainerTypeRegistration (transitively) applicationPermissionGrants Sole field is our non-null narrowing of the official applicationPermissionGrants (see note).
ApplicationPermissionGrant (types.ts) FileStorageContainerTypeAppPermissionGrant appId = Required<Pick<…>> delegatedPermissions/applicationPermissions kept string[] (not the official enum) + required (see note).
4 envelope interfaces (graph-client.ts) shared GraphCollection<T> ListContainerTypesResponse, ApplicationPermissionGrantsResponse, ContainerTypeRegistrationsListResponse, ContainerTypePermissionsResponse collapse onto GraphCollection<T>.

Exact beta type names (verified in node_modules/@microsoft/microsoft-graph-types-beta/microsoft-graph.d.ts)

  • FileStorageContainerType (extends Entity; id/name/owningAppId/createdDateTime/expirationDateTime/etag/billingClassification, …). Note: it does not expose displayName or a permissions nav prop in this version.
  • FileStorageContainerTypeRegistration (extends Entity; applicationPermissionGrants?: NullableOption<FileStorageContainerTypeAppPermissionGrant[]>, owningAppId, registeredDateTime, …).
  • FileStorageContainerTypeAppPermissionGrant (appId?; applicationPermissions?/delegatedPermissions?: NullableOption<FileStorageContainerTypeAppPermission[]>).
  • Permission (beta; roles?: NullableOption<string[]>, grantedToV2?: NullableOption<SharePointIdentitySet>) — the container-type …/permissions resource is the generic Graph permission.
  • Supporting: Entity (id?: string), NullableOption<T> = T | null, FileStorageContainerBillingClassification = "standard" | "trial" | "directToCustomer" | "unknownFutureValue".

Derive pattern + null handling

  • Required<T> strips ? but not | null; beta fields are frequently NullableOption<T>. Fields we dereference/pass non-null are wrapped in NonNullable<…> (ContainerTypePermission.roles). Fields read null-tolerantly (??, ===) keep the official shape.
  • Intentional local narrowings preserved by intersecting/overriding, never widening: billingClassification stays the local BillingClassification union; grantedToV2.user stays the narrowed local shape; grant permission arrays stay string[].
  • Curated human JSDoc preserved and extended onto the derived aliases.

Why the beta package is exact-pinned / types-only / dev-only

  • Types-only: ships only microsoft-graph.d.ts (no main, zero JS). Confirmed the import type erases to zero references in dist (the graph-types-beta literal appears 0× in compiled output).
  • Dev-only: added under devDependencies; never imported at runtime.
  • MIT: the package LICENSE is MIT (matches the stable types package already in the tree). Resolves from the public npm registry.
  • Exact-pinned (0.44.0-preview, no caret): it is a 0.x pre-release, so a caret would allow minor drift — pin for reproducibility (mirrors the existing @microsoft/microsoft-graph-types 2.43.1 exact pin).

Left partially hand-maintained (deliberate — no bad mapping forced)

  • ApplicationPermissionGrant.delegatedPermissions / applicationPermissions: the official grant types these as NullableOption<FileStorageContainerTypeAppPermission[]> (a string-literal enum, nullable). The server builds/sends them as string[] and asserts the registration-PUT body with satisfies ApplicationPermissionGrant; deriving the enum would break that satisfies and the non-null .length/.join reads. So appId derives from the official type (required) while the two arrays stay our string[] narrowing.
  • ContainerTypeRegistration: its sole field is the narrowed non-null applicationPermissionGrants override, so it derives from FileStorageContainerTypeRegistration only transitively (through ApplicationPermissionGrant); forcing a Pick/NullableOption on the single field would add noise without value.

Discipline / scope

  • No behavior/logic/wire change. The prior control-plane function bodies (DESIRED_GRAPH_RESOURCE_ACCESS, registerContainerType, the listContainerTypes staleness writer) are not altered — only the type argument on listContainerTypes's graphRequestBeta<…> call changed.
  • satisfies ApplicationPermissionGrant still compiles.

Test evidence (local pipeline, all green)

  • npm run lint → clean
  • npm run typecheck (tsc --noEmit) → clean
  • npm run build (tsc) → clean
  • npm testTests 682 passed | 3 skipped (685) — unchanged from baseline.

Ref: PR #3 review.

Greg Joseph and others added 2 commits July 9, 2026 08:22
…ontrol-plane contracts

Replace the remaining hand-maintained control-plane (container-type) Microsoft
Graph interfaces with types derived from the official
@microsoft/microsoft-graph-types-beta package (the SPE container-type APIs are
/beta). This is a types-only refactor: no runtime, behavior, or wire-format
change. The beta package is a dev-only, types-only .d.ts dependency that
compiles away to zero runtime JS.

graph-client.ts:
- RawContainerType now derives from the official FileStorageContainerType
  (Pick of the scalar wire fields + intersected local normalize extras;
  every field stays optional so normalizeContainerType({}) still type-checks).
- The four local { value: T[] } envelope interfaces collapse onto the shared
  generic GraphCollection<T>.

types.ts:
- ContainerTypePermission derives from the official beta permission resource
  (roles kept NonNullable; grantedToV2.user narrowed to keep userPrincipalName).
- ContainerTypeRegistrationRecord / ContainerTypeRegistration derive from the
  official FileStorageContainerTypeRegistration.
- ApplicationPermissionGrant derives appId from the official
  FileStorageContainerTypeAppPermissionGrant; the two permission arrays stay
  string[] (not the official enum) so the registration-PUT
  `satisfies ApplicationPermissionGrant` still compiles and .length/.join reads
  stay non-null.

Intentional local narrowings are preserved via intersection (BillingClassification
union, string[] permission arrays, narrowed grantedToV2.user). Pins
@microsoft/microsoft-graph-types-beta at 0.44.0-preview (exact; 0.x) as a
devDependency. Local pipeline green: lint, typecheck, build, and 682 passed /
3 skipped tests (unchanged from baseline). Ref: PR #3 review.

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

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@gnjoseph
Gregory Joseph (gnjoseph) merged commit 1694346 into feat/spe-mcp-server Jul 9, 2026
5 checks passed
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.

1 participant