# Technical documentation — magalies-pharma-heisenberg-print-server

Evidence date: 2026-10-09. Revision: `master` `07aa3df` (2022-10-19).

## What this repository is

A Bitbucket Git repository of a Node.js Express process that renders Zebra ZPL with Handlebars and sends it to a local printer through `@thiagoelg/node-printer`.

There is one branch, `master`. 59 commits, from 2022-07-05 through 2022-10-19. 11 tracked files.

Authors: Nick Thorby (`nick@exonic.co.za`) and Jordan Levy (`jordan@exonic.co.za`). One Jordan commit uses `jord@Jordans-MacBook-Pro.local`. Early Nick commits use the author name `Nick` with the same Exonic address.

`sonar-project.properties` and `sonarqube_scan.bat` were listed by the onboarding scan and are not in git history.

## Repository layout

```text
magalies-pharma-heisenberg-print-server/
  server.js                 Express routes, port, printer queue names
  print.js                  printBarcode, printLabel
  templates/barcodes.zpl    Batch label
  templates/labels.zpl      Standard medicine label
  templates/labels_small.zpl
  package.json              name heisenberg-test-print, main index.js
  package-lock.json         lockfileVersion 2
  README.md                 Heading only
  .gitignore                node_modules
  .DS_Store                 Tracked
  .print.js.swp             Tracked Vim swap, added in b7319b4
```

No `index.js`, Dockerfile, pipeline, `.env` example, test directory, or SQL.

`node_modules` is ignored and is not in git. A checkout does not run until `npm install`. The printer package has `hasInstallScript: true` in the lockfile and depends on `nan` and `prebuild-install`, so install compiles or downloads a native binding. **Implemented** in `package-lock.json`. Which Node ABI that binding must match is **Unknown / Requires Confirmation.**

## Runtime

`package.json` does not set `engines`. Scripts:

| Script | Command |
|---|---|
| `test` | `echo "Error: no test specified" && exit 1` |
| `start` | not defined |

`main` is `index.js`. That file is not in the tree. The process that listens is `server.js`. **Inferred** start command: `node server.js`.

Locked direct dependencies:

| Package | Version |
|---|---|
| `express` | 4.18.1 |
| `body-parser` | 1.20.0 |
| `cors` | 2.8.5 |
| `handlebars` | 4.7.7 |
| `@thiagoelg/node-printer` | 0.5.6 |

Requires in source are `express`, `body-parser`, `cors`, `@thiagoelg/node-printer/lib`, and `handlebars/lib`. The `/lib` paths load an internal entry rather than the package root. **Implemented.**

## HTTP surface

Bind: `app.listen(3000)` with no hostname. **Implemented.** Whether that is wrapped by a reverse proxy or a Windows service is **Unknown / Requires Confirmation.**

| Method and path | Success body | Error body in this repo |
|---|---|---|
| `GET /` | `This is the Heisenberg Print Server` | none |
| `POST /barcode` | `{ "message": "Printing barcodes" }` | `{ "message": "Printing failed" }` when `printBarcode` rejects. Status is still `res.json`'s default |
| `POST /label` | `{ "message": "Printing labels" }` | no `catch` |

`bodyParser.json()` is the only body parser. There is no URL-encoded parser and no explicit size option, so the parser's own default limit applies. **Implemented** as `bodyParser.json()` with no arguments. The numeric default is the library's, not a value in this repo.

### `POST /barcode` body

| Field | Use |
|---|---|
| `description` | Template `description`. Renamed from `label_description` in `07aa3df` |
| `expiry_date` | Template `expiry` |
| `batch_number` | Prefix of the QR value, and template `batch_number`. Renamed from `barcode` in `a44f442` |
| `quantity` | Loop count |
| `starting_number` | First suffix. Falsy becomes `1` |

### `POST /label` body

| Field | Use |
|---|---|
| `description` | Template `description` |
| `directions` | Passed to Handlebars. Printed only by `templates/labels.zpl` |
| `client` | Both label templates |
| `medicine_number` | QR prefix. Renamed from `barcode` in `a44f442` |
| `order_number` | Template `order_number`, printed as `Rx No:`. Renamed from `batch_number` in `a44f442` |
| `quantity` | Loop count |
| `dispensed_by` | Passed to Handlebars. Not referenced by either template at HEAD |
| `contained_quantity` | Printed as `Qty:` |
| `prescriber` | Both label templates |
| `date` | Both label templates |
| `starting_number` | First suffix. Falsy becomes `1` |
| `size` | `small` selects the small template and `Small-Label-Printer`. Anything else selects the standard template and `Big-Label-Printer`. Falsy is passed on as `standard` |

## Print path

`print.js` reads the three templates with `fs.readFileSync` and `utf8` when the module loads. `handlebars.compile` runs on each call, not at load.

Suffix:

```text
("0000" + (starting_number + x)).slice(-4)
```

Batch QR data: `{batch_number}-{suffix}`.

Medicine QR data: `{medicine_number}-{suffix}`.

Copies are joined with `\n` into `complete_string`. `printer.printDirect` options are `data`, `printer`, `type: "RAW"`, `success` (resolve), and `error` (console.error, then `reject()` with no reason).

