Status: π LOCKED FOR v1.0 Last Updated: November 2024
This document defines the stable, public API surface for PAN v1.0. All items marked as STABLE are guaranteed not to have breaking changes in v1.x releases. Breaking changes require a major version bump (v2.0).
STABLE - Constructor signature locked for v1.0
new PanClient(host?: HTMLElement|Document, busSelector?: string)
Parameters:
host (optional) - Element to dispatch/receive events from. Default: documentbusSelector (optional) - CSS selector for bus element. Default: 'pan-bus'Guarantees:
STABLE - Method signature locked for v1.0
client.ready(): Promise<void>
Returns: Promise that resolves when PAN bus is ready
Guarantees:
pan:sys.readyExample:
const client = new PanClient();
await client.ready();
// Bus is now ready for use
STABLE - Method signature locked for v1.0
client.publish(message: PanMessage): void
Parameters:
message - PanMessage object with required topic and data fieldsRequired fields:
message.topic (string) - Topic namemessage.data (any) - Message payloadOptional fields:
message.retain (boolean) - If true, message is retainedmessage.replyTo (string) - Topic to send reply tomessage.correlationId (string) - Correlation ID for request/replymessage.headers (object) - Optional metadataGuarantees:
Example:
// Simple publish
client.publish({
topic: 'users.updated',
data: { id: 123, name: 'Alice' }
});
// Retained message
client.publish({
topic: 'app.state',
data: { theme: 'dark' },
retain: true
});
STABLE - Method signature locked for v1.0
client.subscribe(
topics: string | string[],
handler: (message: PanMessage) => void,
options?: SubscribeOptions
): UnsubscribeFunction
Parameters:
topics - Topic pattern(s) to subscribe to (string or array)handler - Callback function receiving PanMessageoptions (optional) - Subscription optionsSubscribeOptions:
retained (boolean) - If true, receive retained messages immediatelysignal (AbortSignal) - AbortSignal for automatic cleanupReturns: Unsubscribe function () => void
Guarantees:
*) as documentedExample:
// Subscribe to single topic
const unsub = client.subscribe('users.updated', (msg) => {
console.log('User updated:', msg.data);
});
// Subscribe to multiple topics with wildcard
client.subscribe(['users.*', 'posts.*'], (msg) => {
console.log('Received:', msg.topic, msg.data);
});
// With retained messages
client.subscribe('app.state', (msg) => {
console.log('Current state:', msg.data);
}, { retained: true });
// With AbortSignal
const controller = new AbortController();
client.subscribe('events.*', handler, { signal: controller.signal });
// Later: controller.abort(); // Unsubscribes automatically
STABLE - Method signature locked for v1.0
client.request(
topic: string,
data: any,
options?: RequestOptions
): Promise<PanMessage>
Parameters:
topic - Request topic namedata - Request payloadoptions (optional) - Request optionsRequestOptions:
timeoutMs (number) - Request timeout in milliseconds. Default: 5000Returns: Promise
Throws: Error if request times out
Guarantees:
Example:
// Simple request
try {
const response = await client.request('users.get', { id: 123 });
console.log('User:', response.data);
} catch (err) {
console.error('Request failed:', err);
}
// Custom timeout
const response = await client.request('slow.operation', { ... }, {
timeoutMs: 10000 // 10 second timeout
});
STABLE - Static method signature locked for v1.0
PanClient.matches(topic: string, pattern: string): boolean
Parameters:
topic - Topic to test (e.g., βusers.list.stateβ)pattern - Pattern to match (e.g., βusers.β or ββ)Returns: boolean - true if topic matches pattern
Guarantees:
* matches any topicPattern Rules:
users.list.state matches users.list.stateusers.* matches users.list but NOT users.list.state* matches any topicExample:
PanClient.matches('users.list.state', 'users.*') // true
PanClient.matches('users.list.state', 'users.list.state') // true
PanClient.matches('users.list.state', '*') // true
PanClient.matches('users.list.state', 'posts.*') // false
PanClient.matches('users.item.123', 'users.item.*') // true
STABLE - Message envelope format locked for v1.0
interface PanMessage {
topic: string; // Topic name (e.g., "users.list.state")
data: any; // Message payload (any JSON-serializable value)
// Optional fields - auto-generated by bus if not provided
id?: string; // Unique message ID (UUID)
ts?: number; // Timestamp in milliseconds (epoch)
// Optional fields - for message features
retain?: boolean; // If true, message is retained by bus
replyTo?: string; // Topic to send reply to
correlationId?: string; // Correlation ID for request/reply
headers?: Record<string, string>; // Optional metadata
}
topic (required)
data (required)
id (optional)
ts (optional)
retain (optional)
replyTo (optional)
correlationId (optional)
client.request() if not providedheaders (optional)
STABLE - CustomEvent names and signatures locked for v1.0
All PAN CustomEvents use bubbles: true, composed: true to cross shadow DOM boundaries.
Purpose: Signal that PAN bus is ready
new CustomEvent('pan:sys.ready', {
bubbles: true,
composed: true
})
Guarantees:
Purpose: Publish a message to the bus
new CustomEvent('pan:publish', {
detail: PanMessage,
bubbles: true,
composed: true
})
Guarantees:
detail is PanMessage objectPurpose: Subscribe to topics
new CustomEvent('pan:subscribe', {
detail: {
clientId: string,
topics: string[],
options?: { retained?: boolean }
},
bubbles: true,
composed: true
})
Guarantees:
detail.topics is array of topic patternsdetail.options.retained enables retained message deliveryPurpose: Unsubscribe from topics
new CustomEvent('pan:unsubscribe', {
detail: {
clientId: string,
topics: string[]
},
bubbles: true,
composed: true
})
Guarantees:
detail.topics is array of topic patternsPurpose: Deliver message from bus to subscriber
new CustomEvent('pan:deliver', {
detail: PanMessage,
bubbles: false,
composed: false
})
Guarantees:
detail is full PanMessage objectPurpose: Client announces presence to bus
new CustomEvent('pan:hello', {
detail: {
id: string,
caps?: string[]
},
bubbles: true,
composed: true
})
Guarantees:
detail.id is client identifierdetail.caps is optional capabilities arrayLOCKED: The following event name pattern is reserved for PAN:
pan:* - All events starting with pan: are reservedpan:sys.* - System-level eventspan:ext.* - Reserved for extensions/pluginsGuarantees:
pan:* eventspan:* namespacepan:* events MAY be added in v1.x (non-breaking if properly ignored)STABLE - Core conventions locked for v1.0
Standard Format: resource.action.qualifier
Examples:
users.list.state - List of users (retained state)users.item.get - Get single user (request)users.item.save - Save user (request)nav.goto - Navigate to route (command)Guarantees:
Single Segment Wildcard: *
Rules:
users.* matches users.list but NOT users.list.state* matches any single topicusers.*.state, *.item.getGuarantees:
* always matches single segment only**) NOT supported in v1.0LOCKED - Reserved for PAN internals
pan:* - Internal bus communication (system events)pan:$reply:* - Generated reply topics for request/replyGuarantees:
pan:* topicspan:$reply:* topics are auto-generated by client.request()Status: RECOMMENDED (not enforced)
These are conventions, not requirements. Applications MAY use different patterns.
List Operations:
${resource}.list.get - Request list (responds with { items })${resource}.list.state - List state (retained)Item Operations:
${resource}.item.select - Select item (no reply, event only)${resource}.item.get - Get item by ID (request/reply)${resource}.item.save - Save item (request/reply)${resource}.item.delete - Delete item (request/reply)${resource}.item.state.${id} - Per-item state (retained)Examples:
// List users
const response = await client.request('users.list.get', {});
console.log(response.data.items);
// Subscribe to list state
client.subscribe('users.list.state', (msg) => {
console.log('User list:', msg.data.items);
}, { retained: true });
// Get single user
const user = await client.request('users.item.get', { id: 123 });
// Save user
await client.request('users.item.save', { item: { id: 123, name: 'Alice' } });
// Select user (no reply)
client.publish({ topic: 'users.item.select', data: { id: 123 } });
Guarantees:
PAN follows Semantic Versioning 2.0.0
Example: v1.2.3
PanClient API:
PanMessage Format:
CustomEvents:
Topic Conventions:
Allowed in MINOR versions:
Allowed in PATCH versions:
When removing features, we follow this timeline:
Minimum Deprecation Period: 2 MINOR versions or 6 months (whichever is longer)
β PanClient API
constructor, ready(), publish(), subscribe(), request(), matches()β PanMessage Format
topic, data, id, ts, retain, replyTo, correlationId, headersβ CustomEvents
pan:sys.ready, pan:publish, pan:subscribe, pan:unsubscribe, pan:deliver, pan:helloβ Topic Matching
* matching single segmentβ Reserved Namespaces
pan:* for internal usepan:$reply:* for request/replyβ οΈ Internal Implementation
_)β οΈ CRUD Conventions
β οΈ Error Messages
π§ͺ None in v1.0
All APIs in v1.0 are either STABLE or documented as UNSTABLE. No experimental features at release.
When v2.0 is released, a comprehensive migration guide will be provided covering:
This document is LOCKED for v1.0 release. Changes require:
Last Review: November 2024 Next Review: Before v1.1.0 release
End of API Stability Contract