@mybuildex/pkg 0.9.0 → 0.10.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/README.md +18 -0
- package/dist/build/autoload-static.d.ts +10 -0
- package/dist/build/autoload-static.js +155 -0
- package/dist/build/autoload-static.js.map +1 -0
- package/dist/build/bundle.d.ts +28 -0
- package/dist/build/bundle.js +84 -0
- package/dist/build/bundle.js.map +1 -0
- package/dist/build/cli.d.ts +2 -0
- package/dist/build/cli.js +60 -0
- package/dist/build/cli.js.map +1 -0
- package/dist/build/verify-bundle.d.ts +20 -0
- package/dist/build/verify-bundle.js +116 -0
- package/dist/build/verify-bundle.js.map +1 -0
- package/dist/http/gcf-handler.d.ts +9 -0
- package/dist/http/gcf-handler.js +7 -1
- package/dist/http/gcf-handler.js.map +1 -1
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -51,6 +51,24 @@ createAuthMiddleware({
|
|
|
51
51
|
createTenantMiddleware({getTenantClient, defaultClient, strictTenant: true});
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
## 0.10.0 — bundle da API e boot antecipado
|
|
55
|
+
|
|
56
|
+
Tudo opt-in: API que não usa não muda. Medido no piloto da `v3_peoples` (04/10/2026): boot do código da API de 4,8 s para 1,45 s e primeiro GET em instância fria de 4,6 s para 0,79 s.
|
|
57
|
+
|
|
58
|
+
- **`mybuildex-bundle`** (comando de build) — empacota `dist/index.js` em `dist/bundle.js` com o esbuild. No Cloud Run cada `require()` custa ~3 ms e o boot lia ~1.280 arquivos; o bundle troca isso por um arquivo. O `@fastify/autoload` não funciona dentro de um bundle (ele varre a pasta de módulos em runtime), então o comando faz a mesma varredura no build e gera um plugin estático equivalente (`dist/autoload-static.js`), com as regras do autoload 5.x. Depois **confere** que as rotas do bundle são idênticas às do autoload (compara o swagger das duas entradas) e quebra o build se divergirem. `src/app.ts` não muda; dev e teste seguem no autoload de verdade.
|
|
59
|
+
|
|
60
|
+
```jsonc
|
|
61
|
+
// package.json da API
|
|
62
|
+
"main": "dist/bundle.js",
|
|
63
|
+
"scripts": { "build": "tsc && mybuildex-bundle", "gcp-build": "npm run build" },
|
|
64
|
+
"devDependencies": { "esbuild": "^0.28.2" },
|
|
65
|
+
// opcional: libs que a API só carrega sob demanda ficam fora do bundle
|
|
66
|
+
"mybuildex": { "bundle": { "external": ["exceljs", "pdf-lib"] } }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Ficam sempre fora do bundle (vêm do `node_modules`): `@fastify/swagger-ui`, `firebase-admin`, `@google-cloud/storage`, `redis`, `@google/genai` e o WASM do Prisma. A verificação sobe a API com banco falso (porta morta) e precisa do que ela precisa para carregar (ex.: `firebase.json`); `verifyEnv` passa env a mais, `--no-verify` pula. Não cobre `autoHooks` (o comando lança). Stack trace passa a apontar para o `bundle.js`.
|
|
70
|
+
- **`createGcfHandler({server, eagerBoot: true})`** — dispara o `ready()` logo depois da carga do módulo, em vez de esperar a primeira request: a instância que sobe antes do tráfego chega pronta. As garantias do wrapper valem igual (sem `unhandledRejection`; falha de boot vira 503 + saída na request seguinte).
|
|
71
|
+
|
|
54
72
|
## 0.9.0 — cold start e tamanho do bundle
|
|
55
73
|
|
|
56
74
|
**Muda a instalação** (⚠️): a CLI `prisma` saiu das `dependencies` do pacote.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface AutoloadEntry {
|
|
2
|
+
/** Caminho absoluto do arquivo. */
|
|
3
|
+
file: string;
|
|
4
|
+
/** Prefixo de diretório que o autoload daria (undefined na raiz). */
|
|
5
|
+
prefix: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
/** A mesma varredura do findPlugins do autoload (dirNameRoutePrefix: true, sem autoHooks). */
|
|
8
|
+
export declare function findAutoloadEntries(dir: string, prefix?: string, found?: AutoloadEntry[]): AutoloadEntry[];
|
|
9
|
+
/** Código-fonte (CommonJS) do plugin estático; `fromDir` é a pasta onde ele será gravado. */
|
|
10
|
+
export declare function renderAutoloadStatic(entries: AutoloadEntry[], fromDir: string): string;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findAutoloadEntries = findAutoloadEntries;
|
|
7
|
+
exports.renderAutoloadStatic = renderAutoloadStatic;
|
|
8
|
+
// Equivalente ESTÁTICO do @fastify/autoload, gerado em tempo de build.
|
|
9
|
+
//
|
|
10
|
+
// O autoload varre a pasta de módulos em RUNTIME (readdir) e dá require() em
|
|
11
|
+
// cada arquivo pelo caminho. Dentro de um bundle essa pasta não é lida — os
|
|
12
|
+
// módulos estão embutidos — então o autoload não acharia rota nenhuma (ou
|
|
13
|
+
// acharia os arquivos soltos e carregaria tudo de novo, fora do bundle).
|
|
14
|
+
//
|
|
15
|
+
// Aqui a MESMA varredura roda no build (findAutoloadEntries) e vira um plugin
|
|
16
|
+
// com um require() fixo por arquivo (renderAutoloadStatic), que o bundler
|
|
17
|
+
// embute. As regras de "é plugin?", autoPrefix, prefixOverride, autoConfig e
|
|
18
|
+
// dependências são as do autoload 5.x (loadPlugin/registerPlugin), copiadas.
|
|
19
|
+
// Não cobre autoHooks: a varredura lança se encontrar um.
|
|
20
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
21
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
22
|
+
// Padrões copiados dos defaults do @fastify/autoload 5.x.
|
|
23
|
+
const scriptPattern = /(?:(?:^.?|\.[^d]|[^.]d|[^.][^d])\.ts|\.js|\.cjs|\.mjs|\.cts|\.mts)$/iu;
|
|
24
|
+
const indexPattern = /^index(?:\.ts|\.js|\.cjs|\.mjs|\.cts|\.mts)$/iu;
|
|
25
|
+
const autoHooksPattern = /^[_.]?auto_?hooks(?:\.ts|\.js|\.cjs|\.mjs|\.cts|\.mts)$/iu;
|
|
26
|
+
/** A mesma varredura do findPlugins do autoload (dirNameRoutePrefix: true, sem autoHooks). */
|
|
27
|
+
function findAutoloadEntries(dir, prefix, found = []) {
|
|
28
|
+
const list = node_fs_1.default.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
29
|
+
if (list.some((d) => autoHooksPattern.test(d.name))) {
|
|
30
|
+
throw new Error(`autohooks em ${dir}: o autoload estático não cobre autoHooks`);
|
|
31
|
+
}
|
|
32
|
+
const indexDirent = list.find((d) => indexPattern.test(d.name));
|
|
33
|
+
if (indexDirent) {
|
|
34
|
+
found.push({ file: node_path_1.default.join(dir, indexDirent.name), prefix });
|
|
35
|
+
if (!list.some((d) => d.isDirectory()))
|
|
36
|
+
return found;
|
|
37
|
+
}
|
|
38
|
+
if (list.some((d) => d.name === "package.json") && !indexDirent) {
|
|
39
|
+
throw new Error(`@fastify/autoload não importaria o plugin em '${dir}' (package.json sem index)`);
|
|
40
|
+
}
|
|
41
|
+
for (const dirent of list) {
|
|
42
|
+
const file = node_path_1.default.join(dir, dirent.name);
|
|
43
|
+
if (dirent.isDirectory()) {
|
|
44
|
+
findAutoloadEntries(file, (prefix ? `${prefix}/` : "/") + dirent.name, found);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (indexDirent)
|
|
48
|
+
continue;
|
|
49
|
+
if (dirent.isFile() && scriptPattern.test(dirent.name))
|
|
50
|
+
found.push({ file, prefix });
|
|
51
|
+
}
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
/** Código-fonte (CommonJS) do plugin estático; `fromDir` é a pasta onde ele será gravado. */
|
|
55
|
+
function renderAutoloadStatic(entries, fromDir) {
|
|
56
|
+
const rel = (file) => {
|
|
57
|
+
const r = node_path_1.default.relative(fromDir, file).split(node_path_1.default.sep).join("/");
|
|
58
|
+
return r.startsWith(".") ? r : `./${r}`;
|
|
59
|
+
};
|
|
60
|
+
const lines = entries.map((e) => ` {file: ${JSON.stringify(rel(e.file))}, prefix: ${JSON.stringify(e.prefix)}, load: () => require(${JSON.stringify(rel(e.file))})},`);
|
|
61
|
+
return `// GERADO pelo mybuildex-bundle (@mybuildex/pkg) — NÃO EDITAR.
|
|
62
|
+
// Equivalente estático do @fastify/autoload: lista fixa de arquivos (um
|
|
63
|
+
// require por arquivo, que o bundler embute) com as regras do autoload 5.x.
|
|
64
|
+
"use strict";
|
|
65
|
+
|
|
66
|
+
const entries = [
|
|
67
|
+
${lines.join("\n")}
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
function isRouteObject(input) {
|
|
71
|
+
return !!input && Object.prototype.toString.call(input) === "[object Object]" &&
|
|
72
|
+
Object.prototype.hasOwnProperty.call(input, "method");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isPluginOrModule(input) {
|
|
76
|
+
const inputType = Object.prototype.toString.call(input);
|
|
77
|
+
if (/\\[object (?:AsyncFunction|Function|Module)\\]/u.test(inputType)) return true;
|
|
78
|
+
if (Object.prototype.hasOwnProperty.call(input, "default")) return isPluginOrModule(input.default);
|
|
79
|
+
return isRouteObject(input);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function wrapRoutes(content) {
|
|
83
|
+
if (isRouteObject(content)) {
|
|
84
|
+
return async function (fastify) {
|
|
85
|
+
fastify.route(content);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return content;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function loadPlugin(entry, overrideConfig) {
|
|
92
|
+
const content = entry.load();
|
|
93
|
+
if (isPluginOrModule(content) === false) return undefined;
|
|
94
|
+
|
|
95
|
+
const plugin = wrapRoutes(content.default || content);
|
|
96
|
+
const pluginConfig = (content.default && content.default.autoConfig) || content.autoConfig || {};
|
|
97
|
+
const pluginOptions = Object.assign({}, pluginConfig, overrideConfig);
|
|
98
|
+
const pluginMeta = plugin[Symbol.for("plugin-meta")] || {};
|
|
99
|
+
|
|
100
|
+
if (plugin.autoload === false || content.autoload === false) return undefined;
|
|
101
|
+
if (plugin.autoConfig !== undefined) plugin.autoConfig = undefined;
|
|
102
|
+
|
|
103
|
+
pluginOptions.prefix = (pluginOptions.prefix && pluginOptions.prefix.endsWith("/")) ? pluginOptions.prefix.slice(0, -1) : pluginOptions.prefix;
|
|
104
|
+
const prefixOverride = plugin.prefixOverride !== undefined ? plugin.prefixOverride : content.prefixOverride !== undefined ? content.prefixOverride : undefined;
|
|
105
|
+
const prefix = (plugin.autoPrefix !== undefined ? plugin.autoPrefix : content.autoPrefix !== undefined ? content.autoPrefix : undefined) || entry.prefix;
|
|
106
|
+
if (prefixOverride !== undefined) {
|
|
107
|
+
pluginOptions.prefix = prefixOverride;
|
|
108
|
+
} else if (prefix) {
|
|
109
|
+
pluginOptions.prefix = (pluginOptions.prefix || "") + prefix.replace(/\\/+/gu, "/");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
plugin,
|
|
114
|
+
filename: entry.file,
|
|
115
|
+
name: pluginMeta.name || entry.file,
|
|
116
|
+
dependencies: pluginMeta.dependencies,
|
|
117
|
+
options: pluginOptions,
|
|
118
|
+
registered: false,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function registerPlugin(fastify, meta, allPlugins, parentPlugins = {}) {
|
|
123
|
+
const {plugin, name, options, dependencies = []} = meta;
|
|
124
|
+
if (parentPlugins[name]) throw new Error("Cyclic dependency");
|
|
125
|
+
if (meta.registered) return;
|
|
126
|
+
parentPlugins[name] = true;
|
|
127
|
+
for (const dependency of dependencies) {
|
|
128
|
+
if (allPlugins[dependency]) registerPlugin(fastify, allPlugins[dependency], allPlugins, {...parentPlugins});
|
|
129
|
+
}
|
|
130
|
+
fastify.register(plugin, options);
|
|
131
|
+
meta.registered = true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const autoloadStatic = async function autoloadStatic(fastify, options) {
|
|
135
|
+
const pluginsMeta = {};
|
|
136
|
+
for (const entry of entries) {
|
|
137
|
+
const meta = loadPlugin(entry, options && options.options);
|
|
138
|
+
if (meta) pluginsMeta[meta.name] = meta;
|
|
139
|
+
}
|
|
140
|
+
const metas = Object.values(pluginsMeta);
|
|
141
|
+
for (const entry of entries) {
|
|
142
|
+
const meta = metas.find((m) => m.filename === entry.file);
|
|
143
|
+
if (meta) registerPlugin(fastify, meta, pluginsMeta);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// não cria contexto novo, igual ao autoload (e ao fastify-plugin)
|
|
148
|
+
autoloadStatic[Symbol.for("skip-override")] = true;
|
|
149
|
+
|
|
150
|
+
module.exports = autoloadStatic;
|
|
151
|
+
module.exports.fastifyAutoload = autoloadStatic;
|
|
152
|
+
module.exports.default = autoloadStatic;
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=autoload-static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoload-static.js","sourceRoot":"","sources":["../../src/build/autoload-static.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Pacotes que ficam FORA do bundle (continuam vindo do node_modules em runtime). */
|
|
2
|
+
export declare const DEFAULT_BUNDLE_EXTERNAL: readonly string[];
|
|
3
|
+
export interface BundleOptions {
|
|
4
|
+
/** Raiz da API (default: process.cwd()). */
|
|
5
|
+
root?: string;
|
|
6
|
+
/** Pasta do compilado, relativa à raiz (default: "dist"). */
|
|
7
|
+
distDir?: string;
|
|
8
|
+
/** Entrada, relativa a distDir (default: "index.js"). */
|
|
9
|
+
entry?: string;
|
|
10
|
+
/** Saída, relativa a distDir (default: "bundle.js"). */
|
|
11
|
+
outfile?: string;
|
|
12
|
+
/** Pasta que o @fastify/autoload varre, relativa a distDir (default: "modules"). */
|
|
13
|
+
modulesDir?: string;
|
|
14
|
+
/** Pacotes a mais fora do bundle — tipicamente os que a API só carrega sob
|
|
15
|
+
* demanda (`await import("exceljs")`). Somam aos DEFAULT_BUNDLE_EXTERNAL. */
|
|
16
|
+
external?: string[];
|
|
17
|
+
/** `target` do esbuild (default: "node22"). */
|
|
18
|
+
target?: string;
|
|
19
|
+
/** Log (default: console.log). */
|
|
20
|
+
log?: (message: string) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface BundleResult {
|
|
23
|
+
outfile: string;
|
|
24
|
+
bytes: number;
|
|
25
|
+
inputs: number;
|
|
26
|
+
autoloadEntries: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function bundleApi(options?: BundleOptions): Promise<BundleResult>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DEFAULT_BUNDLE_EXTERNAL = void 0;
|
|
7
|
+
exports.bundleApi = bundleApi;
|
|
8
|
+
// Empacota a API num arquivo só para o cold start.
|
|
9
|
+
//
|
|
10
|
+
// POR QUÊ: no Cloud Run cada require() custa ~3 ms (medido na v3_peoples em
|
|
11
|
+
// 04/10/2026: 79% do boot era require de ~1.280 arquivos; com o bundle o boot
|
|
12
|
+
// caiu de 4,8 s para 1,45 s). Um arquivo só troca mais de mil leituras por uma.
|
|
13
|
+
//
|
|
14
|
+
// O @fastify/autoload não funciona dentro de um bundle; aqui ele é trocado
|
|
15
|
+
// (alias) pelo equivalente estático gerado em ./autoload-static. O código da
|
|
16
|
+
// API não muda: dev e teste seguem no autoload de verdade.
|
|
17
|
+
//
|
|
18
|
+
// Só ferramenta de BUILD: nada daqui é exportado pelo index do pacote, e o
|
|
19
|
+
// esbuild é dependência de desenvolvimento da API (peer opcional daqui).
|
|
20
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
21
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
22
|
+
const autoload_static_1 = require("./autoload-static");
|
|
23
|
+
/** Pacotes que ficam FORA do bundle (continuam vindo do node_modules em runtime). */
|
|
24
|
+
exports.DEFAULT_BUNDLE_EXTERNAL = [
|
|
25
|
+
// serve arquivos estáticos da própria pasta (path.join(__dirname, "static"))
|
|
26
|
+
"@fastify/swagger-ui",
|
|
27
|
+
// carrega os serviços por require() sob demanda; no boot são poucos arquivos
|
|
28
|
+
"firebase-admin",
|
|
29
|
+
// só carregam quando usados: dentro do bundle só aumentariam o arquivo que
|
|
30
|
+
// o Node lê em todo cold start
|
|
31
|
+
"@google-cloud/storage",
|
|
32
|
+
"redis",
|
|
33
|
+
"@google/genai",
|
|
34
|
+
// WASM do query compiler do Prisma (MBs em base64): o client gerado só o
|
|
35
|
+
// importa na primeira query
|
|
36
|
+
"@prisma/client/runtime/*.wasm-base64.js",
|
|
37
|
+
];
|
|
38
|
+
function loadEsbuild(root) {
|
|
39
|
+
try {
|
|
40
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
41
|
+
return require(require.resolve("esbuild", { paths: [root, __dirname] }));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new Error("mybuildex-bundle precisa do esbuild na API: npm i -D esbuild");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function bundleApi(options = {}) {
|
|
48
|
+
const root = node_path_1.default.resolve(options.root ?? process.cwd());
|
|
49
|
+
const dist = node_path_1.default.join(root, options.distDir ?? "dist");
|
|
50
|
+
const entry = node_path_1.default.join(dist, options.entry ?? "index.js");
|
|
51
|
+
const outfile = node_path_1.default.join(dist, options.outfile ?? "bundle.js");
|
|
52
|
+
const modulesDir = node_path_1.default.join(dist, options.modulesDir ?? "modules");
|
|
53
|
+
const shim = node_path_1.default.join(dist, "autoload-static.js");
|
|
54
|
+
const log = options.log ?? ((message) => console.log(message));
|
|
55
|
+
if (!node_fs_1.default.existsSync(entry))
|
|
56
|
+
throw new Error(`${node_path_1.default.relative(root, entry)} não existe: rode o tsc antes`);
|
|
57
|
+
const alias = {};
|
|
58
|
+
let autoloadEntries = 0;
|
|
59
|
+
if (node_fs_1.default.existsSync(modulesDir)) {
|
|
60
|
+
const entries = (0, autoload_static_1.findAutoloadEntries)(modulesDir);
|
|
61
|
+
node_fs_1.default.writeFileSync(shim, (0, autoload_static_1.renderAutoloadStatic)(entries, dist));
|
|
62
|
+
alias["@fastify/autoload"] = shim;
|
|
63
|
+
autoloadEntries = entries.length;
|
|
64
|
+
}
|
|
65
|
+
const esbuild = loadEsbuild(root);
|
|
66
|
+
const result = await esbuild.build({
|
|
67
|
+
entryPoints: [entry],
|
|
68
|
+
outfile,
|
|
69
|
+
bundle: true,
|
|
70
|
+
platform: "node",
|
|
71
|
+
target: options.target ?? "node22",
|
|
72
|
+
format: "cjs",
|
|
73
|
+
external: [...exports.DEFAULT_BUNDLE_EXTERNAL, ...(options.external ?? [])],
|
|
74
|
+
alias,
|
|
75
|
+
legalComments: "none",
|
|
76
|
+
logLevel: "warning",
|
|
77
|
+
metafile: true,
|
|
78
|
+
});
|
|
79
|
+
const bytes = node_fs_1.default.statSync(outfile).size;
|
|
80
|
+
const inputs = Object.keys(result.metafile.inputs).length;
|
|
81
|
+
log(`bundle: ${node_path_1.default.relative(root, outfile)} ${(bytes / 1e6).toFixed(1)} MB (${inputs} arquivos embutidos, ${autoloadEntries} arquivos de módulo no autoload estático)`);
|
|
82
|
+
return { outfile, bytes, inputs, autoloadEntries };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/build/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
// mybuildex-bundle — empacota a API (dist/index.js -> dist/bundle.js) e confere
|
|
8
|
+
// que as rotas do bundle são idênticas às do @fastify/autoload.
|
|
9
|
+
//
|
|
10
|
+
// Uso na API (package.json):
|
|
11
|
+
// "main": "dist/bundle.js",
|
|
12
|
+
// "scripts": { "build": "tsc && mybuildex-bundle" }
|
|
13
|
+
//
|
|
14
|
+
// Configuração opcional, no package.json da API:
|
|
15
|
+
// "mybuildex": { "bundle": {
|
|
16
|
+
// "external": ["exceljs", "pdf-lib"], // libs que a API só carrega sob demanda
|
|
17
|
+
// "verifyEnv": {"MINHA_ENV": "x"}, // env a mais para a API carregar na verificação
|
|
18
|
+
// "swaggerPath": "/documentation/json",
|
|
19
|
+
// "entry": "index.js", "outfile": "bundle.js", "modulesDir": "modules", "distDir": "dist"
|
|
20
|
+
// } }
|
|
21
|
+
//
|
|
22
|
+
// Flags: --no-verify (só empacota). MYBUILDEX_BUNDLE_VERIFY=0 faz o mesmo.
|
|
23
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
24
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
25
|
+
const bundle_1 = require("./bundle");
|
|
26
|
+
const verify_bundle_1 = require("./verify-bundle");
|
|
27
|
+
async function main() {
|
|
28
|
+
const root = process.cwd();
|
|
29
|
+
const pkgFile = node_path_1.default.join(root, "package.json");
|
|
30
|
+
const pkg = node_fs_1.default.existsSync(pkgFile) ? JSON.parse(node_fs_1.default.readFileSync(pkgFile, "utf8")) : {};
|
|
31
|
+
const config = pkg?.mybuildex?.bundle ?? {};
|
|
32
|
+
const skipVerify = process.argv.includes("--no-verify") || process.env.MYBUILDEX_BUNDLE_VERIFY === "0";
|
|
33
|
+
await (0, bundle_1.bundleApi)({
|
|
34
|
+
root,
|
|
35
|
+
distDir: config.distDir,
|
|
36
|
+
entry: config.entry,
|
|
37
|
+
outfile: config.outfile,
|
|
38
|
+
modulesDir: config.modulesDir,
|
|
39
|
+
external: config.external,
|
|
40
|
+
target: config.target,
|
|
41
|
+
});
|
|
42
|
+
if (skipVerify) {
|
|
43
|
+
console.log("verify-bundle: pulado (--no-verify)");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const { routes } = (0, verify_bundle_1.verifyBundle)({
|
|
47
|
+
root,
|
|
48
|
+
distDir: config.distDir,
|
|
49
|
+
entry: config.entry,
|
|
50
|
+
outfile: config.outfile,
|
|
51
|
+
swaggerPath: config.swaggerPath,
|
|
52
|
+
env: config.verifyEnv,
|
|
53
|
+
});
|
|
54
|
+
console.log(`verify-bundle: ok — ${routes} rotas idênticas no autoload e no bundle`);
|
|
55
|
+
}
|
|
56
|
+
main().catch((error) => {
|
|
57
|
+
console.error(error?.message ?? error);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/build/cli.ts"],"names":[],"mappings":";;;;;;AACA,gFAAgF;AAChF,gEAAgE;AAChE,EAAE;AACF,6BAA6B;AAC7B,8BAA8B;AAC9B,sDAAsD;AACtD,EAAE;AACF,iDAAiD;AACjD,+BAA+B;AAC/B,0FAA0F;AAC1F,kGAAkG;AAClG,8CAA8C;AAC9C,gGAAgG;AAChG,QAAQ;AACR,EAAE;AACF,2EAA2E;AAC3E,sDAAyB;AACzB,0DAA6B;AAC7B,qCAAmC;AACnC,mDAA6C;AAE7C,KAAK,UAAU,IAAI;IACf,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,iBAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvF,MAAM,MAAM,GAAG,GAAG,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,CAAC;IAEvG,MAAM,IAAA,kBAAS,EAAC;QACZ,IAAI;QACJ,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM;KACxB,CAAC,CAAC;IAEH,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO;IACX,CAAC;IACD,MAAM,EAAC,MAAM,EAAC,GAAG,IAAA,4BAAY,EAAC;QAC1B,IAAI;QACJ,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,GAAG,EAAE,MAAM,CAAC,SAAS;KACxB,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,uBAAuB,MAAM,0CAA0C,CAAC,CAAC;AACzF,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface VerifyBundleOptions {
|
|
2
|
+
/** Raiz da API (default: process.cwd()). */
|
|
3
|
+
root?: string;
|
|
4
|
+
/** Pasta do compilado, relativa à raiz (default: "dist"). */
|
|
5
|
+
distDir?: string;
|
|
6
|
+
/** Entrada original, relativa a distDir (default: "index.js"). */
|
|
7
|
+
entry?: string;
|
|
8
|
+
/** Bundle, relativo a distDir (default: "bundle.js"). */
|
|
9
|
+
outfile?: string;
|
|
10
|
+
/** Caminho do JSON do swagger (default: "/documentation/json"). */
|
|
11
|
+
swaggerPath?: string;
|
|
12
|
+
/** Variáveis de ambiente a mais para a API carregar na verificação. */
|
|
13
|
+
env?: Record<string, string>;
|
|
14
|
+
/** Tempo máximo por entrada, ms (default: 120000). */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface VerifyBundleResult {
|
|
18
|
+
routes: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function verifyBundle(options?: VerifyBundleOptions): VerifyBundleResult;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.verifyBundle = verifyBundle;
|
|
7
|
+
// Confere que o bundle (autoload estático) expõe EXATAMENTE as mesmas rotas
|
|
8
|
+
// que a entrada original com o @fastify/autoload de verdade.
|
|
9
|
+
//
|
|
10
|
+
// Sobe cada entrada num processo próprio, pede o JSON do swagger (ele lista
|
|
11
|
+
// toda rota registrada, com método, caminho e schema) e compara. Também
|
|
12
|
+
// garante que o bundle não leu arquivo solto do dist/ — se leu, o autoload
|
|
13
|
+
// estático não está valendo. Qualquer diferença lança: um bundle com rota
|
|
14
|
+
// faltando não pode chegar no deploy.
|
|
15
|
+
//
|
|
16
|
+
// Não toca em banco: DATABASE_URL aponta para uma porta morta e só o swagger
|
|
17
|
+
// é chamado. Precisa do que a API precisa para CARREGAR (ex.: firebase.json).
|
|
18
|
+
const node_child_process_1 = require("node:child_process");
|
|
19
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
20
|
+
// Roda dentro do processo filho: carrega a entrada e devolve o swagger.
|
|
21
|
+
const WORKER = `
|
|
22
|
+
const http = require("node:http");
|
|
23
|
+
const path = require("node:path");
|
|
24
|
+
const entry = path.resolve(process.argv[1]);
|
|
25
|
+
const swaggerPath = process.argv[2];
|
|
26
|
+
const silent = () => {};
|
|
27
|
+
console.log = silent; console.warn = silent; console.error = silent;
|
|
28
|
+
process.on("unhandledRejection", silent);
|
|
29
|
+
const mod = require(entry);
|
|
30
|
+
const handler = typeof mod === "function" ? mod : (mod.default || Object.values(mod).find((v) => typeof v === "function"));
|
|
31
|
+
const server = http.createServer((req, res) => handler(req, res));
|
|
32
|
+
server.listen(0, "127.0.0.1", () => {
|
|
33
|
+
http.get({host: "127.0.0.1", port: server.address().port, path: swaggerPath}, (res) => {
|
|
34
|
+
let body = "";
|
|
35
|
+
res.on("data", (c) => body += c);
|
|
36
|
+
res.on("end", () => {
|
|
37
|
+
const loose = Object.keys(require.cache).filter((f) => f.startsWith(path.dirname(entry) + path.sep) && f !== entry);
|
|
38
|
+
// sai só depois de o pipe aceitar tudo: exit() direto truncaria o JSON
|
|
39
|
+
process.stdout.write(JSON.stringify({status: res.statusCode, body, loose: loose.length}), () => process.exit(0));
|
|
40
|
+
});
|
|
41
|
+
}).on("error", (e) => { process.stderr.write(String(e)); process.exit(1); });
|
|
42
|
+
});
|
|
43
|
+
`;
|
|
44
|
+
// JSON com as chaves ordenadas: a ORDEM das rotas no swagger não é estável
|
|
45
|
+
// nem entre duas execuções do próprio autoload (ele varre as pastas em
|
|
46
|
+
// paralelo), então só o conteúdo é comparado.
|
|
47
|
+
function canonical(value) {
|
|
48
|
+
if (Array.isArray(value))
|
|
49
|
+
return value.map(canonical);
|
|
50
|
+
if (value && typeof value === "object") {
|
|
51
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonical(value[key])]));
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
function operations(doc) {
|
|
56
|
+
const list = [];
|
|
57
|
+
for (const [route, methods] of Object.entries(doc?.paths ?? {})) {
|
|
58
|
+
for (const method of Object.keys(methods))
|
|
59
|
+
list.push(`${method.toUpperCase()} ${route}`);
|
|
60
|
+
}
|
|
61
|
+
return list.sort();
|
|
62
|
+
}
|
|
63
|
+
function verifyBundle(options = {}) {
|
|
64
|
+
const root = node_path_1.default.resolve(options.root ?? process.cwd());
|
|
65
|
+
const dist = node_path_1.default.join(root, options.distDir ?? "dist");
|
|
66
|
+
const swaggerPath = options.swaggerPath ?? "/documentation/json";
|
|
67
|
+
const swaggerOf = (file) => {
|
|
68
|
+
const label = node_path_1.default.relative(root, file);
|
|
69
|
+
const result = (0, node_child_process_1.spawnSync)(process.execPath, ["-e", WORKER, file, swaggerPath], {
|
|
70
|
+
cwd: root,
|
|
71
|
+
encoding: "utf8",
|
|
72
|
+
timeout: options.timeoutMs ?? 120000,
|
|
73
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
74
|
+
env: {
|
|
75
|
+
...process.env,
|
|
76
|
+
DATABASE_URL: "mysql://verify:verify@127.0.0.1:1/verify_school_1?connection_limit=1",
|
|
77
|
+
HTTP: "https",
|
|
78
|
+
DOMAIN: "verify.local/api",
|
|
79
|
+
PROJECTID: process.env.PROJECTID || "verify",
|
|
80
|
+
APIKEY: process.env.APIKEY || "verify",
|
|
81
|
+
STORAGEBUCKET: process.env.STORAGEBUCKET || "verify.appspot.com",
|
|
82
|
+
REDIS: "",
|
|
83
|
+
...(options.env ?? {}),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
if (result.status !== 0 || !result.stdout) {
|
|
87
|
+
throw new Error(`verify-bundle: ${label} não subiu (status ${result.status}): ${(result.stderr || "").slice(0, 2000)}`);
|
|
88
|
+
}
|
|
89
|
+
const out = JSON.parse(result.stdout);
|
|
90
|
+
if (out.status !== 200)
|
|
91
|
+
throw new Error(`verify-bundle: ${label} respondeu ${out.status} em ${swaggerPath}`);
|
|
92
|
+
return { doc: JSON.parse(out.body), loose: out.loose };
|
|
93
|
+
};
|
|
94
|
+
const original = swaggerOf(node_path_1.default.join(dist, options.entry ?? "index.js"));
|
|
95
|
+
const bundle = swaggerOf(node_path_1.default.join(dist, options.outfile ?? "bundle.js"));
|
|
96
|
+
const a = operations(original.doc);
|
|
97
|
+
const b = operations(bundle.doc);
|
|
98
|
+
const missing = a.filter((op) => !b.includes(op));
|
|
99
|
+
const extra = b.filter((op) => !a.includes(op));
|
|
100
|
+
const problems = [];
|
|
101
|
+
if (a.length === 0)
|
|
102
|
+
problems.push("a entrada original não registrou rota nenhuma (o build está quebrado antes do bundle)");
|
|
103
|
+
if (missing.length)
|
|
104
|
+
problems.push(`rotas que o autoload registra e o bundle NÃO: ${missing.slice(0, 20).join(", ")}`);
|
|
105
|
+
if (extra.length)
|
|
106
|
+
problems.push(`rotas só no bundle: ${extra.slice(0, 20).join(", ")}`);
|
|
107
|
+
if (!missing.length && !extra.length && JSON.stringify(canonical(original.doc)) !== JSON.stringify(canonical(bundle.doc))) {
|
|
108
|
+
problems.push("mesmas rotas, mas o swagger (schemas/tags) difere entre o autoload e o bundle");
|
|
109
|
+
}
|
|
110
|
+
if (bundle.loose > 0)
|
|
111
|
+
problems.push(`o bundle carregou ${bundle.loose} arquivo(s) soltos de ${options.distDir ?? "dist"}/ — o autoload estático não está valendo`);
|
|
112
|
+
if (problems.length)
|
|
113
|
+
throw new Error("verify-bundle: FALHOU\n - " + problems.join("\n - "));
|
|
114
|
+
return { routes: a.length };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=verify-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-bundle.js","sourceRoot":"","sources":["../../src/build/verify-bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,5 +23,14 @@ export interface GcfHandlerOptions {
|
|
|
23
23
|
exitDelayMs?: number;
|
|
24
24
|
/** Função de saída (default: process.exit) — injetável para teste */
|
|
25
25
|
exit?: (code: number) => void;
|
|
26
|
+
/** Boot antecipado (default: false). Dispara o ready() logo depois da
|
|
27
|
+
* carga do módulo, em vez de esperar a primeira request: a instância que
|
|
28
|
+
* sobe antes do tráfego (rollout, autoscaling) chega pronta, e o boot roda
|
|
29
|
+
* na janela de CPU extra do startup do Cloud Run. Medido na v3_peoples em
|
|
30
|
+
* 04/10/2026: eram 2,6 s de boot DENTRO da primeira request. As três
|
|
31
|
+
* garantias do wrapper valem igual — a rejeição do boot antecipado já
|
|
32
|
+
* nasce com handler, e uma falha continua virando 503 + saída na request
|
|
33
|
+
* seguinte. */
|
|
34
|
+
eagerBoot?: boolean;
|
|
26
35
|
}
|
|
27
36
|
export declare function createGcfHandler(options: GcfHandlerOptions): (req: any, res: any) => Promise<void>;
|
package/dist/http/gcf-handler.js
CHANGED
|
@@ -35,7 +35,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
35
35
|
exports.createGcfHandler = createGcfHandler;
|
|
36
36
|
const plugin_1 = require("../cors/plugin");
|
|
37
37
|
function createGcfHandler(options) {
|
|
38
|
-
const { server, origin = "*", methods = plugin_1.DEFAULT_CORS.methods.join(","), headers = "*", maxAge = "3600", handlePreflight = true, bootFailureStatus = 503, bootFailureMessage = "Serviço iniciando, tente novamente em instantes", exitOnBootFailure = true, exitDelayMs = 2000, exit = (code) => process.exit(code), } = options;
|
|
38
|
+
const { server, origin = "*", methods = plugin_1.DEFAULT_CORS.methods.join(","), headers = "*", maxAge = "3600", handlePreflight = true, bootFailureStatus = 503, bootFailureMessage = "Serviço iniciando, tente novamente em instantes", exitOnBootFailure = true, exitDelayMs = 2000, exit = (code) => process.exit(code), eagerBoot = false, } = options;
|
|
39
39
|
// null = ainda não bootou (ou o boot anterior falhou e será re-tentado)
|
|
40
40
|
let readyPromise = null;
|
|
41
41
|
function getReady() {
|
|
@@ -49,6 +49,12 @@ function createGcfHandler(options) {
|
|
|
49
49
|
}
|
|
50
50
|
return readyPromise;
|
|
51
51
|
}
|
|
52
|
+
// nextTick: só depois que o módulo da API terminou de carregar — registros
|
|
53
|
+
// feitos DEPOIS do createGcfHandler (plugins, content type parsers) ainda
|
|
54
|
+
// entram. O catch vazio é o que impede o unhandledRejection aqui: sem
|
|
55
|
+
// request esperando, ninguém mais trataria a falha.
|
|
56
|
+
if (eagerBoot)
|
|
57
|
+
process.nextTick(() => getReady().catch(() => { }));
|
|
52
58
|
let exitScheduled = false;
|
|
53
59
|
// Sai só DEPOIS que a resposta foi escrita no socket: process.exit() no
|
|
54
60
|
// mesmo tick cortaria o 503 e o browser voltaria a ver "erro de CORS".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcf-handler.js","sourceRoot":"","sources":["../../src/http/gcf-handler.ts"],"names":[],"mappings":";AAAA,4EAA4E;AAC5E,uDAAuD;AACvD,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,2DAA2D;AAC3D,+EAA+E;AAC/E,mEAAmE;AACnE,2EAA2E;AAC3E,uEAAuE;AACvE,6EAA6E;AAC7E,wEAAwE;AACxE,qDAAqD;AACrD,EAAE;AACF,gCAAgC;AAChC,+EAA+E;AAC/E,4EAA4E;AAC5E,6EAA6E;AAC7E,+EAA+E;AAC/E,2EAA2E;AAC3E,yEAAyE;AACzE,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,+BAA+B;AAC/B,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,0CAA0C;AAC1C,EAAE;AACF,wEAAwE;AACxE,6EAA6E;;
|
|
1
|
+
{"version":3,"file":"gcf-handler.js","sourceRoot":"","sources":["../../src/http/gcf-handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mybuildex/pkg",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Infra comum das APIs MyBuilder: multitenancy Prisma (pool único), middleware de tenant e CORS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
],
|
|
22
22
|
"main": "dist/index.js",
|
|
23
23
|
"types": "dist/index.d.ts",
|
|
24
|
+
"bin": {
|
|
25
|
+
"mybuildex-bundle": "dist/build/cli.js"
|
|
26
|
+
},
|
|
24
27
|
"files": [
|
|
25
28
|
"dist"
|
|
26
29
|
],
|
|
@@ -45,17 +48,23 @@
|
|
|
45
48
|
"redis": "^5.12.1"
|
|
46
49
|
},
|
|
47
50
|
"peerDependencies": {
|
|
51
|
+
"esbuild": ">=0.20",
|
|
48
52
|
"fastify": ">=4"
|
|
49
53
|
},
|
|
50
54
|
"peerDependenciesMeta": {
|
|
55
|
+
"esbuild": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
51
58
|
"fastify": {
|
|
52
59
|
"optional": true
|
|
53
60
|
}
|
|
54
61
|
},
|
|
55
62
|
"devDependencies": {
|
|
63
|
+
"@fastify/autoload": "^5.0.0",
|
|
56
64
|
"@google-cloud/functions-framework": "^3.5.1",
|
|
57
65
|
"@types/express": "^4.17.25",
|
|
58
66
|
"@types/node": "^22.0.0",
|
|
67
|
+
"esbuild": "^0.28.2",
|
|
59
68
|
"express": "^4.22.2",
|
|
60
69
|
"fastify": "^4.26.2",
|
|
61
70
|
"typescript": "^5.5.0",
|