@absolutejs/absolute 0.19.0-beta.964 → 0.19.0-beta.966

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.
@@ -1,7 +1,6 @@
1
- export type { AngularPageDefinition, AngularPagePropsOf } from '../../types/angular';
1
+ export type { AngularPagePropsOf } from '../../types/angular';
2
2
  export { ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER, buildAbsoluteHttpTransferCacheOptions } from './httpTransferCache';
3
3
  export { createDeterministicRandom, DETERMINISTIC_NOW, DETERMINISTIC_RANDOM, DETERMINISTIC_SEED, provideDeterministicEnv } from './deterministicEnv';
4
- export { defineAngularPage } from './page';
5
4
  export { useResource, useSubscription, useTimers } from './composables';
6
5
  export type { Observer, Resource, ResourceFetcher, ResourceMutator, ResourceOptions, ResourceStart } from './composables';
7
6
  export { preserveAcrossHmr } from './preserveAcrossHmr';
@@ -1,9 +1,8 @@
1
1
  import '@angular/compiler';
2
- export type { AngularPageDefinition, AngularPagePropsOf } from '../../types/angular';
2
+ export type { AngularPagePropsOf } from '../../types/angular';
3
3
  export { ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER, buildAbsoluteHttpTransferCacheOptions } from './httpTransferCache';
4
4
  export { createDeterministicRandom, DETERMINISTIC_NOW, DETERMINISTIC_RANDOM, DETERMINISTIC_SEED, provideDeterministicEnv } from './deterministicEnv';
5
5
  export { handleAngularPageRequest } from './pageHandler';
6
- export { defineAngularPage } from './page';
7
6
  export { useResource, useSubscription, useTimers } from './composables';
8
7
  export type { Observer, Resource, ResourceFetcher, ResourceMutator, ResourceOptions, ResourceStart } from './composables';
9
8
  export { preserveAcrossHmr } from './preserveAcrossHmr';
@@ -1,18 +1,14 @@
1
- import type { AngularPageDefinition, AngularPagePropsOf } from '../../types/angular';
1
+ import type { AngularPagePropsOf } from '../../types/angular';
2
2
  import { type StreamingSlotEnhancerOptions } from '../core/responseEnhancers';
3
3
  type AngularPageRenderOptions = StreamingSlotEnhancerOptions & {
4
4
  collectStreamingSlots?: boolean;
5
5
  };
