@primate/angular 0.1.5 → 0.3.0
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/lib/private/Default.d.ts +17 -0
- package/lib/private/Default.js +53 -0
- package/lib/private/INITIAL_PROPS.d.ts +11 -0
- package/lib/private/INITIAL_PROPS.js +3 -0
- package/lib/private/Runtime.d.ts +13 -0
- package/lib/private/Runtime.js +38 -0
- package/lib/private/client/Validated.d.ts +11 -0
- package/lib/private/client/Validated.js +2 -0
- package/lib/private/client/index.d.ts +14 -0
- package/lib/private/client/index.js +72 -0
- package/lib/private/client/validate.d.ts +25 -0
- package/lib/private/client/validate.js +29 -0
- package/lib/private/create-root.d.ts +3 -0
- package/lib/private/create-root.js +105 -0
- package/lib/private/root-selector.d.ts +3 -0
- package/lib/private/root-selector.js +2 -0
- package/lib/public/INITIAL_PROPS.d.ts +2 -0
- package/lib/public/INITIAL_PROPS.js +2 -0
- package/lib/public/Validated.d.ts +2 -0
- package/lib/public/Validated.js +2 -0
- package/lib/public/browser.d.ts +2 -0
- package/lib/public/browser.js +2 -0
- package/lib/public/default.d.ts +4 -0
- package/lib/public/default.js +3 -0
- package/lib/public/runtime.d.ts +4 -0
- package/lib/public/runtime.js +3 -0
- package/lib/public/validate.d.ts +2 -0
- package/lib/public/validate.js +2 -0
- package/package.json +36 -28
- package/src/private/build/index.js +0 -15
- package/src/private/build/server.js +0 -20
- package/src/private/extension.js +0 -1
- package/src/private/pkgname.js +0 -1
- package/src/private/serve/index.js +0 -10
- package/src/private/serve/make-root.js +0 -17
- package/src/private/serve/render.js +0 -33
- package/src/private/serve/root-component.js +0 -9
- package/src/private/serve/selector.js +0 -1
- package/src/private/serve/set-mode.js +0 -7
- package/src/public/default.js +0 -10
- package/src/public/runtime.js +0 -8
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Runtime from "#Runtime";
|
|
2
|
+
export default class Default extends Runtime {
|
|
3
|
+
root: {
|
|
4
|
+
create: (depth: number, i18n_active: boolean) => string;
|
|
5
|
+
};
|
|
6
|
+
css: {
|
|
7
|
+
filter: RegExp;
|
|
8
|
+
};
|
|
9
|
+
compile: {
|
|
10
|
+
client: (text: string) => {
|
|
11
|
+
js: string;
|
|
12
|
+
css: string;
|
|
13
|
+
};
|
|
14
|
+
server: (text: string) => string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=Default.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import create_root from "#create-root";
|
|
2
|
+
import Runtime from "#Runtime";
|
|
3
|
+
import * as ts from "typescript";
|
|
4
|
+
export default class Default extends Runtime {
|
|
5
|
+
root = {
|
|
6
|
+
create: create_root,
|
|
7
|
+
};
|
|
8
|
+
css = {
|
|
9
|
+
filter: /\.component\.(css)$/,
|
|
10
|
+
};
|
|
11
|
+
compile = {
|
|
12
|
+
client: (text) => {
|
|
13
|
+
const result = ts.transpileModule(text, {
|
|
14
|
+
compilerOptions: {
|
|
15
|
+
module: ts.ModuleKind.ESNext,
|
|
16
|
+
target: ts.ScriptTarget.ES2020,
|
|
17
|
+
experimentalDecorators: true,
|
|
18
|
+
emitDecoratorMetadata: true,
|
|
19
|
+
lib: ["es2020", "dom"],
|
|
20
|
+
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
const styleMatch = text.match(/styles:\s*\[([\s\S]*?)\]/);
|
|
24
|
+
let css = "";
|
|
25
|
+
if (styleMatch) {
|
|
26
|
+
// Extract and process inline styles
|
|
27
|
+
css = styleMatch[1]
|
|
28
|
+
.replace(/['"`]/g, "")
|
|
29
|
+
.replace(/\\n/g, "\n")
|
|
30
|
+
.trim();
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
js: result.outputText,
|
|
34
|
+
css,
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
server: (text) => {
|
|
38
|
+
// TypeScript compilation for server (SSR)
|
|
39
|
+
const result = ts.transpileModule(text, {
|
|
40
|
+
compilerOptions: {
|
|
41
|
+
module: ts.ModuleKind.ESNext,
|
|
42
|
+
target: ts.ScriptTarget.ES2020,
|
|
43
|
+
experimentalDecorators: true,
|
|
44
|
+
emitDecoratorMetadata: true,
|
|
45
|
+
lib: ["es2020"],
|
|
46
|
+
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
return result.outputText;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=Default.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InjectionToken } from "@angular/core";
|
|
2
|
+
import type Dict from "@rcompat/type/Dict";
|
|
3
|
+
type RootProps = {
|
|
4
|
+
components: any[];
|
|
5
|
+
props: Dict[];
|
|
6
|
+
request: any;
|
|
7
|
+
update?: () => void;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: InjectionToken<RootProps>;
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=INITIAL_PROPS.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "@angular/compiler";
|
|
2
|
+
import { type Type } from "@angular/core";
|
|
3
|
+
import FrontendModule from "@primate/core/frontend/Module";
|
|
4
|
+
import type Render from "@primate/core/frontend/Render";
|
|
5
|
+
import "zone.js/node";
|
|
6
|
+
export default class Runtime extends FrontendModule<Type<any>> {
|
|
7
|
+
name: string;
|
|
8
|
+
defaultExtensions: string[];
|
|
9
|
+
layouts: boolean;
|
|
10
|
+
client: boolean;
|
|
11
|
+
render: Render<Type<any>>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=Runtime.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import INITIAL_PROPS from "#INITIAL_PROPS";
|
|
2
|
+
import root from "#root-selector";
|
|
3
|
+
import "@angular/compiler";
|
|
4
|
+
import { importProvidersFrom, provideZoneChangeDetection, } from "@angular/core";
|
|
5
|
+
import { bootstrapApplication, BrowserModule, provideClientHydration, } from "@angular/platform-browser";
|
|
6
|
+
import { provideServerRendering, renderApplication, } from "@angular/platform-server";
|
|
7
|
+
import FrontendModule from "@primate/core/frontend/Module";
|
|
8
|
+
import "zone.js/node";
|
|
9
|
+
export default class Runtime extends FrontendModule {
|
|
10
|
+
name = "angular";
|
|
11
|
+
defaultExtensions = [".component.ts"];
|
|
12
|
+
layouts = true;
|
|
13
|
+
client = true;
|
|
14
|
+
render = async (RootComponent, props) => {
|
|
15
|
+
const providers = [
|
|
16
|
+
importProvidersFrom(BrowserModule),
|
|
17
|
+
provideServerRendering(),
|
|
18
|
+
provideClientHydration(),
|
|
19
|
+
provideZoneChangeDetection({ eventCoalescing: true }),
|
|
20
|
+
{
|
|
21
|
+
provide: INITIAL_PROPS,
|
|
22
|
+
useValue: props,
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
const bootstrap = (context) => bootstrapApplication(RootComponent, { providers }, context);
|
|
26
|
+
const html = await renderApplication(bootstrap, {
|
|
27
|
+
document: `<${root}></${root}>`,
|
|
28
|
+
});
|
|
29
|
+
const headMatch = html.match(/<head>(.*?)<\/head>/s);
|
|
30
|
+
const bodyRegex = new RegExp(`<${root}>([\\s\\S]*?)<\\/${root}>`);
|
|
31
|
+
const bodyMatch = html.match(bodyRegex);
|
|
32
|
+
return {
|
|
33
|
+
body: bodyMatch?.[1] || html,
|
|
34
|
+
head: headMatch?.[1] || "",
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=Runtime.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Signal } from "@angular/core";
|
|
2
|
+
import type ValidateUpdater from "@primate/core/client/ValidateUpdater";
|
|
3
|
+
import type ValidationError from "@primate/core/client/ValidationError";
|
|
4
|
+
type Validated<T> = {
|
|
5
|
+
error: Signal<null | ValidationError>;
|
|
6
|
+
loading: Signal<boolean>;
|
|
7
|
+
update: (updater: ValidateUpdater<T>) => Promise<void>;
|
|
8
|
+
value: Signal<T>;
|
|
9
|
+
};
|
|
10
|
+
export type { Validated as default };
|
|
11
|
+
//# sourceMappingURL=Validated.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "zone.js";
|
|
2
|
+
import "@angular/compiler";
|
|
3
|
+
import type ClientData from "@primate/core/client/Data";
|
|
4
|
+
import type Dict from "@rcompat/type/Dict";
|
|
5
|
+
type Data = ClientData<{
|
|
6
|
+
components: string[];
|
|
7
|
+
props: Dict[];
|
|
8
|
+
}>;
|
|
9
|
+
export default class AngularClient {
|
|
10
|
+
#private;
|
|
11
|
+
static mount(_component: string, data: ClientData<Data>): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import INITIAL_PROPS from "#INITIAL_PROPS";
|
|
2
|
+
import "zone.js";
|
|
3
|
+
import "@angular/compiler";
|
|
4
|
+
import { NgZone, provideZoneChangeDetection, } from "@angular/core";
|
|
5
|
+
import { bootstrapApplication, provideClientHydration, } from "@angular/platform-browser";
|
|
6
|
+
import spa from "@primate/core/client/spa";
|
|
7
|
+
import * as components from "angular:components";
|
|
8
|
+
import root from "angular:root";
|
|
9
|
+
const make_props = (data) => ({
|
|
10
|
+
components: data.components.map(name => components[name]),
|
|
11
|
+
props: data.props,
|
|
12
|
+
request: {
|
|
13
|
+
...data.request,
|
|
14
|
+
url: new URL(location.href),
|
|
15
|
+
},
|
|
16
|
+
update: () => undefined,
|
|
17
|
+
});
|
|
18
|
+
export default class AngularClient {
|
|
19
|
+
static #app;
|
|
20
|
+
static #root;
|
|
21
|
+
static #zone;
|
|
22
|
+
static async mount(_component, data) {
|
|
23
|
+
const providers = [];
|
|
24
|
+
// Add hydration provider for SSR
|
|
25
|
+
if (data.ssr) {
|
|
26
|
+
providers.push(provideClientHydration());
|
|
27
|
+
}
|
|
28
|
+
// Add zone.js change detection
|
|
29
|
+
providers.push(provideZoneChangeDetection({ eventCoalescing: true }));
|
|
30
|
+
// Create the root component props
|
|
31
|
+
const props = make_props(data);
|
|
32
|
+
// Bootstrap the application
|
|
33
|
+
try {
|
|
34
|
+
this.#app = await bootstrapApplication(root, {
|
|
35
|
+
providers: [
|
|
36
|
+
...providers,
|
|
37
|
+
{
|
|
38
|
+
provide: INITIAL_PROPS,
|
|
39
|
+
useValue: props,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
this.#root = this.#app.components[0];
|
|
44
|
+
// initial props
|
|
45
|
+
if (this.#root.instance) {
|
|
46
|
+
this.#root.instance.p = props;
|
|
47
|
+
// change detection
|
|
48
|
+
this.#app.tick();
|
|
49
|
+
}
|
|
50
|
+
if (data.spa) {
|
|
51
|
+
this.#spa();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error("Failed to bootstrap Angular application:", error);
|
|
56
|
+
}
|
|
57
|
+
this.#zone = this.#root.injector.get(NgZone);
|
|
58
|
+
}
|
|
59
|
+
static #spa() {
|
|
60
|
+
window.addEventListener("DOMContentLoaded", () => {
|
|
61
|
+
spa((next, update) => {
|
|
62
|
+
const props = { ...make_props(next), update };
|
|
63
|
+
this.#zone.run(() => {
|
|
64
|
+
this.#root.instance.p = props;
|
|
65
|
+
this.#app.tick();
|
|
66
|
+
});
|
|
67
|
+
update?.();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type Validated from "#client/Validated";
|
|
2
|
+
declare const _default: <T>(initial: T) => {
|
|
3
|
+
delete: (url: string, options?: {
|
|
4
|
+
headers?: import("@rcompat/type/Dict").default<string>;
|
|
5
|
+
map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
|
|
6
|
+
path?: import("@rcompat/type/JSONPointer").default;
|
|
7
|
+
} | undefined) => Validated<T>;
|
|
8
|
+
patch: (url: string, options?: {
|
|
9
|
+
headers?: import("@rcompat/type/Dict").default<string>;
|
|
10
|
+
map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
|
|
11
|
+
path?: import("@rcompat/type/JSONPointer").default;
|
|
12
|
+
} | undefined) => Validated<T>;
|
|
13
|
+
post: (url: string, options?: {
|
|
14
|
+
headers?: import("@rcompat/type/Dict").default<string>;
|
|
15
|
+
map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
|
|
16
|
+
path?: import("@rcompat/type/JSONPointer").default;
|
|
17
|
+
} | undefined) => Validated<T>;
|
|
18
|
+
put: (url: string, options?: {
|
|
19
|
+
headers?: import("@rcompat/type/Dict").default<string>;
|
|
20
|
+
map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
|
|
21
|
+
path?: import("@rcompat/type/JSONPointer").default;
|
|
22
|
+
} | undefined) => Validated<T>;
|
|
23
|
+
};
|
|
24
|
+
export default _default;
|
|
25
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { signal } from "@angular/core";
|
|
2
|
+
import toValidated from "@primate/core/client/toValidated";
|
|
3
|
+
import validate from "@primate/core/client/validate";
|
|
4
|
+
function useValidate(init) {
|
|
5
|
+
const value = signal(init.initial);
|
|
6
|
+
const loading = signal(false);
|
|
7
|
+
const error = signal(null);
|
|
8
|
+
async function update(updater) {
|
|
9
|
+
const previous = value();
|
|
10
|
+
const next = updater(previous);
|
|
11
|
+
value.set(next);
|
|
12
|
+
loading.set(true);
|
|
13
|
+
error.set(null);
|
|
14
|
+
try {
|
|
15
|
+
await validate(init, next);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
// rollback
|
|
19
|
+
value.set(previous);
|
|
20
|
+
error.set(e);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
loading.set(false);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { error, loading, update, value };
|
|
27
|
+
}
|
|
28
|
+
export default toValidated(useValidate);
|
|
29
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import root_selector from "#root-selector";
|
|
2
|
+
export default (depth, i18n_active) => {
|
|
3
|
+
const n = depth - 1;
|
|
4
|
+
const layer = (i, child) => {
|
|
5
|
+
const slot = `slot_${i}`;
|
|
6
|
+
const childTemplate = child
|
|
7
|
+
? `<ng-template #${slot}>${child}</ng-template>`
|
|
8
|
+
: "";
|
|
9
|
+
const inputs = child
|
|
10
|
+
? `(has(${i + 1}) ? slotInputs(${i}, ${slot}) : inputs(${i}))`
|
|
11
|
+
: `inputs(${i})`;
|
|
12
|
+
return `${childTemplate}
|
|
13
|
+
<ng-container *ngComponentOutlet="comp(${i}); inputs: ${inputs}">
|
|
14
|
+
</ng-container>
|
|
15
|
+
`;
|
|
16
|
+
};
|
|
17
|
+
let body = layer(n, null);
|
|
18
|
+
for (let i = n - 1; i >= 0; i--)
|
|
19
|
+
body = layer(i, body);
|
|
20
|
+
const i18n_imports = i18n_active
|
|
21
|
+
? `import t from "#i18n";
|
|
22
|
+
import sInternal from "primate/s/internal";`
|
|
23
|
+
: "";
|
|
24
|
+
const i18n_setup = i18n_active ?
|
|
25
|
+
`if (this.#p.request.context.i18n.locale) {
|
|
26
|
+
t[sInternal].init(this.#p.request.context.i18n.locale);
|
|
27
|
+
}
|
|
28
|
+
this.#off = t.subscribe(() => this.#cdr.markForCheck());
|
|
29
|
+
`
|
|
30
|
+
: "";
|
|
31
|
+
return `
|
|
32
|
+
import {
|
|
33
|
+
Component,
|
|
34
|
+
Input,
|
|
35
|
+
inject,
|
|
36
|
+
ChangeDetectorRef,
|
|
37
|
+
OnDestroy,
|
|
38
|
+
TemplateRef,
|
|
39
|
+
AfterViewInit,
|
|
40
|
+
} from "@angular/core";
|
|
41
|
+
import { CommonModule, NgComponentOutlet } from "@angular/common";
|
|
42
|
+
import INITIAL_PROPS from "@primate/angular/INITIAL_PROPS";
|
|
43
|
+
${i18n_imports}
|
|
44
|
+
|
|
45
|
+
type Dict = Record<string, any>;
|
|
46
|
+
type RootProps = {
|
|
47
|
+
components: any[];
|
|
48
|
+
props: Dict[];
|
|
49
|
+
request: any;
|
|
50
|
+
update?: () => void
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
@Component({
|
|
54
|
+
standalone: true,
|
|
55
|
+
selector: "${root_selector}",
|
|
56
|
+
imports: [CommonModule, NgComponentOutlet],
|
|
57
|
+
template: \`<ng-container *ngIf="P as P">${body}</ng-container>\`
|
|
58
|
+
})
|
|
59
|
+
export default class RootComponent implements OnDestroy {
|
|
60
|
+
#p!: RootProps;
|
|
61
|
+
#cdr = inject(ChangeDetectorRef);
|
|
62
|
+
#off?: () => void;
|
|
63
|
+
|
|
64
|
+
constructor() {
|
|
65
|
+
try {
|
|
66
|
+
const initial = inject<any>(INITIAL_PROPS);
|
|
67
|
+
if (initial) this.#p = initial;
|
|
68
|
+
} catch {}
|
|
69
|
+
${i18n_setup}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@Input({ required: true })
|
|
73
|
+
set p(value: RootProps) {
|
|
74
|
+
this.#p = value;
|
|
75
|
+
this.#cdr.markForCheck(); // root on default CD, zone ticks traverse
|
|
76
|
+
}
|
|
77
|
+
get p(): RootProps { return this.#p; }
|
|
78
|
+
get P(): RootProps { return this.#p; }
|
|
79
|
+
|
|
80
|
+
// is there a component at index i?
|
|
81
|
+
has(i: number) { return !!this.P?.components?.[i]; }
|
|
82
|
+
|
|
83
|
+
// component type for index i
|
|
84
|
+
comp(i: number) { return this.P?.components?.[i]; }
|
|
85
|
+
|
|
86
|
+
// per-layer inputs without slot
|
|
87
|
+
inputs(i: number) {
|
|
88
|
+
return (this.P?.props?.[i] ?? {}) as Dict;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// per-layer inputs + slot template (only used when has(i+1) is true)
|
|
92
|
+
slotInputs(i: number, slot: TemplateRef<unknown>) {
|
|
93
|
+
const base = (this.P?.props?.[i] ?? {}) as Dict;
|
|
94
|
+
return { ...base, slot };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
ngAfterViewInit() {
|
|
98
|
+
t[sInternal].restore();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
ngOnDestroy() { this.#off?.(); }
|
|
102
|
+
}
|
|
103
|
+
`;
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=create-root.js.map
|
package/package.json
CHANGED
|
@@ -1,52 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primate/angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Primate Angular frontend",
|
|
5
|
-
"homepage": "https://
|
|
6
|
-
"bugs": "https://github.com/
|
|
5
|
+
"homepage": "https://primate.run/docs/frontend/angular",
|
|
6
|
+
"bugs": "https://github.com/primate-run/primate/issues",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"files": [
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"/lib/**/*.js",
|
|
10
|
+
"/lib/**/*.d.ts",
|
|
11
|
+
"!/**/*.spec.*"
|
|
11
12
|
],
|
|
12
13
|
"repository": {
|
|
13
14
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/
|
|
15
|
+
"url": "https://github.com/primate-run/primate",
|
|
15
16
|
"directory": "packages/angular"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@angular/
|
|
19
|
-
"@angular/
|
|
20
|
-
"@angular/
|
|
21
|
-
"@angular/
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"
|
|
25
|
-
"@
|
|
19
|
+
"@angular/common": "^20.3.2",
|
|
20
|
+
"@angular/compiler": "^20.3.2",
|
|
21
|
+
"@angular/core": "^20.3.2",
|
|
22
|
+
"@angular/platform-browser": "^20.3.2",
|
|
23
|
+
"@angular/platform-server": "^20.3.2",
|
|
24
|
+
"@angular/ssr": "^20.3.3",
|
|
25
|
+
"@rcompat/assert": "^0.3.1",
|
|
26
|
+
"@rcompat/build": "^0.14.0",
|
|
27
|
+
"@rcompat/crypto": "^0.10.0",
|
|
28
|
+
"@rcompat/fs": "^0.21.1",
|
|
29
|
+
"@rcompat/record": "^0.9.1",
|
|
30
|
+
"typescript": "^5.9.2",
|
|
31
|
+
"zone.js": "^0.15.1",
|
|
32
|
+
"@primate/core": "^0.2.0"
|
|
26
33
|
},
|
|
27
34
|
"peerDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"primate": "^0.32.5"
|
|
35
|
+
"primate": "^0.33.0"
|
|
30
36
|
},
|
|
31
37
|
"type": "module",
|
|
32
38
|
"imports": {
|
|
33
39
|
"#*": {
|
|
34
|
-
"
|
|
35
|
-
"default": "./
|
|
36
|
-
},
|
|
37
|
-
"#build": {
|
|
38
|
-
"livetypes": "./src/private/build/index.js",
|
|
39
|
-
"default": "./src/private/build/index.js"
|
|
40
|
-
},
|
|
41
|
-
"#serve": {
|
|
42
|
-
"livetypes": "./src/private/serve/index.js",
|
|
43
|
-
"default": "./src/private/serve/index.js"
|
|
40
|
+
"apekit": "./src/private/*.ts",
|
|
41
|
+
"default": "./lib/private/*.js"
|
|
44
42
|
}
|
|
45
43
|
},
|
|
46
44
|
"exports": {
|
|
47
45
|
".": {
|
|
48
|
-
"
|
|
49
|
-
"
|
|
46
|
+
"browser": "./lib/public/browser.js",
|
|
47
|
+
"runtime": "./lib/public/runtime.js",
|
|
48
|
+
"default": "./lib/public/default.js"
|
|
49
|
+
},
|
|
50
|
+
"./*": {
|
|
51
|
+
"apekit": "./src/public/*.ts",
|
|
52
|
+
"default": "./lib/public/*.js"
|
|
50
53
|
}
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "npm run clean && tsc",
|
|
57
|
+
"clean": "rm -rf ./lib",
|
|
58
|
+
"lint": "eslint ."
|
|
51
59
|
}
|
|
52
60
|
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import server from "./server.js";
|
|
2
|
-
|
|
3
|
-
export default extension => async (app, next) => {
|
|
4
|
-
const extensions = {
|
|
5
|
-
from: extension,
|
|
6
|
-
to: ".js",
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
app.register(extension, {
|
|
10
|
-
server: component => server(app, component, extensions),
|
|
11
|
-
client: _ => _,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
return next(app);
|
|
15
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import transform from "@rcompat/build/transform";
|
|
2
|
-
|
|
3
|
-
const options = {
|
|
4
|
-
loader: "ts",
|
|
5
|
-
tsconfig: {
|
|
6
|
-
compilerOptions: {
|
|
7
|
-
experimentalDecorators: true,
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default async (app, component, extensions) => {
|
|
13
|
-
const location = app.get("location");
|
|
14
|
-
const source = app.runpath(location.components);
|
|
15
|
-
const { code } = await transform(await component.text(), options);
|
|
16
|
-
const target_base = app.runpath(location.server, location.components);
|
|
17
|
-
const path = target_base.join(`${component.path}.js`.replace(source, ""));
|
|
18
|
-
await path.directory.create();
|
|
19
|
-
await path.write(code.replaceAll(extensions.from, extensions.to));
|
|
20
|
-
};
|
package/src/private/extension.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default ".component.ts";
|
package/src/private/pkgname.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default "@primate/angular";
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { reflectComponentType } from "@angular/core";
|
|
2
|
-
import stringify from "@rcompat/object/stringify";
|
|
3
|
-
import root_component from "./root-component.js";
|
|
4
|
-
|
|
5
|
-
const double_to_single = string => string.replaceAll("\"", "'");
|
|
6
|
-
|
|
7
|
-
export default (real_root, props) => {
|
|
8
|
-
const { selector } = reflectComponentType(real_root);
|
|
9
|
-
const attributes = Object.entries(props)
|
|
10
|
-
.map(([key, value]) => `[${key}]="${double_to_single(stringify(value))}"`)
|
|
11
|
-
.join(" ");
|
|
12
|
-
|
|
13
|
-
return root_component({
|
|
14
|
-
imports: [real_root],
|
|
15
|
-
template: `<${selector} ${attributes}></${selector}>`,
|
|
16
|
-
});
|
|
17
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import "@angular/compiler";
|
|
2
|
-
import {
|
|
3
|
-
bootstrapApplication,
|
|
4
|
-
provideClientHydration,
|
|
5
|
-
} from "@angular/platform-browser";
|
|
6
|
-
import {
|
|
7
|
-
provideServerRendering,
|
|
8
|
-
renderApplication,
|
|
9
|
-
ɵSERVER_CONTEXT,
|
|
10
|
-
} from "@angular/platform-server";
|
|
11
|
-
import "zone.js";
|
|
12
|
-
import make_root from "./make-root.js";
|
|
13
|
-
import selector from "./selector.js";
|
|
14
|
-
|
|
15
|
-
// const common_engine = new CommonEngine();
|
|
16
|
-
|
|
17
|
-
export default async (given_component, props) => {
|
|
18
|
-
const component = make_root(given_component, props);
|
|
19
|
-
const document = `<${selector}></${selector}>`;
|
|
20
|
-
const bootstrap = () => bootstrapApplication(component, {
|
|
21
|
-
providers: [
|
|
22
|
-
provideServerRendering(),
|
|
23
|
-
{ provide: ɵSERVER_CONTEXT, useValue: "analog" },
|
|
24
|
-
...component.renderProviders || [],
|
|
25
|
-
provideClientHydration(),
|
|
26
|
-
],
|
|
27
|
-
});
|
|
28
|
-
const html = await renderApplication(bootstrap, { document });
|
|
29
|
-
const b_s = "<body>";
|
|
30
|
-
const b_e = "</body>";
|
|
31
|
-
// await common_engine.render({ bootstrap, document });
|
|
32
|
-
return html.slice(html.indexOf(b_s) + b_s.length, html.indexOf(b_e));
|
|
33
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default "app-root";
|
package/src/public/default.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import build from "#build";
|
|
2
|
-
import default_extension from "#extension";
|
|
3
|
-
import pkgname from "#pkgname";
|
|
4
|
-
import serve from "#serve";
|
|
5
|
-
|
|
6
|
-
export default ({ extension = default_extension } = {}) => ({
|
|
7
|
-
name: pkgname,
|
|
8
|
-
build: build(extension),
|
|
9
|
-
serve: serve(extension),
|
|
10
|
-
});
|