@markii/pack-build 0.0.1 → 0.17.0-next.2

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
@@ -1,4 +1,10 @@
1
1
  # @markii/pack-build
2
2
 
3
- Placeholder that reserves the name. The first real release is published from
4
- https://github.com/markii-org/markii.
3
+ Builds [Markii](https://github.com/markii-org/markii) component packs:
4
+ compiles a pack's component sources (and the CSS they import) with
5
+ esbuild's WebAssembly build, writes the prebuilt form, or produces a
6
+ `.mkp` archive. It is the one Markii package that carries a build
7
+ toolchain, for authoring hosts and pack build scripts; an app that only
8
+ installs prebuilt packs does not need it. Node only.
9
+
10
+ See `docs/packs.md` in the repository for the pack contract.
@@ -0,0 +1,7 @@
1
+ export type { PackBuildOptions, PackBuildOutcome, PackBuildSource, PackFileReader, } from './pack-build.js';
2
+ export { buildPackRegistrationScript, buildPackTerminalScript, computeCacheKey, } from './pack-build.js';
3
+ export { lintPackCss, lintPackCssColors, lintPackCssPrefix, } from './pack-css-lint.js';
4
+ export type { ConfirmPackOverwrite, ExportPackOptions, PackExportBuilder, PackExportFs, PackExportOutcome, } from './pack-export.js';
5
+ export { exportPack, resolveExportTarget } from './pack-export.js';
6
+ export type { ExportPackArchiveOptions, PackExportArchiveOutcome, } from './pack-export-archive.js';
7
+ export { exportPackArchive } from './pack-export-archive.js';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // @markii/pack-build: compiling a pack's sources and exporting the
2
+ // prebuilt form. Node only (esbuild-wasm, node:fs, node:crypto). The
3
+ // neutral half of the prebuilt-pack convention (file names, shadowing
4
+ // detection) stays in @markii/host, which this package imports.
5
+ export { buildPackRegistrationScript, buildPackTerminalScript, computeCacheKey, } from './pack-build.js';
6
+ export { lintPackCss, lintPackCssColors, lintPackCssPrefix, } from './pack-css-lint.js';
7
+ export { exportPack, resolveExportTarget } from './pack-export.js';
8
+ export { exportPackArchive } from './pack-export-archive.js';
@@ -0,0 +1,113 @@
1
+ import type { PackManifest } from '@markii/pack';
2
+ /**
3
+ * Everything `buildPackRegistrationScript` needs to know about one pack —
4
+ * a host-neutral SUBSET of `apps/vscode`'s `DiscoveredPack` (and whatever
5
+ * an Obsidian host's own discovery module produces): a discovery module's
6
+ * richer, host-specific result (which also carries e.g. a `webview.js`
7
+ * convention path, a `scripts/` directory) is passed here directly and
8
+ * satisfies this shape structurally — no import needed either way, and no
9
+ * host-specific field this module has no business knowing about.
10
+ */
11
+ export interface PackBuildSource {
12
+ /** The pack's own folder on disk — `resolveDir` for the synthetic entry `entrySource` compiles. */
13
+ readonly folder: string;
14
+ readonly manifest: PackManifest;
15
+ /** Local component name -> absolute path to its declared source file (`manifest.components[name]`, resolved against `folder`). */
16
+ readonly componentPaths: Readonly<Record<string, string>>;
17
+ /** Engine id -> (local component name -> absolute source path). A terminal build reads its `ansi` slice here; `componentPaths` stays the `react` slice. Absent means the pack names no sources for any other engine. */
18
+ readonly componentPathsByEngine?: Readonly<Record<string, Readonly<Record<string, string>>>>;
19
+ }
20
+ /** Reads a file's UTF-8 text, or resolves `undefined` if it does not exist / cannot be read. Never rejects for an ordinary "not found" — injected so this module needs no real filesystem to test. Structurally identical to `apps/vscode`'s own `PackFileReader` (`./discover.ts`), deliberately not shared by import: a host's discovery module and this builder are independent seams. */
21
+ export type PackFileReader = (absolutePath: string) => Promise<string | undefined>;
22
+ /** esbuild-wasm's browser (in-process WebAssembly) `build` function signature — imported as a TYPE only, so this line never causes `esbuild-wasm` itself to be pulled into whatever bundles this module (see `loadEsbuildWasm`'s doc comment for why the VALUE side must never be a static import). */
23
+ type EsbuildBuildFn = typeof import('esbuild-wasm/lib/browser.js').build;
24
+ /**
25
+ * The PRE-build cache key for one pack: a SHA-256 of `BUILDER_VERSION`, the
26
+ * manifest (stable-stringified: `Object.keys` order for a plain
27
+ * `Record<string,string>` from `parsePackManifest`'s own construction is
28
+ * already insertion order, and there is exactly one manifest shape), every
29
+ * declared component's absolute path plus its own source bytes, and every
30
+ * CSS file the component sources statically import (`cssSources`, keyed the
31
+ * same way) — so touching any one component file, any CSS file it imports,
32
+ * adding/removing a component, or shipping a new builder version each
33
+ * independently invalidates the cache FILE NAME. Entries are sorted by path
34
+ * first so the digest does not depend on either map's insertion order.
35
+ *
36
+ * This key alone cannot know about a file only a transitive import
37
+ * discovers (this file's top doc comment: the sidecar cache is what
38
+ * catches that). It still decides the cache file's NAME because it is
39
+ * cheap, deterministic, and known before any build attempt — an edit to a
40
+ * declared component or its statically-visible CSS gets a fresh name
41
+ * immediately, and a genuinely stale entry under an unchanged name is
42
+ * still caught by the sidecar hash check before it is ever reused.
43
+ */
44
+ export declare function computeCacheKey(pack: PackBuildSource, componentSources: ReadonlyMap<string, string>, cssSources?: ReadonlyMap<string, string>): string;
45
+ /** What `buildPackRegistrationScript` reports. `'built'` and `'failed'` are real outcomes of an attempted build; `'skipped'` means no attempt was made at all (the default, no-op builder a host may use when no cache directory is configured) — kept distinct from `'failed'` so a caller never records a spurious "build failed" reason for a pack that simply had no build attempted. */
46
+ export type PackBuildOutcome = {
47
+ readonly kind: 'built';
48
+ readonly scriptPath: string;
49
+ /**
50
+ * Absolute path to this build's emitted stylesheet, a SIBLING of
51
+ * `scriptPath` in the same cache directory with the same
52
+ * content-hash base name — present only when at least one built
53
+ * component imported CSS (`import './x.css'`); a pack with no CSS
54
+ * imports produces `undefined` here and no `.css` file is ever
55
+ * written, matching its behavior before this feature existed.
56
+ */
57
+ readonly stylesheetPath?: string;
58
+ /**
59
+ * Rule A/B warnings (`./pack-css-lint.ts`) against `stylesheetPath`'s
60
+ * emitted content — empty when there is no stylesheet, or the
61
+ * stylesheet has no findings. Warnings only: never a build failure,
62
+ * never thrown; a host's own diagnostics surface (`apps/vscode`'s
63
+ * `pack-diagnostics.ts`) surfaces these.
64
+ */
65
+ readonly warnings: readonly string[];
66
+ } | {
67
+ readonly kind: 'failed';
68
+ readonly reason: string;
69
+ } | {
70
+ readonly kind: 'skipped';
71
+ };
72
+ export interface PackBuildOptions {
73
+ /** Absolute path to a real, unbundled `esbuild-wasm/lib/browser.js` — forwarded to `loadEsbuildWasm`. */
74
+ readonly esbuildBrowserModulePath?: string;
75
+ /** Absolute path to the `esbuild.wasm` binary this builder compiles once via `WebAssembly.compile` — forwarded to `loadEsbuildWasm`. */
76
+ readonly esbuildWasmBinaryPath?: string;
77
+ /** Reads one component source file's UTF-8 text, or `undefined` if unreadable — defaults to real `node:fs`. Injected so a build-failure ("missing component source") path is testable without touching disk. */
78
+ readonly readComponentSource?: PackFileReader;
79
+ /** Replaces esbuild-wasm's `build` function outright — for tests that want to assert cache behavior (or a build failure) without paying for a real esbuild-wasm invocation, and for the ANY-real-invocation counting a cache-hit test needs. Bypasses `loadEsbuildWasm`/the module-path options entirely when given. */
80
+ readonly build?: EsbuildBuildFn;
81
+ }
82
+ /**
83
+ * Builds (or reuses a cached build of) one pack's webview registration
84
+ * script. NEVER throws: every failure mode (a missing component source, a
85
+ * broken `.tsx`, an esbuild-wasm error) comes back as
86
+ * `{ kind: 'failed', reason }` — a host records that reason next to the
87
+ * pack and simply excludes it from its own webview/renderer registry, the
88
+ * same quiet degradation as every other pack failure (AGENTS.md's
89
+ * cleanliness rule: never a compiler error dump as page content).
90
+ *
91
+ * `cacheDir` is a HOST-OWNED directory — never the pack's own folder, per
92
+ * AGENTS.md's cleanliness rule that the user's file tree stays clean. A
93
+ * cache hit (the built script for this exact pack content already exists
94
+ * under `cacheDir`) skips esbuild-wasm entirely: esbuild-wasm
95
+ * initialization is not free (see this file's top doc comment for measured
96
+ * figures), and a warm preview open must not pay that cost on every panel
97
+ * (re)creation.
98
+ */
99
+ export declare function buildPackRegistrationScript(pack: PackBuildSource, cacheDir: string, options?: PackBuildOptions): Promise<PackBuildOutcome>;
100
+ /**
101
+ * Builds (or reuses a cached build of) one pack's TERMINAL script
102
+ * (`terminal.js`): the `ansi` sources of every component that names one,
103
+ * compiled through the same esbuild-wasm in-process path, as one
104
+ * self-contained ESM module (no imports: the loader evaluates it from a
105
+ * `data:` URL). `react` and `ink` imports and JSX read the instances the
106
+ * CLI publishes on `globalThis` (`__markiiReactInk`, `__markiiInk`), only
107
+ * inside render-time functions. The output ends by calling
108
+ * `globalThis.__markiiRegisterTerminalPack(manifestJson, components)`.
109
+ * Returns `'skipped'` when no component names an `ansi` source. A CSS
110
+ * import in a terminal source is compiled away and ignored. Never throws.
111
+ */
112
+ export declare function buildPackTerminalScript(pack: PackBuildSource, cacheDir: string, options?: PackBuildOptions): Promise<PackBuildOutcome>;
113
+ export {};