@tabbr/module-cli 0.1.0 → 0.2.0

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/LICENSE CHANGED
@@ -1,34 +1,34 @@
1
- Tabbr Module CLI License
2
-
3
- Copyright (c) 2026 SystemWorks BV. All rights reserved.
4
-
5
- 1. Grant. Subject to the terms below, SystemWorks BV ("Licensor") grants you a
6
- free, non-exclusive, non-transferable, revocable license to use, copy and
7
- modify the Tabbr Module CLI (the "Software") solely to develop, test and
8
- run modules that are deployed on and used with the Tabbr platform operated
9
- by Licensor.
10
-
11
- 2. Restrictions. You may not:
12
- a. use the Software, or any part or derivative of it, for any purpose other
13
- than the one in section 1, including with any platform, product or
14
- service other than Tabbr;
15
- b. distribute, sublicense, sell or publish the Software or derivatives of it,
16
- except as part of a module distributed solely for use on the Tabbr
17
- platform;
18
- c. remove or alter this license or any copyright notice.
19
-
20
- 3. Ownership. The Software is licensed, not sold. Licensor retains all rights,
21
- title and interest in the Software. Modules you write remain yours, but this
22
- license does not grant any right to the Tabbr platform itself, which is
23
- governed by its own terms of use.
24
-
25
- 4. Termination. This license ends automatically if you breach it, or when your
26
- access to the Tabbr platform ends. On termination you must stop using the
27
- Software.
28
-
29
- 5. No warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
30
- TO THE EXTENT PERMITTED BY LAW, LICENSOR IS NOT LIABLE FOR ANY DAMAGES
31
- ARISING FROM THE USE OF THE SOFTWARE.
32
-
33
- 6. Governing law. This license is governed by Belgian law. The courts of Ghent
34
- (Gent), Belgium have exclusive jurisdiction.
1
+ Tabbr Module CLI License
2
+
3
+ Copyright (c) 2026 SystemWorks BV. All rights reserved.
4
+
5
+ 1. Grant. Subject to the terms below, SystemWorks BV ("Licensor") grants you a
6
+ free, non-exclusive, non-transferable, revocable license to use, copy and
7
+ modify the Tabbr Module CLI (the "Software") solely to develop, test and
8
+ run modules that are deployed on and used with the Tabbr platform operated
9
+ by Licensor.
10
+
11
+ 2. Restrictions. You may not:
12
+ a. use the Software, or any part or derivative of it, for any purpose other
13
+ than the one in section 1, including with any platform, product or
14
+ service other than Tabbr;
15
+ b. distribute, sublicense, sell or publish the Software or derivatives of it,
16
+ except as part of a module distributed solely for use on the Tabbr
17
+ platform;
18
+ c. remove or alter this license or any copyright notice.
19
+
20
+ 3. Ownership. The Software is licensed, not sold. Licensor retains all rights,
21
+ title and interest in the Software. Modules you write remain yours, but this
22
+ license does not grant any right to the Tabbr platform itself, which is
23
+ governed by its own terms of use.
24
+
25
+ 4. Termination. This license ends automatically if you breach it, or when your
26
+ access to the Tabbr platform ends. On termination you must stop using the
27
+ Software.
28
+
29
+ 5. No warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
30
+ TO THE EXTENT PERMITTED BY LAW, LICENSOR IS NOT LIABLE FOR ANY DAMAGES
31
+ ARISING FROM THE USE OF THE SOFTWARE.
32
+
33
+ 6. Governing law. This license is governed by Belgian law. The courts of Ghent
34
+ (Gent), Belgium have exclusive jurisdiction.
package/README.md CHANGED
@@ -1,113 +1,193 @@
1
- # @tabbr/module-cli
2
-
3
- Builds a Native Federation club-module workspace and publishes it to a tabbr club. Also fetches
4
- a club's own generated TypeScript typings into your module workspace.
5
-
6
- The quickest start is the starter project,
7
- [systemworks-bv/tabbr-module-starter](https://github.com/systemworks-bv/tabbr-module-starter),
8
- which has this CLI and npm scripts for it set up already.
9
-
10
- ```bash
11
- npm install -D @tabbr/module-cli
12
- ```
13
-
14
- ## Configuration: tabbr.config.json
15
-
16
- Every option can be passed on the command line, but normally lives in `tabbr.config.json` in the
17
- workspace root (option names in camelCase; command-line options win). `init` writes it for you:
18
-
19
- ```bash
20
- npx tabbr-module init # asks for the club code, module id and title
21
- ```
22
-
23
- ```json
24
- {
25
- "club": "ABC",
26
- "apiHost": "https://api.tabbr.be",
27
- "moduleId": "club.abc.my-module",
28
- "title": "My module",
29
- "exposedModule": "./Module",
30
- "exportName": "Module"
31
- }
32
- ```
33
-
34
- ## Usage: publish
35
-
36
- ```
37
- npx tabbr-module publish [--club ABC] [--module-id club.abc.hello] \
38
- [--exposed-module ./Module] [--export-name Module] \
39
- [--icon waving_hand] [--title "Hello"] [--cwd .] [--api-host https://api.tabbr.be]
40
- ```
41
-
42
- You need the ADMIN role in the club you publish to.
43
-
44
- `--cwd` defaults to the current directory; run the command from your module workspace's root
45
- (where its `angular.json`/`federation.config.js` live), or pass `--cwd` to point at it.
46
-
47
- ### What it does
48
-
49
- 1. Runs `ng build` in the target workspace.
50
- 2. Locates the build output (via `angular.json`'s `build-original` target) and verifies
51
- `remoteEntry.json` exists at its root.
52
- 3. Zips the output.
53
- 4. Logs you in via a browser redirect to Keycloak (PKCE, no password ever touches this CLI) and
54
- caches the resulting token at `~/.tabbr/credentials.json` for reuse on later runs.
55
- 5. Uploads the zip to `POST /api/custommodule` with the club in the `X-club` header, which hosts
56
- the files and registers the module against that club. You need the ADMIN role in that club.
57
-
58
- ## Usage: fetch-types
59
-
60
- ```
61
- npx tabbr-module fetch-types [--club ABC] \
62
- [--out src/types/tabbr/entities.d.ts] [--cwd .] [--api-host https://api.tabbr.be]
63
- ```
64
-
65
- **Default (no `--entity`)**: fetches `GET /api/club/{club}/entities/types` - every entity this
66
- club has (custom fields included), as plain TypeScript data interfaces in ONE combined file
67
- (`src/types/tabbr/entities.d.ts` by default). No script-sandbox globals, so safe to have all of
68
- them in scope together - meant for typing your own component code (e.g. an `httpResource`'s
69
- response), not the script editor. This is the easy way to get everything at once.
70
-
71
- ```
72
- npx tabbr-module fetch-types [--club ABC] --entity flight \
73
- [--kind HOOK|CALCULATION|DEFAULT_CALCULATION|RELEVANT_CONDITION] \
74
- [--out src/types/tabbr/flight.hook.d.ts] [--cwd .] [--api-host https://api.tabbr.be]
75
- ```
76
-
77
- **With `--entity`**: fetches `GET /api/{entity}/meta/script?kind={kind}` instead - the same
78
- generated ambient `.d.ts` tabbr-ui's own script editor (Monaco) feeds itself for that entity's
79
- hook/calculation scripts. It types the script sandbox, not your REST responses, and declares
80
- script-only globals (`current`, `onCreate`, ...) that don't exist in a browser context - see the
81
- comment header the command writes atop the output file for the full explanation, and for why
82
- files fetched for different entities/kinds should generally not sit in the same TypeScript
83
- project as each other (or as the combined `entities.d.ts` above).
84
-
85
- Fetched files reflect one specific club's live, possibly-custom field configuration (field names,
86
- custom entities, ...) and are regenerable on demand - add `src/types/tabbr/` (or wherever `--out`
87
- points) to your workspace's `.gitignore` rather than committing them.
88
-
89
- ## Prerequisite: Keycloak redirect URI
90
-
91
- Login opens your browser to Keycloak and catches the redirect on a temporary local HTTP server
92
- (an ephemeral `http://localhost:<port>/callback`). This requires `http://localhost:*` (or your
93
- chosen fixed port) to be added to the `tabbr` Keycloak client's **Valid Redirect URIs** in the
94
- Keycloak admin console - a one-time setup step, not something this CLI can configure itself.
95
-
96
- ## Non-goals (v1)
97
-
98
- No `login`/`logout`/`whoami` subcommands, no multi-club profiles - `publish` covers the
99
- end-to-end flow on its own.
100
-
101
- ## Releasing
102
-
103
- Commit your CLI changes first, then from this package:
104
-
105
- ```bash
106
- npm run release -- patch --dry-run # preview
107
- npm run release -- patch # or minor / major / an explicit 0.3.0
108
- ```
109
-
110
- Same flow as the SDK (see `tabbr-module-sdk/README.md`): the script bumps the version, commits,
111
- tags `cli-v<version>` and pushes; the tag triggers `.github/workflows/publish-module-cli.yml`,
112
- which publishes via npm Trusted Publishing (owner `systemworks-bv`, repository `gliderdesk`,
113
- workflow `publish-module-cli.yml`).
1
+ # @tabbr/module-cli
2
+
3
+ Builds a Native Federation club-module workspace and publishes it to a tabbr club. Also fetches
4
+ a club's own generated TypeScript typings into your module workspace.
5
+
6
+ The quickest start is the starter project,
7
+ [systemworks-bv/tabbr-module-starter](https://github.com/systemworks-bv/tabbr-module-starter),
8
+ which has this CLI and npm scripts for it set up already.
9
+
10
+ ```bash
11
+ npm install -D @tabbr/module-cli
12
+ ```
13
+
14
+ ## Configuration: tabbr.config.json
15
+
16
+ Every option can be passed on the command line, but normally lives in `tabbr.config.json` in the
17
+ workspace root (option names in camelCase; command-line options win). `init` writes it for you:
18
+
19
+ ```bash
20
+ npx tabbr-module init # asks for the club code, module id and a fallback title
21
+ ```
22
+
23
+ ```json
24
+ {
25
+ "club": "ABC",
26
+ "apiHost": "https://api.tabbr.be",
27
+ "moduleId": "club.abc.my-module",
28
+ "title": "My module",
29
+ "exposedModule": "./Module",
30
+ "exportName": "Module"
31
+ }
32
+ ```
33
+
34
+ ### The title and description of your module
35
+
36
+ The name Tabbr shows for your module (in the settings list and its page header) is translated like the one of its
37
+ own modules: put `module.title` and `module.description` in your translation bundles (nested under your module id,
38
+ e.g. `'module.title': 'My module'`) and list the bundles on your module class so the shell can read them:
39
+
40
+ ```ts
41
+ export class Module extends SimpleModuleBase {
42
+ static readonly i18nBundles = I18N_BUNDLES; // the same map you give provideModuleI18n()
43
+ // ...
44
+ }
45
+ ```
46
+
47
+ `title` in `tabbr.config.json` is then only the **fallback**: what is shown while there is no translation (a module
48
+ without bundles, a language it lacks). `description` falls back to the module id.
49
+
50
+ ## Backend modules
51
+
52
+ A module can also have a **backend** part: TypeScript that runs server-side (not in the browser),
53
+ sandboxed, triggered on a cron schedule or on an entity's create/update - see
54
+ `BackendModuleRuntimeService` in `tabbr-api-server`. Add a `"backend"` block to
55
+ `tabbr.config.json`:
56
+
57
+ ```json
58
+ {
59
+ "backend": {
60
+ "entry": "backend/src/index.ts",
61
+ "allowedHosts": ["admin.gliding.app"],
62
+ "localAllowedHosts": ["localhost"],
63
+ "secretFieldNames": ["apiKey"],
64
+ "triggers": [
65
+ { "type": "CRON", "name": "pollFlights", "cronExpression": "*/5 * * * *", "handler": "pollFlights" },
66
+ { "type": "ENTITY_HOOK", "name": "onFlightSaved", "entity": "flight", "event": "onUpdate", "handler": "onFlightSaved" }
67
+ ]
68
+ }
69
+ }
70
+ ```
71
+
72
+ `entry` (default `backend/src/index.ts`) is a normal TypeScript file exporting plain functions:
73
+
74
+ ```ts
75
+ export function pollFlights() {
76
+ const result = http.fetchJson('https://admin.gliding.app/club/abc/api/flights.json', {
77
+ headers: { 'X-API-KEY': tabbr.settings.get('apiKey') },
78
+ });
79
+ // ...
80
+ tabbr.settings.set('lastPullAt', new Date().toISOString());
81
+ }
82
+ ```
83
+
84
+ - `http.fetchJson(url, options?)` - network access, restricted to `allowedHosts`. `localAllowedHosts` is added to that list
85
+ only by a `publish --local` (e.g. `localhost` for a mock of the external service you develop against) - never by a normal publish.
86
+ - `tabbr.settings.get(key)` / `.set(key, value)` - this module's own per-club settings, including
87
+ its own secrets (never sent back to any settings GET response once saved - `secretFieldNames`).
88
+ - `triggers[].type: "CRON"` runs on the given cron expression (server-local time), with no
89
+ triggering entity. `"ENTITY_HOOK"` runs on the named `entity`'s `event` (`onCreate`/`onUpdate`/
90
+ `onDelete`), with that entity bound under its own name (e.g. `flight`) in the handler's scope.
91
+ - Needs `esbuild` installed in the workspace (`npm install -D esbuild`) - only used at publish
92
+ time, bundled into one dependency-free `bundle.js` the server runs in a GraalVM sandbox, so
93
+ regular npm packages can be imported in your TS but nothing Node-specific (no `fs`, no native
94
+ addons) works at runtime.
95
+
96
+ A "resync now" button (or similar) can fire a `CRON` trigger manually:
97
+ `POST /api/custommodule/{moduleId}/trigger/{triggerName}` (ADMIN).
98
+
99
+ ## Usage: publish
100
+
101
+ ```
102
+ npx tabbr-module publish [--club ABC] [--module-id club.abc.hello] \
103
+ [--exposed-module ./Module] [--export-name Module] \
104
+ [--icon waving_hand] [--title "Hello"] # --title: fallback text, see above [--cwd .] [--api-host https://api.tabbr.be]
105
+ ```
106
+
107
+ You need the ADMIN role in the club you publish to.
108
+
109
+ `--cwd` defaults to the current directory; run the command from your module workspace's root
110
+ (where its `angular.json`/`federation.config.js` live), or pass `--cwd` to point at it.
111
+
112
+ ### What it does
113
+
114
+ Builds and publishes whichever parts are present - frontend, backend, or both - in one zip, one
115
+ upload:
116
+
117
+ 1. If `angular.json` exists: runs `ng build`, locates the output (via `angular.json`'s
118
+ `build-original` target) and verifies `remoteEntry.json` exists at its root.
119
+ 2. If `"backend"` is set in `tabbr.config.json`: bundles the backend entry with `esbuild` into a
120
+ single `bundle.js`, and writes `manifest.json` alongside it from the `backend` config.
121
+ 3. Zips it all together - frontend files flat at the zip root (as before), backend files under a
122
+ `backend/` prefix.
123
+ 4. Logs you in via a browser redirect to Keycloak (PKCE, no password ever touches this CLI) and
124
+ caches the resulting token at `~/.tabbr/credentials.json` for reuse on later runs.
125
+ 5. Uploads the zip to `POST /api/custommodule` with the club in the `X-club` header, which hosts
126
+ the frontend files publicly, stores the backend files privately, and registers the module
127
+ against that club. You need the ADMIN role in that club.
128
+
129
+ ### Publishing to a local environment
130
+
131
+ `npx tabbr-module publish --local` publishes into your own local tabbr (the environment behind
132
+ `<club>.local.tabbr.be`) instead of production: it uploads to `https://api.local.tabbr.be` (set
133
+ `"localApiHost"` in `tabbr.config.json` to use another URL) and trusts your mkcert root CA, which Node
134
+ doesn't do on its own (`NODE_EXTRA_CA_CERTS` is set automatically; if mkcert's root CA can't be found,
135
+ set it yourself - `mkcert -CAROOT` shows where it lives). `--club` picks the club in that environment;
136
+ login still goes through the real Keycloak, which local backends validate too.
137
+
138
+ ## Usage: fetch-types
139
+
140
+ ```
141
+ npx tabbr-module fetch-types [--club ABC] \
142
+ [--out src/types/tabbr/entities.d.ts] [--cwd .] [--api-host https://api.tabbr.be]
143
+ ```
144
+
145
+ **Default (no `--entity`)**: fetches `GET /api/club/{club}/entities/types` - every entity this
146
+ club has (custom fields included), as plain TypeScript data interfaces in ONE combined file
147
+ (`src/types/tabbr/entities.d.ts` by default). No script-sandbox globals, so safe to have all of
148
+ them in scope together - meant for typing your own component code (e.g. an `httpResource`'s
149
+ response), not the script editor. This is the easy way to get everything at once.
150
+
151
+ ```
152
+ npx tabbr-module fetch-types [--club ABC] --entity flight \
153
+ [--kind HOOK|CALCULATION|DEFAULT_CALCULATION|RELEVANT_CONDITION] \
154
+ [--out src/types/tabbr/flight.hook.d.ts] [--cwd .] [--api-host https://api.tabbr.be]
155
+ ```
156
+
157
+ **With `--entity`**: fetches `GET /api/{entity}/meta/script?kind={kind}` instead - the same
158
+ generated ambient `.d.ts` tabbr-ui's own script editor (Monaco) feeds itself for that entity's
159
+ hook/calculation scripts. It types the script sandbox, not your REST responses, and declares
160
+ script-only globals (`current`, `onCreate`, ...) that don't exist in a browser context - see the
161
+ comment header the command writes atop the output file for the full explanation, and for why
162
+ files fetched for different entities/kinds should generally not sit in the same TypeScript
163
+ project as each other (or as the combined `entities.d.ts` above).
164
+
165
+ Fetched files reflect one specific club's live, possibly-custom field configuration (field names,
166
+ custom entities, ...) and are regenerable on demand - add `src/types/tabbr/` (or wherever `--out`
167
+ points) to your workspace's `.gitignore` rather than committing them.
168
+
169
+ ## Prerequisite: Keycloak redirect URI
170
+
171
+ Login opens your browser to Keycloak and catches the redirect on a temporary local HTTP server
172
+ (an ephemeral `http://localhost:<port>/callback`). This requires `http://localhost:*` (or your
173
+ chosen fixed port) to be added to the `tabbr` Keycloak client's **Valid Redirect URIs** in the
174
+ Keycloak admin console - a one-time setup step, not something this CLI can configure itself.
175
+
176
+ ## Non-goals (v1)
177
+
178
+ No `login`/`logout`/`whoami` subcommands, no multi-club profiles - `publish` covers the
179
+ end-to-end flow on its own.
180
+
181
+ ## Releasing
182
+
183
+ Commit your CLI changes first, then from this package:
184
+
185
+ ```bash
186
+ npm run release -- patch --dry-run # preview
187
+ npm run release -- patch # or minor / major / an explicit 0.3.0
188
+ ```
189
+
190
+ Same flow as the SDK (see `tabbr-module-sdk/README.md`): the script bumps the version, commits,
191
+ tags `cli-v<version>` and pushes; the tag triggers `.github/workflows/publish-module-cli.yml`,
192
+ which publishes via npm Trusted Publishing (owner `systemworks-bv`, repository `gliderdesk`,
193
+ workflow `publish-module-cli.yml`).
@@ -8,6 +8,7 @@ const { buildAndZip } = require('../src/build');
8
8
  const { publish } = require('../src/publish');