6
- type IsAny<T> = 0 extends 1 & T ? true : false;
7
- type HasNoRequiredAngularProps<Props> = IsAny<Props> extends true ? true : keyof Props extends never ? true : false;
8
- type AngularPageHasOptionalProps<Page> = Page extends {
9
- page: AngularPageDefinition<infer Props>;
10
- } ? HasNoRequiredAngularProps<Props> : Page extends {
11
- default: AngularPageDefinition<infer Props>;
12
- } ? HasNoRequiredAngularProps<Props> : HasNoRequiredAngularProps<AngularPagePropsOf<Page>>;
13
- export type AngularPageRequestInput<Page = {
14
- page: AngularPageDefinition<Record<never, never>>;
15
- }> = AngularPageRenderOptions & {
6
+ /** True when the derived Props record has no required keys — used to
7
+ * flip the `props` argument between required and optional in the
8
+ * request-input shape. Pages with no SSR-injected tokens skip
9
+ * `props` entirely. */
10
+ type HasNoRequiredAngularProps<Props> = keyof Props extends never ? true : Partial<Props> extends Props ? true : false;
11
+ export type AngularPageRequestInput<Page = unknown> = AngularPageRenderOptions & {
16
12
  headTag?: `<head>${string}</head>`;
17
13
  indexPath: string;
18
14
  pagePath: string;
@@ -30,12 +26,10 @@ export type AngularPageRequestInput<Page = {
30
26
  * honoured. For finer control use `Route.data.sitemap` in the
31
27
  * page's `Routes` config, or `sitemap.overrides` in `absolute.config.ts`. */
32
28
  sitemap?: import('../../types/sitemap').PageHandlerSitemapMetadata;
33
- } & (AngularPageHasOptionalProps<Page> extends true ? {
29
+ } & (HasNoRequiredAngularProps<AngularPagePropsOf<Page>> extends true ? {
34
30
  props?: NoInfer<AngularPagePropsOf<Page>>;
35
31
  } : {
36
32
  props: NoInfer<AngularPagePropsOf<Page>>;
37
33
  });
38
- export declare const handleAngularPageRequest: <Page = {
39
- page: AngularPageDefinition<Record<never, never>>;
40
- }>(input: AngularPageRequestInput<Page>) => Promise<Response>;
34
+ export declare const handleAngularPageRequest: <Page = unknown>(input: AngularPageRequestInput<Page>) => Promise<Response>;
41
35
  export {};
@@ -1,6 +1,5 @@
1
- export type { AngularPageDefinition, AngularPagePropsOf } from '../../types/angular';
1
+ export type { AngularPagePropsOf } from '../../types/angular';
2
2
  export { ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER, buildAbsoluteHttpTransferCacheOptions } from './httpTransferCache';
3
3
  export { createDeterministicRandom, DETERMINISTIC_NOW, DETERMINISTIC_RANDOM, DETERMINISTIC_SEED, provideDeterministicEnv } from './deterministicEnv';
4
4
  export { handleAngularPageRequest } from './pageHandler';
5
- export { defineAngularPage } from './page';
6
5
  export { withPendingTask } from './pendingTask';
@@ -16,26 +16,56 @@ export type AngularDeps = {
16
16
  SecurityContext: typeof import('@angular/core').SecurityContext;
17
17
  withHttpTransferCacheOptions: typeof import('@angular/platform-browser').withHttpTransferCacheOptions;
18
18
  };
19
- export type AngularPageDefinition<Props extends Record<string, unknown> = Record<never, never>> = {
20
- component: import('@angular/core').Type<unknown>;
21
- /**
22
- * Optional SPA route configuration for this page. When provided,
23
- * the sitemap pipeline walks it (eagerly resolving `loadChildren`)
24
- * and emits one entry per non-dynamic leaf, prefixed by the
25
- * Elysia mount path. Pass the same `Routes` array given to
26
- * `provideRouter(...)` so the single source of truth stays in
27
- * user code.
28
- */
29
- routes?: import('@angular/router').Routes;
30
- /** Type-only marker used by handleAngularPageRequest to infer route props. */
31
- __absoluteAngularPageProps?: Props;
19
+ /**
20
+ * SCREAMING_SNAKE_CASE → camelCase at the type level. Mirrors the
21
+ * runtime mapping in `ssrRender.ts` that turns a page module's
22
+ * exported `INITIAL_ACCOUNT` token into the `initialAccount` prop
23
+ * the backend pages plugin passes.
24
+ */
25
+ type SnakeToCamel<S extends string> = S extends `${infer First}_${infer Rest}` ? `${Lowercase<First>}${Capitalize<SnakeToCamel<Rest>>}` : Lowercase<S>;
26
+ /** Pull the value type out of `InjectionToken<T>` (loosened to any
27
+ * shape that carries the same `T` generic parameter). */
28
+ type ExtractTokenValue<T> = T extends {
29
+ __NG_ELEMENT_ID__?: unknown;
30
+ ngMetadataName?: 'InjectionToken';
31
+ prototype: infer P;
32
+ } ? P : T extends import('@angular/core').InjectionToken<infer U> ? U : never;
33
+ /** Type guard: is `T` an `InjectionToken<unknown>`? Written
34
+ * structurally so it picks up both Angular's official type and any
35
+ * user-defined token via duck-typing on `prototype`. */
36
+ type IsInjectionToken<T> = T extends import('@angular/core').InjectionToken<unknown> ? true : false;
37
+ /** A token whose value type explicitly includes `undefined` becomes
38
+ * an optional prop — call sites can omit it. `null` does not flip
39
+ * to optional: callers must still pass the value explicitly, even
40
+ * if the value happens to be `null`. */
41
+ type RequiredTokenKey<M, K extends keyof M> = IsInjectionToken<M[K]> extends true ? undefined extends ExtractTokenValue<M[K]> ? never : K & string : never;
42
+ type OptionalTokenKey<M, K extends keyof M> = IsInjectionToken<M[K]> extends true ? undefined extends ExtractTokenValue<M[K]> ? K & string : never : never;
43
+ /**
44
+ * Derives the props shape a page accepts from its module's exported
45
+ * `InjectionToken<T>` declarations. The runtime in `ssrRender.ts`
46
+ * already enforces "each prop must match a token re-exported from
47
+ * the page module"; this type mirrors that. A token whose `T`
48
+ * includes `null`/`undefined` becomes an optional prop, otherwise
49
+ * required.
50
+ */
51
+ export type ExtractPageProps<M> = {
52
+ [K in keyof M as SnakeToCamel<RequiredTokenKey<M, K>>]: ExtractTokenValue<M[K]>;
53
+ } & {
54
+ [K in keyof M as SnakeToCamel<OptionalTokenKey<M, K>>]?: ExtractTokenValue<M[K]>;
32
55
  };
33
- export type AngularPagePropsOf<Page> = Page extends {
34
- page: AngularPageDefinition<infer Props>;
35
- } ? Props : Page extends {
36
- default: AngularPageDefinition<infer Props>;
37
- } ? Props : Record<never, never>;
56
+ /**
57
+ * Props the framework will resolve for a given page module. Pages
58
+ * declare their prop surface by exporting `InjectionToken<T>`s — no
59
+ * wrapper function, no separate props type to maintain.
60
+ */
61
+ export type AngularPagePropsOf<Page> = ExtractPageProps<Page>;
62
+ /**
63
+ * Cached render data per route. The `headTag` is captured once when
64
+ * the page module is registered so subsequent renders skip the
65
+ * filesystem read.
66
+ */
38
67
  export type CachedRouteData = {
39
68
  props: Record<string, unknown> | undefined;
40
69
  headTag: `<head>${string}</head>`;
41
70
  };
71
+ export {};
package/package.json CHANGED
@@ -402,5 +402,5 @@
402
402
  ]
403
403
  }
404
404
  },
405
- "version": "0.19.0-beta.964"
405
+ "version": "0.19.0-beta.966"
406
406
  }
@@ -1,5 +0,0 @@
1
- import type { Type } from '@angular/core';
2
- import type { AngularPageDefinition } from '../../types/angular';
3
- export declare const defineAngularPage: <Props extends Record<string, unknown> = Record<never, never>>(definition: {
4
- component: Type<unknown>;
5
- }) => AngularPageDefinition<Props>;