Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 13 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@ Wire harness drawings from JSON. Design harnesses as `*.harness.json` files (by

## Quickstart

```bash
npm install && npm run build
No install needed — run everything with `npx`:

```bash
# live-preview viewer over a folder of harness files
node packages/cli/dist/index.js dev ./examples
npx almond-harness-studio dev ./harnesses

# validate
node packages/cli/dist/index.js validate examples/*.harness.json
npx almond-harness-studio validate my-harness.harness.json

# pull distributor data (MPN, photo, price) for every referenced part
node packages/cli/dist/index.js parts fetch examples/branched-battery-pigtail.harness.json
npx almond-harness-studio parts fetch my-harness.harness.json

# headless vector PDF export (no browser needed)
node packages/cli/dist/index.js export examples/branched-battery-pigtail.harness.json -o harness.pdf
npx almond-harness-studio export my-harness.harness.json -o harness.pdf

# wiring table + BOM as CSV
node packages/cli/dist/index.js tables examples/branched-battery-pigtail.harness.json
npx almond-harness-studio tables my-harness.harness.json
```

Once the packages are published to npm, the same commands run anywhere as `npx almond-harness-studio <cmd>` — no clone needed.
Or install globally with `npm install -g almond-harness-studio`.

## The format in 30 seconds

Expand All @@ -50,16 +50,16 @@ Components are always real, orderable parts referenced by distributor part numbe
}
```

Supported today: multi-branch harnesses, twisted pairs and shielded multicore cables (`wireGroups`), ring/spade/ferrule/quick-connect/tinned/bare/solder-cup/pin terminations, splices, inline diodes and resistors (flyback diodes, pull resistors), jumper (loopback) wires, connector crimp contacts and hardware (locks/boots/backshells), heatshrink / PET braid / split loom / spiral wrap coverings, striped wire colors, per-node layout overrides, and CSV wiring-table/BOM export (`tables`).
Supported today: multi-branch harnesses, twisted pairs and shielded multicore cables (`wireGroups`), ring/spade/ferrule/quick-connect/tinned/bare/solder-cup/pin terminations, splices, inline diodes and resistors (flyback diodes, pull resistors), jumper (loopback) wires, connector crimp contacts and hardware (locks/boots/backshells), connector assembly details (`face`: real pin pattern with wire colors and bend direction), heatshrink / PET braid / split loom / spiral wrap coverings, striped wire colors, per-node layout overrides, and CSV wiring-table/BOM export (`tables`).

### Part sourcing

`parts fetch` resolves every `part` reference against the distributor and embeds the record under the file's top-level `parts` object — drawings then render offline with product photos and a sourced BOM. LCSC needs no API key; Mouser and Digi-Key keys are yours:

```bash
node packages/cli/dist/index.js config set mouser.apiKey <key> # mouser.com/api-hub
node packages/cli/dist/index.js config set digikey.clientId <id> # developer.digikey.com
node packages/cli/dist/index.js config set digikey.clientSecret <secret>
npx almond-harness-studio config set mouser.apiKey <key> # mouser.com/api-hub
npx almond-harness-studio config set digikey.clientId <id> # developer.digikey.com
npx almond-harness-studio config set digikey.clientSecret <secret>
```

Keys live in `~/.config/almond-harness-studio/config.json` (or `MOUSER_API_KEY`, `DIGIKEY_CLIENT_ID`, `DIGIKEY_CLIENT_SECRET` env vars). The viewer also has an "API keys…" dialog — keys stay in the browser's localStorage and part lookups go through your local dev server.
Expand Down Expand Up @@ -112,6 +112,7 @@ No environment variables or serverless functions are needed — the viewer is fu
## Development

```bash
npm install
npm run dev # Vite dev server with HMR, API backed by ./examples
npm run typecheck
npm run build
Expand All @@ -120,15 +121,6 @@ npm run check:examples # validates all example harnesses

Point the dev viewer at a private data folder: `ALMOND_DATA_DIR=/path/to/harnesses npm run dev`.

### Releasing to npm

Three packages ship together, same version: `@almond-harness-studio/core`, `@almond-harness-studio/app`, and the CLI `almond-harness-studio` (which bundles the viewer for `dev`). From a clean checkout:

```bash
npm ci && npm run build && npm run check:examples
npm publish -w @almond-harness-studio/core -w @almond-harness-studio/app -w almond-harness-studio
```

## License

MIT
11 changes: 11 additions & 0 deletions examples/branched-battery-pigtail.harness.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@
"vendor": "lcsc",
"number": "C30170181"
},
"face": {
"view": "wire-side",
"wireBend": "down",
"note": "PCB PROVIDED BY CUSTOMER (NOT IN BOM)",
"pins": [
{ "pin": "1", "x": 0, "y": 0, "size": 1.7 },
{ "pin": "2", "x": 10, "y": 0, "size": 1.7 },
{ "pin": "S1", "x": 15.5, "y": 3.2, "size": 0.9 },
{ "pin": "S2", "x": 15.5, "y": -3.2, "size": 0.9 }
]
},
"pins": [
{
"id": "1",
Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"packages/*"
],
"scripts": {
"build": "npm run build -w @almond-harness-studio/core -w @almond-harness-studio/app -w almond-harness-studio",
"dev": "npm run dev -w @almond-harness-studio/app",
"build": "npm run build -w @almond-bot/harness-studio-core -w @almond-bot/harness-studio-app -w almond-harness-studio",
"dev": "npm run dev -w @almond-bot/harness-studio-app",
"check:examples": "node packages/cli/dist/index.js validate examples/*.harness.json skill/examples/*.harness.json",
"typecheck": "tsc -b packages/core packages/cli && tsc --noEmit -p packages/app"
},
Expand Down
9 changes: 9 additions & 0 deletions packages/app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @almond-bot/harness-studio-app

Prebuilt viewer app for [almond-harness-studio](https://www.npmjs.com/package/almond-harness-studio) wire harness drawings. This package ships the static `dist/` bundle that the CLI serves for its `dev` live-preview command — you normally don't install it directly.

```bash
npx almond-harness-studio dev ./harnesses
```

Full documentation: [github.com/almond-bot/harness-studio](https://github.com/almond-bot/harness-studio)
6 changes: 3 additions & 3 deletions packages/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@almond-harness-studio/app",
"version": "0.1.0",
"name": "@almond-bot/harness-studio-app",
"version": "0.1.1",
"description": "Viewer app for almond-harness-studio wire harness drawings",
"license": "MIT",
"type": "module",
Expand All @@ -21,7 +21,7 @@
"preview": "vite preview"
},
"dependencies": {
"@almond-harness-studio/core": "0.1.0",
"@almond-bot/harness-studio-core": "0.1.1",
"@fontsource-variable/geist": "^5.2.9",
"@fontsource-variable/inter": "^5.2.8",
"jspdf": "^3.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { collectPartRefs, partKey } from "@almond-harness-studio/core";
import { collectPartRefs, partKey } from "@almond-bot/harness-studio-core";
import { Preview } from "./Preview";
import {
fetchHarnessFile,
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/useHarness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
renderHarnessSvg,
type Harness,
type ValidationIssue,
} from "@almond-harness-studio/core";
} from "@almond-bot/harness-studio-core";

export interface LoadedHarness {
sourceName: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"types": ["vite/client"],
"paths": {
"@almond-harness-studio/core": ["../core/src/index.ts"]
"@almond-bot/harness-studio-core": ["../core/src/index.ts"]
}
},
"include": ["src", "vite.config.ts"]
Expand Down
2 changes: 1 addition & 1 deletion packages/app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default defineConfig({
plugins: [react(), harnessApi()],
resolve: {
alias: {
"@almond-harness-studio/core": path.resolve(here, "../core/src/index.ts"),
"@almond-bot/harness-studio-core": path.resolve(here, "../core/src/index.ts"),
},
},
});
10 changes: 6 additions & 4 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "almond-harness-studio",
"version": "0.1.0",
"version": "0.1.1",
"description": "CLI for almond-harness-studio: live-preview server, validation, and headless PDF export of wire harness drawings",
"license": "MIT",
"type": "module",
Expand Down Expand Up @@ -33,11 +33,13 @@
],
"scripts": {
"build": "tsc -b",
"dev": "tsc -b --watch"
"dev": "tsc -b --watch",
"prepack": "cp ../../README.md ./README.md",
"postpack": "rm -f ./README.md"
},
"dependencies": {
"@almond-harness-studio/core": "0.1.0",
"@almond-harness-studio/app": "0.1.0",
"@almond-bot/harness-studio-core": "0.1.1",
"@almond-bot/harness-studio-app": "0.1.1",
"chokidar": "^4.0.3",
"commander": "^14.0.0",
"pdfkit": "^0.17.1",
Expand Down
10 changes: 6 additions & 4 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ import {
buildWireList,
type Harness,
type PartsCache,
} from "@almond-harness-studio/core";
} from "@almond-bot/harness-studio-core";
Comment thread
shawnpatel marked this conversation as resolved.
import { createApiHandler } from "./middleware.js";
import { CONFIG_PATH, loadConfig, resolvePart, saveConfigValue } from "./vendors.js";

const require = createRequire(import.meta.url);
const { version: cliVersion } = require("../package.json") as { version: string };

const program = new Command();
program
.name("almond-harness-studio")
.description("Wire harness drawings from JSON: live preview, validation, and PDF export")
.version("0.1.0");
.version(cliVersion);

function loadAndValidate(file: string, raw: string): { harness?: Harness; ok: boolean } {
let data: unknown;
Expand Down Expand Up @@ -273,8 +276,7 @@ const MIME: Record<string, string> = {

function findAppDist(): string | null {
try {
const require = createRequire(import.meta.url);
const appPkg = require.resolve("@almond-harness-studio/app/package.json");
const appPkg = require.resolve("@almond-bot/harness-studio-app/package.json");
return path.join(path.dirname(appPkg), "dist");
} catch {
return null;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { promises as fs } from "node:fs";
import path from "node:path";
import type { IncomingMessage, ServerResponse } from "node:http";
import { collectPartRefs, partKey, type Harness, type PartsCache } from "@almond-harness-studio/core";
import { collectPartRefs, partKey, type Harness, type PartsCache } from "@almond-bot/harness-studio-core";
import { loadConfig, resolvePart, type VendorConfig } from "./vendors.js";

type Next = () => void;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/vendors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { promises as fs } from "node:fs";
import os from "node:os";
import path from "node:path";
import type { PartRef, ResolvedPart } from "@almond-harness-studio/core";
import type { PartRef, ResolvedPart } from "@almond-bot/harness-studio-core";

/**
* Distributor API clients. Parts are always sourced from a real vendor:
Expand Down
11 changes: 11 additions & 0 deletions packages/core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# @almond-bot/harness-studio-core

Schema, validation, tree layout, and pure SVG-string rendering for [almond-harness-studio](https://www.npmjs.com/package/almond-harness-studio) wire harness drawings. No React — runs in Node and the browser.

Most users want the CLI instead:

```bash
npx almond-harness-studio dev ./harnesses
```

Full documentation: [github.com/almond-bot/harness-studio](https://github.com/almond-bot/harness-studio)
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@almond-harness-studio/core",
"version": "0.1.0",
"name": "@almond-bot/harness-studio-core",
"version": "0.1.1",
"description": "Schema, validation, layout, and SVG rendering for almond-harness-studio wire harness drawings",
"license": "MIT",
"type": "module",
Expand Down
Loading
Loading