@remarkkpt/foundry-installer 0.1.0 → 0.1.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/README.md +11 -5
- package/install.sh +79 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@ Num terminal do macOS, executa (precisa do Node/npm):
|
|
|
10
10
|
npx @remarkkpt/foundry-installer
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Alternativa preparada para Macs sem Node/npm, só após publicar 0.1.1:
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
|
-
installer="$(curl -fsSL https://unpkg.com/@remarkkpt/foundry-installer@0.1.
|
|
16
|
+
installer="$(curl -fsSL https://unpkg.com/@remarkkpt/foundry-installer@0.1.1/install.sh)" && /bin/bash -c "$installer"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
A alternativa `curl` não exige Node/npm para arrancar. Mantém-se `@0.1.
|
|
19
|
+
A alternativa `curl` não exige Node/npm para arrancar. Mantém-se `@0.1.1`
|
|
20
20
|
para executar o script desta versão, sem mudar para futuras versões automaticamente.
|
|
21
21
|
|
|
22
22
|
O instalador oferece preparar os
|
|
@@ -31,8 +31,14 @@ confirmação; o conteúdo existente é preservado. Uma instalação adequada é
|
|
|
31
31
|
reutilizada. Falhas de descarga/instalação preservam a versão ativa anterior.
|
|
32
32
|
O prefixo npm anteriormente documentado em `~/.local/share/foundry/node_modules`
|
|
33
33
|
também é reutilizado: os seus ficheiros são conferidos contra o pacote da release
|
|
34
|
-
com SHA-256 validado e o comando existente é conservado.
|
|
35
|
-
|
|
34
|
+
com SHA-256 validado e o comando existente é conservado. O launcher documentado anterior é reconhecido pelo conteúdo integral. Se a versão
|
|
35
|
+
for diferente, o instalador explica e pede confirmação para atualizar. Só depois
|
|
36
|
+
de verificar a nova CLI move o prefixo anterior para
|
|
37
|
+
`~/.local/share/foundry/backups/legacy-…`, juntamente com o launcher, e indica
|
|
38
|
+
o backup. Recusar preserva tudo. Se a ativação falhar antes de o novo comando ficar ativo, o instalador tenta repor o prefixo e o comando anteriores. Se o prefixo for reposto, regressa à localização original; caso contrário, permanece no backup indicado. Depois de o novo comando ficar ativo, não há restauro automático e o backup é conservado.
|
|
39
|
+
Com o launcher documentado, também se oferece atualização confirmada quando
|
|
40
|
+
os ficheiros diferem apesar de terem o mesmo número de versão. Sem esse launcher,
|
|
41
|
+
a mesma versão divergente é preservada e recusada para conferência manual.
|
|
36
42
|
|
|
37
43
|
Este pacote não contém credenciais nem publica código. O acesso à Foundry
|
|
38
44
|
continua limitado aos convidados do repositório privado.
|
package/install.sh
CHANGED
|
@@ -52,13 +52,26 @@ version=0.1.0-alpha.1
|
|
|
52
52
|
tag="v$version"
|
|
53
53
|
base="$HOME/.local/share/foundry"
|
|
54
54
|
bin="$HOME/.local/bin"
|
|
55
|
-
for item in "$HOME/.local" "$HOME/.local/share" "$base" "$base/versions" "$bin"; do
|
|
55
|
+
for item in "$HOME/.local" "$HOME/.local/share" "$base" "$base/versions" "$base/backups" "$bin"; do
|
|
56
56
|
[[ ! -L "$item" ]] || fail "Destino simbólico inesperado: $item. Nenhuma instalação substituída."
|
|
57
57
|
done
|
|
58
58
|
mkdir -p "$base/versions" "$bin"
|
|
59
59
|
launcher="$bin/foundry"
|
|
60
|
+
legacy_launcher=false
|
|
61
|
+
if [[ -f "$launcher" && ! -L "$launcher" ]]; then
|
|
62
|
+
# Recognize the complete documented 17/10 launcher, scoped to this HOME.
|
|
63
|
+
# A comment or a substring alone must never authorize replacing a command.
|
|
64
|
+
if node - "$launcher" "$HOME" <<'JS'
|
|
65
|
+
const fs = require('node:fs');
|
|
66
|
+
const expected = '#!/bin/sh\n# Foundry uses Node 24 without changing the default Node for other tools.\nPATH="/opt/homebrew/opt/node@24/bin:$PATH"\nexport PATH\nexec /opt/homebrew/opt/node@24/bin/node ' + process.argv[3] + '/.local/share/foundry/node_modules/@remarkkpt/foundry/dist/cli.js "$@"\n';
|
|
67
|
+
process.exit(fs.readFileSync(process.argv[2], 'utf8') === expected ? 0 : 1);
|
|
68
|
+
JS
|
|
69
|
+
then legacy_launcher=true; fi
|
|
70
|
+
fi
|
|
60
71
|
if [[ -e "$launcher" || -L "$launcher" ]]; then
|
|
61
|
-
[[
|
|
72
|
+
if [[ "$legacy_launcher" != true ]]; then
|
|
73
|
+
[[ -f "$launcher" && ! -L "$launcher" ]] && grep -qx '# Foundry bootstrap launcher v1' "$launcher" || fail 'Já existe outro comando em ~/.local/bin/foundry; foi preservado. Confira esse comando e guarde-o noutro local antes de repetir o instalador.'
|
|
74
|
+
fi
|
|
62
75
|
fi
|
|
63
76
|
work=$(mktemp -d "$base/versions/.prepare-XXXXXXXX")
|
|
64
77
|
printf 'A conferir a versão privada %s…\n' "$tag"
|
|
@@ -72,7 +85,9 @@ JS
|
|
|
72
85
|
) || fail 'O manifesto da versão não tem identidade válida; instalação recusada.'
|
|
73
86
|
read -r commit digest <<< "$metadata"
|
|
74
87
|
download_package() {
|
|
75
|
-
|
|
88
|
+
if [[ ! -f "$work/foundry.tgz" ]]; then
|
|
89
|
+
gh release download "$tag" --repo "$repository" --pattern foundry.tgz --dir "$work" || fail 'A descarga falhou; a instalação anterior foi preservada.'
|
|
90
|
+
fi
|
|
76
91
|
local actual
|
|
77
92
|
actual=$(/usr/bin/shasum -a 256 "$work/foundry.tgz"); actual=${actual%% *}
|
|
78
93
|
[[ "$actual" == "$digest" ]] || fail 'SHA-256 divergente; instalação recusada. A versão anterior foi preservada.'
|
|
@@ -81,9 +96,37 @@ download_package() {
|
|
|
81
96
|
# installed files against the identified artifact rather than trusting version.
|
|
82
97
|
legacy="$base/node_modules/@remarkkpt/foundry"
|
|
83
98
|
reuse_legacy=false
|
|
99
|
+
update_legacy=false
|
|
100
|
+
legacy_backup=
|
|
101
|
+
legacy_moved=false
|
|
102
|
+
restore_legacy() {
|
|
103
|
+
local status=$?
|
|
104
|
+
if [[ "$status" != 0 && "$legacy_moved" == true ]]; then
|
|
105
|
+
if mv "$legacy_backup/node_modules" "$base/node_modules"; then
|
|
106
|
+
if [[ -f "$legacy_backup/foundry" ]]; then cp -p "$legacy_backup/foundry" "$launcher"; fi
|
|
107
|
+
printf 'A instalação anterior foi reposta; backup: %s\n' "$legacy_backup" >&2
|
|
108
|
+
else printf 'A instalação anterior está no backup: %s. Reponha node_modules antes de repetir.\n' "$legacy_backup" >&2; fi
|
|
109
|
+
fi
|
|
110
|
+
}
|
|
111
|
+
trap restore_legacy EXIT
|
|
84
112
|
if [[ -e "$legacy" || -L "$legacy" ]]; then
|
|
85
113
|
download_package
|
|
86
114
|
/usr/bin/tar -xzf "$work/foundry.tgz" -C "$work" || fail 'Não foi possível conferir o pacote; a instalação anterior foi preservada.'
|
|
115
|
+
legacy_version=$(node - "$legacy" <<'JS'
|
|
116
|
+
const fs = require('node:fs'), path = require('node:path');
|
|
117
|
+
for (let dir = process.argv[2]; dir !== path.dirname(dir); dir = path.dirname(dir)) {
|
|
118
|
+
if (fs.lstatSync(dir).isSymbolicLink()) throw Error('Symbolic package directory');
|
|
119
|
+
}
|
|
120
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(process.argv[2], 'package.json')));
|
|
121
|
+
if (pkg.name !== '@remarkkpt/foundry' || !/^[0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9.-]+)?$/.test(pkg.version)) throw Error('Invalid previous package');
|
|
122
|
+
console.log(pkg.version);
|
|
123
|
+
JS
|
|
124
|
+
) || fail 'Não foi possível identificar a instalação anterior; foi preservada. Confira o pacote antes de repetir.'
|
|
125
|
+
if [[ "$legacy_version" != "$version" ]]; then
|
|
126
|
+
printf 'A Foundry anterior é a versão %s; a versão preparada é %s. A atualização guarda a anterior num backup identificado.\n' "$legacy_version" "$version"
|
|
127
|
+
confirm "Atualizar Foundry para $version, guardando a instalação anterior?" || fail 'Atualização cancelada; instalação e comando anteriores preservados.'
|
|
128
|
+
update_legacy=true
|
|
129
|
+
else
|
|
87
130
|
if ! node - "$work/package" "$legacy" "$version" "$base/node_modules/.bin/foundry" <<'JS'
|
|
88
131
|
const fs = require('node:fs'), path = require('node:path');
|
|
89
132
|
const [expected, installed, version, executable] = process.argv.slice(2);
|
|
@@ -106,16 +149,27 @@ compare();
|
|
|
106
149
|
if (fs.realpathSync(executable) !== path.join(installed, 'dist/cli.js')) throw Error('Command points elsewhere');
|
|
107
150
|
fs.accessSync(executable, fs.constants.X_OK);
|
|
108
151
|
JS
|
|
109
|
-
then
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
152
|
+
then
|
|
153
|
+
if [[ "$legacy_launcher" == true ]]; then
|
|
154
|
+
printf 'A instalação anterior tem a mesma versão, mas difere da versão preparada. A atualização guarda os ficheiros anteriores num backup identificado.\n'
|
|
155
|
+
confirm "Atualizar Foundry para $version, guardando a instalação anterior?" || fail 'Atualização cancelada; instalação e comando anteriores preservados.'
|
|
156
|
+
update_legacy=true
|
|
157
|
+
else fail 'A instalação anterior não corresponde à versão preparada; foi preservada. Confira-a antes de voltar a instalar.'; fi
|
|
158
|
+
else
|
|
159
|
+
"$node_executable" "$legacy/dist/cli.js" --help >/dev/null 2>&1 || fail 'A instalação anterior não arranca; foi preservada. Confira-a antes de voltar a instalar.'
|
|
160
|
+
reuse_legacy=true
|
|
161
|
+
printf 'A instalação adequada desta versão foi preservada no prefixo npm anterior.\n'
|
|
162
|
+
fi
|
|
163
|
+
fi
|
|
113
164
|
fi
|
|
165
|
+
if [[ "$legacy_launcher" == true && ! -d "$legacy" ]]; then fail 'O launcher anterior foi reconhecido, mas falta o pacote. Reponha a instalação anterior ou guarde o launcher antes de repetir.'; fi
|
|
114
166
|
target="$base/versions/$digest"
|
|
115
167
|
adequate=false
|
|
116
168
|
if [[ "$reuse_legacy" == true ]]; then
|
|
117
|
-
|
|
118
|
-
|
|
169
|
+
if [[ "$legacy_launcher" != true ]]; then
|
|
170
|
+
bin="$base/node_modules/.bin"
|
|
171
|
+
launcher="$bin/foundry"
|
|
172
|
+
fi
|
|
119
173
|
else
|
|
120
174
|
if [[ -d "$target" && ! -L "$target" && -f "$target/receipt.json" ]]; then
|
|
121
175
|
if node - "$target/receipt.json" "$commit" "$digest" <<'JS'
|
|
@@ -128,7 +182,9 @@ JS
|
|
|
128
182
|
fi
|
|
129
183
|
if [[ "$adequate" == false ]]; then
|
|
130
184
|
[[ ! -e "$target" && ! -L "$target" ]] || fail 'A cópia desta versão não passou a verificação; foi preservada para inspeção.'
|
|
131
|
-
|
|
185
|
+
if [[ "$update_legacy" != true ]]; then
|
|
186
|
+
confirm "Instalar Foundry $version (commit $commit) uma vez neste Mac?" || fail 'Instalação cancelada.'
|
|
187
|
+
fi
|
|
132
188
|
download_package
|
|
133
189
|
npm install --prefix "$work" --offline --ignore-scripts --no-save --no-audit --no-fund "$work/foundry.tgz" || fail 'A instalação falhou; a versão anterior foi preservada.'
|
|
134
190
|
node - "$work/node_modules/@remarkkpt/foundry/package.json" "$version" <<'JS'
|
|
@@ -143,6 +199,17 @@ JS
|
|
|
143
199
|
else
|
|
144
200
|
printf 'A instalação adequada desta versão foi preservada.\n'
|
|
145
201
|
fi
|
|
202
|
+
# Move the old prefix only after the new CLI passed all checks. The EXIT trap
|
|
203
|
+
# restores it if activation fails. Backups are never followed through a symlink.
|
|
204
|
+
if [[ "$update_legacy" == true ]]; then
|
|
205
|
+
[[ ! -L "$base/backups" ]] || fail 'Destino de backup simbólico; instalação anterior preservada.'
|
|
206
|
+
mkdir -p "$base/backups"
|
|
207
|
+
legacy_backup=$(mktemp -d "$base/backups/legacy-XXXXXXXX")
|
|
208
|
+
if [[ -f "$launcher" ]]; then cp -p "$launcher" "$legacy_backup/foundry"; fi
|
|
209
|
+
mv "$base/node_modules" "$legacy_backup/node_modules"
|
|
210
|
+
legacy_moved=true
|
|
211
|
+
printf 'Backup da instalação anterior: %s\n' "$legacy_backup"
|
|
212
|
+
fi
|
|
146
213
|
# Atomic pointer replacement leaves the previous version untouched on failure.
|
|
147
214
|
node - "$base" "$target" <<'JS'
|
|
148
215
|
const fs = require('node:fs'), path = require('node:path');
|
|
@@ -154,6 +221,7 @@ JS
|
|
|
154
221
|
} > "$bin/.foundry-$$"
|
|
155
222
|
chmod 755 "$bin/.foundry-$$"
|
|
156
223
|
mv -f "$bin/.foundry-$$" "$launcher"
|
|
224
|
+
legacy_moved=false
|
|
157
225
|
fi
|
|
158
226
|
case ":$PATH:" in
|
|
159
227
|
*":$bin:"*) ;;
|
|
@@ -166,7 +234,7 @@ case ":$PATH:" in
|
|
|
166
234
|
esac
|
|
167
235
|
[[ ! -L "$profile" ]] || fail 'O perfil da shell é um link simbólico; foi preservado.'
|
|
168
236
|
line='export PATH="$HOME/.local/bin:$PATH" # Foundry bootstrap'
|
|
169
|
-
if [[ "$reuse_legacy" == true ]]; then line='export PATH="$HOME/.local/share/foundry/node_modules/.bin:$PATH" # Foundry bootstrap'; fi
|
|
237
|
+
if [[ "$reuse_legacy" == true && "$legacy_launcher" != true ]]; then line='export PATH="$HOME/.local/share/foundry/node_modules/.bin:$PATH" # Foundry bootstrap'; fi
|
|
170
238
|
if ! grep -Fqx "$line" "$profile" 2>/dev/null; then printf '\n%s\n' "$line" >> "$profile"; fi
|
|
171
239
|
;;
|
|
172
240
|
esac
|
package/package.json
CHANGED