@crab-dev/wake 0.1.16 → 0.1.18

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/CHANGELOG.md CHANGED
@@ -1,7 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.18
4
+
5
+ - Added native component-library ESM, CommonJS, declaration, and extracted CSS builds through `wake library build` and `buildLibrary()` without changing application builds.
6
+ - Added strict Rust-native token and docgen generators through `wake library token`, `wake library docgen`, `generateCssToken()`, and `generateDocgen()`.
7
+ - Added `defineTokens()` to `@crab-dev/css` for deeply immutable design tokens that can be safely evaluated across module boundaries.
8
+ - Added stable package-prefixed CSS class names, PnP-aware static analysis, transactional library outputs, and fail-closed public type diagnostics.
9
+
10
+ ## 0.1.17
11
+
12
+ - Added AST-driven CSS parsing shared by compilation, CSS-in-JS nesting, editor diagnostics, and semantic highlighting, removing the legacy TextMate injection grammar.
13
+ - Added Node library bundle APIs and CLI support with incremental rebuild coverage and updated documentation.
14
+ - Added complete CI release coverage for all seven public npm packages and GitHub-only multi-platform VSIX releases.
15
+
3
16
  ## 0.1.16
4
17
 
18
+ - Added Node 20 CommonJS single-file bundles with atomic exact-outfile writes, host externals, declaration-ordered Node conditional exports, usable source-map results, and matching Rust/npm CLI support.
5
19
  - Automatically loaded Crab UI component CSS from package identity across `node_modules`, workspaces, and Yarn PnP virtual, unplugged, and zip layouts without runtime CSS imports.
6
20
  - Added issuer-scoped Yarn PnP dependency fallbacks for Components workbenches while preserving aliases, package-owned dependency versions, exports errors, and ambiguous virtual-locator rejection.
7
21
  - Preserved configured Demo accent colors independently from the neutral workbench theme.
package/README.md CHANGED
@@ -9,9 +9,13 @@ npx wake build
9
9
  ```
10
10
 
11
11
  ```js
12
- import { build, startDevServer } from '@crab-dev/wake'
12
+ import { build, buildLibrary, bundle, generateCssToken, generateDocgen, startDevServer } from '@crab-dev/wake'
13
13
 
14
14
  await build({ cwd: process.cwd() })
15
+ await buildLibrary({ cwd: process.cwd(), entry: 'src/index.ts' })
16
+
17
+ await generateCssToken({ cwd: process.cwd(), configPath: 'token.toml' })
18
+ await generateDocgen({ cwd: process.cwd(), entry: 'src/button.tsx' })
15
19
 
16
20
  const server = await startDevServer({ port: 5173 })
17
21
  console.log(server.url)
@@ -27,6 +31,41 @@ The stable API also includes in-memory `bundle()`, incremental
27
31
  and server operations accept `AbortSignal`; long-lived contexts and servers
28
32
  support explicit close methods and JavaScript disposal protocols.
29
33
 
34
+ Node-hosted tools can request an exact CommonJS artifact without Web output:
35
+
36
+ ```js
37
+ await bundle({
38
+ entry: 'src/extension.ts',
39
+ outfile: 'dist/extension.js',
40
+ platform: 'node',
41
+ format: 'cjs',
42
+ target: 'node20',
43
+ external: ['vscode'],
44
+ })
45
+ ```
46
+
47
+ `platform: 'node'` defaults to CommonJS and `node20`, so `format` and `target`
48
+ can be omitted. `bundle()` returns a dedicated result whose `code` is always a
49
+ string. With `sourceMap: true`, `sourceMap` is returned in memory; when
50
+ `outfile` is present Wake also writes `<outfile>.map`, exposes
51
+ `sourceMapFile`, and appends the matching `sourceMappingURL`.
52
+
53
+ Component packages can generate design-token TypeScript without a Node-based
54
+ generator by running `wake library token` or calling `generateCssToken()`. The
55
+ generator supports recursive package imports in Yarn PnP and `node_modules`,
56
+ rejects missing references and cycles, and atomically writes only the output
57
+ declared by `build.output`.
58
+
59
+ `wake library build` and `buildLibrary()` emit `esm/index.mjs`,
60
+ `cjs/index.cjs`, `declarations/index.d.ts`, and optional `css/index.css` from
61
+ the native library graph. Outputs are staged and committed together; unsafe
62
+ public type inference or static-style failures preserve the previous build.
63
+
64
+ Component API metadata can be generated without `react-docgen` by running
65
+ `wake library docgen` or calling `generateDocgen()`. Entry resolution follows
66
+ the CLI override, package configuration, then the default export from
67
+ `src/index.ts`; failures leave the previous `public/docgen.json` untouched.
68
+
30
69
  Full documentation:
