From 5c7aa416e4d2388eb43dc9ecd9661953740c22a3 Mon Sep 17 00:00:00 2001 From: Ricardo Devis Agullo Date: Mon, 10 Aug 2026 19:13:16 +0200 Subject: [PATCH] Document CORS config, promise plugins/adapters, and legacy template warning Reflects several recently merged oc registry PRs that weren't yet covered by the docs site: - Configurable `cors` registry option (origin/credentials/allowedHeaders/ methods), including a new example and defaults table entries (opencomponents/oc#1545). - Plugins' `register` can now return a Promise instead of using the `next()` callback; callback style remains supported with a deprecation warning (opencomponents/oc#1542). - HTTP server adapters (Express/Fastify) support a promise-based `listen()`/`close()` lifecycle via `supportsPromiseLifecycle`, alongside the deprecated callback form (opencomponents/oc#1544). - The registry `error` event's `code` is now the adapter-neutral `SERVER_ERROR` instead of `EXPRESS_ERROR` (opencomponents/oc#1547). - `oc init` emits a one-time deprecation warning when given the bare `jade`/`handlebars` template names, pointing to `oc-template-es6` (opencomponents/oc#1546). opencomponents/oc#1543 (isolating deferred plugin loads across concurrent registries) is an internal correctness fix with no user-facing config or API change, so it isn't documented here. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- website/docs/building/cli.md | 9 +++ .../docs/registry/registry-configuration.md | 65 ++++++++++++++++++- .../docs/registry/registry-server-adapters.md | 20 ++++++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/website/docs/building/cli.md b/website/docs/building/cli.md index ea1b972..44788db 100644 --- a/website/docs/building/cli.md +++ b/website/docs/building/cli.md @@ -248,6 +248,15 @@ $ oc init components/test-component oc-template-es6 which will create `test-component` in `components` directory. +:::caution Deprecated bare template names +Passing the bare legacy names `jade` or `handlebars` as `templateType` (e.g. +`oc init my-component jade`) still works — they resolve to +`oc-template-jade` / `oc-template-handlebars` as before — but now emits a +one-time deprecation warning pointing you to the modern ESM component +runtime, `oc-template-es6`. Explicitly passing `oc-template-jade` or +`oc-template-handlebars` is unaffected and stays silent. +::: + --- ### mock diff --git a/website/docs/registry/registry-configuration.md b/website/docs/registry/registry-configuration.md index 6a4f292..a3db6b2 100644 --- a/website/docs/registry/registry-configuration.md +++ b/website/docs/registry/registry-configuration.md @@ -181,6 +181,11 @@ For unsuscribing to all [events](#registry-events). | routes[].method | string | yes\* | - | HTTP method for the route (e.g. "get", "post") (\*required for each route) | | routes[].handler | function | yes\* | - | Express-compatible handler function for the route (\*required for each route) | | plugins | object | no | `{}` | Collection of plugins initialized for this registry instance. Populated via `registry.register(...)` | +| cors | object | no | - | Configures the CORS headers sent by the registry. Omit to keep the existing default headers unchanged (see [CORS configuration](#cors-configuration)) | +| cors.origin | string | no | `"*"` | Value sent as `Access-Control-Allow-Origin` | +| cors.credentials | boolean | no | `true` | When `true`, sends `Access-Control-Allow-Credentials: true`. When `false`, the header is omitted | +| cors.allowedHeaders | string or array | no | `"Origin, X-Requested-With, Content-Type, Accept, traceparent"` | Value sent as `Access-Control-Allow-Headers`. An array is joined with `, ` | +| cors.methods | string or array | no | `"GET, OPTIONS, PUT, POST"` | Value sent as `Access-Control-Allow-Methods`. An array is joined with `, ` | ## Configuration Examples @@ -287,6 +292,36 @@ var registry = new oc.Registry(configuration); registry.start(); ``` +### CORS Configuration + +`cors` is fully optional; omitting it keeps the registry's existing default headers (`Access-Control-Allow-Origin: *`, credentials enabled, and the current allowed headers/methods) exactly as before: + +```js +var oc = require("oc"); + +var configuration = { + baseUrl: "https://components.mycompany.com/", + port: 3000, + cors: { + origin: "https://www.mycompany.com", + credentials: false, + allowedHeaders: ["Origin", "Content-Type", "Accept"], + methods: ["GET", "OPTIONS"], + }, + s3: { + bucket: "my-components-bucket", + region: "us-east-1", + componentsDir: "components", + path: "//s3.amazonaws.com/my-components-bucket/", + }, +}; + +var registry = new oc.Registry(configuration); +registry.start(); +``` + +`allowedHeaders` and `methods` accept either a comma-separated string or an array of strings (joined with `, ` for you). Invalid values (e.g. a non-string `origin`, or a non-boolean `credentials`) fail registry startup with a configuration error rather than being silently ignored. + ### Local Development Configuration Prefer `oc dev` over hand-rolling this. The CLI starts a registry with `local: true` and the right defaults for day-to-day component work. @@ -441,10 +476,14 @@ options.routes = [ | ------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | cache-poll | object | Fired when the components list is refreshed. The callback data contains the last edit unix utc timestamp. | | component-retrieved | object | Fired when the component is retrieved. This includes the component's validation, data gathering and execution, view retrieving, and (when requested) rendering. The callback data contains the duration, component details, and, in case, the error details. | -| error | object | Fired when an internal operation errors. | +| error | `{ code, message }` | Fired when an internal operation errors, e.g. an HTTP server adapter failure. `code` is a stable, adapter-neutral category — server adapter errors use `SERVER_ERROR` regardless of whether the registry runs on Express, Fastify, or another adapter. `message` is the original error message. | | request | object | Fired every time the registry receives a request. The callback data contains some request and response details. | | start | undefined | Fired when the registry starts | +:::note +The `error` event's `code` used to be the transport-specific `EXPRESS_ERROR`. It is now the adapter-neutral `SERVER_ERROR`; the `{ code, message }` shape and the original error message are unchanged. +::: + ## Plugins Plugins are a way to extend registry's context allowing components to inherit custom functionalities. They can be configured to receive component context information (name and version) when needed for enhanced security and decision-making capabilities. @@ -453,13 +492,13 @@ Plugins are a way to extend registry's context allowing components to inherit cu A plugin consists of two main parts: -- **register**: Function called during plugin initialization +- **register**: Function called during plugin initialization. It can either call the `next(err)` callback (legacy style) or return a `Promise` that resolves on success and rejects on failure — both are fully supported - **execute**: Function that provides the actual plugin functionality - **context** (optional): Boolean flag to enable component context awareness ### Basic Plugin Example -This is a basic plugin example without context awareness: +This is a basic plugin example without context awareness, using the callback style: ```js // ./registry/oc-plugins/hobknob.js @@ -478,6 +517,26 @@ module.exports.execute = function (featureName) { }; ``` +`register` can also return a `Promise` instead of calling `next`, which is convenient when the setup logic is `async`: + +```js +// ./registry/oc-plugins/hobknob.js +var connection; +var client = require("./hobknob-client"); + +module.exports.register = async function (options, dependencies) { + connection = await client.connect(options.connectionString); +}; + +module.exports.execute = function (featureName) { + return connection.get(featureName); +}; +``` + +:::note +Callback-style `register(options, dependencies, next)` still works and remains fully supported; it emits a one-time deprecation warning and will be removed in OpenComponents v1. +::: + ### Context-Aware Plugin Example When you need to make decisions based on which component is calling the plugin, you can enable context awareness: diff --git a/website/docs/registry/registry-server-adapters.md b/website/docs/registry/registry-server-adapters.md index 722a1dd..8de2893 100644 --- a/website/docs/registry/registry-server-adapters.md +++ b/website/docs/registry/registry-server-adapters.md @@ -128,3 +128,23 @@ built-in adapters (route registration, body parsing, cookies, file uploads, request timing, logging, error handling, listen/close, etc.), and pass it as `server.adapter`. Look at `oc-fastify-server-adapter`'s source for a complete reference implementation. + +### Adapter lifecycle: `listen()` / `close()` + +Both the built-in Express adapter and `oc-fastify-server-adapter` support a +promise-based lifecycle in addition to the original callback style: + +```ts +listen(opts: HttpServerListenOptions): Promise; +listen(opts: HttpServerListenOptions, cb: (err?: Error) => void): void; +close(): Promise; +close(cb: (err?: Error) => void): void; +``` + +An adapter opts into the promise form by setting `supportsPromiseLifecycle: true`; +the registry calls `listen()`/`close()` without a callback in that case and +awaits the returned promise. Adapters that only implement the callback form +keep working unchanged — `registry.start()`/`registry.close()` wrap them in a +promise automatically — but calling `listen`/`close` directly with a callback +now emits a one-time deprecation warning, since the callback form will be +removed in OpenComponents v1.