@velarscript/cli 0.11.0 → 0.12.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.
Files changed (78) hide show
  1. package/README.md +15 -10
  2. package/dist/cli.js +147 -41
  3. package/dist/cli.js.map +1 -1
  4. package/dist/deployment-verifier.d.ts.map +1 -1
  5. package/dist/deployment-verifier.js +1 -3
  6. package/dist/deployment-verifier.js.map +1 -1
  7. package/dist/extension-metadata.d.ts.map +1 -1
  8. package/dist/extension-metadata.js +1 -0
  9. package/dist/extension-metadata.js.map +1 -1
  10. package/dist/language-server-tool.d.ts +0 -1
  11. package/dist/language-server-tool.d.ts.map +1 -1
  12. package/dist/language-server-tool.js +0 -4
  13. package/dist/language-server-tool.js.map +1 -1
  14. package/dist/node-application.d.ts +13 -0
  15. package/dist/node-application.d.ts.map +1 -0
  16. package/dist/node-application.js +276 -0
  17. package/dist/node-application.js.map +1 -0
  18. package/dist/official-language-server-extensions.d.ts.map +1 -1
  19. package/dist/official-language-server-extensions.js +13 -1
  20. package/dist/official-language-server-extensions.js.map +1 -1
  21. package/dist/production-build.d.ts +1 -1
  22. package/dist/production-build.d.ts.map +1 -1
  23. package/dist/production-build.js +0 -2
  24. package/dist/production-build.js.map +1 -1
  25. package/dist/production-verifier.js +1 -17
  26. package/dist/production-verifier.js.map +1 -1
  27. package/dist/project-format.d.ts +1 -1
  28. package/dist/project-format.d.ts.map +1 -1
  29. package/dist/project-format.js +1 -1
  30. package/dist/project-format.js.map +1 -1
  31. package/dist/project.d.ts +3 -0
  32. package/dist/project.d.ts.map +1 -1
  33. package/dist/project.js +64 -0
  34. package/dist/project.js.map +1 -1
  35. package/dist/resource-output.d.ts +3 -1
  36. package/dist/resource-output.d.ts.map +1 -1
  37. package/dist/resource-output.js +15 -11
  38. package/dist/resource-output.js.map +1 -1
  39. package/dist/standard-modules.d.ts +3 -12
  40. package/dist/standard-modules.d.ts.map +1 -1
  41. package/dist/standard-modules.js +13 -3045
  42. package/dist/standard-modules.js.map +1 -1
  43. package/dist/static-deployment.d.ts +1 -8
  44. package/dist/static-deployment.d.ts.map +1 -1
  45. package/dist/static-deployment.js +3 -28
  46. package/dist/static-deployment.js.map +1 -1
  47. package/dist/test-output.d.ts +1 -1
  48. package/dist/test-output.d.ts.map +1 -1
  49. package/dist/test-output.js.map +1 -1
  50. package/dist/version.d.ts +2 -2
  51. package/dist/version.d.ts.map +1 -1
  52. package/dist/version.js +2 -2
  53. package/dist/version.js.map +1 -1
  54. package/package.json +9 -11
  55. package/skill/ai-skill-desktop.md +84 -0
  56. package/skill/ai-skill-node.md +287 -0
  57. package/skill/ai-skill-web.md +150 -0
  58. package/skill/ai-skill.md +36 -263
  59. package/dist/build-engine-tool.d.ts +0 -3
  60. package/dist/build-engine-tool.d.ts.map +0 -1
  61. package/dist/build-engine-tool.js +0 -34
  62. package/dist/build-engine-tool.js.map +0 -1
  63. package/dist/packaged-official-tool.d.ts +0 -8
  64. package/dist/packaged-official-tool.d.ts.map +0 -1
  65. package/dist/packaged-official-tool.js +0 -32
  66. package/dist/packaged-official-tool.js.map +0 -1
  67. package/dist/project-task-bundle-entry.d.ts +0 -2
  68. package/dist/project-task-bundle-entry.d.ts.map +0 -1
  69. package/dist/project-task-bundle-entry.js +0 -18
  70. package/dist/project-task-bundle-entry.js.map +0 -1
  71. package/dist/project-task-invocation.d.ts +0 -16
  72. package/dist/project-task-invocation.d.ts.map +0 -1
  73. package/dist/project-task-invocation.js +0 -72
  74. package/dist/project-task-invocation.js.map +0 -1
  75. package/dist/project-task-tool.d.ts +0 -3
  76. package/dist/project-task-tool.d.ts.map +0 -1
  77. package/dist/project-task-tool.js +0 -61
  78. package/dist/project-task-tool.js.map +0 -1