Printer name constants in `server.js`:

| Constant | Queue string | Used for |
|---|---|---|
| `barcode_printer` | `Barcode-Printer` | every `/barcode` call |
| `small_label_printer` | `Small-Label-Printer` | `/label` when `size == 'small'` |
| `large_label_printer` | `Big-Label-Printer` | every other `/label` call |

History of those strings, from `server.js` diffs:

| When | Names |
|---|---|
| `ea73a4b` (2022-07-05) | Label `XP-TT426B-2`, barcode `XP-TT426B` |
| `07f6024` (2022-07-26) | Label `XP-TT426B-2`, barcode `XP-TT426B` after a short-lived `Xprinter XP-TT426B` on both |
| `f9a9c98` (2022-10-12) | Small `XP-TT426B`. Barcode and large both `XP-TT426B-2` |
| `231ccd3` (2022-10-19) | Current names |

## ZPL templates at HEAD

Commands below are the text of the files. Printer interpretation of a command that this process never tests is **Unknown**.

### `templates/barcodes.zpl`

- `^XA` … `^XZ`
- `^LH30,0`
- Font `^A0N,18,20`, block `^FB225,3,0,C,10`
- Field `{{description}}`, `Expiry:{{expiry}}`, `{{batch_number}}`
- QR `^BQN,2,3^FD,,,{{barcode}}`
- `^SF%%%%%%dddd`
- `^PQ{{quantity}}` which the renderer sets to 1

### `templates/labels.zpl`

- `^LH0,288`, orientation `^FWR`
- Description in `^CF0,18,50`
- Body in `^CFC,12,12`: `Directions: {{directions}}`, `{{client}}`, `Rx No:{{order_number}}`, `{{prescriber}}`, `Qty:{{contained_quantity}}`, `{{date}}`
- QR `^BQN,2,3,^FD,,,{{barcode}}`
- No `^PQ` and no `^SF`

### `templates/labels_small.zpl`

- Second line is `LH36,42` with no leading `^`. The other two templates use `^LH`. **Implemented** as that byte sequence. **Requires Confirmation** whether the printer applies label home.
- Font `^CFA,13,10`
- `{{description}}`, `{{client}}`, `Rx No:{{order_number}}`, `Qty:{{contained_quantity}}`, `{{prescriber}}`, `{{date}}`
- QR `^BQB,2,3,^FD,,,{{barcode}}` (orientation `B`, unlike `N` on the other two)
- No directions, no `^PQ`, no `^SF`

`593ccfa` (2022-10-12, "fixed qr codes ignoring letters") introduced the commas before `{{barcode}}`. Later "fixed bq size" commits on 2022-10-19 set the magnification argument to `3` and produced the three-comma form now in git.

## Hosting history

The Bitbucket remote inspected here is `git@bitbucket.org:overdrive/magalies-pharma-heisenberg-print-server.git`, branch `master`.

Merge messages record two earlier hosts:

- `gitlab.assemble.co.za:magalies-pharma/heisenberg-print-server` (`49c6f3e`, 2022-07-26)
- `ssh://git-codecommit.eu-west-1.amazonaws.com/v1/repos/magalies-pharma-heisenberg-print-server` (`f22c5fc`, `7ec216f`, 2022-10-12), including branch `testing/local`

Neither remote is configured in the clone used for this document. `package.json` has no `repository` field.

No deployment descriptor names a server, a port mapping, or a Windows service. Where the process runs is **Unknown / Requires Confirmation.**

## Auth, storage, jobs, monitoring

| Area | In this repository |
|---|---|
| Authentication | None |
| Authorisation | None |
| Session | None |
| Database | None |
| File storage | The three ZPL templates only. No uploads |
| Queue or worker | The OS print spooler, via `printDirect`. No application queue |
| Background job | No |
| Logging | `console.log` on listen. `console.error` on printer error. No log library |
| Metrics or health JSON | No. `GET /` returns a fixed sentence |
| Secrets in git | No passwords or keys were found in the tracked source |
| Tests | `npm test` fails on purpose. No runner |

## Security notes from the code

These are observations, not a pentest.

- Any client that can open port 3000 can submit a print job. **Implemented.**
- CORS is enabled without an origin argument. **Implemented.**
- Printer errors on `/barcode` are returned as HTTP 200 with a message string. **Implemented.**
- `quantity` is not capped, and each unit adds a full ZPL document to one string. **Implemented.**
- `.print.js.swp` is tracked. It is an editor swap file from `b7319b4`, not a runtime input.

## Development and test process

No contribution guide. Work on 2022-10-19 is a sequence of small commits that adjust one template or one variable at a time, including eighteen commits titled "updated medicine label heading".

The only automated command in `package.json` exits 1. Nothing in git shows a manual test checklist. Sixteen commits on 2022-10-19 are titled "updated medicine label heading".

## Related Silicon Ark project

`magalies-pharma-heisenberg-serverless` documents the Heisenberg API: batches, batch items, and a packaging scan that splits a barcode on the first `-`. This print server is a separate repository and does not import that code. A caller that printed here and scanned there is **Inferred**, and **Requires Confirmation**.
