Internal visibility
Some members of a component are implementation details: a connection pool, a helper, a policy object. internal(...) marks them so that other layers do not see them, while the same layer still can.
import { internal } from '@atom-forge/laminar';
export const emailService = defineService((config) => {
async function connectToSmtp() { }
async function sendEmail(to: string, body: string) {
await connectToSmtp();
}
return {
sendEmail,
connectToSmtp: internal(connectToSmtp),
};
});
PublicLayer<T>
PublicLayer<T> recursively removes every property marked internal. Function signatures are preserved. A layer that consumes another layer types its factory argument as PublicLayer<…>:
type ModulesLayer = Layer<
[Config, Services],
Modules,
[Config, PublicLayer<Services>, Modules]
>;
flowchart LR
subgraph Services
direction TB
P[sendEmail]
I[connectToSmtp internal]
end
subgraph Modules
M[auth module]
end
M -->|PublicLayer| P
M -. hidden .-x I
Who decides
The parent marks a child internal, not the child itself. The child stays reusable:
return {
public: conferencePublicModule(),
policy: internal(conferencePolicyModule()),
};
Internal visibility
Some members of a component are implementation details: a connection pool, a helper, a policy object.
internal(...)marks them so that other layers do not see them, while the same layer still can.import { internal } from '@atom-forge/laminar'; export const emailService = defineService((config) => { async function connectToSmtp() { /* … */ } async function sendEmail(to: string, body: string) { await connectToSmtp(); } return { sendEmail, connectToSmtp: internal(connectToSmtp), }; });PublicLayer<T>PublicLayer<T>recursively removes every property markedinternal. Function signatures are preserved. A layer that consumes another layer types its factory argument asPublicLayer<…>:type ModulesLayer = Layer< [Config, Services], Modules, [Config, PublicLayer<Services>, Modules] >;flowchart LR subgraph Services direction TB P[sendEmail] I[connectToSmtp internal] end subgraph Modules M[auth module] end M -->|PublicLayer| P M -. hidden .-x IWho decides
The parent marks a child internal, not the child itself. The child stays reusable:
// conferenceModule return { public: conferencePublicModule(), policy: internal(conferencePolicyModule()), // the parent decides };