@@ -0,0 +1,287 @@
1
+ # The VelarScript Node AI skill brief
2
+
3
+ Load this after `velar skill core`. This brief contains only the Node owner’s
4
+ contract. Core does not learn server declarations, path-pattern strings, Node
5
+ capabilities, or application configuration.
6
+
7
+ ## Ownership and application entry
8
+
9
+ A Node service activates the extension and names one exported `ServeApp`:
10
+
11
+ ```json
12
+ {
13
+ "formatVersion": 2,
14
+ "entry": "src/main.vel",
15
+ "outDir": "dist",
16
+ "publicDir": "public",
17
+ "extensions": ["@velarscript/node"],
18
+ "node": {
19
+ "app": "app",
20
+ "host": "127.0.0.1",
21
+ "port": 3000,
22
+ "maxBodyBytes": 16777216,
23
+ "build": {"sourceMaps": false}
24
+ }
25
+ }
26
+ ```
27
+
28
+ The entry exports application data; it does not need a manually named function
29
+ or top-level `serve(...)` call:
30
+
31
+ ```velar fragment
32
+ import {app as routes} from "./app.vel"
33
+
34
+ export const app = routes
35
+ ```
36
+
37
+ Use `velar dev` while editing, `velar serve` for checked production runtime
38
+ behavior, and `velar build` for a standalone Node output directory. A direct
39
+ `serve(app, port=0)` call is still correct in integration tests or an embedded
40
+ server.
41
+
42
+ `@name` keeps its one language-wide role: it qualifies a compiler-owned name
43
+ in the current context. In a `server` block, the available names are `@get`,
44
+ `@post`, `@put`, `@patch`, and `@delete`. They are not decorators,
45
+ functions, imports, annotations, first-class values, or user extension points.
46
+
47
+ ## Routes and checked inputs
48
+
49
+ A server is an immutable anonymous route table:
50
+
51
+ ```velar
52
+ import {HttpError, created} from "velar/serve"
53
+
54
+ type CreateArticle:
55
+ title: string
56
+
57
+ export server articles:
58
+ /// Reports whether this service is ready.
59
+ @get(p"/health") => {ok: true}
60
+
61
+ @get(p"/articles/{id:number}", details: bool = false):
62
+ if id < 1:
63
+ throw HttpError(404, {error: "article_not_found"})
64
+ return {id, details}
65
+
66
+ @post(p"/articles", input: CreateArticle):
67
+ return created({id: 1, title: input.title})
68
+ ```
69
+
70
+ The path is written once. A capture such as `{id:number}` declares `id`
71
+ directly in the route body, so never repeat it in the argument list. Captures
72
+ require an ASCII half-width `:` and accept `string`, `number`, `bool`, or
73
+ a named enum. The Node-only `p"..."` prefix marks a compile-time reverse
74
+ matcher; an ordinary string is not accepted, and Core does not recognize this
75
+ prefix.
76
+
77
+ Unadorned scalar and `List<scalar>` parameters are query inputs. A default makes
78
+ the input optional. Repeated query values populate a List; a repeated scalar is
79
+ a 422 error. On `POST`, `PUT`, or `PATCH`, one concrete Data parameter is the
80
+ checked JSON body. A `Request` parameter explicitly requests the complete
81
+ request, including `queryAll` and cooperative `cancellation`. Ambiguous bodies,
82
+ duplicate declarations, conflicting path shapes, and unsupported path types are
83
+ compile errors.
84
+
85
+ Use ordinary values for the cases that need more than inference:
86
+
87
+ ```velar
88
+ import {input, provide, security} from "velar/serve"
89
+
90
+ type User:
91
+ id: string
92
+
93
+ type UploadMetadata:
94
+ title: string
95
+
96
+ const currentUser = provide(
97
+ inputs={token: security.bearer()},
98
+ resolve=async values => {id: values.token},
99
+ )
100
+
101
+ server account:
102
+ @get(p"/me",
103
+ user=input.dependency(currentUser),
104
+ tenant=input.header("x-tenant"),
105
+ session=input.cookie("session", default=null),
106
+ ) => {id: user.id, tenant, session}
107
+
108
+ @post(p"/images",
109
+ metadata=input.form(UploadMetadata),
110
+ image=input.upload("image", maxBytes=8_388_608),
111
+ ) => {title: metadata.title, filename: image.filename}
112
+ ```
113
+
114
+ `input.query`, `input.header`, and `input.cookie` select named scalar
115
+ values. `input.form(Type)` checks URL-encoded or multipart fields, including
116
+ repeated fields for `List<scalar>` properties; duplicate scalar fields fail.
117
+ `input.upload` returns an `Upload` whose bytes are valid only for the request
118
+ lifetime; copy or persist them before retaining data. `security.apiKey`,
119
+ `basic`, `bearer`, `oauth2`, and `openId` parse credentials and also
120
+ feed OpenAPI security schemes.
121
+
122
+ `provide(inputs, resolve, scope="request", release=null, eager=false)` declares
123
+ a dependency as data. A request-scoped provider resolves once per request even
124
+ when injected repeatedly and releases after response/background completion.
125
+ An app-scoped provider may depend only on other app-scoped providers, may be
126
+ eager, and releases during shutdown. Cycles and provider-budget exhaustion fail
127
+ closed. Do not build a controller or container layer around it.
128
+
129
+ ## Composition, lifecycle, and middleware
130
+
131
+ Compose route tables as values:
132
+
133
+ ```velar fragment
134
+ import {RouteDocumentation, docs, lifecycle, middleware, prefix, staticFiles, use} from "velar/serve"
135
+
136
+ const service = lifecycle(
137
+ prefix("/api", articles),
138
+ startup=async () => null,
139
+ shutdown=async () => null,
140
+ )
141
+
142
+ const hardened = use(service, [
143
+ middleware.trustedHosts(["api.example.com", "127.0.0.1"]),
144
+ middleware.cors(origins=["https://app.example.com"], credentials=true),
145
+ middleware.requestId(),
146
+ middleware.securityHeaders(),
147
+ middleware.compression(minimumBytes=1024),
148
+ middleware.timeout(10_000),
149
+ middleware.concurrency(256),
150
+ ])
151
+
152
+ const articleDocs: RouteDocumentation = {summary: "Read article", tags: ["articles"], errors: Map([[404, "Article not found"]])}
153
+ const routeDocs: Map<string, RouteDocumentation> = Map([["GET /api/articles/{id:number}", articleDocs]])
154
+
155
+ export server app:
156
+ ...docs(hardened, title="Article API", version="1.0.0", routes=routeDocs)
157
+ ...staticFiles("/", root="public", fallback="index.html")
158
+ ```
159
+
160
+ `prefix` changes a literal route prefix; `bodyLimit` narrows one route
161
+ table’s body budget; `use` attaches middleware only to the routes it receives.
162
+ A middleware continuation is single-use. Built-ins also include access logging
163
+ and explicit error recovery. A timeout response does not pretend downstream
164
+ work was cancelled: its request resources remain alive until that work really
165
+ ends, and the runtime caps unfinished timed-out tasks.
166
+
167
+ `lifecycle` owns paired startup and shutdown hooks. Successful startups unwind
168
+ in reverse order; a failed startup does not run its paired shutdown.
169
+ `background(response, task)` keeps request-scoped resources valid until the
170
+ task finishes. `setCookie` and
171
+ `clearCookie` add checked cookie headers, preserving separate `Set-Cookie`
172
+ fields. Never start long-lived work by
173
+ dropping a Promise; use an owned lifecycle, background task, Worker, or process.
174
+
175
+ `docs` adds a bundled offline UI and OpenAPI 3.1 JSON. Compiler route types
176
+ and response helpers supply parameter, body, response, content-type, and static
177
+ success-status schemas. Applicable framework-generated 400, 401, 413, 415, and
178
+ 422 responses are included automatically; a preceding `///` comment supplies
179
+ the route description. The optional ordinary typed
180
+ `Map<string, RouteDocumentation>` can add
181
+ summary, description, tags, success status, documented error statuses, or hide
182
+ a route, keyed by strings such as `"GET /articles/{id:number}"`. This metadata
183
+ is data, not another `@` category.
184
+
185
+ ## Responses and realtime
186
+
187
+ Ordinary Data returns JSON. Use the explicit helpers only when transport
188
+ semantics matter: `json`, `created`, `noContent`, `redirect`, `text`,
189
+ `file`, `stream`, `sse`, `background`, `setCookie`, and
190
+ `clearCookie`. `HttpError(status, body, headers=null)` is the expected HTTP
191
+ failure. Unexpected failures are reported on stderr and become an opaque 500.
192
+
193
+ `HEAD` reuses `GET` without a body. `OPTIONS` and 405 responses publish a
194
+ complete `Allow` header. Final response statuses are 200 through 599; 204 and
195
+ 304 are bodyless. Streaming follows write backpressure; each chunk and the
196
+ total stream are bounded. SSE accepts text or checked
197
+ `{data, event?, id?, retry?}` events. Static and returned files are canonical
198
+ root-contained, streamed reads with validators and one byte range.
199
+
200
+ `velar/websocket.listen({http: app, ...})` serves a `ServeApp` and WebSocket
201
+ upgrades on one native server and owns the application lifecycle. Connections
202
+ are pull-based. Always consume `next()`, handle backpressure, and stop the
203
+ server.
204
+
205
+ ## Tests
206
+
207
+ Use `velar/server-test` only from `*.test.vel`. It runs the real ServeApp
208
+ router, providers, lifecycle, cookies, forms, uploads, streams, and files in
209
+ process without opening a port:
210
+
211
+ ```velar fragment
212
+ import {client} from "velar/server-test"
213
+ import {expect} from "velar/test"
214
+ import {app} from "./app.vel"
215
+
216
+ test "health endpoint":
217
+ const api = await client(app)
218
+ try:
219
+ const response = await api.get("/api/health")
220
+ expect(response.status).toBe(200)
221
+ expect(await response.text()).toContain("ok")
222
+ finally:
223
+ await api.close()
224
+ ```
225
+
226
+ Pass a `Map<Provider, value>` as the second `client` argument to override
227
+ dependencies. Request options support headers, JSON, text, form Maps, and file
228
+ Maps. Test WebSocket behavior through a real local `velar/websocket` server,
229
+ because WebSocket upgrades are a transport boundary rather than an in-process
230
+ HTTP request.
231
+
232
+ ## Memory and ownership rules
233
+
234
+ The runtime has hard ceilings; application code must preserve them:
235
+
236
+ - Request bodies are at most 16 MiB, with narrower per-route and project limits.
237
+ HTTP request bodies, buffered responses, static files, and stream chunks also
238
+ share one 128 MiB isolated-host budget.
239
+ - Live inbound HTTP requests and middleware concurrency are capped at 4,096.
240
+ ServeApp routes, request providers, app providers, and timed-out unfinished
241
+ work have separate count limits.
242
+ - WebSocket queued bytes and pending-send bytes share a 128 MiB budget. Global
243
+ limits also cover active connections, pending connection objects, queued
244
+ message objects, and pending send Promises, including zero-byte messages.
245
+ - Multipart parsing reuses bounded body storage; an `Upload` is invalidated
246
+ when its request scope ends. Provider caches and release lists are explicitly
247
+ cleared at request or application shutdown.
248
+ - Development rebuilds serialize changes, retain one last-good child, stop the
249
+ old child before replacing it, and delete temporary build sandboxes.
250
+
251
+ Set smaller limits for the domain instead of treating framework maxima as
252
+ defaults. Stream large data, consume pull queues promptly, close every owned
253
+ capability, and keep caches explicitly bounded.
254
+
255
+ ## Concurrency and shutdown rules
256
+
257
+ Concurrency limits are admission control, not a lock around application data.
258
+ The runtime guarantees that an application-scoped provider initializes once,
259
+ concurrent `stop` or `close` calls join the same completion, shutdown refuses
260
+ new work, requests receive cooperative cancellation, and provider release begins
261
+ only after every admitted request has finished its response, timed-out
262
+ continuation, background work, and request cleanup. `stop(grace=30000)` bounds
263
+ the drain wait without releasing live request resources early. WebSocket stop
264
+ closes connections in parallel with a bounded handshake and releases unread
265
+ queues and pending-send reservations.
266
+
267
+ Application code still owns business-level consistency. Do not use an
268
+ unprotected module-level mutable record as a cross-request database. Put
269
+ multi-write invariants in a database transaction or another capability that
270
+ provides atomic operations. Always await stream writes, allow only one active
271
+ pull from an async iterator, and make retryable handlers idempotent. A
272
+ `middleware.concurrency` limit protects capacity; it does not make a shared
273
+ read-modify-write sequence atomic.
274
+
275
+ ## Node capabilities and finish
276
+
277
+ Use `velar/fs`, `velar/path`, `velar/process`, `velar/env`,
278
+ `velar/terminal`, `velar/http`, `velar/worker`, and `velar/websocket` instead of
279
+ ambient Node globals. Databases are ordinary external source packages: use the
280
+ engine-neutral `@velarscript/database` model contract and install an adapter
281
+ such as `@velarscript/sqlite`. Third-party packages cross a checked `extern
282
+ module` adapter first; keep `import js unsafe` at one narrow validation
283
+ boundary.
284
+
285
+ Run `velar format --check`, `velar check`, `velar test`, and
286
+ `velar build`. The complete runnable spelling lives in
287
+ `examples/tour/node/`; current diagnostics outrank this brief.
@@ -0,0 +1,150 @@
1
+ # The VelarScript Web AI skill brief
2
+
3
+ Load this after `velar skill core`. This file contains only the Web extension's
4
+ contract; Core syntax stays owned by the Core brief. It ships with the
5
+ toolchain and `velar skill web` prints it verbatim.
6
+
7
+ ## Ownership
8
+
9
+ The manifest activates Web explicitly:
10
+
11
+ ```json
12
+ {
13
+ "formatVersion": 2,
14
+ "entry": "src/main.vel",
15
+ "extensions": ["@velarscript/web"],
16
+ "web": {"title": "My App"}
17
+ }
18
+ ```
19
+
20
+ `@velarscript/web` owns `component`, JSX, `state`, `computed`, `resource`,
21
+ `action`, `watch`, `look`, `keyframes`, `mount`, Web units, its standard
22
+ modules, and the `web` manifest key. Without that extension these are not Core
23
+ syntax. Web visual builders are named imports from `velar/look`; there is no
24
+ `Look.` namespace.
25
+
26
+ `@name` keeps the same language-wide role: it qualifies a compiler-owned name
27
+ in the current context. Components own `@mounted:` and `@cleanup:`; Look owns
28
+ conditions such as `@hover` and `@before`. They are not decorators, calls, or
29
+ values, and user code cannot declare new `@` names.
30
+
31
+ The toolchain writes `dist/index.html`; do not author it. `web.title` and
32
+ `web.icon` supply document metadata, `public/` is copied through, and other
33
+ assets are content-hashed.
34
+
35
+ ## Components and reactivity
36
+
37
+ A component returns JSX directly. The four reactive cells have distinct jobs:
38
+
39
+ - `state` owns a fact.
40
+ - `computed name = ...` derives synchronously and is read bare.
41
+ - `resource name: T = load()` owns async loading state.
42
+ - `action name():` owns a user operation and exposes `pending` and `error`.
43
+
44
+ ```velar fragment
45
+ component TicketPanel(id: string):
46
+ state draft = ""
47
+ resource ticket: Ticket = loadTicket(id)
48
+ computed heading = ticket.value?.title ?? "Loading"
49
+
50
+ action save():
51
+ await saveDraft(id, draft)
52
+
53
+ watch id:
54
+ async ticket.reload()
55
+
56
+ return <section>
57
+ <h2>{heading}</h2>
58
+ <textarea bind:value={draft}></textarea>
59
+ <button disabled={save.pending} on:click={save}>Save</button>
60
+ </section>
61
+ ```
62
+
63
+ A resource loads once at mount. Refetching after an input changes is an
64
+ explicit `watch` plus detached `async resource.reload()`. Actions do not queue;
65
+ disable or otherwise guard a trigger when concurrent calls are unwanted.
66
+
67
+ `@mounted:` runs after insertion and may await. `@cleanup:` runs before removal
68
+ and is synchronous. A component may still declare ordinary methods named
69
+ `mounted` or `cleanup` because compiler-owned names occupy a separate namespace.
70
+
71
+ Events use `on:click={handler}`. Writable form paths use `bind:value`,
72
+ `bind:checked`, or `bind:group`; do not read `event.target`. A JSX tag body is
73
+ received only through an explicitly declared `children: WebNode` prop.
74
+ Conditional rendering is an expression, and repeated children need stable
75
+ `key` values.
76
+
77
+ Props are live reactive inputs. Their data is mutable unless the author writes
78
+ an explicit `readonly` view.
79
+
80
+ ## Look
81
+
82
+ `look:` is checked visual data. CSS keywords are strings, property names use
83
+ DOM camelCase, and units are literals:
84
+
85
+ ```velar fragment
86
+ import {border, rgb, spacing} from "velar/look"
87
+
88
+ const buttonLook = look:
89
+ border = border(0px, rgb(220, 224, 235))
90
+ borderRadius = 10px
91
+ padding = spacing(10px, 14px)
92
+ cursor = "pointer"
93
+
94
+ if @hover:
95
+ background = rgb(235, 240, 255)
96
+ ```
97
+
98
+ A module-level Look literal is built once and cannot read reactive state. Put a
99
+ changing visual on the element with `look={active ? enabledLook : disabledLook}`
100
+ or a typed `look:color={...}` binding. Checked motion is a module-level
101
+ `keyframes:` value passed to `animate` from `velar/look`; do not use a raw CSS
102
+ animation string. Unsupported styling uses explicit `import css unsafe
103
+ "./file.css" before look` or `after look`.
104
+
105
+ ## Storage and tests
106
+
107
+ `velar/storage` stores JSON and validates on read. A generic type spelling is
108
+ not a runtime value, so name the complete type:
109
+
110
+ ```velar fragment
111
+ import {storage} from "velar/storage"
112
+
113
+ type SavedItem:
114
+ title: string
115
+
116
+ type SavedItems = List<SavedItem>
117
+
118
+ const items = storage.get("reading", SavedItems, [])
119
+ storage.set("reading", items)
120
+ ```
121
+
122
+ Keep `src/main.vel` as the mounted entry and put testable components and logic
123
+ in imported modules. Plain `*.test.vel` files run headlessly. A
124
+ `*.browser.test.vel` file drives the already-built page through
125
+ `velar/web-test`; it does not mount a second app and cannot use JSX or
126
+ `document` in its test body:
127
+
128
+ ```velar fragment
129
+ import {expect} from "velar/test"
130
+ import {browser, localStorage} from "velar/web-test"
131
+
132
+ test "adding a link shows it in the list":
133
+ await browser.open("/")
134
+ await browser.fill("#title", "Vel")
135
+ await browser.click("#add")
136
+ await browser.waitForText("[data-item]", "Vel")
137
+ expect(await browser.text("[data-count]")).toBe("1")
138
+ expect(await localStorage.get("reading")).toBe(`[{"title":"Vel"}]`)
139
+ ```
140
+
141
+ Bare `velar test --browser` means Chromium; use `--browser=all` for a
142
+ cross-browser claim. `velar/web-test` is legal only in browser-test modules.
143
+ Application code that needs the page uses checked `velar/browser` APIs.
144
+
145
+ ## Finish
146
+
147
+ Run `velar format`, `velar check`, `velar test`, the project's browser tests,
148
+ and `velar build`. The complete runnable vocabulary lives in
149
+ `examples/tour/web/`; diagnostics outrank this brief when the two appear to
150
+ disagree.