@altronix/cli 0.7.2 → 0.7.4

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/src/build.ts DELETED
@@ -1,354 +0,0 @@
1
- import dotenv from "dotenv";
2
- import { Ajv, JSONSchemaType } from "ajv";
3
- import { Command } from "commander";
4
- import path from "node:path";
5
- import fs from "node:fs";
6
- import cp from "node:child_process";
7
- import {
8
- concat,
9
- from,
10
- lastValueFrom,
11
- merge,
12
- mergeMap,
13
- Observable,
14
- OperatorFunction,
15
- } from "rxjs";
16
-
17
- interface AtxConfig {
18
- configs?: string[];
19
- overlays?: string[];
20
- }
21
- interface AtxBoard {
22
- [key: string]: AtxConfig;
23
- }
24
-
25
- interface AtxBuild {
26
- sourceDir: string;
27
- binaryDir: string;
28
- installDir: string;
29
- boards: { [key: string]: AtxBoard };
30
- }
31
- interface AtxWorkspace {
32
- applications: { [key: string]: AtxBuild };
33
- bootloaders: { [key: string]: AtxBuild };
34
- }
35
-
36
- const ajv = new Ajv({ allErrors: true, verbose: true });
37
- const schemaBuild: JSONSchemaType<{ [key: string]: AtxBuild }> = {
38
- type: "object",
39
- required: [],
40
- patternProperties: {
41
- ".*": {
42
- type: "object",
43
- required: ["sourceDir", "binaryDir", "installDir", "boards"],
44
- properties: {
45
- sourceDir: { type: "string" },
46
- binaryDir: { type: "string" },
47
- installDir: { type: "string" },
48
- boards: {
49
- type: "object",
50
- required: [],
51
- patternProperties: {
52
- ".*": {
53
- type: "object",
54
- required: [],
55
- patternProperties: {
56
- ".*": {
57
- type: "object",
58
- properties: {
59
- configs: {
60
- type: "array",
61
- items: { type: "string" },
62
- nullable: true,
63
- },
64
- overlays: {
65
- type: "array",
66
- items: { type: "string" },
67
- nullable: true,
68
- },
69
- },
70
- },
71
- },
72
- },
73
- },
74
- },
75
- },
76
- },
77
- },
78
- };
79
- const schema: JSONSchemaType<AtxWorkspace> = {
80
- type: "object",
81
- required: ["applications", "bootloaders"],
82
- additionalProperties: false,
83
- properties: {
84
- applications: schemaBuild,
85
- bootloaders: schemaBuild,
86
- },
87
- };
88
- const validate = ajv.compile(schema);
89
-
90
- interface Version {
91
- major: number;
92
- minor: number;
93
- patch: number;
94
- tweak: number;
95
- extra: string;
96
- }
97
- async function parseAppVersion(v: string): Promise<Version> {
98
- const data = await fs.promises.readFile(v, "ascii");
99
- const reMajor = data.matchAll(/^VERSION_MAJOR = ([0-9]+)/gm).next();
100
- const reMinor = data.matchAll(/^VERSION_MINOR = ([0-9]+)/gm).next();
101
- const rePatch = data.matchAll(/^PATCHLEVEL = ([0-9]+)/gm).next();
102
- const reTweak = data.matchAll(/^VERSION_TWEAK = ([0-9]+)/gm).next();
103
- const reExtra = data.matchAll(/^EXTRAVERSION = ([.a-zA-Z-]+)/gm).next();
104
-
105
- return {
106
- major: reMajor.value ? parseInt(reMajor.value[1]) : 0,
107
- minor: reMinor.value ? parseInt(reMinor.value[1]) : 0,
108
- patch: rePatch.value ? parseInt(rePatch.value[1]) : 0,
109
- tweak: reTweak.value ? parseInt(reTweak.value[1]) : 0,
110
- extra: reExtra.value ? reExtra.value[1] : "",
111
- };
112
- }
113
-
114
- function formatVersion(ver: Version): string {
115
- const { major, minor, patch, tweak, extra } = ver;
116
- return extra.length
117
- ? `${major}-${minor}-${patch}-${tweak}-${extra}`
118
- : `${major}-${minor}-${patch}-${tweak}`;
119
- }
120
-
121
- interface WestOptions {
122
- cwd: string;
123
- name: string;
124
- board: string;
125
- config: string;
126
- version: string;
127
- sourceDir: string;
128
- binaryDir: string;
129
- installDir: string;
130
- outputFile: string;
131
- errorFile: string;
132
- confs: string[];
133
- overlays: string[];
134
- }
135
-
136
- async function normalizeWestOptions(
137
- appName: string,
138
- boardName: string,
139
- configName: string,
140
- app: AtxBuild,
141
- cwd: string
142
- ) {
143
- const resolve = (dir: string, from?: string) =>
144
- path.isAbsolute(dir) ? dir : path.resolve(from || cwd, dir);
145
- const sourceDir = resolve(app.sourceDir);
146
- const binaryDir = path.join(resolve(app.binaryDir), boardName, configName);
147
- const installDir = resolve(app.installDir);
148
- const confs = app.boards[boardName][configName].configs || [];
149
- const versionFile = path.join(sourceDir, "VERSION");
150
- const version = formatVersion(await parseAppVersion(versionFile));
151
- const overlays = [];
152
- return {
153
- name: appName,
154
- board: boardName,
155
- config: configName,
156
- cwd,
157
- version,
158
- sourceDir,
159
- binaryDir,
160
- installDir,
161
- outputFile: path.join(binaryDir, "build.log"),
162
- errorFile: path.join(binaryDir, "build.err"),
163
- confs,
164
- overlays,
165
- };
166
- }
167
-
168
- function extraApplicationConfs(extraConfs: string): Observable<void> {
169
- const key = process.env["ALTRONIX_RELEASE_KEY"];
170
- if (!key) throw new Error("missing ALTRONIX_RELEASE_KEY from environment");
171
- const extraConfsData = [
172
- `CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="${key}"`,
173
- `CONFIG_BOOTLOADER_MCUBOOT=y`,
174
- `CONFIG_ATX_UPDATE_ENABLE=y`,
175
- ].join("\r\n");
176
- return from(fs.promises.writeFile(extraConfs, extraConfsData));
177
- }
178
-
179
- function emulateBytePages(board: string) {
180
- return (
181
- board.startsWith("atsame54_xpro") ||
182
- board.startsWith("netway4e1bt") ||
183
- board.startsWith("netway4eb") ||
184
- board.startsWith("netway5pq") ||
185
- board.startsWith("oa2b")
186
- );
187
- }
188
-
189
- function extraBootloaderConfs(
190
- board: string,
191
- extraConfs: string
192
- ): Observable<void> {
193
- const key = process.env["ALTRONIX_RELEASE_KEY"];
194
- if (!key) throw new Error("missing ALTRONIX_RELEASE_KEY from environment");
195
- const extraConfsData = [`CONFIG_BOOT_SIGNATURE_KEY_FILE="${key}"`];
196
- if (emulateBytePages(board)) {
197
- extraConfsData.push(`CONFIG_SOC_FLASH_SAM0_EMULATE_BYTE_PAGES=y`);
198
- }
199
- return from(fs.promises.writeFile(extraConfs, extraConfsData.join("\r\n")));
200
- }
201
-
202
- function west(args: WestOptions): Observable<void> {
203
- const { cwd, board, sourceDir, binaryDir, confs, overlays } = args;
204
- const westArgs = [
205
- `build`,
206
- `-b ${board}`,
207
- `-s ${sourceDir}`,
208
- `-d ${binaryDir}`,
209
- `--`,
210
- `-DEXTRA_CONF_FILE="${[...confs].join(";")}"`,
211
- `-DEXTRA_DTC_OVERLAY_FILE="${[...overlays].join(";")}"`,
212
- ];
213
-
214
- return new Observable((subscriber) => {
215
- const west = cp.spawn("west", westArgs, { cwd, shell: true });
216
- const fout = fs.createWriteStream(args.outputFile);
217
- const ferr = fs.createWriteStream(args.errorFile);
218
- west.stdout.pipe(fout);
219
- west.stderr.pipe(ferr);
220
- west.on("error", (e) => {
221
- subscriber.error(e);
222
- fout.close();
223
- ferr.close();
224
- });
225
- west.on("exit", () => {
226
- fout.close();
227
- ferr.close();
228
- subscriber.next();
229
- subscriber.complete();
230
- });
231
- });
232
- }
233
-
234
- function installSignedBin(args: WestOptions): Observable<void> {
235
- const { name, config, version, board, binaryDir, installDir: dir } = args;
236
- const src = path.join(binaryDir, "zephyr", "zephyr.signed.bin");
237
- const dst = path.join(
238
- dir,
239
- `${board}-${name}-${config}-${version}.signed.bin`
240
- );
241
- return new Observable((subscriber) => {
242
- fs.promises
243
- .copyFile(src, dst)
244
- .then(() => subscriber.next())
245
- .catch((e) => subscriber.error(e))
246
- .finally(() => subscriber.complete());
247
- });
248
- }
249
-
250
- function installBin(args: WestOptions): Observable<void> {
251
- const { name, config, board, binaryDir, installDir: dir } = args;
252
- const src = path.join(binaryDir, "zephyr", "zephyr.bin");
253
- const dst = path.join(dir, `${board}-${name}-${config}.bin`);
254
- return new Observable((subscriber) => {
255
- fs.promises
256
- .copyFile(src, dst)
257
- .then(() => subscriber.next())
258
- .catch((e) => subscriber.error(e))
259
- .finally(() => subscriber.complete());
260
- });
261
- }
262
-
263
- function mkdir(): OperatorFunction<string, void> {
264
- return (obs$) =>
265
- obs$.pipe(
266
- mergeMap(
267
- (dir) =>
268
- new Observable<void>((subscriber) => {
269
- fs.promises
270
- .mkdir(dir, { recursive: true })
271
- .then(() => subscriber.next())
272
- .catch((e) => subscriber.error(e))
273
- .finally(() => subscriber.complete());
274
- })
275
- )
276
- );
277
- }
278
-
279
- interface RunBuildOptions {
280
- install$: Observable<void>;
281
- config$: Observable<void>;
282
- }
283
- function runBuild({
284
- install$,
285
- config$,
286
- }: RunBuildOptions): OperatorFunction<WestOptions, void> {
287
- return (obs$) => {
288
- // Create all the directories for our build
289
- const dirs$ = obs$.pipe(
290
- mergeMap(({ binaryDir, installDir }) => from([binaryDir, installDir])),
291
- mkdir()
292
- );
293
- // Run west commands
294
- const build$ = obs$.pipe(mergeMap((opts) => west(opts)));
295
- return concat(dirs$, config$, build$, install$);
296
- };
297
- }
298
-
299
- export async function build(this: Command): Promise<void> {
300
- const config = this.opts().config || path.resolve("./", "atx.json");
301
- const cwd = path.resolve(path.dirname(config));
302
- const data = await fs.promises.readFile(config, "ascii");
303
- const atx: AtxWorkspace = JSON.parse(data);
304
- const extraAppConfFile = "application.conf";
305
- const extraBootConfFile = "bootloader.conf";
306
- if (!validate(atx)) throw validate.errors;
307
- const env = path.resolve(cwd, ".env");
308
- dotenv.config({ path: env });
309
- const apps = Object.keys(atx.applications).flatMap((app) => {
310
- return Object.keys(atx.applications[app].boards).flatMap((board) => {
311
- return Object.keys(atx.applications[app].boards[board]).map((config) =>
312
- normalizeWestOptions(app, board, config, atx.applications[app], cwd)
313
- );
314
- });
315
- });
316
-
317
- const bootloaders = Object.keys(atx.bootloaders).flatMap((app) => {
318
- return Object.keys(atx.bootloaders[app].boards).flatMap((board) => {
319
- return Object.keys(atx.bootloaders[app].boards[board]).map((config) =>
320
- normalizeWestOptions(app, board, config, atx.bootloaders[app], cwd)
321
- );
322
- });
323
- });
324
-
325
- const apps$ = from(await Promise.all(apps));
326
- const bootloaders$ = from(await Promise.all(bootloaders));
327
- return lastValueFrom(
328
- merge(
329
- bootloaders$.pipe(
330
- runBuild({
331
- install$: bootloaders$.pipe(mergeMap((opts) => installBin(opts))),
332
- config$: bootloaders$.pipe(
333
- mergeMap(({ board, binaryDir }) =>
334
- extraBootloaderConfs(
335
- board,
336
- path.join(binaryDir, extraBootConfFile)
337
- )
338
- )
339
- ),
340
- })
341
- ),
342
- apps$.pipe(
343
- runBuild({
344
- install$: apps$.pipe(mergeMap((opts) => installSignedBin(opts))),
345
- config$: apps$.pipe(
346
- mergeMap(({ binaryDir }) =>
347
- extraApplicationConfs(path.join(binaryDir, extraAppConfFile))
348
- )
349
- ),
350
- })
351
- )
352
- )
353
- );
354
- }
package/src/index.ts DELETED
@@ -1,40 +0,0 @@
1
- import { program } from "commander";
2
- import path from "path";
3
- import fs from "fs";
4
- import * as seedle from "./seedle";
5
- import { build } from "./build";
6
-
7
- (async function main() {
8
- // Parse package.json to get version
9
- const pkg = path.resolve(__dirname, "..", "package.json");
10
- const ver = JSON.parse(await fs.promises.readFile(pkg, "ascii")).version;
11
- const cwd = path.resolve("./");
12
-
13
- program
14
- .name("atx")
15
- .description("build atx zdk projects")
16
- .version(ver);
17
-
18
- // Scan command
19
- const ignore = "node_modules;target;build;.git";
20
- program
21
- .command("scan")
22
- .description("scan for *.cddl files")
23
- .option("-p, --path <PATH>", "root directory to start scan", cwd)
24
- .option("-m, --matches <REGEX>", "match expression", ".*cddl$")
25
- .option("-i, --ignores <REGEX>", "ignore directories", ignore)
26
- .action(seedle.scan);
27
-
28
- // Build command
29
- program
30
- .command("build")
31
- .description("build atx zdk application")
32
- .option("-c, --config <CONFIG>", "workspace config file")
33
- .action(build);
34
-
35
- try {
36
- await program.parseAsync();
37
- } catch (e) {
38
- console.error(e);
39
- }
40
- })();
package/src/seedle.ts DELETED
@@ -1,39 +0,0 @@
1
- import { Command } from "commander";
2
- import path from "path";
3
- import fs from "fs";
4
- import dotenv from "dotenv";
5
-
6
- export async function scan(this: Command) {
7
- // parse matches
8
- const matches = this.opts()
9
- .matches.split(";")
10
- .map((s: string) => new RegExp(s, "g"));
11
-
12
- // parse ignores
13
- const ignores = this.opts()
14
- .ignores.split(";")
15
- .map((s: string) => new RegExp(s, "g"));
16
-
17
- // parse start directory and load env.
18
- const start = this.opts().path;
19
- const env = path.join(start, ".env");
20
- dotenv.config({ path: env });
21
-
22
- // Log out matches
23
- for await (const f of walk(start, matches, ignores)) {
24
- console.log(f);
25
- }
26
- }
27
-
28
- async function* walk(dir: string, matches: RegExp[], ignores: RegExp[]) {
29
- for await (const d of await fs.promises.opendir(dir)) {
30
- const entry = path.join(dir, d.name);
31
- if (d.isDirectory()) {
32
- const i = ignores.map((i) => entry.match(i)).filter((r) => r);
33
- if (i.length == 0) yield* await walk(entry, matches, ignores);
34
- } else if (d.isFile()) {
35
- const m = matches.map((m) => entry.match(m)).filter((r) => r);
36
- if (m.length > 0) yield entry;
37
- }
38
- }
39
- }
package/tsconfig.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "lib": ["ES2022"],
6
- "moduleResolution": "Node16",
7
- "declaration": true,
8
- "composite": true,
9
- "isolatedModules": true,
10
- "allowSyntheticDefaultImports": true,
11
- "importHelpers": true,
12
- "alwaysStrict": true,
13
- "sourceMap": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "noFallthroughCasesInSwitch": true,
16
- "noImplicitReturns": true,
17
- "noUnusedLocals": true,
18
- "noUnusedParameters": true,
19
- "noImplicitAny": false,
20
- "noImplicitThis": false,
21
- "strictNullChecks": true,
22
- "paths":{
23
- "@altronix/wasm/zdk": ["../wasm/zdk"]
24
- }
25
- },
26
- "references":[
27
- {"path": "tsconfig.lib.json"}
28
- ]
29
- }
package/tsconfig.lib.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "build",
5
- "rootDir": "src"
6
- },
7
- "include": ["src/**/*"]
8
- }