chore(deps): upgrade @sdcorejs/utils to 1.2.3 on every line - #64
Merged
Merged
Conversation
Move the runtime dependency from 1.1.4 to 1.2.3 in v19 (canonical) and roll it out to v20/v21/v22 and the showcase. 1.2.3 is the first 1.2 release whose legacy date helpers accept backend timestamps with sub-millisecond fractions and colon-less offsets again. With 1.2.0-1.2.2, Core Legacy rendered every such table date as "--". Lockfiles change only the @sdcorejs/utils entry (1.2.3 drops its optional rxjs peer). Each lockfile keeps its original indentation, v19/v20/v21 and the showcase were installed with --legacy-peer-deps, and v22 with a clean install, all on Node 22.22.3. Adapting to the 1.2 contract without changing @sdcorejs/angular behaviour: - normalizeAsync now returns a structural subscribable, which toSignal and defer/combineLatest reject. auth.service and sd-breadcrumb adapt MaybeAsync to a real Observable (same adapter as Core Legacy), so re-emitting sources stay live. - getNestedValue returns T | undefined; TableFormatService types cell values through one documented SdTableCellValue alias, as Core Legacy does. - BrowserUtilities.upload now rejects with FilePickerCancelledError on cancel or timeout instead of resolving empty. sd-upload-file no longer shows an error toast for it, SdApiService.upload() still resolves undefined without a request, and SdExcelService.upload() still resolves an empty result. Validation errors are unchanged. - MaybeAsync<T> is now T | PromiseLike<T> | SubscribableLike<T> instead of including RxJS Observable<T>. SubscribableLike does not accept an Observable of a narrower type: Observable<string> for string | null | undefined, an Observable of a subtype, or an Observable of one union member. That broke consumer code such as the showcase's BehaviorSubject<string> breadcrumb label. The public async slots (breadcrumb label, auth signout / changePassword / authInfo, layout sidebar / userInfo, permission loadPermissions / getToken) are typed MaybeAsync<T> | Observable<T>, which restores the 1.1.x acceptance, and internal resolveMaybeAsync calls pin their type argument. Regression specs cover each point, including typed (satisfies) configs that fail to compile against the unwidened types and a datetime pipe spec for microsecond timestamps. Docs for auth, layout, permission, breadcrumb and query-bar plus CHANGELOG [Unreleased] are updated. Verified: check:sync; tsc on v19/v20/v21/v22 and the showcase; v19 and v22 suites with coverage (5936/5936 each); v19 library build; test:scripts; eslint on the changed files reports nothing new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sdcorejs
added a commit
that referenced
this pull request
Sep 30, 2026
…bump @sdcorejs/utils to 1.2.4 (#65) * chore(deps): bump @sdcorejs/utils to 1.2.4 on every line 1.2.4 fixes the root cause of the Observable typing break upstream (sdcorejs-utils #14). SubscribableLike.subscribe no longer includes null in its first parameter. The null had blocked TypeScript's contravariant check against RxJS's single-argument overload, so an Observable of a narrower type (Observable<string> for string | null | undefined, a subtype, one union member) was rejected as MaybeAsync<T>. It now fits in application code too, not only in the Core slots widened in #64. The explicit MaybeAsync<T> | Observable<T> slots from #64 stay: redundant with 1.2.4 but harmless, and they keep the 1.1.x contract visible in the public types. Each lockfile (v19-v22, showcase) changes only the @sdcorejs/utils entry and keeps its original indentation; v22 stays LF. CHANGELOG [Unreleased] and sd-query-bar.md are updated. Verified: check:sync; tsc on v19/v20/v21/v22 and the showcase; v19 library build; v19 suite with coverage 5952/5954. The two failures are SdImageEditor canvas export specs, which pass alone (114/114) and do not use @sdcorejs/utils. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(api): API handlers from lazy routes (provideSdApiConfiguration) and longest-prefix selection SdHttpInterceptor is registered at the root injector through HTTP_INTERCEPTORS and resolved inject(SD_API_CONFIG) once, at construction; SdApiService did the same. A library that provides { provide: SD_API_CONFIG, multi: true } in an NgModule loaded with loadChildren puts it in the lazy route's child injector, which the root interceptor never sees. Every handler was lost in silence: no headers, no beforeRemote/afterRemote, no error toast. One Portal hit this with four lazy libraries and had to re-register every library configuration at root. - SdApiHandlerRegistry (providedIn root) holds runtime registrations as a signal. register() returns an idempotent unregister. - provideSdApiConfiguration(Class | value): EnvironmentProviders registers on scope creation through provideEnvironmentInitializer and unregisters through the scope's DestroyRef. A class is provided inside the scope so it can inject scoped dependencies. The same declaration works in root providers, an eager NgModule, a lazy Route.providers and a loadChildren module. It is exported from @sdcorejs/angular/services/api and covered by public-api.spec. - The interceptor and SdApiService resolve per request from the static SD_API_CONFIG list plus the registry. Root providers behave as before, and SdApiModule still does not call provideHttpClient. - Behaviour change: among matching handlers, the longest matching host prefix (origin + path, via sdMatchesSecureRoute) wins instead of the first in registration order; ties keep order, root first. Host matching itself is unchanged. The token alias and blank-host handling (steps D and E) already existed here. Core Legacy 19.0.41 ships the same registry API and longest-prefix rule but keeps raw startsWith matching; the CHANGELOG records the difference. Specs (api-handler-registry.spec.ts) cover: - a lazy Route.providers handler after activation; - a loadChildren NgModule class configuration with a scoped dependency; - no interception after the scope injector is destroyed; - root and lazy coexisting with the longest prefix winning, in both orders; - tie order; - SdApiService mapResponse from a lazy handler; - the SD_API_CONFIG / SD_API_CONFIGURATION token alias; - blank hosts. Rolled out from v19 to v20/v21/v22 with npm run sync; v22 stays LF. Verified: - npm run check:sync: passes. - npm run lint:release on Node 22.22.3: all four lines pass. - ng test --code-coverage in v19, v20, v21 and v22: 5964/5964 each, exit 0. - npm run test:scripts: 225/225. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(api): pick up SD_API_CONFIG from lazy route injectors without library changes SdApiHandlerRegistry now reads the SD_API_CONFIG entries of every injector the Router creates for a route (Route.providers, or the NgModule of loadChildren). It walks router.config when the registry is created and on each RoutesRecognized, so registration happens in the same navigation, before guards, resolvers and components. Each injector is read once, with { self: true }, and its entries are removed when the injector is destroyed, including by the Angular 21+ router injector cleanup. Libraries keep their plain { provide: SD_API_CONFIG, useClass, multi: true } provider and do not need to know whether the shell mounts them eagerly or lazily. provideSdApiConfiguration stays for values and for scopes the Router does not create. Rolled out to v20, v21 and v22. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: nghiatt15_onemount <nghiatt15@onemount.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This upgrades
@sdcorejs/utilsfrom 1.1.4 to 1.2.3 in v19 (canonical), rolls it out to v20/v21/v22 withnpm run sync, and updates the showcase. 1.2.3 is the first 1.2 release whose legacy date helpers accept backend timestamps again (2026-07-09T08:49:29.851409Z,+0700); with 1.2.0–1.2.2, Core Legacy rendered those table dates as--.Each lockfile changes only the
@sdcorejs/utilsentry (1.2.3 drops its optionalrxjspeer). Every lockfile keeps its original indentation. Installs follow the repo policy on Node 22.22.3:--legacy-peer-depsfor v19/v20/v21 and the showcase, a clean install for v22.1.2 contract changes and how this PR absorbs them
normalizeAsyncreturns a structuralSubscribableLiketoSignal(auth) anddefer/combineLatest(breadcrumb) no longer compileMaybeAsyncto a real RxJSObservable(same as Core Legacy); re-emitting sources stay livegetNestedValuereturnsT | undefinedTableFormatServicestops compilingSdTableCellValuealias, as in Core LegacyBrowserUtilities.uploadrejectsFilePickerCancelledErroron cancel or timeoutsd-upload-fileshows an error toast when the user cancels;SdApiService.upload()andSdExcelService.upload()throwundefined, and{ items: [], file: null }respectively; validation errors are unchangedMaybeAsync<T>no longer includes RxJSObservable<T>Observable<string>forstring | null | undefined, an Observable of a subtype, or an Observable of one union member is rejected (the showcase'sBehaviorSubject<string>breadcrumb label failed)MaybeAsync<T> | Observable<T>, which is what 1.1.x accepted; internalresolveMaybeAsynccalls pin their type argumentThe slots widened are:
sd-breadcrumblabel; authsignout,changePasswordandauthInfo; layoutsidebaranduserInfofactories; permissionloadPermissionsandgetToken.Tests
satisfies) regression specs for breadcrumb, auth, layout and permission. I checked with atscprobe that these assignments fail against the unwidenedMaybeAsyncof 1.2.3.SdApiService.upload,SdExcelService.uploadandsd-upload-file.sdFormatDatetimespec for microsecond, nanosecond and colon-less-offset timestamps, as a guard for future utils bumps.Verification
This branch is rebased on
main, so it includes #63.npm run check:sync: passes.tsc -p tsconfig.spec.jsonon v19/v20/v21/v22, andtscon the showcase: 0 errors.ng test sdcorejs-angular --code-coverage(Node 22.22.3): 5954/5954 each, thresholds met.ng build sdcorejs-angular,npm run test:scripts, and eslint on the changed files: no new findings.dependencieschanges for every target, so the release-contract snapshot for the next suffix (scripts/release-contracts/3.0.json) has to record this reviewed dependency change when it is created.🤖 Generated with Claude Code