The free @vazen/toml package reads ProSpace .psa planogram files from JDA and Blue Yonder Space Planning. It converts them to JSON or Vazen TOML, and writes them back as PSA. It runs without Space Planning.
PSA files
Read and convert ProSpace PSA planogram files
Is this your file?
A ProSpace PSA file is text. It starts with these lines:
PROSPACE SCHEMATIC FILE
; Version 2024.4.0
; Codepage=1252The version changes from file to file. Unreal Engine animation files also use the .psa extension. This package does not read them.
Installation
Install the package and Effect from npm:
npm install @vazen/toml effectThe package needs Node.js >=24 and ES modules. Effect ^4.0.0 is a peer dependency. A Python package is planned.
The examples on this page use @vazen/toml 0.4.0 and Node.js 24.
Convert PSA to JSON
Download the made-up file v2024.4.0.psa (opens in a new tab) and save it as example.psa, or run:
curl -o example.psa https://raw.githubusercontent.com/vazen/toml/main/typescript/src/psa/.test-data/v2024.4.0.psaSave this script as convert-to-json.mjs beside the file. Then run node convert-to-json.mjs.
import { readFileSync, writeFileSync } from 'node:fs';
import {
decodeVazenProjectFromPsaFile,
encodeJsonFileFromVazenProject,
} from '@vazen/toml';
const { project } = decodeVazenProjectFromPsaFile(readFileSync('example.psa'));
writeFileSync(
'example.vazen.json',
encodeJsonFileFromVazenProject({ project }),
);The start of example.vazen.json is:
{
"schema": "vazen/layout",
"schema_version": "0.3.0",
"name": "Fictional Project 5",
"products": [
{
"ref": "p_18jm0l02ylwz1",
"name": "Product 01",
"gtin": "5000000000001",
"dimensions": {
"width": 65,
"height": 120,
"depth": 60
},
"_psa__id": "7000001",Convert PSA to Vazen TOML
Save this script as convert-to-toml.mjs beside the file. Then run node convert-to-toml.mjs.
import { readFileSync, writeFileSync } from 'node:fs';
import {
decodeVazenProjectFromPsaFile,
encodeTomlFileFromVazenProject,
} from '@vazen/toml';
const { project, source, messages } = decodeVazenProjectFromPsaFile(
readFileSync('example.psa'),
);
writeFileSync(
'example.vazen.toml',
encodeTomlFileFromVazenProject({ project }),
);
console.log(source);
// Output: { declaredVersion: '2024.4.0', format: 'psa' }
console.log(messages);
// Output: []The start of example.vazen.toml is:
schema = "vazen/layout"
schema_version = "0.3.0"
name = "Fictional Project 5"
_psa__key = "PRJ-5"
_psa__primary_key = "id"
_psa__case_multiple = 1
_psa__days_supply = 7
_psa__number_of_stores = 12The JSON and the TOML file hold the same tables:
- Each planogram becomes a fixture.
- Each fixture row becomes equipment in that fixture.
- Each position becomes a site.
- Every length is in millimetres.
- A value with a standard key uses that key. Every other value becomes a
_psa__key on its table, unless the value is the column’s default.
The specification defines each table.
Convert from the command line
The package's vazen-toml command converts a file without a script, and never changes the file. This writes the same example.vazen.toml:
npx @vazen/toml@0.4.0 convert example.psa --to toml > example.vazen.tomlinspect lists the plans in a file, and --plan converts one of them. The package README (opens in a new tab) lists the command's diagnostics and exit codes.
Write a PSA file
encodePsaFileFromVazenProject writes a layout as a PSA file. This script reads example.vazen.toml and writes it as PSA:
import { readFileSync, writeFileSync } from 'node:fs';
import {
decodeVazenProjectFromTomlFile,
encodePsaFileFromVazenProject,
} from '@vazen/toml';
const { project } = decodeVazenProjectFromTomlFile(
readFileSync('example.vazen.toml', 'utf8'),
);
writeFileSync('example-copy.psa', encodePsaFileFromVazenProject({ project }));The writer writes PSA 2024.4.0. The version option names another version that PsaVersion lists: 2017.1.0, 2017.2.0, 2019.1.0, 2019.1.1, 2020.1.0, 2020.1.1, 2021.1.2, 2023.1.0, 2024.1.0, 2024.4.0.
const bytes = encodePsaFileFromVazenProject({ project, version: '2017.2.0' });The writer refuses a value that a column of that version cannot hold. It writes every file in Windows-1252.
What a conversion keeps
The reader reads a file as UTF-8 if it is valid UTF-8, and as Windows-1252 if not. Reading makes a best effort and reports any lost values, uncertain interpretations or generated ids in messages, beside the project. An empty list means no messages were reported. Each entry identifies the affected record type, rows and column where known:
| Message | Meaning |
|---|---|
UnlistedWidth | Rows with a cell count that no listed version has for their type. They are read by position, so a value can be in the wrong column. |
DroppedCells | Values in cells after the last column of a row. They are dropped. |
UnreadCells | Cells that their column cannot read. They are read as empty. |
IgnoredRows | Rows with no place in PsaData, such as a position before the first fixture of its planogram. They are ignored. |
GeneratedIds | Planograms without a key. Each gets an id from its place in the file, such as planogram-1, which writing puts in its key. |
Read a PSA file, then write the project as PSA again. The project can pass through TOML or JSON between the two steps. For a file read with no messages, the new file holds the same values, with these differences:
- A cell that holds its column’s default can become empty, and an empty cell can get the default. The value does not change.
- Text is written in Unicode’s composed form, and U+FFFD is written as
?. - A length is rounded to nine decimal places of a millimetre.
- The number format, line endings and row order can change.
So a round trip does not give the same bytes. The PSA README (opens in a new tab) gives every rule for reading and writing.
Edit PSA records
To edit PSA columns directly, read the records, not a project. decodePsaDataFromPsaFile returns PsaData, the rows of the file as records, and its messages. encodePsaFileFromPsaData writes the records as a file. The API overview lists every function.
Blue Yonder and .psa are trademarks of their respective owners. Vazen is not affiliated with or endorsed by Blue Yonder. PSA support was built from PSA files that customers supplied or that were published online; column and value names follow ProSpace’s field definitions. No Blue Yonder software was used.