everything-dev 1.50.0 → 1.51.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/dist/types.d.mts CHANGED
@@ -379,9 +379,9 @@ declare const BosConfigSchema: z.ZodObject<{
379
379
  type BosConfig = z.infer<typeof BosConfigSchema>;
380
380
  declare const RuntimeConfigSchema: z.ZodObject<{
381
381
  env: z.ZodEnum<{
382
+ development: "development";
382
383
  production: "production";
383
384
  staging: "staging";
384
- development: "development";
385
385
  }>;
386
386
  account: z.ZodString;
387
387
  domain: z.ZodOptional<z.ZodString>;
@@ -508,9 +508,9 @@ declare const RuntimeConfigSchema: z.ZodObject<{
508
508
  type RuntimeConfig = z.infer<typeof RuntimeConfigSchema>;
509
509
  declare const ClientRuntimeConfigSchema: z.ZodObject<{
510
510
  env: z.ZodEnum<{
511
+ development: "development";
511
512
  production: "production";
512
513
  staging: "staging";
513
- development: "development";
514
514
  }>;
515
515
  account: z.ZodString;
516
516
  networkId: z.ZodEnum<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "everything-dev",
3
- "version": "1.50.0",
3
+ "version": "1.51.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=20.11"
@@ -140,7 +140,7 @@
140
140
  "dotenv": "^17.3.1",
141
141
  "effect": "^3.21.0",
142
142
  "execa": "^9.5.2",
143
- "every-plugin": "^2.9.1",
143
+ "every-plugin": "^2.9.2",
144
144
  "glob": "^13.0.6",
145
145
  "gradient-string": "^3.0.0",
146
146
  "ink": "^6.8.0",
@@ -17,17 +17,22 @@ export default createPlugin.withPlugins<PluginsClient>()({
17
17
  secrets: z.object({ /* typed env vars, defaults for dev */ }),
18
18
  context: z.object({ /* per-request context injected by host */ }),
19
19
  contract,
20
- initialize: (config, plugins) => Effect.promise(async () => {
21
- return { db, upvoteService, publisher, auth, plugins };
22
- }),
23
- shutdown: (services) => Effect.promise(async () => { /* cleanup */ }),
24
- createRouter: (services, builder) => ({
20
+ initialize: (config, plugins, tools) =>
21
+ Effect.gen(function* () {
22
+ const registry = yield* tools.buildService(
23
+ RegistryTag,
24
+ RegistryLive.pipe(Layer.provide(DatabaseLive(config.secrets.API_DATABASE_URL))),
25
+ );
26
+ return { registry, publisher, auth: plugins.auth, plugins };
27
+ }),
28
+ shutdown: (deps) => Effect.promise(async () => { /* cleanup */ }),
29
+ createRouter: (deps, builder) => ({
25
30
  ping: builder.ping.handler(async () => ({ status: "ok", timestamp })),
26
31
  }),
27
32
  });
28
33
  ```
29
34
 
30
- Fields: `variables` (public config), `secrets` (private env), `context` (per-request host context), `contract` (oRPC router), `initialize` (startup, returns services), `createRouter` (maps procedures to handlers), `shutdown` (cleanup). `plugins` in `initialize` gives typed factories for all other plugins.
35
+ Fields: `variables` (public config), `secrets` (private env), `context` (per-request host context), `contract` (oRPC router), `initialize` (startup, returns services; third arg `tools` for scoped resources), `createRouter` (maps procedures to handlers), `shutdown` (cleanup). `plugins` in `initialize` gives typed factories for all other plugins. Use `tools.buildService(tag, layer)` for DB-backed services, caches, and other scoped resources.
31
36
 
32
37
  ## oRPC Contract Design
33
38
 
@@ -193,10 +198,11 @@ export function buildPluginContext(c) {
193
198
  The API plugin receives `auth` in `initialize`:
194
199
 
195
200
  ```ts
196
- initialize: (config, plugins) => Effect.promise(async () => {
197
- const { auth, ...restPlugins } = plugins;
198
- return { auth, plugins: restPlugins, ... };
199
- })
201
+ initialize: (config, plugins, _tools) =>
202
+ Effect.gen(function* () {
203
+ const { auth, ...restPlugins } = plugins;
204
+ return { auth, plugins: restPlugins, ... };
205
+ })
200
206
  ```
201
207
 
202
208
  Use `getAuthClient()` for in-process calls:
@@ -279,11 +285,12 @@ const baseApi = await loadPluginEntry(runtime, apiEntry, integrityRegistry, plug
279
285
  The API plugin receives `plugins` in `initialize`:
280
286
 
281
287
  ```ts
282
- initialize: (config, plugins) => Effect.promise(async () => {
283
- const authClient = plugins.auth({ reqHeaders: someHeaders });
284
- const session = await authClient.getSession();
285
- return { auth: plugins.auth, plugins, ... };
286
- })
288
+ initialize: (config, plugins, _tools) =>
289
+ Effect.gen(function* () {
290
+ const authClient = plugins.auth({ reqHeaders: someHeaders });
291
+ const session = await authClient.getSession();
292
+ return { auth: plugins.auth, plugins, ... };
293
+ })
287
294
  ```
288
295
 
289
296
  ### API-Owned Registry Pattern
@@ -309,7 +316,22 @@ import { runEffect } from "@/lib/context";
309
316
  const result = await runEffect(services.myService.doSomething(input));
310
317
  ```
311
318
 
312
- Best practices: Keep service interfaces Effect-native, bridge to async only at the handler boundary via `runEffect()`. Use `Context.Tag` for DI between services. Initialize long-lived resources in `initialize` and return them as services.
319
+ Best practices: Keep service interfaces Effect-native, bridge to async only at the handler boundary via `runEffect()`. Use `Context.Tag` for DI between services.
320
+
321
+ **Scoped resources** — For DB pools, caches, publishers, or any resource that must live for the plugin's lifetime, build them inside `initialize` using `tools.buildService(tag, layer)`. This binds the resource to the plugin lifecycle scope — it persists until plugin shutdown and is automatically released.
322
+
323
+ ```ts
324
+ initialize: (config, plugins, tools) =>
325
+ Effect.gen(function* () {
326
+ const repo = yield* tools.buildService(
327
+ MyRepoTag,
328
+ MyRepoLive.pipe(Layer.provide(DatabaseLive(config.secrets.MY_DATABASE_URL))),
329
+ );
330
+ return { repo, plugins };
331
+ }),
332
+ ```
333
+
334
+ Do **not** use `Effect.provide(Tag, Layer.scoped(...))` inside `initialize` for long-lived resources — it creates a transient scope that closes immediately. `tools.buildService(...)` uses the plugin's lifecycle scope instead.
313
335
 
314
336
  ### SSR Proxy Client
315
337
 
@@ -159,20 +159,23 @@ export default createPlugin.withPlugins<PluginsClient>()({
159
159
 
160
160
  contract,
161
161
 
162
- initialize: (config) =>
162
+ initialize: (config, _plugins, tools) =>
163
163
  Effect.gen(function* () {
164
164
  const service = new TemplateService(config.variables.baseUrl, config.secrets.apiKey, config.variables.timeout);
165
165
  yield* service.ping(); // health check on startup
166
166
 
167
167
  const publisher = new MemoryPublisher({ resumeRetentionSeconds: 120 });
168
168
 
169
+ // For scoped resources (DB pools, caches, repositories):
170
+ // const repo = yield* tools.buildService(MyRepoTag, MyRepoLive.pipe(...))
171
+
169
172
  return { service, publisher };
170
173
  }),
171
174
 
172
175
  shutdown: () => Effect.void,
173
176
 
174
- createRouter: (context, builder) => {
175
- const { service, publisher } = context;
177
+ createRouter: (deps, builder) => {
178
+ const { service, publisher } = deps;
176
179
  const requireAuth = builder.middleware(async ({ context, next }) => {
177
180
  if (!context.userId) throw new ORPCError("UNAUTHORIZED", { message: "User ID required" });
178
181
  return next({ context: { ...context, userId: context.userId } });
@@ -236,7 +239,8 @@ Good practice:
236
239
  **`variables`** — Public config exposed in `bos.config.json` (typed, with defaults).
237
240
  **`secrets`** — Private values from `process.env` (typed, dev defaults).
238
241
  **`context`** — Per-request context injected by the host. See "Request Context Reference" below for all available fields.
239
- **`initialize`** — Effect-based startup. Create services, publishers, DB connections. Return value is passed as `context` to `createRouter`.
242
+ **`initialize`** — Effect-based startup. Create services, publishers, DB connections. Receives an optional third argument `tools` for building scoped resources. Return value is passed as `deps` to `createRouter`.
243
+ **`tools`** — Framework-provided third argument in `initialize(config, plugins, tools)`. Use `tools.buildService(tag, layer)` to build scoped resources (DB pools, caches, repositories) that live for the plugin's lifetime.
240
244
  **`createRouter`** — Maps contract procedures to handlers. Receives the value returned by `initialize` plus a pre-configured `builder`.
241
245
 
242
246
  ## Request Context Reference