31
70
 
32
71
  - [Node.js API](https://github.com/hotlif/wake/blob/canary/docs/reference/node-api.mdx)
package/bin/terminal.mjs CHANGED
@@ -87,6 +87,16 @@ export function formatBuildResult(ui, result, label = 'Built', extra = '') {
87
87
  return lines
88
88
  }
89
89
 
90
+ export function formatGeneratorResult(ui, result, label) {
91
+ const bytes = (result.files || []).reduce((sum, file) => sum + Number(file.bytes || 0), 0)
92
+ return [
93
+ ` ${ui.ok('✓')} ${ui.bold(label)} ${ui.accent(`in ${humanDuration(result.durationMs)}`)}`,
94
+ ` ${(result.files || []).length} ${ui.dim('files')} ${ui.dim('·')} ${ui.accent(humanBytes(bytes))}`,
95
+ ` ${ui.dim('Output')} ${ui.accent(result.outputFile)}`,
96
+ '',
97
+ ]
98
+ }
99
+
90
100
  export function formatServerReady(ui, url, metrics) {
91
101
  const lines = [
92
102
  ` ${ui.ok('✓')} ${ui.bold('Development server ready')}`,
package/bin/wake.mjs CHANGED
@@ -3,10 +3,15 @@
3
3
  import { readFile } from 'node:fs/promises'
4
4
  import {
5
5
  build,
6
+ buildLibrary,
6
7
  buildDocs,
8
+ bundle,
9
+ generateCssToken,
10
+ generateDocgen,
7
11
  startDevServer,
8
12
  startDocsDevServer,
9
13
  version,
14
+ WakeError,
10
15
  } from '../index.mjs'
11
16
  import { parse, tokenize } from '../experimental.mjs'
12
17
  import {
@@ -18,6 +23,7 @@ import {
18
23
  formatBuildResult,
19
24
  formatError,
20
25
  formatFinalSummary,
26
+ formatGeneratorResult,
21
27
  formatServerReady,
22
28
  observeServer,
23
29
  setDashboardEndpoint,
@@ -32,6 +38,10 @@ const HELP = `Wake ${version()}
32
38
  Usage:
33
39
  wake [--ui auto|tui|plain] [--no-color] <command>
34
40
  wake build [entry] [--outdir DIR] [--cache] [--sourcemap]
41
+ wake bundle <entry> --outfile FILE [--platform browser|node] [--format iife|cjs]
42
+ [--target node20] [--external PACKAGE] [--minify] [--sourcemap]
43
+ [--cache] [--config FILE]
44
+ wake library token [project] [--config token.toml]
35
45
  wake dev [root] [--entry FILE] [--host HOST] [--port PORT] [--open]
36
46
  wake docs build [root] [--mode site|components] [--outdir DIR] [--base PATH]
37
47
  wake docs dev [root] [--mode site|components] [--host HOST] [--port PORT] [--open]
@@ -45,15 +55,24 @@ Options:
45
55
  --format Human or JSON output for parse/tokenize (default: auto)
46
56
  `
47
57
 
48
- function takeOption(args, name) {
58
+ function takeOption(args, name, usage = false) {
49
59
  const index = args.indexOf(name)
50
60
  if (index === -1) return undefined
51
- if (index + 1 >= args.length) throw new Error(`${name} requires a value`)
61
+ if (index + 1 >= args.length) {
62
+ const message = `${name} requires a value`
63
+ throw usage ? usageError(message) : new Error(message)
64
+ }
52
65
  const [value] = args.splice(index + 1, 1)
53
66
  args.splice(index, 1)
54
67
  return value
55
68
  }
56
69
 
70
+ function usageError(message) {
71
+ const error = new WakeError('WAKE_CONFIG', message)
72
+ error.exitCode = 2
73
+ return error
74
+ }
75
+
57
76
  function takeFlag(args, name) {
58
77
  const index = args.indexOf(name)
59
78
  if (index === -1) return false
@@ -61,6 +80,15 @@ function takeFlag(args, name) {
61
80
  return true
62
81
  }
63
82
 
83
+ function takeOptions(args, name, usage = false) {
84
+ const values = []
85
+ for (;;) {
86
+ const value = takeOption(args, name, usage)
87
+ if (value === undefined) return values
88
+ values.push(value)
89
+ }
90
+ }
91
+
64
92
  function commonOptions(args) {
65
93
  return {
66
94
  configPath: takeOption(args, '--config'),
@@ -78,6 +106,13 @@ function validateChoice(value, name, choices) {
78
106
  return value
79
107
  }
80
108
 
109
+ function validateBundleChoice(value, name, choices) {
110
+ if (!choices.includes(value)) {
111
+ throw usageError(`${name} must be one of: ${choices.join(', ')}`)
112
+ }
113
+ return value
114
+ }
115
+
81
116
  function ensureStaticMode(uiMode) {
82
117
  if (uiMode === 'tui') {
83
118
  throw new Error('--ui tui is only available for dev and docs dev')
@@ -245,6 +280,54 @@ export async function runCli(argv = process.argv.slice(2)) {
245
280
  return 0
246
281
  }
247
282
 
283
+ if (command === 'bundle') {
284
+ ensureStaticMode(uiMode)
285
+ const options = { configPath: takeOption(args, '--config', true) }
286
+ options.outfile = takeOption(args, '--outfile', true)
287
+ const platform = takeOption(args, '--platform', true)
288
+ if (platform !== undefined) {
289
+ options.platform = validateBundleChoice(platform, '--platform', ['browser', 'node'])
290
+ }
291
+ const format = takeOption(args, '--format', true)
292
+ if (format !== undefined) {
293
+ options.format = validateBundleChoice(format, '--format', ['iife', 'cjs'])
294
+ }
295
+ options.target = takeOption(args, '--target', true)
296
+ options.external = takeOptions(args, '--external', true)
297
+ options.minify = takeFlag(args, '--minify')
298
+ options.sourceMap = takeFlag(args, '--sourcemap')
299
+ options.cache = takeFlag(args, '--cache')
300
+ options.entry = args.shift()
301
+ if (!options.entry || !options.outfile) {
302
+ throw usageError('bundle requires one entry and --outfile FILE')
303
+ }
304
+ if (args.length) throw usageError(`unknown bundle arguments: ${args.join(' ')}`)
305
+ printLines(formatBanner(ui, 'bundle', version()))
306
+ printResult(ui, await bundle(options), 'Bundled')
307
+ return 0
308
+ }
309
+
310
+ if (command === 'library') {
311
+ ensureStaticMode(uiMode)
312
+ const action = args.shift()
313
+ if (action !== 'build' && action !== 'token' && action !== 'docgen') {
314
+ throw usageError('library requires build, token, or docgen')
315
+ }
316
+ const options = action === 'token'
317
+ ? { configPath: takeOption(args, '--config', true) }
318
+ : { entry: takeOption(args, '--entry', true) }
319
+ if (args[0]) options.cwd = args.shift()
320
+ if (args.length) throw usageError(`unknown library ${action} arguments: ${args.join(' ')}`)
321
+ printLines(formatBanner(ui, `library ${action}`, version()))
322
+ if (action === 'build') {
323
+ printResult(ui, await buildLibrary(options), 'Built library')
324
+ return 0
325
+ }
326
+ const result = action === 'token' ? await generateCssToken(options) : await generateDocgen(options)
327
+ printLines(formatGeneratorResult(ui, result, action === 'token' ? 'Tokens generated' : 'Docgen generated'))
328
+ return 0
329
+ }
330
+
248
331
  if (command === 'dev') {
249
332
  const options = commonOptions(args)
250
333
  options.entry = takeOption(args, '--entry')
@@ -342,5 +425,5 @@ try {
342
425
  const noColor = process.argv.includes('--no-color')
343
426
  const ui = createUi(!noColor && supportsColor())
344
427
  printLines(formatError(ui, error))
345
- process.exitCode = 1
428
+ process.exitCode = error.exitCode || 1
346
429
  }
package/index.cjs CHANGED
@@ -25,6 +25,21 @@ async function bundle(options) {
25
25
  return invoke(native.bundle(JSON.stringify(value), signal))
26
26
  }
27
27
 
28
+ async function buildLibrary(options) {
29
+ const [value, signal] = splitOptions(options)
30
+ return invoke(native.buildLibrary(JSON.stringify(value), signal))
31
+ }
32
+
33
+ async function generateCssToken(options) {
34
+ const [value, signal] = splitOptions(options)
35
+ return invoke(native.generateCssToken(JSON.stringify(value), signal))
36
+ }
37
+
38
+ async function generateDocgen(options) {
39
+ const [value, signal] = splitOptions(options)
40
+ return invoke(native.generateDocgen(JSON.stringify(value), signal))
41
+ }
42
+
28
43
  class BuildContext {
29
44
  #native
30
45
  #closed = false
@@ -197,8 +212,11 @@ module.exports = {
197
212
  DevServer,
198
213
  WakeError,
199
214
  build,
215
+ buildLibrary,
200
216
  buildDocs,
201
217
  bundle,
218
+ generateCssToken,
219
+ generateDocgen,
202
220
  createBuildContext,
203
221
  startDevServer,
204
222
  startDocsDevServer,
package/index.d.ts CHANGED
@@ -8,6 +8,18 @@ export type WakeErrorCode =
8
8
  | 'WAKE_CANCELLED'
9
9
  | 'WAKE_UNSUPPORTED_PLATFORM'
10
10
  | 'WAKE_INTERNAL'
11
+ | 'WAKE_TOKEN_IO'
12
+ | 'WAKE_TOKEN_CONFIG'
13
+ | 'WAKE_TOKEN_IMPORT'
14
+ | 'WAKE_TOKEN_CYCLE'
15
+ | 'WAKE_TOKEN_REF'
16
+ | 'WAKE_DOCGEN_IO'
17
+ | 'WAKE_DOCGEN_CONFIG'
18
+ | 'WAKE_DOCGEN_ENTRY'
19
+ | 'WAKE_DOCGEN_TYPE'
20
+ | 'WAKE_LIBRARY_BUILD'
21
+ | 'WAKE_LIBRARY_TYPE'
22
+ | 'WAKE_LIBRARY_OUTPUT'
11
23
 
12
24
  export interface Diagnostic {
13
25
  severity: 'error' | 'warning' | 'note' | 'help'
@@ -39,9 +51,25 @@ export interface BuildOptions extends ProjectOptions {
39
51
  sourceMap?: boolean
40
52
  }
41
53
 
54
+ export type BundlePlatform = 'browser' | 'node'
55
+ export type BundleFormat = 'iife' | 'cjs'
56
+ export type NodeTarget = `node${number}` | `node${number}.${number}`
57
+
58
+ export interface BundleOptions extends ProjectOptions {
59
+ entry?: string
60
+ outfile?: string
61
+ platform?: BundlePlatform
62
+ format?: BundleFormat
63
+ target?: NodeTarget
64
+ external?: string[]
65
+ minify?: boolean
66
+ sourceMap?: boolean
67
+ cache?: boolean
68
+ }
69
+
42
70
  export interface OutputFile {
43
71
  path: string
44
- kind: 'chunk' | 'css' | 'asset' | 'html'
72
+ kind: 'entry' | 'chunk' | 'css' | 'declaration' | 'asset' | 'html' | 'map'
45
73
  bytes: number
46
74
  }
47
75
 
@@ -57,26 +85,79 @@ export interface BuildResult {
57
85
  diagnostics: Diagnostic[]
58
86
  }
59
87
 
60
- export interface BundleResult extends BuildResult {
88
+ export interface BundleResult {
89
+ success: true
90
+ moduleCount: number
91
+ updatedModuleCount: number
92
+ cachedModuleCount: number
93
+ durationMs: number
94
+ outputFile?: string
61
95
  code: string
62
- outputDir?: undefined
96
+ sourceMap?: string
97
+ sourceMapFile?: string
98
+ files: OutputFile[]
99
+ diagnostics: Diagnostic[]
63
100
  }
64
101
 
65
- export type DocsMode = 'site' | 'components'
102
+ export interface LibraryBuildOptions {
103
+ cwd?: string
104
+ entry?: string
105
+ signal?: AbortSignal
106
+ }
66
107
 
67
- export interface DocsRoute {
68
- id: string
69
- file: string
70
- title: string
71
- description: string
72
- group: string
73
- groupOrder: number
74
- order: number
75
- slug: string
76
- status: string
77
- draft: boolean
78
- headings: Array<{ depth: number; title: string; id: string }>
108
+ export interface LibraryBuildResult extends BuildResult {
109
+ outputDir: string
110
+ esmEntry: string
111
+ cjsEntry: string
112
+ declarationEntry: string
113
+ cssEntry?: string
79
114
  }
115
+
116
+ export interface GenerateCssTokenOptions {
117
+ cwd?: string
118
+ configPath?: string
119
+ signal?: AbortSignal
120
+ }
121
+
122
+ export interface GenerateCssTokenResult {
123
+ success: true
124
+ durationMs: number
125
+ outputFile: string
126
+ files: OutputFile[]
127
+ }
128
+
129
+ export interface GenerateDocgenOptions {
130
+ cwd?: string
131
+ entry?: string
132
+ signal?: AbortSignal
133
+ }
134
+
135
+ export interface GenerateDocgenResult {
136
+ success: true
137
+ durationMs: number
138
+ entry: string
139
+ outputFile: string
140
+ files: OutputFile[]
141
+ }
142
+
143
+ export type DocsMode = 'site' | 'components'
144
+
145
+ export interface DocsRoute {
146
+ id: string
147
+ file: string
148
+ title: string
149
+ description: string
150
+ kind: 'overview' | 'tutorial' | 'guide' | 'reference' | 'component'
151
+ group: string
152
+ groupId: string
153
+ section: string
154
+ sectionId: string
155
+ slug: string
156
+ status: string
157
+ draft: boolean
158
+ hidden: boolean
159
+ headings: Array<{ depth: number; title: string; id: string }>
160
+ }
80
161
  export interface DocsDemo {
81
162
  id: string
82
163
  title: string
@@ -146,8 +227,11 @@ export class DevServer extends EventEmitter {
146
227
  }
147
228
 
148
229
  export function version(): string
149
- export function bundle(options: BuildOptions): Promise<BundleResult>
230
+ export function bundle(options: BundleOptions): Promise<BundleResult>
150
231
  export function build(options?: BuildOptions): Promise<BuildResult>
232
+ export function buildLibrary(options?: LibraryBuildOptions): Promise<LibraryBuildResult>
233
+ export function generateCssToken(options?: GenerateCssTokenOptions): Promise<GenerateCssTokenResult>
234
+ export function generateDocgen(options?: GenerateDocgenOptions): Promise<GenerateDocgenResult>
151
235
  export function createBuildContext(options?: BuildOptions): Promise<BuildContext>
152
236
  export function startDevServer(options?: DevServerOptions): Promise<DevServer>
153
237
  export function buildDocs(options?: DocsBuildOptions): Promise<DocsBuildResult>
@@ -158,8 +242,11 @@ declare const wake: {
158
242
  DevServer: typeof DevServer
159
243
  WakeError: typeof WakeError
160
244
  build: typeof build
245
+ buildLibrary: typeof buildLibrary
161
246
  buildDocs: typeof buildDocs
162
247
  bundle: typeof bundle
248
+ generateCssToken: typeof generateCssToken
249
+ generateDocgen: typeof generateDocgen
163
250
  createBuildContext: typeof createBuildContext
164
251
  startDevServer: typeof startDevServer
165
252
  startDocsDevServer: typeof startDocsDevServer
package/index.mjs CHANGED
@@ -5,8 +5,11 @@ export const {
5
5
  DevServer,
6
6
  WakeError,
7
7
  build,
8
+ buildLibrary,
8
9
  buildDocs,
9
10
  bundle,
11
+ generateCssToken,
12
+ generateDocgen,
10
13
  createBuildContext,
11
14
  startDevServer,
12
15
  startDocsDevServer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crab-dev/wake",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Wake native web build tools for Node.js",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "repository": {
@@ -64,7 +64,7 @@
64
64
  "@crab-dev/rc-text-edit": "^0.0.1",
65
65
  "@crab-dev/rc-tooltip": "^0.0.2",
66
66
  "@crab-dev/rc-tree": "^0.1.2",
67
- "@linaria/core": "^8.1.1",
67
+ "@crab-dev/css": "0.1.18",
68
68
  "lucide-react": "^1.23.0"
69
69
  },
70
70
  "peerDependencies": {
@@ -72,11 +72,11 @@
72
72
  "react-dom": "^19.2.8"
73
73
  },
74
74
  "optionalDependencies": {
75
- "@crab-dev/wake-darwin-arm64": "0.1.16",
76
- "@crab-dev/wake-darwin-x64": "0.1.16",
77
- "@crab-dev/wake-linux-arm64-gnu": "0.1.16",
78
- "@crab-dev/wake-linux-x64-gnu": "0.1.16",
79
- "@crab-dev/wake-win32-x64-msvc": "0.1.16"
75
+ "@crab-dev/wake-darwin-arm64": "0.1.18",
76
+ "@crab-dev/wake-darwin-x64": "0.1.18",
77
+ "@crab-dev/wake-linux-arm64-gnu": "0.1.18",
78
+ "@crab-dev/wake-linux-x64-gnu": "0.1.18",
79
+ "@crab-dev/wake-win32-x64-msvc": "0.1.18"
80
80
  },
81
81
  "publishConfig": {
82
82
  "access": "public",