9
9
  const { fetchScriptTypes, fetchAllEntityTypes, VALID_KINDS } = require('../src/fetch-types');
10
10
  const { CONFIG_FILE, DEFAULT_API_HOST, readConfig, requireClub, runInit } = require('../src/config');
11
+ const { DEFAULT_LOCAL_API_HOST, trustLocalCertificateOrRespawn } = require('../src/local');
11
12
  const DEFAULT_KIND = 'HOOK'; // matches the server's own @RequestParam default for /meta/script
12
13
 
13
14
  function parseArgs(argv) {
@@ -24,6 +25,7 @@ function parseArgs(argv) {
24
25
  case '--title': args.title = next(); break;
25
26
  case '--cwd': args.cwd = path.resolve(next()); break;
26
27
  case '--api-host': args.apiHost = next(); break;
28
+ case '--local': args.local = true; break;
27
29
  case '--entity': args.entity = next(); break;
28
30
  case '--kind': args.kind = next(); break;
29
31
  case '--out': args.out = next(); break;
@@ -44,17 +46,36 @@ Asks for the club code (and module id / title) and writes ${CONFIG_FILE}.
44
46
 
45
47
  Usage: tabbr-module publish [options]
46
48
 
49
+ Builds and publishes whichever parts of the workspace are present, in ONE upload: a frontend (an
50
+ Angular project with a Native Federation "exposes" entry) and/or a backend (a "backend" block in
51
+ ${CONFIG_FILE} pointing at TypeScript run server-side - see README.md). At least one must be
52
+ present.
53
+
47
54
  Required (command line or ${CONFIG_FILE}):
48
55
  --club <CODE> Club code to publish to, e.g. ABC; you need the ADMIN role there
49
56
  --module-id <id> Module id, unique within the club, e.g. club.abc.hello
57
+
58
+ Required for a module with a frontend part:
50
59
  --exposed-module <./Foo> Key in your federation.config.js "exposes" map
51
60
  --export-name <Foo> Named (or default) export implementing PlatformModuleImplementation
52
61
 
62
+ Backend part (all in ${CONFIG_FILE} under "backend", not as CLI flags):
63
+ entry TS entry point, default "backend/src/index.ts"
64
+ allowedHosts External hosts your module's http.fetchJson() may reach
65
+ secretFieldNames Names of your module's settings keys that hold secrets (masked from
66
+ every settings GET response once saved)
67
+ triggers [{type: "CRON", name, cronExpression, handler} |
68
+ {type: "ENTITY_HOOK", name, entity, event, handler}]
69
+
53
70
  Optional:
54
71
  --icon <name> Menu icon name
55
- --title <text> Display title
56
- --cwd <path> Angular workspace to build (default: current directory)
72
+ --title <text> Fallback title (module.title in your i18n bundle is what is shown)
73
+ --cwd <path> Workspace to build (default: current directory)
57
74
  --api-host <url> Tabbr API host (default: ${DEFAULT_API_HOST})
75
+ --local Publish to your own local backend (https://api.local.tabbr.be, i.e. the
76
+ environment behind <club>.local.tabbr.be) instead of production;
77
+ "localApiHost" in ${CONFIG_FILE} overrides the URL. Trusts your mkcert
78
+ root CA automatically.
58
79
 
59
80
  Requires the tabbr Keycloak client's Valid Redirect URIs to include http://localhost:*
60
81
  (a Keycloak admin-console setting - see README.md).
@@ -95,11 +116,12 @@ async function runPublish(args) {
95
116
  args.club = requireClub(args.club);
96
117
  requireFlags(args, {
97
118
  moduleId: '--module-id',
98
- exposedModule: '--exposed-module',
99
- exportName: '--export-name',
100
119
  });
120
+ // exposedModule/exportName are only required for a module with a frontend part (an Angular
121
+ // project at --cwd); buildAndZip/the server reject a module with neither a frontend nor a
122
+ // backend part, so an all-blank publish still fails, just with a clearer error.
101
123
 
102
- const zipBuffer = await buildAndZip(args.cwd);
124
+ const zipBuffer = await buildAndZip(args.cwd, args);
103
125
  const accessToken = await getAccessToken();
104
126
  const result = await publish({
105
127
  apiHost: args.apiHost,
@@ -208,6 +230,12 @@ async function main() {
208
230
  return;
209
231
  }
210
232
  const args = { apiHost: DEFAULT_API_HOST, ...readConfig(flags.cwd), ...flags };
233
+ if (args.local && !flags.apiHost) {
234
+ // --local targets your own local backend (https://api.local.tabbr.be, the same one
235
+ // <club>.local.tabbr.be talks to); "localApiHost" in tabbr.config.json overrides it.
236
+ args.apiHost = args.localApiHost || DEFAULT_LOCAL_API_HOST;
237
+ }
238
+ trustLocalCertificateOrRespawn(args.apiHost);
211
239
  if (command === 'publish') {
212
240
  await runPublish(args);
213
241
  } else {
@@ -217,5 +245,12 @@ async function main() {
217
245
 
218
246
  main().catch(err => {
219
247
  console.error(err.message || err);
248
+ const code = String(err && err.cause && err.cause.code || '');
249
+ if (/CERT|SELF_SIGNED|UNABLE_TO_(GET|VERIFY)/.test(code)) {
250
+ console.error(
251
+ '\nThe server\'s TLS certificate is not trusted by Node. For a local environment (*.local.tabbr.be) run ' +
252
+ '"mkcert -install" and set NODE_EXTRA_CA_CERTS to the path of mkcert\'s rootCA.pem ("mkcert -CAROOT").'
253
+ );
254
+ }
220
255
  process.exit(1);
221
256
  });
package/package.json CHANGED
@@ -1,33 +1,34 @@
1
- {
2
- "name": "@tabbr/module-cli",
3
- "version": "0.1.0",
4
- "description": "Set up, build and publish a Native Federation club module to a tabbr club.",
5
- "license": "SEE LICENSE IN LICENSE",
6
- "author": "SystemWorks BV",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/systemworks-bv/gliderdesk.git",
10
- "directory": "tabbr-module-cli"
11
- },
12
- "publishConfig": {
13
- "access": "public",
14
- "registry": "https://registry.npmjs.org/"
15
- },
16
- "bin": {
17
- "tabbr-module": "bin/tabbr-module.js"
18
- },
19
- "files": [
20
- "bin",
21
- "src"
22
- ],
23
- "scripts": {
24
- "release": "node scripts/release.mjs"
25
- },
26
- "engines": {
27
- "node": ">=20"
28
- },
29
- "dependencies": {
30
- "archiver": "^7.0.1",
31
- "open": "^10.1.0"
32
- }
33
- }
1
+ {
2
+ "name": "@tabbr/module-cli",
3
+ "version": "0.2.0",
4
+ "description": "Set up, build and publish a Native Federation club module to a tabbr club.",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "author": "SystemWorks BV",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/systemworks-bv/gliderdesk.git",
10
+ "directory": "tabbr-module-cli"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "registry": "https://registry.npmjs.org/"
15
+ },
16
+ "bin": {
17
+ "tabbr-module": "bin/tabbr-module.js"
18
+ },
19
+ "files": [
20
+ "bin",
21
+ "src"
22
+ ],
23
+ "scripts": {
24
+ "release": "node scripts/release.mjs",
25
+ "publish:local": "yalc publish --push"
26
+ },
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
30
+ "dependencies": {
31
+ "archiver": "^7.0.1",
32
+ "open": "^10.1.0"
33
+ }
34
+ }