@microteia/console 2.35.0 → 2.36.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.
@@ -22,6 +22,11 @@
22
22
  - fix(command): what was broken, and what it did to whoever hit it.
23
23
  -->
24
24
 
25
+ #### [2.36.0] — 2026-11-05
26
+
27
+ - fix(environment): every command that acts on an installation (`readEnvironment`) refuses when the installation's `CONSOLE-VERSIONS.md` names a Console newer than the one running. An older Console rewrites `microteia.yaml` with only the sections it knows and replaces `CONSOLE-VERSIONS.md` and `MICROTEIA.md` with its own texts — nothing failed: a forgotten copy of Console 2.6.0, left in a folder of the installation, ran `unpack` there, the `login:` block disappeared and the Console history lost thirty versions without a word. No new field marks it, on purpose: an older Console would drop the field it does not know.
28
+ - feat(version): `microteia --version` still answers in that case, and says which Console last updated the installation.
29
+
25
30
  #### [2.35.0] — 2026-11-02
26
31
 
27
32
  - feat(publish): the releases repository README links to the official documentation (https://doc.microteia.com), and `publish` rewrites it whenever it differs from the current text — after the catalog, warning instead of failing. It was written only when seeding an empty repository, so the README of an existing one stayed frozen at the text of its first `publish` and no change to it ever arrived. `publish --dry-run` says when it would be rewritten.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Microteia Console 2.35.0
1
+ # Microteia Console 2.36.0
2
2
 
3
3
  Installs and updates Microteia in a Firebase project you own. It has no npm dependencies of its own —
4
4
  what it needs are command-line tools that are already on the machine, listed at the bottom.
@@ -73,6 +73,28 @@ export interface Environment {
73
73
  export declare const ENVIRONMENT_FILE = "microteia.yaml";
74
74
  export declare const parseEnvironment: (source: string) => Environment;
75
75
  export declare const serializeEnvironment: (environment: Environment) => string;
76
+ /**
77
+ * O Console que deixou esta instalação como ela está, quando ele é MAIS NOVO que o que está rodando.
78
+ *
79
+ * O sinal é o topo do `CONSOLE-VERSIONS.md` da raiz, que o `unpack` sobrepõe com o histórico do próprio
80
+ * binário — é, portanto, o último Console que trocou o kernel ali. Nenhum campo novo foi inventado para
81
+ * isso, e é deliberado: um Console antigo apagaria o campo que ele não conhece, que é o defeito inteiro.
82
+ *
83
+ * Sem o arquivo (instalação anterior a ele, ou apagado) não há o que comparar, e nada é recusado.
84
+ */
85
+ export declare const newerConsoleThanThis: (root: string) => Promise<string | null>;
86
+ /**
87
+ * Lê o `microteia.yaml` — e RECUSA quando um Console mais novo já passou por aqui.
88
+ *
89
+ * Um Console antigo reescreve este arquivo só com as seções que conhece, e sobrepõe o
90
+ * `CONSOLE-VERSIONS.md` e o `MICROTEIA.md` com os textos dele. Nada disso falha: a configuração que ele
91
+ * não conhece some, e o histórico volta meses, em silêncio. Foi o que aconteceu quando uma cópia
92
+ * esquecida do Console, numa pasta da instalação, rodou o `unpack` — o bloco `login:` desapareceu, e o
93
+ * histórico do Console perdeu trinta versões.
94
+ *
95
+ * A recusa fica aqui porque este é o primeiro passo de todo comando que AGE sobre a instalação, antes de
96
+ * qualquer escrita. O `--version` lê o arquivo por outro caminho, e continua respondendo.
97
+ */
76
98
  export declare const readEnvironment: (path: string) => Promise<Environment>;
77
99
  export declare const writeEnvironment: (path: string, environment: Environment) => Promise<void>;
78
100
  export declare const slug: (value: string) => string;
@@ -1,4 +1,8 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ import { compareVersions } from '../kernel/manifest.js';
4
+ import { CLI_VERSION } from '../shared/paths.js';
5
+ import { CONSOLE_CHANGELOG, changelogVersions } from '../vendor/changelogs.js';
2
6
  export const ENVIRONMENT_FILE = 'microteia.yaml';
3
7
  /**
4
8
  * O YAML aqui é um SUBCONJUNTO deliberado: mapas de dois níveis com valores escalares, que é a forma
@@ -140,9 +144,36 @@ login:
140
144
  # To USE an extension inside the organization, install it from the Extensions screen instead.
141
145
  extensions: ${quote(environment.login.extensions)}
142
146
  `;
147
+ /**
148
+ * O Console que deixou esta instalação como ela está, quando ele é MAIS NOVO que o que está rodando.
149
+ *
150
+ * O sinal é o topo do `CONSOLE-VERSIONS.md` da raiz, que o `unpack` sobrepõe com o histórico do próprio
151
+ * binário — é, portanto, o último Console que trocou o kernel ali. Nenhum campo novo foi inventado para
152
+ * isso, e é deliberado: um Console antigo apagaria o campo que ele não conhece, que é o defeito inteiro.
153
+ *
154
+ * Sem o arquivo (instalação anterior a ele, ou apagado) não há o que comparar, e nada é recusado.
155
+ */
156
+ export const newerConsoleThanThis = async (root) => {
157
+ const contents = await readFile(join(root, CONSOLE_CHANGELOG), 'utf8').catch(() => null);
158
+ const latest = contents === null ? undefined : changelogVersions(contents)[0];
159
+ return latest !== undefined && compareVersions(latest, CLI_VERSION) > 0 ? latest : null;
160
+ };
161
+ /**
162
+ * Lê o `microteia.yaml` — e RECUSA quando um Console mais novo já passou por aqui.
163
+ *
164
+ * Um Console antigo reescreve este arquivo só com as seções que conhece, e sobrepõe o
165
+ * `CONSOLE-VERSIONS.md` e o `MICROTEIA.md` com os textos dele. Nada disso falha: a configuração que ele
166
+ * não conhece some, e o histórico volta meses, em silêncio. Foi o que aconteceu quando uma cópia
167
+ * esquecida do Console, numa pasta da instalação, rodou o `unpack` — o bloco `login:` desapareceu, e o
168
+ * histórico do Console perdeu trinta versões.
169
+ *
170
+ * A recusa fica aqui porque este é o primeiro passo de todo comando que AGE sobre a instalação, antes de
171
+ * qualquer escrita. O `--version` lê o arquivo por outro caminho, e continua respondendo.
172
+ */
143
173
  export const readEnvironment = async (path) => {
174
+ let environment;
144
175
  try {
145
- return parseEnvironment(await readFile(path, 'utf8'));
176
+ environment = parseEnvironment(await readFile(path, 'utf8'));
146
177
  }
147
178
  catch (error) {
148
179
  if (error.code === 'ENOENT') {
@@ -150,6 +181,14 @@ export const readEnvironment = async (path) => {
150
181
  }
151
182
  throw error;
152
183
  }
184
+ const newer = await newerConsoleThanThis(dirname(path));
185
+ if (newer !== null) {
186
+ throw new Error(`This installation was last updated by Microteia Console ${newer}, and this is ${CLI_VERSION}.\n`
187
+ + `An older Console rewrites ${ENVIRONMENT_FILE} without the settings it does not know, and replaces\n`
188
+ + `${CONSOLE_CHANGELOG} with an older history, so it stops here. Update it with "npm i -g @microteia/console",\n`
189
+ + 'and check that the "microteia" you ran is that one, not a copy left in a folder.');
190
+ }
191
+ return environment;
153
192
  };
154
193
  export const writeEnvironment = async (path, environment) => {
155
194
  await writeFile(path, serializeEnvironment(environment));
@@ -1,7 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { CLI_VERSION } from '../shared/paths.js';
4
- import { ENVIRONMENT_FILE, parseEnvironment } from './environment.js';
4
+ import { ENVIRONMENT_FILE, newerConsoleThanThis, parseEnvironment } from './environment.js';
5
5
  import { installPath } from './unpack.js';
6
6
  /**
7
7
  * O que `microteia --version` responde.
@@ -59,6 +59,15 @@ export const versionReport = async (directory, newer) => {
59
59
  lines.push('');
60
60
  lines.push(`${inPlace} is in place and ${deployed} is what the project runs. "microteia deploy" publishes it.`);
61
61
  }
62
+ /**
63
+ * É a pergunta que se faz quando um comando recusa por isto — e a resposta tem de estar aqui, porque
64
+ * o `--version` é o único que continua rodando com o Console velho.
65
+ */
66
+ const newerConsole = await newerConsoleThanThis(directory);
67
+ if (newerConsole !== null) {
68
+ lines.push('');
69
+ lines.push(`Console ${newerConsole} last updated this installation. This one is older and will not act on it.`);
70
+ }
62
71
  /**
63
72
  * E o que o canal oferece, quando há canal alcançável. Vem por último porque é a única linha que
64
73
  * depende de rede: se ela faltar, tudo acima continua sendo a resposta inteira.
@@ -87,4 +87,4 @@ export declare const consoleRoot: string;
87
87
  * de código nunca chegou a quem instala. Este bloco fica sendo o que ele já era antes de crescer: a
88
88
  * política de semver da ferramenta, mais o registro do que motivou as versões até a `2.5.0`.
89
89
  */
90
- export declare const CLI_VERSION = "2.35.0";
90
+ export declare const CLI_VERSION = "2.36.0";
@@ -94,4 +94,4 @@ export const consoleRoot = resolve(here, '..', '..');
94
94
  * de código nunca chegou a quem instala. Este bloco fica sendo o que ele já era antes de crescer: a
95
95
  * política de semver da ferramenta, mais o registro do que motivou as versões até a `2.5.0`.
96
96
  */
97
- export const CLI_VERSION = '2.35.0';
97
+ export const CLI_VERSION = '2.36.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microteia/console",
3
- "version": "2.35.0",
3
+ "version": "2.36.0",
4
4
  "description": "Install and update Microteia in a Firebase project you own.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",