@oscaraccountant/cli 0.0.0-stage → 0.1.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 +21 -0
- package/README.md +29 -2
- package/bin/oscar.js +153 -0
- package/package.json +41 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OscarAI OÜ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @oscaraccountant/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`oscar`, the command-line tool of the Oscar accounting API.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @oscaraccountant/cli login # log in in the browser (or --device, or --api-key)
|
|
7
|
+
npx @oscaraccountant/cli whoami
|
|
8
|
+
npx @oscaraccountant/cli invoices list --all
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install it once: `npm install --global @oscaraccountant/cli`, then run `oscar`.
|
|
12
|
+
|
|
13
|
+
`oscar login` stores its credential in the keychain of the OS. On a server or
|
|
14
|
+
in CI, set `OSCAR_API_KEY` to an organization API key instead: it wins over
|
|
15
|
+
the login.
|
|
16
|
+
|
|
17
|
+
The package holds a small Node script. The binary itself comes in one optional package per
|
|
18
|
+
platform (`@oscaraccountant/cli-linux-x64`, `-linux-arm64`, `-darwin-arm64`, `-darwin-x64`,
|
|
19
|
+
`-win32-x64`, `-win32-arm64`), and npm installs only the one for your machine. There is no
|
|
20
|
+
install script.
|
|
21
|
+
|
|
22
|
+
When `oscar` says that the binary is missing, npm skipped the optional package: this happens
|
|
23
|
+
when a lockfile was made on another platform, or with `--omit=optional`. Delete `node_modules`
|
|
24
|
+
and `package-lock.json` and install again.
|
|
25
|
+
|
|
26
|
+
The documentation of the commands is `oscar --help`, and the guides and the
|
|
27
|
+
reference of the API are at <https://oscaraccountant.com/docs>. The source is
|
|
28
|
+
<https://github.com/oscaraccountant/oscaraccountant-rust>.
|
|
29
|
+
|
|
30
|
+
MIT License, copyright OscarAI OÜ.
|
package/bin/oscar.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `oscar` command of @oscaraccountant/cli. It finds the binary of this platform in its optional
|
|
3
|
+
// dependency @oscaraccountant/cli-<platform>-<arch>, runs it with the same arguments, and ends
|
|
4
|
+
// with the same exit code or signal. No dependency and no postinstall script: the pattern of
|
|
5
|
+
// esbuild and Biome.
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const childProcess = require('child_process');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
const PACKAGES = {
|
|
12
|
+
'darwin-arm64': '@oscaraccountant/cli-darwin-arm64',
|
|
13
|
+
'darwin-x64': '@oscaraccountant/cli-darwin-x64',
|
|
14
|
+
'linux-x64': '@oscaraccountant/cli-linux-x64',
|
|
15
|
+
'linux-arm64': '@oscaraccountant/cli-linux-arm64',
|
|
16
|
+
'win32-x64': '@oscaraccountant/cli-win32-x64',
|
|
17
|
+
'win32-arm64': '@oscaraccountant/cli-win32-arm64',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// The signals the shim passes on to the binary. On Windows the console sends Ctrl+C to every
|
|
21
|
+
// process on it, so the shim only keeps itself alive.
|
|
22
|
+
const SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGBREAK'];
|
|
23
|
+
|
|
24
|
+
function version() {
|
|
25
|
+
try {
|
|
26
|
+
return require('../package.json').version;
|
|
27
|
+
} catch {
|
|
28
|
+
return 'latest';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The platform package of this machine, or null when there is none. */
|
|
33
|
+
function packageName(platform, arch) {
|
|
34
|
+
return PACKAGES[`${platform}-${arch}`] || null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The message when the binary cannot be found. */
|
|
38
|
+
function missingMessage(platform, arch, name) {
|
|
39
|
+
if (name === null) {
|
|
40
|
+
return (
|
|
41
|
+
`oscar: there is no oscar binary for ${platform}-${arch}.\n` +
|
|
42
|
+
`The supported platforms are: ${Object.keys(PACKAGES).join(', ')}.\n`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return (
|
|
46
|
+
`oscar: the binary for ${platform}-${arch} is missing: the optional package ${name} is not installed.\n` +
|
|
47
|
+
'This happens when a lockfile was made on another platform (https://github.com/npm/cli/issues/4828),\n' +
|
|
48
|
+
'or when optional dependencies are turned off (--omit=optional, --no-optional).\n' +
|
|
49
|
+
'To fix it, delete node_modules and package-lock.json and install again with optional dependencies,\n' +
|
|
50
|
+
`or run: npx @oscaraccountant/cli@${version()}\n`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The path of the binary: OSCAR_CLI_BINARY when set (for tests), else the file of the platform
|
|
56
|
+
* package. null when it is not installed.
|
|
57
|
+
*/
|
|
58
|
+
function binaryPath(env, platform, arch, resolve) {
|
|
59
|
+
if (env.OSCAR_CLI_BINARY) {
|
|
60
|
+
return env.OSCAR_CLI_BINARY;
|
|
61
|
+
}
|
|
62
|
+
const name = packageName(platform, arch);
|
|
63
|
+
if (name === null) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const file = platform === 'win32' ? 'oscar.exe' : 'oscar';
|
|
67
|
+
try {
|
|
68
|
+
return resolve(`${name}/bin/${file}`);
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Some package managers drop the executable bit; put it back when the file allows it. */
|
|
75
|
+
function ensureExecutable(file, platform) {
|
|
76
|
+
if (platform === 'win32') {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
fs.accessSync(file, fs.constants.X_OK);
|
|
81
|
+
} catch {
|
|
82
|
+
try {
|
|
83
|
+
fs.chmodSync(file, 0o755);
|
|
84
|
+
} catch {
|
|
85
|
+
// The run below reports the real error.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The exit code of a process that a signal ended, as a shell reports it. */
|
|
91
|
+
function signalExitCode(signal) {
|
|
92
|
+
const number = require('os').constants.signals[signal];
|
|
93
|
+
return 128 + (number || 1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function main() {
|
|
97
|
+
const platform = process.platform;
|
|
98
|
+
const arch = process.arch;
|
|
99
|
+
const binary = binaryPath(process.env, platform, arch, require.resolve);
|
|
100
|
+
if (binary === null) {
|
|
101
|
+
process.stderr.write(missingMessage(platform, arch, packageName(platform, arch)));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
ensureExecutable(binary, platform);
|
|
105
|
+
const child = childProcess.spawn(binary, process.argv.slice(2), {
|
|
106
|
+
stdio: 'inherit',
|
|
107
|
+
windowsHide: false,
|
|
108
|
+
});
|
|
109
|
+
const forwarders = new Map();
|
|
110
|
+
for (const signal of SIGNALS) {
|
|
111
|
+
const forward = () => {
|
|
112
|
+
if (platform !== 'win32' && child.exitCode === null) {
|
|
113
|
+
try {
|
|
114
|
+
child.kill(signal);
|
|
115
|
+
} catch {
|
|
116
|
+
// The child has ended already.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
try {
|
|
121
|
+
process.on(signal, forward);
|
|
122
|
+
forwarders.set(signal, forward);
|
|
123
|
+
} catch {
|
|
124
|
+
// A signal this platform does not have.
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
child.on('error', (error) => {
|
|
128
|
+
process.stderr.write(`oscar: cannot run ${binary}: ${error.message}\n`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
});
|
|
131
|
+
child.on('exit', (code, signal) => {
|
|
132
|
+
for (const [name, forward] of forwarders) {
|
|
133
|
+
process.removeListener(name, forward);
|
|
134
|
+
}
|
|
135
|
+
if (signal) {
|
|
136
|
+
// End the same way, so the caller sees the signal.
|
|
137
|
+
setTimeout(() => process.exit(signalExitCode(signal)), 200);
|
|
138
|
+
try {
|
|
139
|
+
process.kill(process.pid, signal);
|
|
140
|
+
} catch {
|
|
141
|
+
process.exit(signalExitCode(signal));
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
process.exit(code === null ? 1 : code);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = { PACKAGES, binaryPath, missingMessage, packageName, signalExitCode, version };
|
|
150
|
+
|
|
151
|
+
if (require.main === module) {
|
|
152
|
+
main();
|
|
153
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscaraccountant/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "oscar, the command-line tool of the Oscar accounting API",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "OscarAI OÜ",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/oscaraccountant/oscaraccountant-rust.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://oscaraccountant.com/docs",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/oscaraccountant/oscaraccountant-rust/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"oscar",
|
|
17
|
+
"accounting",
|
|
18
|
+
"api",
|
|
19
|
+
"cli",
|
|
20
|
+
"bookkeeping",
|
|
21
|
+
"invoices",
|
|
22
|
+
"estonia"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"oscar": "bin/oscar.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/oscar.js",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"optionalDependencies": {
|
|
36
|
+
"@oscaraccountant/cli-darwin-arm64": "0.1.0",
|
|
37
|
+
"@oscaraccountant/cli-darwin-x64": "0.1.0",
|
|
38
|
+
"@oscaraccountant/cli-linux-x64": "0.1.0",
|
|
39
|
+
"@oscaraccountant/cli-linux-arm64": "0.1.0",
|
|
40
|
+
"@oscaraccountant/cli-win32-x64": "0.1.0",
|
|
41
|
+
"@oscaraccountant/cli-win32-arm64": "0.1.0"
|
|
42
|
+
}
|
|
43
|
+
}
|