@neetru/cli 1.0.0 → 2.0.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/CHANGELOG.md +136 -0
- package/README.md +109 -152
- package/dist/commands/add.d.ts +8 -3
- package/dist/commands/add.js +70 -143
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/ai.d.ts +4 -0
- package/dist/commands/ai.js +88 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/autocomplete.d.ts +7 -0
- package/dist/commands/autocomplete.js +107 -0
- package/dist/commands/autocomplete.js.map +1 -0
- package/dist/commands/build.d.ts +18 -0
- package/dist/commands/build.js +288 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.js +70 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/db.d.ts +14 -0
- package/dist/commands/db.js +187 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/deploy.d.ts +16 -3
- package/dist/commands/deploy.js +400 -180
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.d.ts +27 -0
- package/dist/commands/doctor.js +211 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/env.d.ts +15 -0
- package/dist/commands/env.js +56 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/fn.d.ts +6 -0
- package/dist/commands/fn.js +87 -0
- package/dist/commands/fn.js.map +1 -0
- package/dist/commands/init.d.ts +10 -3
- package/dist/commands/init.js +212 -143
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +6 -3
- package/dist/commands/login.js +222 -92
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +1 -0
- package/dist/commands/logout.js +28 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/logs.d.ts +14 -3
- package/dist/commands/logs.js +132 -106
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/mocks.d.ts +5 -0
- package/dist/commands/mocks.js +23 -0
- package/dist/commands/mocks.js.map +1 -0
- package/dist/commands/open.d.ts +4 -3
- package/dist/commands/open.js +53 -85
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/promote.d.ts +9 -0
- package/dist/commands/promote.js +114 -0
- package/dist/commands/promote.js.map +1 -0
- package/dist/commands/publish.d.ts +14 -0
- package/dist/commands/publish.js +180 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/status.d.ts +5 -3
- package/dist/commands/status.js +91 -93
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.d.ts +12 -0
- package/dist/commands/upgrade.js +77 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/validate.d.ts +1 -3
- package/dist/commands/validate.js +83 -91
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/whoami.d.ts +5 -3
- package/dist/commands/whoami.js +76 -28
- package/dist/commands/whoami.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +337 -36
- package/dist/index.js.map +1 -1
- package/dist/lib/ai/context.d.ts +11 -0
- package/dist/lib/ai/context.js +112 -0
- package/dist/lib/ai/context.js.map +1 -0
- package/dist/lib/ai/orchestrator.d.ts +10 -0
- package/dist/lib/ai/orchestrator.js +92 -0
- package/dist/lib/ai/orchestrator.js.map +1 -0
- package/dist/lib/api-client.d.ts +21 -0
- package/dist/lib/api-client.js +65 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/auth.d.ts +15 -0
- package/dist/lib/auth.js +98 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config-schema.d.ts +165 -0
- package/dist/lib/config-schema.js +57 -0
- package/dist/lib/config-schema.js.map +1 -0
- package/dist/lib/config.d.ts +15 -0
- package/dist/lib/config.js +33 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +35 -33
- package/templates/auth/callback.ts +22 -0
- package/templates/auth/sign-in.tsx +41 -0
- package/templates/billing/checkout.ts +22 -0
- package/templates/billing/page.tsx +43 -0
- package/templates/support/ticket-form.tsx +68 -0
- package/templates/usage/track.ts +30 -0
- package/templates/users/profile.tsx +43 -0
- package/LICENSE +0 -21
- package/dist/commands/add.d.ts.map +0 -1
- package/dist/commands/deploy.d.ts.map +0 -1
- package/dist/commands/generate-types.d.ts +0 -3
- package/dist/commands/generate-types.d.ts.map +0 -1
- package/dist/commands/generate-types.js +0 -150
- package/dist/commands/generate-types.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/logs.d.ts.map +0 -1
- package/dist/commands/open.d.ts.map +0 -1
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/whoami.d.ts.map +0 -1
- package/dist/config.d.ts +0 -14
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -83
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/scaffold/auth.d.ts +0 -3
- package/dist/scaffold/auth.d.ts.map +0 -1
- package/dist/scaffold/auth.js +0 -228
- package/dist/scaffold/auth.js.map +0 -1
- package/dist/scaffold/billing.d.ts +0 -3
- package/dist/scaffold/billing.d.ts.map +0 -1
- package/dist/scaffold/billing.js +0 -184
- package/dist/scaffold/billing.js.map +0 -1
- package/dist/scaffold/usage.d.ts +0 -3
- package/dist/scaffold/usage.d.ts.map +0 -1
- package/dist/scaffold/usage.js +0 -173
- package/dist/scaffold/usage.js.map +0 -1
- package/dist/scaffold/users.d.ts +0 -3
- package/dist/scaffold/users.d.ts.map +0 -1
- package/dist/scaffold/users.js +0 -135
- package/dist/scaffold/users.js.map +0 -1
package/dist/scaffold/auth.js
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.scaffoldAuth = scaffoldAuth;
|
|
37
|
-
const fs = __importStar(require("fs-extra"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
async function scaffoldAuth(config, outDir) {
|
|
40
|
-
const files = [
|
|
41
|
-
{
|
|
42
|
-
name: 'auth.ts',
|
|
43
|
-
content: `/**
|
|
44
|
-
* Neetru Auth — gerado por neetru add auth
|
|
45
|
-
* Fluxo OAuth 2.0 / OIDC via Neetru Core
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
const NEETRU_CORE_URL = process.env.NEETRU_CORE_URL ?? '${config.coreUrl}';
|
|
49
|
-
const CLIENT_ID = process.env.NEETRU_CLIENT_ID ?? '${config.clientId}';
|
|
50
|
-
const CLIENT_SECRET = process.env.NEETRU_CLIENT_SECRET ?? '';
|
|
51
|
-
|
|
52
|
-
export interface NeetruTokens {
|
|
53
|
-
access_token: string;
|
|
54
|
-
refresh_token: string;
|
|
55
|
-
token_type: string;
|
|
56
|
-
expires_in: number;
|
|
57
|
-
scope: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface NeetruUser {
|
|
61
|
-
uid: string;
|
|
62
|
-
email: string;
|
|
63
|
-
displayName?: string;
|
|
64
|
-
photoURL?: string;
|
|
65
|
-
tenantId?: string;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Gera a URL de autorização OAuth para redirecionar o usuário ao Neetru Core.
|
|
70
|
-
*/
|
|
71
|
-
export function getAuthorizationUrl(redirectUri: string, state?: string): string {
|
|
72
|
-
const params = new URLSearchParams({
|
|
73
|
-
client_id: CLIENT_ID,
|
|
74
|
-
redirect_uri: redirectUri,
|
|
75
|
-
response_type: 'code',
|
|
76
|
-
scope: 'openid profile email',
|
|
77
|
-
...(state ? { state } : {}),
|
|
78
|
-
});
|
|
79
|
-
return \`\${NEETRU_CORE_URL}/api/oauth/authorize?\${params.toString()}\`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Troca o authorization code por tokens de acesso.
|
|
84
|
-
* Chamar no callback route após o redirect do Neetru Core.
|
|
85
|
-
*/
|
|
86
|
-
export async function exchangeCodeForTokens(
|
|
87
|
-
code: string,
|
|
88
|
-
redirectUri: string
|
|
89
|
-
): Promise<NeetruTokens> {
|
|
90
|
-
const res = await fetch(\`\${NEETRU_CORE_URL}/api/oauth/token\`, {
|
|
91
|
-
method: 'POST',
|
|
92
|
-
headers: { 'Content-Type': 'application/json' },
|
|
93
|
-
body: JSON.stringify({
|
|
94
|
-
code,
|
|
95
|
-
client_id: CLIENT_ID,
|
|
96
|
-
client_secret: CLIENT_SECRET,
|
|
97
|
-
redirect_uri: redirectUri,
|
|
98
|
-
grant_type: 'authorization_code',
|
|
99
|
-
}),
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
if (!res.ok) {
|
|
103
|
-
const err = await res.text();
|
|
104
|
-
throw new Error(\`Token exchange failed: \${res.status} — \${err}\`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return res.json() as Promise<NeetruTokens>;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Renova o access token usando o refresh token.
|
|
112
|
-
*/
|
|
113
|
-
export async function refreshAccessToken(refreshToken: string): Promise<NeetruTokens> {
|
|
114
|
-
const res = await fetch(\`\${NEETRU_CORE_URL}/api/oauth/token\`, {
|
|
115
|
-
method: 'POST',
|
|
116
|
-
headers: { 'Content-Type': 'application/json' },
|
|
117
|
-
body: JSON.stringify({
|
|
118
|
-
grant_type: 'refresh_token',
|
|
119
|
-
refresh_token: refreshToken,
|
|
120
|
-
client_id: CLIENT_ID,
|
|
121
|
-
client_secret: CLIENT_SECRET,
|
|
122
|
-
}),
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
if (!res.ok) {
|
|
126
|
-
throw new Error(\`Token refresh failed: \${res.status}\`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return res.json() as Promise<NeetruTokens>;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Revoga um refresh token (logout).
|
|
134
|
-
*/
|
|
135
|
-
export async function revokeToken(refreshToken: string): Promise<void> {
|
|
136
|
-
await fetch(\`\${NEETRU_CORE_URL}/api/oauth/revoke\`, {
|
|
137
|
-
method: 'POST',
|
|
138
|
-
headers: { 'Content-Type': 'application/json' },
|
|
139
|
-
body: JSON.stringify({ token: refreshToken, client_id: CLIENT_ID }),
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Busca o perfil do usuário autenticado.
|
|
145
|
-
*/
|
|
146
|
-
export async function getUserProfile(accessToken: string): Promise<NeetruUser> {
|
|
147
|
-
const res = await fetch(\`\${NEETRU_CORE_URL}/api/userinfo\`, {
|
|
148
|
-
headers: { Authorization: \`Bearer \${accessToken}\` },
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
if (!res.ok) {
|
|
152
|
-
throw new Error(\`Failed to fetch user profile: \${res.status}\`);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return res.json() as Promise<NeetruUser>;
|
|
156
|
-
}
|
|
157
|
-
`,
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
name: 'auth-middleware.ts',
|
|
161
|
-
content: `/**
|
|
162
|
-
* Neetru Auth Middleware — Next.js App Router
|
|
163
|
-
* Protege rotas que requerem autenticação Neetru.
|
|
164
|
-
*/
|
|
165
|
-
|
|
166
|
-
import { cookies } from 'next/headers';
|
|
167
|
-
import { getUserProfile, refreshAccessToken, type NeetruUser } from './auth';
|
|
168
|
-
|
|
169
|
-
export interface NeetruSession {
|
|
170
|
-
user: NeetruUser;
|
|
171
|
-
accessToken: string;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Obtém a sessão Neetru do cookie httpOnly.
|
|
176
|
-
* Retorna null se não autenticado ou sessão expirada.
|
|
177
|
-
*/
|
|
178
|
-
export async function getNeetruSession(): Promise<NeetruSession | null> {
|
|
179
|
-
const cookieStore = await cookies();
|
|
180
|
-
const accessToken = cookieStore.get('neetru_access_token')?.value;
|
|
181
|
-
const refreshToken = cookieStore.get('neetru_refresh_token')?.value;
|
|
182
|
-
|
|
183
|
-
if (!accessToken && !refreshToken) return null;
|
|
184
|
-
|
|
185
|
-
try {
|
|
186
|
-
const user = await getUserProfile(accessToken ?? '');
|
|
187
|
-
return { user, accessToken: accessToken ?? '' };
|
|
188
|
-
} catch {
|
|
189
|
-
// Try refreshing
|
|
190
|
-
if (!refreshToken) return null;
|
|
191
|
-
|
|
192
|
-
try {
|
|
193
|
-
const tokens = await refreshAccessToken(refreshToken);
|
|
194
|
-
const user = await getUserProfile(tokens.access_token);
|
|
195
|
-
// Note: caller should update cookies with new tokens
|
|
196
|
-
return { user, accessToken: tokens.access_token };
|
|
197
|
-
} catch {
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* HOF para Server Actions — exige sessão Neetru válida.
|
|
205
|
-
*/
|
|
206
|
-
export function requireNeetruSession<TInput, TOutput>(
|
|
207
|
-
fn: (session: NeetruSession, input: TInput) => Promise<TOutput>
|
|
208
|
-
) {
|
|
209
|
-
return async (input: TInput): Promise<TOutput> => {
|
|
210
|
-
const session = await getNeetruSession();
|
|
211
|
-
if (!session) {
|
|
212
|
-
throw new Error('Não autenticado. Faça login com Neetru.');
|
|
213
|
-
}
|
|
214
|
-
return fn(session, input);
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
`,
|
|
218
|
-
},
|
|
219
|
-
];
|
|
220
|
-
const created = [];
|
|
221
|
-
for (const file of files) {
|
|
222
|
-
const filePath = path.join(outDir, file.name);
|
|
223
|
-
await fs.writeFile(filePath, file.content, 'utf-8');
|
|
224
|
-
created.push(path.relative(process.cwd(), filePath));
|
|
225
|
-
}
|
|
226
|
-
return created;
|
|
227
|
-
}
|
|
228
|
-
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/scaffold/auth.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,oCA6LC;AAjMD,6CAA+B;AAC/B,2CAA6B;AAGtB,KAAK,UAAU,YAAY,CAAC,MAAoB,EAAE,MAAc;IACrE,MAAM,KAAK,GAA6C;QACtD;YACE,IAAI,EAAE,SAAS;YACf,OAAO,EAAE;;;;;0DAK2C,MAAM,CAAC,OAAO;qDACnB,MAAM,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4GnE;SACI;QACD;YACE,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDd;SACI;KACF,CAAC;IAEF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../../src/scaffold/billing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAsB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAiJ7F"}
|
package/dist/scaffold/billing.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.scaffoldBilling = scaffoldBilling;
|
|
37
|
-
const fs = __importStar(require("fs-extra"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
async function scaffoldBilling(config, outDir) {
|
|
40
|
-
const files = [
|
|
41
|
-
{
|
|
42
|
-
name: 'billing.ts',
|
|
43
|
-
content: `/**
|
|
44
|
-
* Neetru Billing — gerado por neetru add billing
|
|
45
|
-
* Client para consulta de assinaturas, planos e entitlements.
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
const NEETRU_CORE_URL = process.env.NEETRU_CORE_URL ?? '${config.coreUrl}';
|
|
49
|
-
const CLIENT_ID = process.env.NEETRU_CLIENT_ID ?? '${config.clientId}';
|
|
50
|
-
|
|
51
|
-
export interface NeetruSubscription {
|
|
52
|
-
id: string;
|
|
53
|
-
status: 'active' | 'cancelled' | 'past_due' | 'trialing';
|
|
54
|
-
planId: string;
|
|
55
|
-
planName: string;
|
|
56
|
-
priceMonthly: number;
|
|
57
|
-
currentPeriodEnd: string;
|
|
58
|
-
autoRenew: boolean;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface NeetruPlan {
|
|
62
|
-
id: string;
|
|
63
|
-
name: string;
|
|
64
|
-
priceMonthly: number;
|
|
65
|
-
features: string[];
|
|
66
|
-
limits: Record<string, number>;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface NeetruEntitlement {
|
|
70
|
-
featureKey: string;
|
|
71
|
-
allowed: boolean;
|
|
72
|
-
limit?: number;
|
|
73
|
-
used?: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function apiRequest<T>(
|
|
77
|
-
endpoint: string,
|
|
78
|
-
accessToken: string,
|
|
79
|
-
options?: RequestInit
|
|
80
|
-
): Promise<T> {
|
|
81
|
-
const res = await fetch(\`\${NEETRU_CORE_URL}\${endpoint}\`, {
|
|
82
|
-
...options,
|
|
83
|
-
headers: {
|
|
84
|
-
'Authorization': \`Bearer \${accessToken}\`,
|
|
85
|
-
'X-Client-ID': CLIENT_ID,
|
|
86
|
-
'Content-Type': 'application/json',
|
|
87
|
-
...(options?.headers ?? {}),
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
if (!res.ok) {
|
|
92
|
-
const err = await res.text().catch(() => res.statusText);
|
|
93
|
-
throw new Error(\`Neetru API error \${res.status}: \${err}\`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return res.json() as Promise<T>;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export const neetruBilling = {
|
|
100
|
-
/**
|
|
101
|
-
* Retorna a assinatura ativa do usuário autenticado.
|
|
102
|
-
* Retorna null se sem assinatura ativa.
|
|
103
|
-
*/
|
|
104
|
-
async getSubscription(accessToken: string): Promise<NeetruSubscription | null> {
|
|
105
|
-
try {
|
|
106
|
-
return await apiRequest<NeetruSubscription>('/api/v1/billing/subscription', accessToken);
|
|
107
|
-
} catch (e) {
|
|
108
|
-
if ((e as Error).message.includes('404')) return null;
|
|
109
|
-
throw e;
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Lista todos os planos disponíveis (não requer autenticação).
|
|
115
|
-
*/
|
|
116
|
-
async listPlans(): Promise<NeetruPlan[]> {
|
|
117
|
-
const res = await fetch(\`\${NEETRU_CORE_URL}/api/v1/plans?clientId=\${CLIENT_ID}\`);
|
|
118
|
-
if (!res.ok) throw new Error('Falha ao buscar planos');
|
|
119
|
-
return res.json() as Promise<NeetruPlan[]>;
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Verifica se uma feature está disponível no plano do usuário.
|
|
124
|
-
*/
|
|
125
|
-
async checkEntitlement(
|
|
126
|
-
accessToken: string,
|
|
127
|
-
featureKey: string
|
|
128
|
-
): Promise<NeetruEntitlement> {
|
|
129
|
-
return apiRequest<NeetruEntitlement>(
|
|
130
|
-
\`/api/v1/billing/entitlements/\${encodeURIComponent(featureKey)}\`,
|
|
131
|
-
accessToken
|
|
132
|
-
);
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Verifica múltiplos entitlements de uma vez.
|
|
137
|
-
*/
|
|
138
|
-
async checkEntitlements(
|
|
139
|
-
accessToken: string,
|
|
140
|
-
featureKeys: string[]
|
|
141
|
-
): Promise<Record<string, NeetruEntitlement>> {
|
|
142
|
-
const params = new URLSearchParams();
|
|
143
|
-
featureKeys.forEach((k) => params.append('feature', k));
|
|
144
|
-
return apiRequest<Record<string, NeetruEntitlement>>(
|
|
145
|
-
\`/api/v1/billing/entitlements?\${params.toString()}\`,
|
|
146
|
-
accessToken
|
|
147
|
-
);
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Gera URL de checkout para upgrade de plano.
|
|
152
|
-
*/
|
|
153
|
-
async getCheckoutUrl(accessToken: string, planId: string, returnUrl: string): Promise<string> {
|
|
154
|
-
const result = await apiRequest<{ checkoutUrl: string }>(
|
|
155
|
-
'/api/v1/billing/checkout',
|
|
156
|
-
accessToken,
|
|
157
|
-
{
|
|
158
|
-
method: 'POST',
|
|
159
|
-
body: JSON.stringify({ planId, returnUrl }),
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
return result.checkoutUrl;
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Gera URL do portal de billing self-service (Minha Conta Neetru).
|
|
167
|
-
*/
|
|
168
|
-
getPortalUrl(returnUrl: string): string {
|
|
169
|
-
const params = new URLSearchParams({ clientId: CLIENT_ID, returnUrl });
|
|
170
|
-
return \`\${NEETRU_CORE_URL}/minhaconta?\${params.toString()}\`;
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
`,
|
|
174
|
-
},
|
|
175
|
-
];
|
|
176
|
-
const created = [];
|
|
177
|
-
for (const file of files) {
|
|
178
|
-
const filePath = path.join(outDir, file.name);
|
|
179
|
-
await fs.writeFile(filePath, file.content, 'utf-8');
|
|
180
|
-
created.push(path.relative(process.cwd(), filePath));
|
|
181
|
-
}
|
|
182
|
-
return created;
|
|
183
|
-
}
|
|
184
|
-
//# sourceMappingURL=billing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"billing.js","sourceRoot":"","sources":["../../src/scaffold/billing.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,0CAiJC;AArJD,6CAA+B;AAC/B,2CAA6B;AAGtB,KAAK,UAAU,eAAe,CAAC,MAAoB,EAAE,MAAc;IACxE,MAAM,KAAK,GAA6C;QACtD;YACE,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE;;;;;0DAK2C,MAAM,CAAC,OAAO;qDACnB,MAAM,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4HnE;SACI;KACF,CAAC;IAEF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/scaffold/usage.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/scaffold/usage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAsB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsI3F"}
|
package/dist/scaffold/usage.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.scaffoldUsage = scaffoldUsage;
|
|
37
|
-
const fs = __importStar(require("fs-extra"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
async function scaffoldUsage(config, outDir) {
|
|
40
|
-
const content = `/**
|
|
41
|
-
* Neetru Usage Reporter — gerado por neetru add usage
|
|
42
|
-
* Envia eventos de uso para metered billing via Neetru Core.
|
|
43
|
-
* Eventos são acumulados em memória e enviados em batch a cada 60s.
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
const NEETRU_CORE_URL = process.env.NEETRU_CORE_URL ?? '${config.coreUrl}';
|
|
47
|
-
const CLIENT_ID = process.env.NEETRU_CLIENT_ID ?? '${config.clientId}';
|
|
48
|
-
|
|
49
|
-
export interface UsageEvent {
|
|
50
|
-
eventType: string;
|
|
51
|
-
quantity: number;
|
|
52
|
-
tenantId?: string;
|
|
53
|
-
metadata?: Record<string, string | number | boolean>;
|
|
54
|
-
timestamp?: number;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export class NeetruUsageReporter {
|
|
58
|
-
private queue: UsageEvent[] = [];
|
|
59
|
-
private flushInterval: ReturnType<typeof setInterval> | null = null;
|
|
60
|
-
private accessToken: string;
|
|
61
|
-
private readonly batchSize: number;
|
|
62
|
-
private readonly flushIntervalMs: number;
|
|
63
|
-
|
|
64
|
-
constructor(options: {
|
|
65
|
-
accessToken: string;
|
|
66
|
-
batchSize?: number;
|
|
67
|
-
flushIntervalMs?: number;
|
|
68
|
-
}) {
|
|
69
|
-
this.accessToken = options.accessToken;
|
|
70
|
-
this.batchSize = options.batchSize ?? 50;
|
|
71
|
-
this.flushIntervalMs = options.flushIntervalMs ?? 60_000;
|
|
72
|
-
this.startAutoFlush();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Registra um evento de uso.
|
|
77
|
-
* Os eventos são enviados automaticamente em batch.
|
|
78
|
-
*/
|
|
79
|
-
track(eventType: string, quantity: number = 1, metadata?: UsageEvent['metadata']): void {
|
|
80
|
-
this.queue.push({
|
|
81
|
-
eventType,
|
|
82
|
-
quantity,
|
|
83
|
-
metadata,
|
|
84
|
-
timestamp: Date.now(),
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
if (this.queue.length >= this.batchSize) {
|
|
88
|
-
this.flush().catch(console.error);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Envia todos os eventos pendentes imediatamente.
|
|
94
|
-
*/
|
|
95
|
-
async flush(): Promise<void> {
|
|
96
|
-
if (this.queue.length === 0) return;
|
|
97
|
-
|
|
98
|
-
const batch = this.queue.splice(0, this.batchSize);
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
const res = await fetch(\`\${NEETRU_CORE_URL}/api/v1/usage\`, {
|
|
102
|
-
method: 'POST',
|
|
103
|
-
headers: {
|
|
104
|
-
'Authorization': \`Bearer \${this.accessToken}\`,
|
|
105
|
-
'X-Client-ID': CLIENT_ID,
|
|
106
|
-
'Content-Type': 'application/json',
|
|
107
|
-
},
|
|
108
|
-
body: JSON.stringify({ events: batch }),
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
if (!res.ok) {
|
|
112
|
-
// Put events back in queue to retry
|
|
113
|
-
this.queue.unshift(...batch);
|
|
114
|
-
console.error(\`[NeetruUsage] Flush failed: \${res.status}\`);
|
|
115
|
-
}
|
|
116
|
-
} catch (err) {
|
|
117
|
-
// Network error — put events back
|
|
118
|
-
this.queue.unshift(...batch);
|
|
119
|
-
console.error('[NeetruUsage] Network error during flush:', err);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Atualiza o access token (ex: após refresh).
|
|
125
|
-
*/
|
|
126
|
-
updateToken(newToken: string): void {
|
|
127
|
-
this.accessToken = newToken;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Para o auto-flush e envia eventos pendentes.
|
|
132
|
-
* Chamar ao encerrar a aplicação (process.on('beforeExit')).
|
|
133
|
-
*/
|
|
134
|
-
async destroy(): Promise<void> {
|
|
135
|
-
if (this.flushInterval) {
|
|
136
|
-
clearInterval(this.flushInterval);
|
|
137
|
-
this.flushInterval = null;
|
|
138
|
-
}
|
|
139
|
-
await this.flush();
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
private startAutoFlush(): void {
|
|
143
|
-
this.flushInterval = setInterval(() => {
|
|
144
|
-
this.flush().catch(console.error);
|
|
145
|
-
}, this.flushIntervalMs);
|
|
146
|
-
|
|
147
|
-
// Don't block process exit
|
|
148
|
-
if (this.flushInterval.unref) {
|
|
149
|
-
this.flushInterval.unref();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Singleton for convenience
|
|
155
|
-
let _instance: NeetruUsageReporter | null = null;
|
|
156
|
-
|
|
157
|
-
export function initUsageReporter(accessToken: string): NeetruUsageReporter {
|
|
158
|
-
_instance = new NeetruUsageReporter({ accessToken });
|
|
159
|
-
return _instance;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export function getUsageReporter(): NeetruUsageReporter {
|
|
163
|
-
if (!_instance) {
|
|
164
|
-
throw new Error('UsageReporter não inicializado. Chame initUsageReporter(accessToken) primeiro.');
|
|
165
|
-
}
|
|
166
|
-
return _instance;
|
|
167
|
-
}
|
|
168
|
-
`;
|
|
169
|
-
const filePath = path.join(outDir, 'usage-reporter.ts');
|
|
170
|
-
await fs.writeFile(filePath, content, 'utf-8');
|
|
171
|
-
return [path.relative(process.cwd(), filePath)];
|
|
172
|
-
}
|
|
173
|
-
//# sourceMappingURL=usage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/scaffold/usage.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,sCAsIC;AA1ID,6CAA+B;AAC/B,2CAA6B;AAGtB,KAAK,UAAU,aAAa,CAAC,MAAoB,EAAE,MAAc;IACtE,MAAM,OAAO,GAAG;;;;;;0DAMwC,MAAM,CAAC,OAAO;qDACnB,MAAM,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyHnE,CAAC;IAEA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACxD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;AAClD,CAAC"}
|
package/dist/scaffold/users.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/scaffold/users.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAsB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgG3F"}
|