@freecodecamp/universe-cli 0.8.0 → 0.8.1
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 +29 -13
- package/README.md +12 -71
- package/dist/index.cjs +20 -9
- package/dist/index.js +20 -9
- package/package.json +3 -3
package/LICENSE
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014, freeCodeCamp.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Universe CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A CLI for freeCodeCamp staff and operators to deploy, manage and maintain constellation apps on the freeCodeCamp Universe Platform.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -52,82 +52,23 @@ Verify:
|
|
|
52
52
|
universe --version
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
##
|
|
56
|
-
|
|
57
|
-
Top-level (cross-cutting):
|
|
58
|
-
|
|
59
|
-
```sh
|
|
60
|
-
universe login # GitHub OAuth device flow → ~/.config/universe-cli/token
|
|
61
|
-
universe logout # delete stored token
|
|
62
|
-
universe whoami # echo current login + authorized-sites count
|
|
63
|
-
universe --version # CLI version
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Static-site verbs (namespaced under `static`):
|
|
67
|
-
|
|
68
|
-
```sh
|
|
69
|
-
universe static deploy [--promote] [--dir <path>]
|
|
70
|
-
universe static promote [--from <deployId>]
|
|
71
|
-
universe static rollback --to <deployId>
|
|
72
|
-
universe static ls [--site <site>]
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Static-app registry (namespaced under `sites`, staff-gated writes):
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
universe sites ls [--mine] # list registered sites; `--mine` filters to your authorized set
|
|
79
|
-
universe sites register <slug> [--team=<name>...] # create new entry (staff; defaults --team to staff)
|
|
80
|
-
universe sites update <slug> --team=<name>... # replace teams list (staff)
|
|
81
|
-
universe sites rm <slug> # delete entry (staff; R2 deploy bytes untouched)
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Repository creation + approval queue (namespaced under `repo`):
|
|
55
|
+
## Quickstart
|
|
85
56
|
|
|
86
57
|
```sh
|
|
87
|
-
universe
|
|
88
|
-
|
|
89
|
-
universe
|
|
90
|
-
universe
|
|
91
|
-
universe repo approve <id> [--yes] # approve → creates the repo via the Apollo-11 App (admin)
|
|
92
|
-
universe repo reject <id> [--reason <text>] [--yes] # reject a pending request (admin)
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Repo requests enter an artemis-owned approval queue (independent of the legacy Windmill flow). The Apollo-11 GitHub App key lives in the cluster, never the CLI — the CLI only carries your GitHub bearer.
|
|
96
|
-
|
|
97
|
-
All commands support `--json` for CI integration.
|
|
98
|
-
|
|
99
|
-
## Identity (priority chain)
|
|
100
|
-
|
|
101
|
-
The CLI resolves a GitHub identity in this order — first match wins:
|
|
102
|
-
|
|
103
|
-
1. `$GITHUB_TOKEN` / `$GH_TOKEN` env (CI explicit)
|
|
104
|
-
1. Device-flow stored token at `~/.config/universe-cli/token` (`universe login`)
|
|
105
|
-
1. `gh auth token` shell-out (laptop fallback when no `universe login` token)
|
|
106
|
-
|
|
107
|
-
CI runners must export `$GITHUB_TOKEN` explicitly. artemis validates the bearer via GitHub `GET /user`, then authorizes server-side against the Valkey-backed registry. Run `universe whoami` to see which slot resolved; inspect the sites you can deploy to with `universe sites ls --mine`.
|
|
108
|
-
|
|
109
|
-
## Configuration (`platform.yaml`)
|
|
110
|
-
|
|
111
|
-
Every site has a `platform.yaml` at its repo root. Minimal valid file:
|
|
112
|
-
|
|
113
|
-
```yaml
|
|
114
|
-
site: my-site
|
|
58
|
+
universe login # GitHub OAuth device flow
|
|
59
|
+
# add a platform.yaml at your repo root with: site: my-site
|
|
60
|
+
universe static deploy # upload the build to a new preview deploy
|
|
61
|
+
universe static promote # point production at that deploy
|
|
115
62
|
```
|
|
116
63
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
No credential fields. The proxy holds the R2 admin key; the CLI never reads or writes one.
|
|
64
|
+
## Docs
|
|
120
65
|
|
|
121
|
-
|
|
66
|
+
Start with the [Staff Guide](docs/STAFF-GUIDE.md). See the [command reference](docs/reference.md), the [`platform.yaml` schema](docs/platform-yaml.md), or [architecture & internals](docs/README.md).
|
|
122
67
|
|
|
123
|
-
|
|
68
|
+
## License
|
|
124
69
|
|
|
125
|
-
|
|
70
|
+
Copyright © 2014 freeCodeCamp.org
|
|
126
71
|
|
|
127
|
-
|
|
128
|
-
| --------------------------- | ---------------------------------------------- | ---------------------------------------------------------- |
|
|
129
|
-
| `UNIVERSE_PROXY_URL` | `https://uploads.freecode.camp` | Override proxy host (staging etc.) |
|
|
130
|
-
| `UNIVERSE_GH_CLIENT_ID` | _baked-in freeCodeCamp-Universe GitHub App id_ | Override GitHub App client id (fork tenants, `login` only) |
|
|
131
|
-
| `GITHUB_TOKEN` / `GH_TOKEN` | — | Slot 1 of identity chain |
|
|
72
|
+
The content of this repository is bound by the following license:
|
|
132
73
|
|
|
133
|
-
|
|
74
|
+
- The computer software is licensed under the [BSD-3-Clause](LICENSE) license.
|
package/dist/index.cjs
CHANGED
|
@@ -25489,7 +25489,7 @@ var APP_DIR2 = "universe-cli";
|
|
|
25489
25489
|
var CACHE_FILE = "update-check.json";
|
|
25490
25490
|
var PKG_NAME = "@freecodecamp/universe-cli";
|
|
25491
25491
|
var NPM_LATEST_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
25492
|
-
var TTL_MS =
|
|
25492
|
+
var TTL_MS = 6 * 60 * 60 * 1e3;
|
|
25493
25493
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
25494
25494
|
function configBase2() {
|
|
25495
25495
|
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
@@ -25577,10 +25577,12 @@ function parseVersion(s) {
|
|
|
25577
25577
|
if (nums.some((n) => Number.isNaN(n))) return null;
|
|
25578
25578
|
return [nums[0], nums[1], nums[2]];
|
|
25579
25579
|
}
|
|
25580
|
-
async function refreshIfStale(now = Date.now()) {
|
|
25580
|
+
async function refreshIfStale(now = Date.now(), options = {}) {
|
|
25581
25581
|
if (isDisabled()) return;
|
|
25582
|
-
|
|
25583
|
-
|
|
25582
|
+
if (!options.force) {
|
|
25583
|
+
const cache = await readCache();
|
|
25584
|
+
if (cache !== null && now - cache.lastCheck < TTL_MS) return;
|
|
25585
|
+
}
|
|
25584
25586
|
const latest = await fetchLatest();
|
|
25585
25587
|
if (latest === null) return;
|
|
25586
25588
|
try {
|
|
@@ -25635,7 +25637,7 @@ function installExitNotice(current) {
|
|
|
25635
25637
|
}
|
|
25636
25638
|
|
|
25637
25639
|
// src/cli.ts
|
|
25638
|
-
var version2 = true ? "0.8.
|
|
25640
|
+
var version2 = true ? "0.8.1" : "0.0.0";
|
|
25639
25641
|
function handleActionError(command, json2, err) {
|
|
25640
25642
|
const ctx = { json: json2, command };
|
|
25641
25643
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
@@ -25650,11 +25652,17 @@ function findFirstPositional(args) {
|
|
|
25650
25652
|
}
|
|
25651
25653
|
return -1;
|
|
25652
25654
|
}
|
|
25653
|
-
function
|
|
25655
|
+
function isVersionRequest(args) {
|
|
25656
|
+
return args.includes("--version") || args.includes("-v");
|
|
25657
|
+
}
|
|
25658
|
+
async function run(argv = process.argv) {
|
|
25654
25659
|
installExitNotice(version2);
|
|
25655
|
-
void refreshIfStale().catch(() => {
|
|
25656
|
-
});
|
|
25657
25660
|
const args = argv.slice(2);
|
|
25661
|
+
const versionRequested = isVersionRequest(args);
|
|
25662
|
+
if (!versionRequested) {
|
|
25663
|
+
void refreshIfStale().catch(() => {
|
|
25664
|
+
});
|
|
25665
|
+
}
|
|
25658
25666
|
const firstPosIdx = findFirstPositional(args);
|
|
25659
25667
|
const namespace = firstPosIdx >= 0 ? args[firstPosIdx] : void 0;
|
|
25660
25668
|
const isStatic = namespace === "static";
|
|
@@ -25947,6 +25955,9 @@ function run(argv = process.argv) {
|
|
|
25947
25955
|
cli.version(version2);
|
|
25948
25956
|
cli.parse(argv);
|
|
25949
25957
|
}
|
|
25958
|
+
if (versionRequested) {
|
|
25959
|
+
await refreshIfStale(Date.now(), { force: true });
|
|
25960
|
+
}
|
|
25950
25961
|
}
|
|
25951
25962
|
|
|
25952
25963
|
// src/lib/fatal.ts
|
|
@@ -25965,4 +25976,4 @@ function installFatalHandlers(onFatal = defaultOnFatal) {
|
|
|
25965
25976
|
|
|
25966
25977
|
// src/index.ts
|
|
25967
25978
|
installFatalHandlers();
|
|
25968
|
-
run();
|
|
25979
|
+
void run();
|
package/dist/index.js
CHANGED
|
@@ -2842,7 +2842,7 @@ var APP_DIR2 = "universe-cli";
|
|
|
2842
2842
|
var CACHE_FILE = "update-check.json";
|
|
2843
2843
|
var PKG_NAME = "@freecodecamp/universe-cli";
|
|
2844
2844
|
var NPM_LATEST_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
2845
|
-
var TTL_MS =
|
|
2845
|
+
var TTL_MS = 6 * 60 * 60 * 1e3;
|
|
2846
2846
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
2847
2847
|
function configBase2() {
|
|
2848
2848
|
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
@@ -2930,10 +2930,12 @@ function parseVersion(s) {
|
|
|
2930
2930
|
if (nums.some((n) => Number.isNaN(n))) return null;
|
|
2931
2931
|
return [nums[0], nums[1], nums[2]];
|
|
2932
2932
|
}
|
|
2933
|
-
async function refreshIfStale(now = Date.now()) {
|
|
2933
|
+
async function refreshIfStale(now = Date.now(), options = {}) {
|
|
2934
2934
|
if (isDisabled()) return;
|
|
2935
|
-
|
|
2936
|
-
|
|
2935
|
+
if (!options.force) {
|
|
2936
|
+
const cache = await readCache();
|
|
2937
|
+
if (cache !== null && now - cache.lastCheck < TTL_MS) return;
|
|
2938
|
+
}
|
|
2937
2939
|
const latest = await fetchLatest();
|
|
2938
2940
|
if (latest === null) return;
|
|
2939
2941
|
try {
|
|
@@ -2988,7 +2990,7 @@ function installExitNotice(current) {
|
|
|
2988
2990
|
}
|
|
2989
2991
|
|
|
2990
2992
|
// src/cli.ts
|
|
2991
|
-
var version = true ? "0.8.
|
|
2993
|
+
var version = true ? "0.8.1" : "0.0.0";
|
|
2992
2994
|
function handleActionError(command, json, err) {
|
|
2993
2995
|
const ctx = { json, command };
|
|
2994
2996
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
@@ -3003,11 +3005,17 @@ function findFirstPositional(args) {
|
|
|
3003
3005
|
}
|
|
3004
3006
|
return -1;
|
|
3005
3007
|
}
|
|
3006
|
-
function
|
|
3008
|
+
function isVersionRequest(args) {
|
|
3009
|
+
return args.includes("--version") || args.includes("-v");
|
|
3010
|
+
}
|
|
3011
|
+
async function run(argv = process.argv) {
|
|
3007
3012
|
installExitNotice(version);
|
|
3008
|
-
void refreshIfStale().catch(() => {
|
|
3009
|
-
});
|
|
3010
3013
|
const args = argv.slice(2);
|
|
3014
|
+
const versionRequested = isVersionRequest(args);
|
|
3015
|
+
if (!versionRequested) {
|
|
3016
|
+
void refreshIfStale().catch(() => {
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3011
3019
|
const firstPosIdx = findFirstPositional(args);
|
|
3012
3020
|
const namespace = firstPosIdx >= 0 ? args[firstPosIdx] : void 0;
|
|
3013
3021
|
const isStatic = namespace === "static";
|
|
@@ -3300,6 +3308,9 @@ function run(argv = process.argv) {
|
|
|
3300
3308
|
cli.version(version);
|
|
3301
3309
|
cli.parse(argv);
|
|
3302
3310
|
}
|
|
3311
|
+
if (versionRequested) {
|
|
3312
|
+
await refreshIfStale(Date.now(), { force: true });
|
|
3313
|
+
}
|
|
3303
3314
|
}
|
|
3304
3315
|
|
|
3305
3316
|
// src/lib/fatal.ts
|
|
@@ -3318,4 +3329,4 @@ function installFatalHandlers(onFatal = defaultOnFatal) {
|
|
|
3318
3329
|
|
|
3319
3330
|
// src/index.ts
|
|
3320
3331
|
installFatalHandlers();
|
|
3321
|
-
run();
|
|
3332
|
+
void run();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@freecodecamp/universe-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "vitest run",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"prepare": "husky"
|
|
12
12
|
},
|
|
13
13
|
"author": "Mrugesh Mohapatra <noreply@mrugesh.dev> (https://mrugesh.dev/)",
|
|
14
|
-
"license": "
|
|
14
|
+
"license": "BSD-3-Clause",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "git+https://github.com/freeCodeCamp-Universe/universe-cli.git"
|
|
@@ -58,4 +58,4 @@
|
|
|
58
58
|
"deployment",
|
|
59
59
|
"freecodecamp"
|
|
60
60
|
]
|
|
61
|
-
}
|
|
61
|
+
}
|