@webjsdev/server 0.8.19 → 0.8.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -312,6 +312,11 @@ export declare function resolveVendorImports(
312
312
  export declare function clearVendorCache(): void;
313
313
  /** Read a package's installed version from `node_modules`, or null. */
314
314
  export declare function getPackageVersion(pkgName: string, appDir: string): string | null;
315
+ /** Read a package's installed `dependencies` + `peerDependencies` (hoist-aware), or null. */
316
+ export declare function getPackageManifest(
317
+ pkgName: string,
318
+ appDir: string,
319
+ ): { dependencies: Record<string, string>; peerDependencies: Record<string, string> } | null;
315
320
  /** Resolve a list of `pkg@version` installs to importmap entries via a provider. */
316
321
  export declare function jspmGenerate(installs: string[], provider?: string): Promise<Record<string, string>>;
317
322
  /** Pin every (or the named) bare imports to `.webjs/vendor/importmap.json`. */
@@ -340,6 +345,14 @@ export declare function updatePinned(appDir: string, opts?: { from?: string }):
340
345
  export declare function readPinFile(
341
346
  appDir: string,
342
347
  ): Promise<{ imports: Record<string, string>; integrity?: Record<string, string>; provider?: string } | null>;
348
+ /**
349
+ * Make the opt-in `webjs vendor pin` output committable. Heals an app's
350
+ * `.gitignore` when a `.webjs` exclusion would swallow the pins, and is a
351
+ * no-op when they are already committable. Called only from `vendor pin`.
352
+ */
353
+ export declare function ensureVendorCommittable(
354
+ appDir: string,
355
+ ): Promise<{ ignored: boolean; patched: boolean; gitignorePath: string | null }>;
343
356
  /** Serve a downloaded `/__webjs/vendor/*` bundle file (`--download` mode). */
344
357
  export declare function serveDownloadedBundle(
345
358
  appDir: string,
@@ -349,6 +362,50 @@ export declare function serveDownloadedBundle(
349
362
  export declare const SUPPORTED_PROVIDERS: Set<string>;
350
363
  /** Normalize / validate a provider name. */
351
364
  export declare function normalizeProvider(name: string): string;
365
+ /**
366
+ * Validate a produced importmap's pinned dependency graph for coherence
367
+ * (issue #450). For each resolved package, checks that the version pinned for
368
+ * every OTHER resolved package it depends on satisfies the declared range.
369
+ * Pure in `(imports, getManifest)`, so the same dep set yields the same verdict
370
+ * over a live importmap and a vendored one. Degrades to `unverified` when a
371
+ * manifest is unavailable.
372
+ */
373
+ export declare function checkImportmapCoherence(
374
+ imports: Record<string, string>,
375
+ opts: {
376
+ getManifest: (
377
+ pkg: string,
378
+ version: string,
379
+ ) =>
380
+ | { dependencies?: Record<string, string>; peerDependencies?: Record<string, string> }
381
+ | null
382
+ | Promise<{ dependencies?: Record<string, string>; peerDependencies?: Record<string, string> } | null>;
383
+ },
384
+ ): Promise<{
385
+ conflicts: Array<{
386
+ pkg: string;
387
+ version: string;
388
+ dependsOn: string;
389
+ kind: 'dependency' | 'peerDependency';
390
+ requiredRange: string;
391
+ pinnedVersion: string;
392
+ }>;
393
+ unverified: Array<{ pkg: string; reason: string }>;
394
+ checked: number;
395
+ }>;
396
+ /** Extract `{ basePackage -> pinned version }` from an importmap's `imports` map. */
397
+ export declare function extractPinnedVersions(
398
+ imports: Record<string, string>,
399
+ ): Map<string, string>;
400
+ /**
401
+ * Does `version` satisfy the npm `range`? Pragmatic, dependency-free. Returns
402
+ * `null` for a range shape it cannot statically evaluate (the "could not
403
+ * verify" signal).
404
+ */
405
+ export declare function satisfiesSemverRange(
406
+ version: string,
407
+ range: string,
408
+ ): boolean | null;
352
409
 
353
410
  // ---------------------------------------------------------------------------
354
411
  // module-graph.js
@@ -701,6 +758,43 @@ export interface ProviderConfig {
701
758
  [key: string]: unknown;
702
759
  }
703
760
 
761
+ /**
762
+ * The augmentable session-user interface (#451), NextAuth/Auth.js style.
763
+ *
764
+ * It is EMPTY by default. An app declares the fields its `session`/`jwt`
765
+ * callbacks set (e.g. crisp sets `session.user.id = token.uid`) by augmenting
766
+ * it, which then types every `auth()` call globally with no cast and catches
767
+ * typos:
768
+ *
769
+ * ```ts
770
+ * declare module '@webjsdev/server' {
771
+ * interface AuthUser {
772
+ * id: string;
773
+ * username: string;
774
+ * }
775
+ * }
776
+ * ```
777
+ *
778
+ * Left un-augmented, `auth().user` falls back to `Record<string, unknown>` (see
779
+ * {@link ResolvedAuthUser}), so every pre-#451 app that reads `user.<field>`
780
+ * without declaring a shape keeps compiling unchanged. For per-instance typing
781
+ * instead of a global augmentation, parameterise the factory:
782
+ * `createAuth<MyUser>(...)`, whose `auth()` returns `{ user: MyUser }`.
783
+ */
784
+ export interface AuthUser {}
785
+
786
+ /**
787
+ * The resolved session-user shape used when `createAuth` is called WITHOUT an
788
+ * explicit type argument: the augmented {@link AuthUser} when an app declared
789
+ * one, else the open `Record<string, unknown>` (the pre-#451 default). The
790
+ * `keyof` probe is how the un-augmented empty interface degrades to the loose
791
+ * record so existing untyped code is unaffected, while an augmented interface
792
+ * gives precise, typo-catching fields.
793
+ */
794
+ export type ResolvedAuthUser = keyof AuthUser extends never
795
+ ? Record<string, unknown>
796
+ : AuthUser;
797
+
704
798
  /** Auth configuration for `createAuth`. */
705
799
  export interface AuthConfig {
706
800
  providers: ProviderConfig[];
@@ -711,9 +805,15 @@ export interface AuthConfig {
711
805
  pages?: { signIn?: string; signOut?: string; error?: string };
712
806
  }
713
807
 
714
- /** The auth system created by `createAuth`. */
715
- export interface AuthInstance {
716
- auth: (req?: Request) => Promise<{ user: Record<string, unknown> } | null>;
808
+ /**
809
+ * The auth system created by `createAuth`. `TUser` is the resolved session-user
810
+ * shape; it defaults to {@link ResolvedAuthUser} (the augmented {@link AuthUser}
811
+ * if an app declared one, else `Record<string, unknown>`) so a module
812
+ * augmentation flows to every `auth()` call, and can be overridden per instance
813
+ * via `createAuth<MyUser>(...)`.
814
+ */
815
+ export interface AuthInstance<TUser = ResolvedAuthUser> {
816
+ auth: (req?: Request) => Promise<{ user: TUser } | null>;
717
817
  signIn: (
718
818
  provider: string,
719
819
  data?: Record<string, unknown>,
@@ -723,8 +823,14 @@ export interface AuthInstance {
723
823
  handlers: { GET: (req: Request) => Promise<Response>; POST: (req: Request) => Promise<Response> };
724
824
  }
725
825
 
726
- /** Create the auth system. */
727
- export declare function createAuth(config: AuthConfig): AuthInstance;
826
+ /**
827
+ * Create the auth system. Parameterise with the session-user shape
828
+ * (`createAuth<MyUser>(...)`) for per-instance typing, or augment the
829
+ * {@link AuthUser} interface for global typing; both make `auth().user` typed
830
+ * with no cast. Defaults to the open {@link AuthUser}, so existing untyped code
831
+ * keeps compiling unchanged.
832
+ */
833
+ export declare function createAuth<TUser = ResolvedAuthUser>(config: AuthConfig): AuthInstance<TUser>;
728
834
  /** The credentials (email/password) provider. */
729
835
  export declare function Credentials(opts: Record<string, unknown>): ProviderConfig;
730
836
  /** The Google OAuth provider. */
package/index.js CHANGED
@@ -21,6 +21,7 @@ export {
21
21
  resolveVendorImports,
22
22
  clearVendorCache,
23
23
  getPackageVersion,
24
+ getPackageManifest,
24
25
  jspmGenerate,
25
26
  pinAll,
26
27
  unpinPackage,
@@ -30,9 +31,13 @@ export {
30
31
  hasVendorPin,
31
32
  updatePinned,
32
33
  readPinFile,
34
+ ensureVendorCommittable,
33
35
  serveDownloadedBundle,
34
36
  SUPPORTED_PROVIDERS,
35
37
  normalizeProvider,
38
+ checkImportmapCoherence,
39
+ extractPinnedVersions,
40
+ satisfiesSemverRange,
36
41
  } from './src/vendor.js';
37
42
  export { buildModuleGraph, transitiveDeps } from './src/module-graph.js';
38
43
  export { scanComponents, primeComponentRegistry, extractComponents, findOrphanComponents } from './src/component-scanner.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webjsdev/server",
3
- "version": "0.8.19",
3
+ "version": "0.8.21",
4
4
  "type": "module",
5
5
  "description": "webjs dev/prod server: SSR, router, API, server actions, live reload",
6
6
  "main": "index.js",
package/src/auth.js CHANGED
@@ -192,6 +192,13 @@ export function GitHub(opts = {}) {
192
192
 
193
193
  /**
194
194
  * Create the auth system.
195
+ *
196
+ * The session-user shape is typed via the `@webjsdev/server` overlay: augment
197
+ * its `AuthUser` interface (NextAuth/Auth.js style) for global typing, or call
198
+ * `createAuth<MyUser>(...)` from TypeScript for per-instance typing. See #451
199
+ * and the auth recipe. This JSDoc keeps the loose runtime shape; the precise
200
+ * typing lives in `index.d.ts` (types-only, no runtime effect).
201
+ *
195
202
  * @param {AuthConfig} config
196
203
  * @returns {{
197
204
  * auth: (req?: Request) => Promise<{ user: Record<string,unknown> }|null>,