@owlmeans/create-app 0.1.18-rc.55 → 0.1.18-rc.56

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/README.md CHANGED
@@ -9,7 +9,7 @@ bun create @owlmeans/app my-app
9
9
  # or
10
10
  yarn create @owlmeans/app my-app
11
11
  # or
12
- npx @owlmeans/create-app@^0.1.18-rc.55 my-app
12
+ npx @owlmeans/create-app@^0.1.18-rc.56 my-app
13
13
  ```
14
14
 
15
15
  ## What it generates
@@ -31,6 +31,13 @@ The web app ships a basic shadcn UI **navigation + layout** and a **Session** sc
31
31
  that creates, lists and removes items held in a **session-scoped in-memory resource**
32
32
  (`@owlmeans/static-resource`) on the backend — no database required.
33
33
 
34
+ Logging goes through [`@owlmeans/log`](https://www.npmjs.com/package/@owlmeans/log), with the level
35
+ set per environment and never in code: the api's `config.ts` reads `LOG_LEVEL` (default `info`) and
36
+ `LOG_DEBUG` from the Bun runtime, the web's reads `VITE_LOG_LEVEL` (default `debug` under `vite`,
37
+ `info` in a build) and `VITE_LOG_DEBUG` at build time. The shared `sources/common` config runs in
38
+ both runtimes, so it sets no level and no `cfg.debug` flag. Local values go in the git-ignored
39
+ `sources/api/.env` / `sources/web/.env`.
40
+
34
41
  By default the scaffolder also installs dependencies and **deploys agent guidance**
35
42
  into the project via [`@owlmeans/agent-skills`](https://www.npmjs.com/package/@owlmeans/agent-skills)
36
43
  (`.agents/skills/`).
package/build/args.js CHANGED
@@ -5,7 +5,7 @@ Usage:
5
5
  npm create @owlmeans/app@latest <dir> [options]
6
6
  bun create @owlmeans/app <dir> [options]
7
7
  yarn create @owlmeans/app <dir> [options]
8
- npx @owlmeans/create-app@^0.1.18-rc.55 <dir> [options]
8
+ npx @owlmeans/create-app@^0.1.18-rc.56 <dir> [options]
9
9
 
10
10
  Generates three workspaces (common + api + web) with shadcn UI navigation and
11
11
  layout, no authentication, and a session-scoped in-memory resource on the
package/build/bin.js CHANGED
File without changes
package/build/run.js CHANGED
@@ -50,7 +50,7 @@ export const run = async (args) => {
50
50
  log(args.install
51
51
  ? '\nDeploying agent skills via @owlmeans/agent-skills…'
52
52
  : '\nDeploying harness guidance via @owlmeans/agent-skills (general skills only — re-run'
53
- + '\n`npx @owlmeans/agent-skills@^0.1.18-rc.46` after installing to add the package-specific ones)…');
53
+ + '\n`npx @owlmeans/agent-skills@^0.1.18-rc.47` after installing to add the package-specific ones)…');
54
54
  try {
55
55
  const result = await installSkills({
56
56
  dir: dest,
@@ -62,7 +62,7 @@ export const run = async (args) => {
62
62
  help: false,
63
63
  });
64
64
  if (result.code !== 0) {
65
- process.stderr.write(` agent-skills exited with code ${result.code} — you can re-run \`npx @owlmeans/agent-skills@^0.1.18-rc.46\` later.\n`);
65
+ process.stderr.write(` agent-skills exited with code ${result.code} — you can re-run \`npx @owlmeans/agent-skills@^0.1.18-rc.47\` later.\n`);
66
66
  }
67
67
  }
68
68
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/create-app",
3
- "version": "0.1.18-rc.55",
3
+ "version": "0.1.18-rc.56",
4
4
  "license": "MIT",
5
5
  "description": "Scaffold a fullstack OwlMeans Common app — common + api + web workspaces, shadcn UI navigation/layout, no auth, and a session-scoped in-memory resource, or --bare for the demo-free shell. Also usable programmatically via scaffold(). Deploys agent skills via @owlmeans/agent-skills by default.",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "template"
31
31
  ],
