onboarding-kit 0.0.0-stage → 0.2.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 +102 -2
- package/dist/adapters/nest.d.ts +15 -0
- package/dist/adapters/nest.js +53 -0
- package/dist/adapters/next.d.ts +23 -0
- package/dist/adapters/next.js +41 -0
- package/dist/adapters/node.d.ts +10 -0
- package/dist/adapters/node.js +33 -0
- package/dist/brand.d.ts +38 -0
- package/dist/brand.js +319 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +272 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +63 -0
- package/dist/load.d.ts +19 -0
- package/dist/load.js +59 -0
- package/dist/render/assets.d.ts +4 -0
- package/dist/render/assets.js +512 -0
- package/dist/render/copy.d.ts +140 -0
- package/dist/render/copy.js +343 -0
- package/dist/render/html.d.ts +12 -0
- package/dist/render/html.js +74 -0
- package/dist/render/index.d.ts +9 -0
- package/dist/render/index.js +230 -0
- package/dist/render/slides.d.ts +19 -0
- package/dist/render/slides.js +232 -0
- package/dist/template.d.ts +14 -0
- package/dist/template.js +96 -0
- package/dist/types.d.ts +163 -0
- package/dist/types.js +6 -0
- package/dist/validate.d.ts +17 -0
- package/dist/validate.js +236 -0
- package/package.json +75 -4
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formato do arquivo onboarding.json.
|
|
3
|
+
* Chaves que começam com "_" (ex.: "_instructions") são para a IA e são ignoradas pelo visualizador.
|
|
4
|
+
*/
|
|
5
|
+
/** Referência a um trecho do código: "caminho/arquivo.ts" ou "caminho/arquivo.ts:42". */
|
|
6
|
+
export type Evidence = string;
|
|
7
|
+
export type Framework = "next" | "nest" | "node";
|
|
8
|
+
export interface OnboardingMeta {
|
|
9
|
+
schemaVersion: string;
|
|
10
|
+
/** "pending" enquanto a IA não preencheu; "filled" depois. */
|
|
11
|
+
status: "pending" | "filled";
|
|
12
|
+
/** Idioma em que a IA deve escrever o conteúdo, ex.: "pt-BR". */
|
|
13
|
+
language: string;
|
|
14
|
+
framework: Framework | "";
|
|
15
|
+
generatedAt: string;
|
|
16
|
+
generatedBy: string;
|
|
17
|
+
/** Hash do commit (git rev-parse HEAD) analisado. */
|
|
18
|
+
commit: string;
|
|
19
|
+
}
|
|
20
|
+
export interface OnboardingProject {
|
|
21
|
+
name: string;
|
|
22
|
+
tagline: string;
|
|
23
|
+
purpose: string;
|
|
24
|
+
audience: string;
|
|
25
|
+
status: string;
|
|
26
|
+
repoUrl: string;
|
|
27
|
+
}
|
|
28
|
+
export interface GettingStarted {
|
|
29
|
+
prerequisites: string[];
|
|
30
|
+
setup: string[];
|
|
31
|
+
commands: {
|
|
32
|
+
name: string;
|
|
33
|
+
command: string;
|
|
34
|
+
description: string;
|
|
35
|
+
}[];
|
|
36
|
+
envVars: {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
required: boolean;
|
|
40
|
+
}[];
|
|
41
|
+
}
|
|
42
|
+
export interface StackItem {
|
|
43
|
+
name: string;
|
|
44
|
+
category: string;
|
|
45
|
+
version: string;
|
|
46
|
+
why: string;
|
|
47
|
+
evidence: Evidence[];
|
|
48
|
+
}
|
|
49
|
+
export interface ArchitectureModule {
|
|
50
|
+
name: string;
|
|
51
|
+
path: string;
|
|
52
|
+
responsibility: string;
|
|
53
|
+
}
|
|
54
|
+
export interface Architecture {
|
|
55
|
+
summary: string;
|
|
56
|
+
/** Diagrama em sintaxe Mermaid (sem as cercas ```). */
|
|
57
|
+
diagram: string;
|
|
58
|
+
modules: ArchitectureModule[];
|
|
59
|
+
}
|
|
60
|
+
export interface Convention {
|
|
61
|
+
title: string;
|
|
62
|
+
description: string;
|
|
63
|
+
example: string;
|
|
64
|
+
evidence: Evidence[];
|
|
65
|
+
}
|
|
66
|
+
export interface BusinessActor {
|
|
67
|
+
name: string;
|
|
68
|
+
description: string;
|
|
69
|
+
evidence: Evidence[];
|
|
70
|
+
}
|
|
71
|
+
export interface BusinessFlow {
|
|
72
|
+
name: string;
|
|
73
|
+
steps: string[];
|
|
74
|
+
evidence: Evidence[];
|
|
75
|
+
}
|
|
76
|
+
export interface Business {
|
|
77
|
+
/** Como o produto gera valor ou receita. */
|
|
78
|
+
model: string;
|
|
79
|
+
/** O valor entregue para quem usa. */
|
|
80
|
+
valueProposition: string;
|
|
81
|
+
actors: BusinessActor[];
|
|
82
|
+
flows: BusinessFlow[];
|
|
83
|
+
}
|
|
84
|
+
export interface GlossaryTerm {
|
|
85
|
+
term: string;
|
|
86
|
+
definition: string;
|
|
87
|
+
}
|
|
88
|
+
export interface BusinessRule {
|
|
89
|
+
title: string;
|
|
90
|
+
description: string;
|
|
91
|
+
evidence: Evidence[];
|
|
92
|
+
}
|
|
93
|
+
export interface Feature {
|
|
94
|
+
name: string;
|
|
95
|
+
description: string;
|
|
96
|
+
entryPoints: Evidence[];
|
|
97
|
+
status: string;
|
|
98
|
+
}
|
|
99
|
+
export interface TourStep {
|
|
100
|
+
file: Evidence;
|
|
101
|
+
explanation: string;
|
|
102
|
+
}
|
|
103
|
+
export interface Tour {
|
|
104
|
+
title: string;
|
|
105
|
+
description: string;
|
|
106
|
+
steps: TourStep[];
|
|
107
|
+
}
|
|
108
|
+
export interface Gotcha {
|
|
109
|
+
title: string;
|
|
110
|
+
description: string;
|
|
111
|
+
evidence: Evidence[];
|
|
112
|
+
}
|
|
113
|
+
export interface Decision {
|
|
114
|
+
title: string;
|
|
115
|
+
context: string;
|
|
116
|
+
decision: string;
|
|
117
|
+
evidence: Evidence[];
|
|
118
|
+
}
|
|
119
|
+
export interface FirstTask {
|
|
120
|
+
title: string;
|
|
121
|
+
description: string;
|
|
122
|
+
files: Evidence[];
|
|
123
|
+
}
|
|
124
|
+
export interface BrandInfo {
|
|
125
|
+
/** Cor principal da marca em hex (#RRGGBB). */
|
|
126
|
+
primaryColor: string;
|
|
127
|
+
/** Outras cores da paleta em hex. */
|
|
128
|
+
palette: string[];
|
|
129
|
+
/** Caminho relativo do logo (ex.: public/logo.svg). */
|
|
130
|
+
logo: string;
|
|
131
|
+
/** Caminho relativo do favicon (ex.: public/favicon.ico). */
|
|
132
|
+
favicon: string;
|
|
133
|
+
evidence: Evidence[];
|
|
134
|
+
}
|
|
135
|
+
export interface OnboardingData {
|
|
136
|
+
$schema?: string;
|
|
137
|
+
_instructions?: unknown;
|
|
138
|
+
meta: OnboardingMeta;
|
|
139
|
+
project: OnboardingProject;
|
|
140
|
+
/** Opcional em arquivos gerados antes da v0.2. */
|
|
141
|
+
business?: Business;
|
|
142
|
+
gettingStarted: GettingStarted;
|
|
143
|
+
stack: StackItem[];
|
|
144
|
+
architecture: Architecture;
|
|
145
|
+
conventions: Convention[];
|
|
146
|
+
domain: {
|
|
147
|
+
glossary: GlossaryTerm[];
|
|
148
|
+
businessRules: BusinessRule[];
|
|
149
|
+
};
|
|
150
|
+
features: Feature[];
|
|
151
|
+
tours: Tour[];
|
|
152
|
+
gotchas: Gotcha[];
|
|
153
|
+
decisions: Decision[];
|
|
154
|
+
firstTasks: FirstTask[];
|
|
155
|
+
/** Cores e logo do projeto, usados para dar a cara da marca à apresentação. Opcional. */
|
|
156
|
+
brand?: BrandInfo;
|
|
157
|
+
}
|
|
158
|
+
export interface OnboardingOptions {
|
|
159
|
+
/** Caminho do onboarding.json. Padrão: "<cwd>/onboarding.json". */
|
|
160
|
+
file?: string;
|
|
161
|
+
/** Liga ou desliga a rota. Padrão: ligada fora de produção (NODE_ENV !== "production"). */
|
|
162
|
+
enabled?: boolean;
|
|
163
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface Issue {
|
|
2
|
+
level: "error" | "warning";
|
|
3
|
+
path: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ValidateOptions {
|
|
7
|
+
/** Raiz do repositório, usada para conferir as evidências. */
|
|
8
|
+
root: string;
|
|
9
|
+
/** Commit atual (git rev-parse HEAD), para avisar quando o JSON está desatualizado. */
|
|
10
|
+
headCommit?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Separa "src/a.ts:10" ou "src/a.ts:10-20" em caminho e linha. */
|
|
13
|
+
export declare function parseEvidence(ref: string): {
|
|
14
|
+
file: string;
|
|
15
|
+
line?: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function validateOnboarding(data: unknown, options: ValidateOptions): Issue[];
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseEvidence = parseEvidence;
|
|
4
|
+
exports.validateOnboarding = validateOnboarding;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const brand_1 = require("./brand");
|
|
8
|
+
const load_1 = require("./load");
|
|
9
|
+
/** Campo que identifica cada item e precisa estar preenchido. */
|
|
10
|
+
const ARRAY_SECTIONS = [
|
|
11
|
+
{ path: "business.actors", key: "name", evidence: "warning", optional: true },
|
|
12
|
+
{ path: "business.flows", key: "name", evidence: "warning", optional: true },
|
|
13
|
+
{ path: "stack", key: "name", evidence: "warning", min: 1 },
|
|
14
|
+
{ path: "architecture.modules", key: "path" },
|
|
15
|
+
{ path: "conventions", key: "title", evidence: "error" },
|
|
16
|
+
{ path: "domain.glossary", key: "term" },
|
|
17
|
+
{ path: "domain.businessRules", key: "title", evidence: "error" },
|
|
18
|
+
{ path: "features", key: "name", min: 1 },
|
|
19
|
+
{ path: "tours", key: "title" },
|
|
20
|
+
{ path: "gotchas", key: "title", evidence: "error" },
|
|
21
|
+
{ path: "decisions", key: "title", evidence: "warning" },
|
|
22
|
+
{ path: "firstTasks", key: "title" },
|
|
23
|
+
{ path: "gettingStarted.commands", key: "command" },
|
|
24
|
+
{ path: "gettingStarted.envVars", key: "name" },
|
|
25
|
+
];
|
|
26
|
+
const EVIDENCE_KEYS = new Set(["evidence", "entryPoints", "files"]);
|
|
27
|
+
const SECRET_PATTERNS = [
|
|
28
|
+
{ name: "chave AWS", re: /\bAKIA[0-9A-Z]{16}\b/, level: "error" },
|
|
29
|
+
{ name: "chave de API (sk-...)", re: /\bsk-[A-Za-z0-9_-]{20,}/, level: "error" },
|
|
30
|
+
{ name: "token do GitHub", re: /\bgh[pousr]_[A-Za-z0-9]{30,}/, level: "error" },
|
|
31
|
+
{ name: "token do Slack", re: /\bxox[abprs]-[A-Za-z0-9-]{10,}/, level: "error" },
|
|
32
|
+
{ name: "chave do Google", re: /\bAIza[0-9A-Za-z_-]{35}\b/, level: "error" },
|
|
33
|
+
{ name: "chave privada", re: /-----BEGIN [A-Z ]*PRIVATE KEY-----/, level: "error" },
|
|
34
|
+
{ name: "JWT", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, level: "error" },
|
|
35
|
+
{ name: "URL com usuário e senha", re: /\b[a-z][a-z0-9+.-]*:\/\/[^\s:@/"]+:[^\s@/"]+@/i, level: "warning" },
|
|
36
|
+
];
|
|
37
|
+
function get(obj, path) {
|
|
38
|
+
return path.split(".").reduce((acc, key) => (acc && typeof acc === "object" ? acc[key] : undefined), obj);
|
|
39
|
+
}
|
|
40
|
+
function isObj(v) {
|
|
41
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
42
|
+
}
|
|
43
|
+
/** Separa "src/a.ts:10" ou "src/a.ts:10-20" em caminho e linha. */
|
|
44
|
+
function parseEvidence(ref) {
|
|
45
|
+
const match = /^(.*?)(?::(\d+)(?:-\d+)?)?$/.exec(ref.trim());
|
|
46
|
+
const file = (match?.[1] ?? ref).trim();
|
|
47
|
+
const line = match?.[2] ? Number(match[2]) : undefined;
|
|
48
|
+
return { file, line };
|
|
49
|
+
}
|
|
50
|
+
function checkEvidence(ref, at, root, issues) {
|
|
51
|
+
if (typeof ref !== "string" || ref.trim() === "")
|
|
52
|
+
return;
|
|
53
|
+
const { file, line } = parseEvidence(ref);
|
|
54
|
+
if ((0, node_path_1.isAbsolute)(file)) {
|
|
55
|
+
issues.push({ level: "error", path: at, message: `use caminho relativo à raiz, não absoluto: "${ref}"` });
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const full = (0, node_path_1.resolve)(root, file);
|
|
59
|
+
const rel = (0, node_path_1.relative)(root, full);
|
|
60
|
+
if (rel.startsWith("..") || rel.split(node_path_1.sep).includes("..")) {
|
|
61
|
+
issues.push({ level: "error", path: at, message: `caminho fora do repositório: "${ref}"` });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!(0, node_fs_1.existsSync)(full)) {
|
|
65
|
+
issues.push({ level: "error", path: at, message: `arquivo não existe: "${file}"` });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (line !== undefined && (0, node_fs_1.statSync)(full).isFile()) {
|
|
69
|
+
const total = (0, node_fs_1.readFileSync)(full, "utf8").split("\n").length;
|
|
70
|
+
if (line < 1 || line > total) {
|
|
71
|
+
issues.push({ level: "warning", path: at, message: `linha ${line} não existe em "${file}" (${total} linhas)` });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function walkEvidence(value, at, root, issues) {
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
value.forEach((v, i) => walkEvidence(v, `${at}[${i}]`, root, issues));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!isObj(value))
|
|
81
|
+
return;
|
|
82
|
+
for (const [key, v] of Object.entries(value)) {
|
|
83
|
+
if (key.startsWith("_") || key === "meta")
|
|
84
|
+
continue;
|
|
85
|
+
const here = at ? `${at}.${key}` : key;
|
|
86
|
+
if (EVIDENCE_KEYS.has(key) && Array.isArray(v)) {
|
|
87
|
+
v.forEach((ref, i) => checkEvidence(ref, `${here}[${i}]`, root, issues));
|
|
88
|
+
}
|
|
89
|
+
else if ((key === "file" || key === "logo" || key === "favicon") && typeof v === "string") {
|
|
90
|
+
checkEvidence(v, here, root, issues);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
walkEvidence(v, here, root, issues);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function validateOnboarding(data, options) {
|
|
98
|
+
const issues = [];
|
|
99
|
+
const err = (path, message) => issues.push({ level: "error", path, message });
|
|
100
|
+
const warn = (path, message) => issues.push({ level: "warning", path, message });
|
|
101
|
+
if (!isObj(data)) {
|
|
102
|
+
err("", "o arquivo precisa ser um objeto JSON");
|
|
103
|
+
return issues;
|
|
104
|
+
}
|
|
105
|
+
// meta
|
|
106
|
+
const meta = data.meta;
|
|
107
|
+
if (!isObj(meta)) {
|
|
108
|
+
err("meta", "seção ausente");
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
if (meta.status !== "filled")
|
|
112
|
+
err("meta.status", 'ainda não foi preenchido pela IA (esperado "filled")');
|
|
113
|
+
if ((0, load_1.isBlank)(meta.generatedAt))
|
|
114
|
+
warn("meta.generatedAt", "vazio");
|
|
115
|
+
if ((0, load_1.isBlank)(meta.generatedBy))
|
|
116
|
+
warn("meta.generatedBy", "vazio");
|
|
117
|
+
if (options.headCommit) {
|
|
118
|
+
if ((0, load_1.isBlank)(meta.commit)) {
|
|
119
|
+
warn("meta.commit", "vazio: preencha com `git rev-parse HEAD`");
|
|
120
|
+
}
|
|
121
|
+
else if (!options.headCommit.startsWith(String(meta.commit)) && !String(meta.commit).startsWith(options.headCommit)) {
|
|
122
|
+
warn("meta.commit", `gerado no commit ${String(meta.commit).slice(0, 7)}, mas o HEAD é ${options.headCommit.slice(0, 7)}: peça à IA para atualizar`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// project
|
|
127
|
+
const project = data.project;
|
|
128
|
+
if (!isObj(project)) {
|
|
129
|
+
err("project", "seção ausente");
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
for (const key of ["name", "purpose"]) {
|
|
133
|
+
if ((0, load_1.isBlank)(project[key]))
|
|
134
|
+
err(`project.${key}`, "obrigatório");
|
|
135
|
+
}
|
|
136
|
+
for (const key of ["tagline", "audience"]) {
|
|
137
|
+
if ((0, load_1.isBlank)(project[key]))
|
|
138
|
+
warn(`project.${key}`, "vazio");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// architecture
|
|
142
|
+
const architecture = data.architecture;
|
|
143
|
+
if (!isObj(architecture)) {
|
|
144
|
+
err("architecture", "seção ausente");
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
if ((0, load_1.isBlank)(architecture.summary))
|
|
148
|
+
warn("architecture.summary", "vazio");
|
|
149
|
+
if (typeof architecture.diagram === "string" && architecture.diagram.trim().startsWith("```")) {
|
|
150
|
+
err("architecture.diagram", "remova as cercas ``` e deixe só o código Mermaid");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const business = data.business;
|
|
154
|
+
if (business === undefined) {
|
|
155
|
+
warn("business", "seção ausente: rode `npx onboarding-kit init --force` num arquivo novo ou peça à IA para adicionar o modelo de negócio");
|
|
156
|
+
}
|
|
157
|
+
else if (!isObj(business)) {
|
|
158
|
+
err("business", "precisa ser um objeto");
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
if ((0, load_1.isBlank)(business.model))
|
|
162
|
+
warn("business.model", "vazio");
|
|
163
|
+
if ((0, load_1.isBlank)(business.valueProposition))
|
|
164
|
+
warn("business.valueProposition", "vazio");
|
|
165
|
+
if (Array.isArray(business.flows)) {
|
|
166
|
+
business.flows.forEach((flow, i) => {
|
|
167
|
+
if (isObj(flow) && !(0, load_1.isBlank)(flow) && Array.isArray(flow.steps) && flow.steps.some(load_1.isBlank)) {
|
|
168
|
+
err(`business.flows[${i}].steps`, "tem passos em branco");
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const brand = data.brand;
|
|
174
|
+
if (brand !== undefined && !isObj(brand)) {
|
|
175
|
+
err("brand", "precisa ser um objeto");
|
|
176
|
+
}
|
|
177
|
+
else if (isObj(brand)) {
|
|
178
|
+
const colors = [["brand.primaryColor", brand.primaryColor], ...(Array.isArray(brand.palette) ? brand.palette.map((c, i) => [`brand.palette[${i}]`, c]) : [])];
|
|
179
|
+
for (const [path, value] of colors) {
|
|
180
|
+
if (typeof value === "string" && !(0, load_1.isBlank)(value) && !(0, brand_1.parseColor)(value))
|
|
181
|
+
warn(String(path), `cor não reconhecida: "${value}" (use hex, ex.: #4f46e5)`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!isObj(data.gettingStarted))
|
|
185
|
+
err("gettingStarted", "seção ausente");
|
|
186
|
+
if (!isObj(data.domain))
|
|
187
|
+
err("domain", "seção ausente");
|
|
188
|
+
// listas
|
|
189
|
+
for (const section of ARRAY_SECTIONS) {
|
|
190
|
+
const list = get(data, section.path);
|
|
191
|
+
if (list === undefined) {
|
|
192
|
+
if (!section.optional)
|
|
193
|
+
err(section.path, "seção ausente");
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (!Array.isArray(list)) {
|
|
197
|
+
err(section.path, "precisa ser uma lista");
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
let real = 0;
|
|
201
|
+
list.forEach((item, i) => {
|
|
202
|
+
const at = `${section.path}[${i}]`;
|
|
203
|
+
if ((0, load_1.isBlank)(item)) {
|
|
204
|
+
err(at, "item modelo em branco: substitua por um item real ou remova");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
real++;
|
|
208
|
+
if (!isObj(item))
|
|
209
|
+
return;
|
|
210
|
+
if ((0, load_1.isBlank)(item[section.key]))
|
|
211
|
+
err(`${at}.${section.key}`, "obrigatório");
|
|
212
|
+
if (section.evidence && Array.isArray(item.evidence) && item.evidence.every(load_1.isBlank)) {
|
|
213
|
+
issues.push({ level: section.evidence, path: `${at}.evidence`, message: "sem evidência no código" });
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
if (section.min && real < section.min)
|
|
217
|
+
err(section.path, `precisa de pelo menos ${section.min} item`);
|
|
218
|
+
}
|
|
219
|
+
for (const key of ["prerequisites", "setup"]) {
|
|
220
|
+
const list = get(data, `gettingStarted.${key}`);
|
|
221
|
+
if (Array.isArray(list) && list.length > 0 && list.every(load_1.isBlank)) {
|
|
222
|
+
err(`gettingStarted.${key}`, "só tem itens em branco: preencha ou deixe a lista vazia");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
walkEvidence(data, "", options.root, issues);
|
|
226
|
+
// segredos (ignora as instruções)
|
|
227
|
+
const { _instructions, ...content } = data;
|
|
228
|
+
void _instructions;
|
|
229
|
+
const text = JSON.stringify(content);
|
|
230
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
231
|
+
if (pattern.re.test(text)) {
|
|
232
|
+
issues.push({ level: pattern.level, path: "(arquivo)", message: `possível segredo encontrado: ${pattern.name}. Remova antes de commitar.` });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return issues;
|
|
236
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onboarding-kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Onboarding de projetos gerado pela sua IA local: um JSON descreve o projeto e o onboarding-kit o apresenta em /onboarding.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"onboarding-kit": "./dist/cli/index.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./node": {
|
|
17
|
+
"types": "./dist/adapters/node.d.ts",
|
|
18
|
+
"default": "./dist/adapters/node.js"
|
|
19
|
+
},
|
|
20
|
+
"./next": {
|
|
21
|
+
"types": "./dist/adapters/next.d.ts",
|
|
22
|
+
"default": "./dist/adapters/next.js"
|
|
23
|
+
},
|
|
24
|
+
"./nest": {
|
|
25
|
+
"types": "./dist/adapters/nest.d.ts",
|
|
26
|
+
"default": "./dist/adapters/nest.js"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"typesVersions": {
|
|
31
|
+
"*": {
|
|
32
|
+
"node": [
|
|
33
|
+
"./dist/adapters/node.d.ts"
|
|
34
|
+
],
|
|
35
|
+
"next": [
|
|
36
|
+
"./dist/adapters/next.d.ts"
|
|
37
|
+
],
|
|
38
|
+
"nest": [
|
|
39
|
+
"./dist/adapters/nest.d.ts"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
51
|
+
"test": "npm run build && node --test test/*.test.js",
|
|
52
|
+
"prepublishOnly": "npm test"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"onboarding",
|
|
56
|
+
"documentation",
|
|
57
|
+
"ai",
|
|
58
|
+
"nextjs",
|
|
59
|
+
"nestjs",
|
|
60
|
+
"developer-experience"
|
|
61
|
+
],
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@nestjs/common": ">=9"
|
|
64
|
+
},
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"@nestjs/common": {
|
|
67
|
+
"optional": true
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@nestjs/common": "^11.0.0",
|
|
72
|
+
"@types/node": "^22.0.0",
|
|
73
|
+
"reflect-metadata": "^0.2.2",
|
|
74
|
+
"rxjs": "^7.8.1",
|
|
75
|
+
"typescript": "^5.6.0"
|
|
76
|
+
}
|
|
77
|
+
}
|