@bitmagic/cli 0.1.53-dev.1 → 0.1.53-dev.11
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/README.md +140 -36
- package/dist/assets/revoxelize.d.ts +61 -1
- package/dist/assets/revoxelize.js +157 -13
- package/dist/assets/revoxelize.js.map +1 -1
- package/dist/cli.d.ts +35 -1
- package/dist/cli.js +18 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/assets.js +3 -2
- package/dist/commands/assets.js.map +1 -1
- package/dist/commands/build.d.ts +4 -0
- package/dist/commands/build.js +7 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cover.d.ts +5 -0
- package/dist/commands/cover.js +3 -0
- package/dist/commands/cover.js.map +1 -1
- package/dist/commands/dev.js +1 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/forge.d.ts +4 -0
- package/dist/commands/forge.js +9 -0
- package/dist/commands/forge.js.map +1 -1
- package/dist/commands/generate.d.ts +25 -0
- package/dist/commands/generate.js +80 -8
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +12 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/publish.d.ts +39 -5
- package/dist/commands/publish.js +102 -21
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/reload.js +1 -3
- package/dist/commands/reload.js.map +1 -1
- package/dist/commands/reset-account.js +25 -8
- package/dist/commands/reset-account.js.map +1 -1
- package/dist/commands/self-update.d.ts +67 -0
- package/dist/commands/self-update.js +196 -0
- package/dist/commands/self-update.js.map +1 -0
- package/dist/commands/upgrade.js +5 -2
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/editor/asset-detail-panel.d.ts +2 -2
- package/dist/editor/asset-detail-panel.js +5 -2
- package/dist/editor/asset-detail-panel.js.map +1 -1
- package/dist/editor/cli-update.d.ts +32 -0
- package/dist/editor/cli-update.js +67 -0
- package/dist/editor/cli-update.js.map +1 -0
- package/dist/editor/publish-panel.d.ts +31 -0
- package/dist/editor/publish-panel.js +69 -0
- package/dist/editor/publish-panel.js.map +1 -0
- package/dist/editor/server.js +43 -1
- package/dist/editor/server.js.map +1 -1
- package/dist/editor/shell-page.js +249 -8
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/forge/upload-proxy.d.ts +14 -0
- package/dist/forge/upload-proxy.js +28 -1
- package/dist/forge/upload-proxy.js.map +1 -1
- package/dist/generate/model.d.ts +7 -0
- package/dist/generate/model.js +13 -3
- package/dist/generate/model.js.map +1 -1
- package/dist/generate/prop.d.ts +20 -0
- package/dist/generate/prop.js +22 -2
- package/dist/generate/prop.js.map +1 -1
- package/dist/generate/vehicle.d.ts +2 -0
- package/dist/generate/vehicle.js +1 -0
- package/dist/generate/vehicle.js.map +1 -1
- package/dist/project/dev-handle.d.ts +28 -0
- package/dist/project/dev-handle.js +43 -0
- package/dist/project/dev-handle.js.map +1 -1
- package/dist/project/jobs.js +11 -9
- package/dist/project/jobs.js.map +1 -1
- package/dist/publish/bundle.d.ts +35 -8
- package/dist/publish/bundle.js +41 -13
- package/dist/publish/bundle.js.map +1 -1
- package/dist/publish/client.d.ts +13 -2
- package/dist/publish/client.js.map +1 -1
- package/dist/publish/record.d.ts +22 -0
- package/dist/publish/record.js +62 -0
- package/dist/publish/record.js.map +1 -0
- package/dist/render/qr-output.d.ts +44 -0
- package/dist/render/qr-output.js +71 -0
- package/dist/render/qr-output.js.map +1 -0
- package/dist/render/qr-png.d.ts +37 -0
- package/dist/render/qr-png.js +111 -0
- package/dist/render/qr-png.js.map +1 -0
- package/dist/render/qr-terminal.d.ts +63 -0
- package/dist/render/qr-terminal.js +142 -0
- package/dist/render/qr-terminal.js.map +1 -0
- package/dist/render/qr.d.ts +51 -0
- package/dist/render/qr.js +516 -0
- package/dist/render/qr.js.map +1 -0
- package/dist/scaffold/project-files.d.ts +42 -9
- package/dist/scaffold/project-files.js +242 -43
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/project.js +2 -1
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/suggest-template.d.ts +2 -0
- package/dist/scaffold/suggest-template.js +2 -1
- package/dist/scaffold/suggest-template.js.map +1 -1
- package/dist/telemetry/command-context.d.ts +12 -0
- package/dist/telemetry/command-context.js +7 -0
- package/dist/telemetry/command-context.js.map +1 -1
- package/dist/telemetry/creator-prompt.d.ts +35 -0
- package/dist/telemetry/creator-prompt.js +45 -0
- package/dist/telemetry/creator-prompt.js.map +1 -0
- package/dist/update/check.js +2 -1
- package/dist/update/check.js.map +1 -1
- package/dist/update/notice.d.ts +31 -1
- package/dist/update/notice.js +39 -5
- package/dist/update/notice.js.map +1 -1
- package/dist/update/self-install.d.ts +175 -0
- package/dist/update/self-install.js +335 -0
- package/dist/update/self-install.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drawing a QR code into the terminal, so the URL `bitmagic publish` just printed can be scanned
|
|
3
|
+
* off the screen instead of retyped into a phone. The Creator has had this since it shipped — the
|
|
4
|
+
* publish dialog ends on a QR — and the CLI's publish is the same moment: `--visibility private`
|
|
5
|
+
* puts a real, phone-reachable URL on a game nobody else can find, which is exactly a "try it on
|
|
6
|
+
* my phone" build.
|
|
7
|
+
*
|
|
8
|
+
* The contract is `inline-image.ts`'s, deliberately: the code is strictly ADDITIONAL. The caller
|
|
9
|
+
* prints the URL first, unconditionally; this either draws underneath it or does nothing at all. It
|
|
10
|
+
* never replaces a line and it never reports failure as an error, because an agent tool is usually
|
|
11
|
+
* what reads this output.
|
|
12
|
+
*
|
|
13
|
+
* That last clause is also why nothing should call this module directly. Refusing to DRAW into a
|
|
14
|
+
* pipe is right; having nothing to offer when there is one is not, and since an agent drives most
|
|
15
|
+
* publishes, the pipe is the common case rather than the edge. `qr-output.ts` owns that decision —
|
|
16
|
+
* it asks this module first and falls back to a PNG file — and `bitmagic publish` goes through it.
|
|
17
|
+
*
|
|
18
|
+
* Where it DIVERGES from that file is the gate. `supportsInlineImage` is an allowlist of terminals
|
|
19
|
+
* known to implement the iTerm2 protocol, because the ones that do not print a screenful of raw
|
|
20
|
+
* base64. Nothing here is exotic: half-block characters and SGR colour are universal, and tmux
|
|
21
|
+
* passes both through rather than swallowing them. So the gate below asks what the terminal can do
|
|
22
|
+
* — is it a terminal at all, is it wide enough — and never who it is.
|
|
23
|
+
*/
|
|
24
|
+
export interface TerminalQrEnv {
|
|
25
|
+
TERM?: string | undefined;
|
|
26
|
+
BITMAGIC_NO_QR?: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether this terminal can show a scannable code at all.
|
|
30
|
+
*
|
|
31
|
+
* Not an allowlist — see the file header. `TERM=dumb` is the one terminal that answers no on its
|
|
32
|
+
* own behalf, and a non-TTY means something is reading this rather than looking at it — which is a
|
|
33
|
+
* reason not to paint escape sequences, NOT a reason to withhold the code. `qr-output.ts` writes an
|
|
34
|
+
* image for every case this function turns down.
|
|
35
|
+
*/
|
|
36
|
+
export declare function supportsTerminalQr(env: TerminalQrEnv, isTTY: boolean): boolean;
|
|
37
|
+
/** How many columns the drawn code occupies, quiet zone included. */
|
|
38
|
+
export declare function terminalQrWidth(matrix: boolean[][]): number;
|
|
39
|
+
/**
|
|
40
|
+
* The code as terminal lines, quiet zone included and each line self-contained.
|
|
41
|
+
*
|
|
42
|
+
* Exported so a test can read the output without a TTY. The padded symbol has an odd number of
|
|
43
|
+
* module rows — the module count is always odd and the quiet zone adds an even number — so the
|
|
44
|
+
* final terminal row pairs its top half against a light row that is not in the symbol. That is
|
|
45
|
+
* correct rather than a rounding artefact: it reads as one more row of quiet zone.
|
|
46
|
+
*/
|
|
47
|
+
export declare function terminalQrLines(matrix: boolean[][]): string[];
|
|
48
|
+
export interface RenderTerminalQrOptions {
|
|
49
|
+
env?: TerminalQrEnv;
|
|
50
|
+
isTTY?: boolean;
|
|
51
|
+
/** Terminal width. Undefined means unknown, which is treated as wide enough. */
|
|
52
|
+
columns?: number | undefined;
|
|
53
|
+
write?: (chunk: string) => void;
|
|
54
|
+
caption?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Draw `text` as a QR code if this terminal can show one. Returns whether anything was drawn, so a
|
|
58
|
+
* caller can decide what else to say — never throws, and never writes when unsupported.
|
|
59
|
+
*
|
|
60
|
+
* The caption and the code go out in a single write, so the creator never sees an invitation to
|
|
61
|
+
* scan with nothing under it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function renderTerminalQr(text: string, options?: RenderTerminalQrOptions): boolean;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drawing a QR code into the terminal, so the URL `bitmagic publish` just printed can be scanned
|
|
3
|
+
* off the screen instead of retyped into a phone. The Creator has had this since it shipped — the
|
|
4
|
+
* publish dialog ends on a QR — and the CLI's publish is the same moment: `--visibility private`
|
|
5
|
+
* puts a real, phone-reachable URL on a game nobody else can find, which is exactly a "try it on
|
|
6
|
+
* my phone" build.
|
|
7
|
+
*
|
|
8
|
+
* The contract is `inline-image.ts`'s, deliberately: the code is strictly ADDITIONAL. The caller
|
|
9
|
+
* prints the URL first, unconditionally; this either draws underneath it or does nothing at all. It
|
|
10
|
+
* never replaces a line and it never reports failure as an error, because an agent tool is usually
|
|
11
|
+
* what reads this output.
|
|
12
|
+
*
|
|
13
|
+
* That last clause is also why nothing should call this module directly. Refusing to DRAW into a
|
|
14
|
+
* pipe is right; having nothing to offer when there is one is not, and since an agent drives most
|
|
15
|
+
* publishes, the pipe is the common case rather than the edge. `qr-output.ts` owns that decision —
|
|
16
|
+
* it asks this module first and falls back to a PNG file — and `bitmagic publish` goes through it.
|
|
17
|
+
*
|
|
18
|
+
* Where it DIVERGES from that file is the gate. `supportsInlineImage` is an allowlist of terminals
|
|
19
|
+
* known to implement the iTerm2 protocol, because the ones that do not print a screenful of raw
|
|
20
|
+
* base64. Nothing here is exotic: half-block characters and SGR colour are universal, and tmux
|
|
21
|
+
* passes both through rather than swallowing them. So the gate below asks what the terminal can do
|
|
22
|
+
* — is it a terminal at all, is it wide enough — and never who it is.
|
|
23
|
+
*/
|
|
24
|
+
import { encodeQr } from './qr.js';
|
|
25
|
+
/** Written as an escape rather than a literal control byte, so the source stays greppable. */
|
|
26
|
+
const ESC = '\u001b';
|
|
27
|
+
/**
|
|
28
|
+
* Black on bright white, and the reset that closes every line.
|
|
29
|
+
*
|
|
30
|
+
* Explicit on purpose. A scanner wants dark modules on a light field, and the creator's terminal is
|
|
31
|
+
* probably a dark theme — left to inherit, the code would come out inverted, which many scanners
|
|
32
|
+
* cope with and some do not. The reset ends each line so the colour cannot bleed into a wrapped
|
|
33
|
+
* line or the prompt. Bright white (107) rather than plain white (47) because the latter is a light
|
|
34
|
+
* grey in most palettes, and contrast is the one thing a scanner cannot make up for.
|
|
35
|
+
*/
|
|
36
|
+
const PAINT = `${ESC}[30;107m`;
|
|
37
|
+
const RESET = `${ESC}[0m`;
|
|
38
|
+
/**
|
|
39
|
+
* Quiet-zone width in modules, matching the `margin: 2` the Creator passes `QRCode.toDataURL` —
|
|
40
|
+
* a value already proven to scan in production. The spec asks for 4; if scans ever prove flaky,
|
|
41
|
+
* that is the knob, and it costs 4 columns and 1 line.
|
|
42
|
+
*/
|
|
43
|
+
const QUIET_ZONE = 2;
|
|
44
|
+
/**
|
|
45
|
+
* Two module rows per terminal row, drawn with half-blocks.
|
|
46
|
+
*
|
|
47
|
+
* This is what makes the code square. Terminal cells are roughly twice as tall as they are wide, so
|
|
48
|
+
* one module per cell would stretch the symbol into a rectangle no scanner would read; half-blocks
|
|
49
|
+
* put two module rows in one cell and bring the aspect ratio back to 1:1.
|
|
50
|
+
*/
|
|
51
|
+
const BOTH_DARK = '█'; // full block
|
|
52
|
+
const TOP_DARK = '▀'; // upper half block
|
|
53
|
+
const BOTTOM_DARK = '▄'; // lower half block
|
|
54
|
+
const BOTH_LIGHT = ' ';
|
|
55
|
+
/**
|
|
56
|
+
* Whether this terminal can show a scannable code at all.
|
|
57
|
+
*
|
|
58
|
+
* Not an allowlist — see the file header. `TERM=dumb` is the one terminal that answers no on its
|
|
59
|
+
* own behalf, and a non-TTY means something is reading this rather than looking at it — which is a
|
|
60
|
+
* reason not to paint escape sequences, NOT a reason to withhold the code. `qr-output.ts` writes an
|
|
61
|
+
* image for every case this function turns down.
|
|
62
|
+
*/
|
|
63
|
+
export function supportsTerminalQr(env, isTTY) {
|
|
64
|
+
if (!isTTY)
|
|
65
|
+
return false;
|
|
66
|
+
if (env.BITMAGIC_NO_QR)
|
|
67
|
+
return false;
|
|
68
|
+
return env.TERM !== 'dumb';
|
|
69
|
+
}
|
|
70
|
+
/** How many columns the drawn code occupies, quiet zone included. */
|
|
71
|
+
export function terminalQrWidth(matrix) {
|
|
72
|
+
return matrix.length + QUIET_ZONE * 2;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The code as terminal lines, quiet zone included and each line self-contained.
|
|
76
|
+
*
|
|
77
|
+
* Exported so a test can read the output without a TTY. The padded symbol has an odd number of
|
|
78
|
+
* module rows — the module count is always odd and the quiet zone adds an even number — so the
|
|
79
|
+
* final terminal row pairs its top half against a light row that is not in the symbol. That is
|
|
80
|
+
* correct rather than a rounding artefact: it reads as one more row of quiet zone.
|
|
81
|
+
*/
|
|
82
|
+
export function terminalQrLines(matrix) {
|
|
83
|
+
const width = terminalQrWidth(matrix);
|
|
84
|
+
const height = width;
|
|
85
|
+
const dark = (row, col) => {
|
|
86
|
+
const r = row - QUIET_ZONE;
|
|
87
|
+
const c = col - QUIET_ZONE;
|
|
88
|
+
if (r < 0 || c < 0 || r >= matrix.length || c >= matrix.length)
|
|
89
|
+
return false;
|
|
90
|
+
return matrix[r][c];
|
|
91
|
+
};
|
|
92
|
+
const lines = [];
|
|
93
|
+
for (let row = 0; row < height; row += 2) {
|
|
94
|
+
let line = '';
|
|
95
|
+
for (let col = 0; col < width; col += 1) {
|
|
96
|
+
const top = dark(row, col);
|
|
97
|
+
const bottom = row + 1 < height && dark(row + 1, col);
|
|
98
|
+
if (top && bottom)
|
|
99
|
+
line += BOTH_DARK;
|
|
100
|
+
else if (top)
|
|
101
|
+
line += TOP_DARK;
|
|
102
|
+
else if (bottom)
|
|
103
|
+
line += BOTTOM_DARK;
|
|
104
|
+
else
|
|
105
|
+
line += BOTH_LIGHT;
|
|
106
|
+
}
|
|
107
|
+
lines.push(`${PAINT}${line}${RESET}`);
|
|
108
|
+
}
|
|
109
|
+
return lines;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Draw `text` as a QR code if this terminal can show one. Returns whether anything was drawn, so a
|
|
113
|
+
* caller can decide what else to say — never throws, and never writes when unsupported.
|
|
114
|
+
*
|
|
115
|
+
* The caption and the code go out in a single write, so the creator never sees an invitation to
|
|
116
|
+
* scan with nothing under it.
|
|
117
|
+
*/
|
|
118
|
+
export function renderTerminalQr(text, options = {}) {
|
|
119
|
+
const env = options.env ?? process.env;
|
|
120
|
+
const isTTY = options.isTTY ?? process.stdout.isTTY === true;
|
|
121
|
+
if (!supportsTerminalQr(env, isTTY))
|
|
122
|
+
return false;
|
|
123
|
+
const matrix = encodeQr(text);
|
|
124
|
+
if (matrix === null)
|
|
125
|
+
return false;
|
|
126
|
+
// A code wider than the terminal wraps, and a wrapped code is not a code — it is noise that
|
|
127
|
+
// looks like output. Better to leave the plain URL standing on its own.
|
|
128
|
+
const columns = options.columns ?? process.stdout.columns;
|
|
129
|
+
if (typeof columns === 'number' && columns < terminalQrWidth(matrix))
|
|
130
|
+
return false;
|
|
131
|
+
const caption = options.caption ?? 'Scan to play on your phone:';
|
|
132
|
+
const write = options.write ?? ((chunk) => process.stdout.write(chunk));
|
|
133
|
+
try {
|
|
134
|
+
write(`\n${caption}\n\n${terminalQrLines(matrix).join('\n')}\n\n`);
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// A closed or non-writable stdout is not worth failing a successful publish over.
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=qr-terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-terminal.js","sourceRoot":"","sources":["../../src/render/qr-terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A QR encoder, so `bitmagic publish` can hand the creator's phone the URL it just printed.
|
|
3
|
+
*
|
|
4
|
+
* The Creator does this server-side already — `PublishController.generateQRCode` calls the `qrcode`
|
|
5
|
+
* package and the publish dialog shows the PNG. The CLI cannot follow it there: `qrcode` drags in
|
|
6
|
+
* `dijkstrajs`, `pngjs` and `yargs@15`, and `@bitmagic/cli` is a published package with four
|
|
7
|
+
* deliberately-chosen runtime dependencies. So the encoder lives here instead, cut down to exactly
|
|
8
|
+
* what a published-game URL needs:
|
|
9
|
+
*
|
|
10
|
+
* - **Byte mode only.** A URL is bytes. Numeric, alphanumeric and kanji modes would encode it
|
|
11
|
+
* smaller in theory and never in practice, because `https://` alone rules out alphanumeric.
|
|
12
|
+
* - **Error correction level M only**, matching the Creator's `errorCorrectionLevel: 'M'` — a code
|
|
13
|
+
* scanned from this terminal and one scanned from the publish dialog then behave identically.
|
|
14
|
+
* - **Versions 1-9 only.** The character-count indicator is 8 bits up to version 9 and 16 bits
|
|
15
|
+
* from version 10, so stopping here removes a branch and four tables. Version 9 holds 180 bytes;
|
|
16
|
+
* the longest URL this ever sees is the dev portal's, around 60. Anything longer returns null
|
|
17
|
+
* rather than growing the tables — see `encodeQr`.
|
|
18
|
+
*
|
|
19
|
+
* Structure follows ISO/IEC 18004. Every table below is a literal with the spec's own name for it,
|
|
20
|
+
* and `__tests__/qr.test.ts` checks each one against fixtures generated by the `qrcode` package, so
|
|
21
|
+
* a transposed digit fails loudly instead of producing a code that scans as garbage.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* The spec's four penalty rules (8.8.2), summed. Lower is better.
|
|
25
|
+
*
|
|
26
|
+
* Scored over the entire symbol including function patterns, as the spec requires — the finders'
|
|
27
|
+
* own 1:1:3:1:1 ratio is exactly what rule 3 hunts for elsewhere, and excluding them would let a
|
|
28
|
+
* mask hide a false finder against a real one.
|
|
29
|
+
*/
|
|
30
|
+
export declare function maskPenalty(matrix: boolean[][]): number;
|
|
31
|
+
/**
|
|
32
|
+
* Encode `text` with an explicitly chosen mask.
|
|
33
|
+
*
|
|
34
|
+
* Exported for the fixture tests, which pin the mask so they compare structure — codewords, ECC,
|
|
35
|
+
* interleaving, function patterns, format bits — rather than a mask heuristic. Callers outside the
|
|
36
|
+
* tests want `encodeQr`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function encodeQrWithMask(text: string, mask: number): boolean[][] | null;
|
|
39
|
+
/**
|
|
40
|
+
* Encode `text` as a matrix of modules, row-major, true meaning dark. Null when it does not fit.
|
|
41
|
+
*
|
|
42
|
+
* The mask is chosen by the spec's penalty rules. That choice is a legibility heuristic and not a
|
|
43
|
+
* correctness property — all eight masks produce a valid, scannable symbol, and a decoder reads the
|
|
44
|
+
* chosen one out of the format information either way.
|
|
45
|
+
*
|
|
46
|
+
* There is no quiet zone here: it belongs to whatever draws the symbol, which knows what it is
|
|
47
|
+
* drawing onto. `qr-terminal.ts` paints its own.
|
|
48
|
+
*/
|
|
49
|
+
export declare function encodeQr(text: string): boolean[][] | null;
|
|
50
|
+
/** The longest text this encoder can hold, in bytes. Exported so a caller can explain a refusal. */
|
|
51
|
+
export declare const MAX_BYTES: number;
|