32
32
  "dependencies": {
33
- "@owlmeans/agent-skills": "^0.1.18-rc.46"
33
+ "@owlmeans/agent-skills": "^0.1.18-rc.47"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@owlmeans/dep-config": "workspace:*",
@@ -87,6 +87,17 @@ package that owns its browser consumer imports `apiConfigPlugin({ allow, deny? }
87
87
  nested `deny` selector when a public collection carries a credential. Databases, queues, SMTP,
88
88
  tokens, secrets and internal addresses never belong in an `allow` selector.
89
89
 
90
+ ## Logging (mandatory)
91
+
92
+ Before adding any log line, catch block or `console` call, follow the `logging` skill (mechanics: `log`).
93
+
94
+ - No `console.*`: `const log = logger('<scope>')` from `@owlmeans/log`, a deliberate level, the
95
+ `Error` itself to `log.error`; never secrets, tokens or personal content.
96
+ - The level is set per environment, never in code: the api reads `LOG_LEVEL` / `LOG_DEBUG`
97
+ (default `info`), the web build reads `VITE_LOG_LEVEL` / `VITE_LOG_DEBUG` (`debug` under `vite`,
98
+ `info` in a build). Local values go in the git-ignored `sources/api/.env` / `sources/web/.env`.
99
+ - Never set `cfg.debug = { all: true }` — it does not control logging and must not reach production.
100
+
90
101
  ## Skills
91
102
 
92
103
  Reusable guidance lives in `.agents/skills/<name>/SKILL.md`, deployed by `@owlmeans/agent-skills`
@@ -94,8 +105,9 @@ from the installed `@owlmeans/*` packages. Agents load a skill by topic, or you
94
105
  explicitly. Copilot and Codex read `.agents/skills/` directly; Claude Code reads the generated
95
106
  symlinks in `.claude/skills/` (see "Claude Code" below).
96
107
 
97
- - After adding or updating any `@owlmeans/*` dependency, run `npx @owlmeans/agent-skills@^0.1.18-rc.46` to refresh
108
+ - After adding or updating any `@owlmeans/*` dependency, run `npx @owlmeans/agent-skills@^0.1.18-rc.47` to refresh
98
109
  the deployed skills.
110
+ - `/logging` — before adding any log line, catch block or `console` call (mechanics: `/log`).
99
111
  - Deployed files carry an `AUTO-GENERATED` banner and are refreshed in place — never hand-edit them.
100
112
  - To capture your own guidance, see the `skill-authoring` skill; to turn repeatedly-used memory into
101
113
  a skill, `memory-promotion`. Keep it inside this repository, in `.agents/skills/` — never in a
@@ -29,6 +29,19 @@ bun run dev
29
29
  > `sources/common/src/config.ts`). If you edit `sources/common`, restart `bun run dev` to
30
30
  > rebuild it before the API and web pick up the changes.
31
31
 
32
+ ## Logging
33
+
34
+ Log through `@owlmeans/log` (`const log = logger('<scope>')`), never `console.*`. The level is set
35
+ per environment, not in code:
36
+
37
+ | Runtime | Variables | Default |
38
+ |---|---|---|
39
+ | api (`sources/api/src/config.ts`) | `LOG_LEVEL`, `LOG_DEBUG` | `info` |
40
+ | web (`sources/web/src/config.ts`, build time) | `VITE_LOG_LEVEL`, `VITE_LOG_DEBUG` | `debug` under `vite`, `info` in a build |
41
+
42
+ `*_DEBUG` lists scopes forced to debug (`*` for all). Local values go in `sources/api/.env` /
43
+ `sources/web/.env` (git-ignored).
44
+
32
45
  ## Adding your first feature
33
46
 
34
47
  1. **`sources/common/src/entrypoints.ts`** — declare the route as an OwlMeans *entrypoint* and
@@ -53,5 +66,5 @@ them; write your own guidance as separate, un-bannered files. Refresh after addi
53
66
  `@owlmeans/*` packages:
54
67
 
55
68
  ```sh
56
- npx @owlmeans/agent-skills@^0.1.18-rc.46
69
+ npx @owlmeans/agent-skills@^0.1.18-rc.47
57
70
  ```
@@ -7,3 +7,8 @@ An OwlMeans application has shared protocol declarations in `sources/common`, se
7
7
  and gates are declared once in common; runtime packages bind them without changing the declaration.
8
8
 
9
9
  Use `bun run build` from the project root to build every workspace.
10
+
11
+ Logging goes through `@owlmeans/log`. The api's level comes from `LOG_LEVEL` (default `info`) and
12
+ `LOG_DEBUG` (scopes forced to debug, `*` for all); the web build's from `VITE_LOG_LEVEL` (default
13
+ `debug` under `vite`, `info` in a build) and `VITE_LOG_DEBUG`. Put local values in
14
+ `sources/api/.env` / `sources/web/.env` (git-ignored).
@@ -43,3 +43,22 @@ const sessions = await context.entrypoint(sessionProtocols.list).call({ query: {
43
43
  Use `schema<T>(...)` or `typed<T>(...)` at the contract boundary. Bind all route parents with their
44
44
  children. Keep organization entity values on the wire as `entitySlug`; database relations use
45
45
  `entityId` only.
46
+
47
+ ## Configuration per runtime
48
+
49
+ The shared config in `common` (services, alias, security) is imported by both runtimes, so it
50
+ never reads `process.env` or `import.meta.env`, and it never sets `cfg.debug = { all: true }`.
51
+ Each runtime's own `config.ts` adds what depends on its environment — the log level above all
52
+ (`logging`, `log`), behind a type-only `import type {} from '@owlmeans/log'`:
53
+
54
+ ```ts
55
+ // api/src/config.ts — Bun runtime env
56
+ cfg.log = { level: process.env.LOG_LEVEL || 'info', debug: process.env.LOG_DEBUG ?? '' }
57
+
58
+ // web/src/config.ts — Vite build-time env, typed in vite-env.d.ts
59
+ const env = import.meta.env
60
+ cfg.log = { level: env.VITE_LOG_LEVEL || (env.PROD ? 'info' : 'debug'), debug: env.VITE_LOG_DEBUG ?? '' }
61
+ ```
62
+
63
+ The server and client contexts apply `cfg.log` themselves; application code logs through
64
+ `logger('<scope>')` from `@owlmeans/log`, never `console.*`.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: logging
3
+ description: Logging policy for any OwlMeans application — no bare console calls; every line through @owlmeans/log with a scope and a deliberate level; what belongs at info vs debug; never log secrets or personal content; debug off in production, with the level set per environment (a server's config file, a browser's build-time env); analytics events as a call option routed to plugins. Use when adding any log line or a catch block, debugging with prints, deciding what an operator should see in production, setting a log level for an environment, or reviewing code that calls console.
4
+ user-invocable: false
5
+ metadata:
6
+ scope: general
7
+ ---
8
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
9
+
10
+ # Logging — the policy
11
+
12
+ The mechanics are the `log` skill (`@owlmeans/log`). This is what to do in application code.
13
+
14
+ 1. **No `console.*`.** `import { logger } from '@owlmeans/log'`, `const log = logger('<scope>')` once per
15
+ module, then `log.debug|info|warn|error(message, data?, options?)`. A scope is lowercase and
16
+ colon-separated (`orders`, `orders:import`).
17
+ 2. **Choose the level on purpose.** `debug` is for diagnosis (per request, progress, dumps) — it is OFF
18
+ in production. `info` is what an operator wants to read in production: a job started or stopped, a
19
+ subscription or payment event, a sign-in, a server listening. `warn`: it degraded and went on.
20
+ `error`: the work failed. A line that fires every few seconds is `debug` or `logThrottle`d.
21
+ 3. **Stable message, variable data.** `log.info('Order shipped', { orderId, carrier })` — not a
22
+ sentence assembled from values. Give a significant event a dotted name: `{ event: 'order.shipped' }`.
23
+ 4. **Pass the `Error`.** `log.error('Import failed', error)` — never `error.message` alone, never
24
+ `JSON.stringify(error)`. In a browser the `Error` object must reach `console.error`; the logger does
25
+ that, and an error reporter hooked there keeps working.
26
+ 5. **Never log secrets or personal content**: tokens, keys, passwords, authorization or cookie headers,
27
+ request or response bodies, user text, file contents, environment values. Log ids, names, sizes,
28
+ counts. A catch that only logs has not told the user anything — the user-facing report is a separate
29
+ step (a message, a state), and `log.error` is the operator's record.
30
+ 6. **Analytics are a parameter, not a second API.** `log.info('…', data, { analytics: 'event_name' })`
31
+ hands the call to the registered analytics plugins (`@owlmeans/web-log` for a tag manager); add
32
+ `console: false` to keep it out of the log. Only for events something should count.
33
+ 7. **The level is set per environment, never in code.** A server declares `cfg.log` leaves as config
34
+ file paths (a ConfigMap or a `LOG_LEVEL` environment variable); a browser takes a build-time
35
+ constant (`VITE_LOG_LEVEL`). Development defaults to `debug`, a production build to `info`. Do not
36
+ hard-code `cfg.debug = { all: true }` — `debug.all` does not control logging and must not be on in
37
+ production.
38
+ 8. **Tests read the log with `memoryPlugin()`**; they do not spy on `console`.
@@ -47,7 +47,7 @@ How you research the repo depends on whether `@owlmeans/*` is linked locally:
47
47
  **https://github.com/owlmeans/common** — `tree.md` and package READMEs — to find the right package.
48
48
 
49
49
  This is the same dev-linked detection `@owlmeans/agent-skills` uses (see its `detectLinked`). After
50
- adding an `@owlmeans/*` dependency, run `npx @owlmeans/agent-skills@^0.1.18-rc.46` to deploy its
50
+ adding an `@owlmeans/*` dependency, run `npx @owlmeans/agent-skills@^0.1.18-rc.47` to deploy its
51
51
  skill. Prefer an `@owlmeans/*` package over a third-party library or bespoke code whenever one fits.
52
52
 
53
53
  ### Never add an OwlMeans dependency without an explicit range
@@ -6,6 +6,11 @@ dist
6
6
  bun.lock
7
7
  bun.lockb
8
8
 
9
+ # Developer-local environment (LOG_LEVEL, VITE_LOG_LEVEL, …)
10
+ .env
11
+ .env.local
12
+ .env.*.local
13
+
9
14
  # Generated Claude Code skill symlinks (canonical skills live in .agents/skills/)
10
15
  .claude/skills/*
11
16
  !.claude/skills/.gitkeep
@@ -11,8 +11,9 @@
11
11
  "typecheck": "tsc -b"
12
12
  },
13
13
  "dependencies": {
14
- "@owlmeans/server-app": "^0.1.18-rc.49",
15
- "@owlmeans/static-resource": "^0.1.18-rc.36",
14
+ "@owlmeans/log": "^0.1.18-rc.0",
15
+ "@owlmeans/server-app": "^0.1.18-rc.50",
16
+ "@owlmeans/static-resource": "^0.1.18-rc.37",
16
17
  "__APP_SLUG__-common": "workspace:^"
17
18
  },
18
19
  "devDependencies": {
@@ -1,8 +1,15 @@
1
1
  import { config } from '@owlmeans/server-app'
2
2
  import { APP_API, commonConfig } from '__APP_SLUG__-common'
3
3
  import type { Config } from './types.js'
4
+ // The module augmentation that gives the config its `log` field — a side-effect import only.
5
+ import type {} from '@owlmeans/log'
4
6
 
5
7
  // The server listens on the APP_API service route's port (3000), declared in common/config.ts.
6
8
  const cfg = config<Config>(APP_API, commonConfig as Config)
7
9
 
10
+ // The log level comes from the runtime environment, never from code: `info` unless LOG_LEVEL
11
+ // says otherwise; LOG_DEBUG lists scopes forced to debug (`*` for all). Bun reads
12
+ // `sources/api/.env` on its own.
13
+ cfg.log = { level: process.env.LOG_LEVEL || 'info', debug: process.env.LOG_DEBUG ?? '' }
14
+
8
15
  export default cfg
@@ -1,9 +1,15 @@
1
+ import { logger } from '@owlmeans/log'
1
2
  import { main } from '@owlmeans/server-app'
2
3
  import config from './config.js'
3
4
  import { makeContext } from './context.js'
4
5
  import { appBindings } from './entrypoints.js'
5
6
  import type { Config, Context } from './types.js'
6
7
 
8
+ const log = logger('api')
9
+
7
10
  const context = makeContext<Config, Context>(config)
8
11
 
9
- main<{}, Config, Context>(context, appBindings)
12
+ main<{}, Config, Context>(context, appBindings).catch(error => {
13
+ log.error('Start failed', error)
14
+ process.exit(1)
15
+ })
@@ -19,10 +19,10 @@
19
19
  "typecheck": "tsc -b"
20
20
  },
21
21
  "dependencies": {
22
- "@owlmeans/config": "^0.1.18-rc.41",
22
+ "@owlmeans/config": "^0.1.18-rc.42",
23
23
  "@owlmeans/entrypoint": "^0.1.18-rc.39",
24
24
  "@owlmeans/error": "^0.1.18-rc.36",
25
- "@owlmeans/resource": "^0.1.18-rc.37",
25
+ "@owlmeans/resource": "^0.1.18-rc.38",
26
26
  "@owlmeans/route": "^0.1.18-rc.33",
27
27
  "ajv": "^8.17.1"
28
28
  },
@@ -18,7 +18,8 @@ service({
18
18
  base: 'api',
19
19
  }, cfg)
20
20
 
21
- cfg.debug = { all: true }
21
+ // No log level here: this file runs in Bun AND in the browser, so each runtime's own config.ts
22
+ // sets `cfg.log` from its environment (api: LOG_LEVEL / LOG_DEBUG, web: VITE_LOG_LEVEL / VITE_LOG_DEBUG).
22
23
  cfg.alias = APP
23
24
  // Local dev serves the API over plain HTTP. Without this the web client builds https:// URLs
24
25
  // and every call fails. In production put the API behind TLS and remove this line.
@@ -11,16 +11,17 @@
11
11
  "preview": "vite preview"
12
12
  },
13
13
  "dependencies": {
14
- "@owlmeans/client": "^0.1.18-rc.48",
15
- "@owlmeans/client-config": "^0.1.18-rc.41",
16
- "@owlmeans/client-context": "^0.1.18-rc.45",
17
- "@owlmeans/client-entrypoint": "^0.1.18-rc.44",
18
- "@owlmeans/client-i18n": "^0.1.18-rc.47",
14
+ "@owlmeans/client": "^0.1.18-rc.49",
15
+ "@owlmeans/client-config": "^0.1.18-rc.42",
16
+ "@owlmeans/client-context": "^0.1.18-rc.46",
17
+ "@owlmeans/client-entrypoint": "^0.1.18-rc.45",
18
+ "@owlmeans/client-i18n": "^0.1.18-rc.48",
19
19
  "@owlmeans/entrypoint": "^0.1.18-rc.39",
20
+ "@owlmeans/log": "^0.1.18-rc.0",
20
21
  "@owlmeans/route": "^0.1.18-rc.33",
21
- "@owlmeans/state": "^0.1.18-rc.36",
22
- "@owlmeans/web-client": "^0.1.18-rc.58",
23
- "@owlmeans/web-panel": "^0.1.18-rc.68",
22
+ "@owlmeans/state": "^0.1.18-rc.37",
23
+ "@owlmeans/web-client": "^0.1.18-rc.59",
24
+ "@owlmeans/web-panel": "^0.1.18-rc.69",
24
25
  "@radix-ui/react-label": "^2.1.0",
25
26
  "@radix-ui/react-navigation-menu": "^1.2.14",
26
27
  "@radix-ui/react-progress": "^1.1.0",
@@ -1,7 +1,15 @@
1
1
  import { config } from '@owlmeans/web-panel'
2
2
  import { APP_WEB, commonConfig } from '__APP_SLUG__-common'
3
3
  import type { Config } from './types.js'
4
+ // The module augmentation that gives the config its `log` field — a side-effect import only.
5
+ import type {} from '@owlmeans/log'
4
6
 
5
7
  const cfg: Config = config(APP_WEB, commonConfig as Config)
6
8
 
9
+ // The log level is decided at BUILD time (the logger is configured before the first render):
10
+ // `debug` under `vite`, `info` in a production build, unless `sources/web/.env` sets
11
+ // VITE_LOG_LEVEL; VITE_LOG_DEBUG lists scopes forced to debug (`*` for all).
12
+ const env = import.meta.env
13
+ cfg.log = { level: env.VITE_LOG_LEVEL || (env.PROD ? 'info' : 'debug'), debug: env.VITE_LOG_DEBUG ?? '' }
14
+
7
15
  export default cfg
@@ -1 +1,8 @@
1
1
  /// <reference types="vite/client" />
2
+
3
+ interface ImportMetaEnv {
4
+ /** `debug` | `info` | `warn` | `error` | `silent`. Default: `debug` under `vite`, `info` in a build. */
5
+ readonly VITE_LOG_LEVEL?: string
6
+ /** Scopes forced to debug whatever the level is, e.g. `session,i18n` or `*`. */
7
+ readonly VITE_LOG_DEBUG?: string
8
+ }