runcloud 0.2.182 → 0.2.188
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/dist/commands/build.js +1 -1
- package/dist/commands/dogfood.js +435 -0
- package/dist/commands/link.js +3 -2
- package/dist/commands/pull.js +1 -1
- package/dist/commands/run-cloud.js +31 -1
- package/dist/commands/website.js +88 -2
- package/dist/commands/websiteTemplate.generated.js +21 -0
- package/dist/config.js +15 -4
- package/dist/index.js +2 -0
- package/dist/services-manifest.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/runcloud-0.2.188.tgz +0 -0
- package/skills/run-cloud-sandboxes/SKILL.md +1 -0
- package/runcloud-0.2.182.tgz +0 -0
package/dist/commands/build.js
CHANGED
|
@@ -481,7 +481,7 @@ export function registerBuild(program) {
|
|
|
481
481
|
}
|
|
482
482
|
const { client } = makeClient();
|
|
483
483
|
const projectId = opts.remoteSource
|
|
484
|
-
? opts.project
|
|
484
|
+
? (opts.project ? resolveProject(process.cwd(), opts.project) : readProjectLink(opts.sourcePath ?? '.')?.projectId)
|
|
485
485
|
: resolveProject(process.cwd(), opts.project);
|
|
486
486
|
if (platform === 'android') {
|
|
487
487
|
await runAndroidSimulatorBuild(client, projectId, opts);
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { createInterface } from 'node:readline';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import { ApiClient, friendlyApiError } from '../api.js';
|
|
8
|
+
import { requireCredentials } from '../config.js';
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
export const DOGFOOD_SECRET_GROUP = 'newly-dogfood';
|
|
11
|
+
export const DOGFOOD_AGENT_ACCOUNT = 'newly-dogfood-agent@newly-v3-dev.iam.gserviceaccount.com';
|
|
12
|
+
export const DEFAULT_DOGFOOD_MODEL = 'deepseek-v4-1-flash';
|
|
13
|
+
export const CREDS_REFRESH_MS = 40 * 60 * 1000;
|
|
14
|
+
function dogfoodStatePath() {
|
|
15
|
+
return join(process.env.NEWLY_HOME ?? join(homedir(), '.newly'), 'dogfood.json');
|
|
16
|
+
}
|
|
17
|
+
function readState() {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(readFileSync(dogfoodStatePath(), 'utf8'));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function writeState(state) {
|
|
26
|
+
const path = dogfoodStatePath();
|
|
27
|
+
mkdirSync(join(path, '..'), { recursive: true });
|
|
28
|
+
writeFileSync(path, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
|
|
29
|
+
}
|
|
30
|
+
function dogfoodSessionPath() {
|
|
31
|
+
return join(process.env.NEWLY_HOME ?? join(homedir(), '.newly'), 'dogfood-session');
|
|
32
|
+
}
|
|
33
|
+
function readDogfoodSession() {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(readFileSync(dogfoodSessionPath(), 'utf8'));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function writeDogfoodSession(session) {
|
|
42
|
+
const path = dogfoodSessionPath();
|
|
43
|
+
mkdirSync(join(path, '..'), { recursive: true });
|
|
44
|
+
writeFileSync(path, JSON.stringify(session, null, 2) + '\n', { mode: 0o600 });
|
|
45
|
+
chmodSync(path, 0o600);
|
|
46
|
+
}
|
|
47
|
+
function dogfoodApiUrl() {
|
|
48
|
+
return (process.env.NEWLY_AUTH_API_URL ?? requireCredentials().apiUrl).replace(/\/$/, '');
|
|
49
|
+
}
|
|
50
|
+
function api() {
|
|
51
|
+
const apiUrl = dogfoodApiUrl();
|
|
52
|
+
const session = readDogfoodSession();
|
|
53
|
+
if (!session || session.apiUrl !== apiUrl) {
|
|
54
|
+
throw new Error(`not signed in to ${apiUrl} for dogfood: run \`newly dogfood login\` (scripts/dogfood.sh login)`);
|
|
55
|
+
}
|
|
56
|
+
return { client: new ApiClient(apiUrl, session.token), apiUrl };
|
|
57
|
+
}
|
|
58
|
+
const postJson = (fetchFn, url, body) => fetchFn(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
|
|
59
|
+
export async function sendSignInCode(apiUrl, email, fetchFn = fetch) {
|
|
60
|
+
const sent = await postJson(fetchFn, `${apiUrl}/api/auth/email-otp/send-verification-otp`, { email, type: 'sign-in' });
|
|
61
|
+
if (!sent.ok)
|
|
62
|
+
throw new Error(`could not send a sign-in code to ${email} (HTTP ${sent.status})`);
|
|
63
|
+
}
|
|
64
|
+
export async function verifySignInCode(apiUrl, email, code, fetchFn = fetch) {
|
|
65
|
+
const otp = code.trim();
|
|
66
|
+
if (!otp)
|
|
67
|
+
throw new Error('no code entered');
|
|
68
|
+
const signedIn = await postJson(fetchFn, `${apiUrl}/api/auth/sign-in/email-otp`, { email, otp });
|
|
69
|
+
if (!signedIn.ok)
|
|
70
|
+
throw new Error(`sign-in refused (HTTP ${signedIn.status}); check the code and try again`);
|
|
71
|
+
const token = signedIn.headers.get('set-auth-token');
|
|
72
|
+
if (!token)
|
|
73
|
+
throw new Error('sign-in succeeded but no session token came back');
|
|
74
|
+
return token;
|
|
75
|
+
}
|
|
76
|
+
function ask(question) {
|
|
77
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
78
|
+
return new Promise((resolve) => rl.question(question, (answer) => { rl.close(); resolve(answer); }));
|
|
79
|
+
}
|
|
80
|
+
function projectIdFrom(explicit, apiUrl) {
|
|
81
|
+
if (explicit)
|
|
82
|
+
return explicit;
|
|
83
|
+
const state = readState();
|
|
84
|
+
if (state && state.apiUrl === apiUrl)
|
|
85
|
+
return state.projectId;
|
|
86
|
+
throw new Error('no dogfood project yet: run `newly dogfood setup` (or pass --project <id>)');
|
|
87
|
+
}
|
|
88
|
+
async function run(fn) {
|
|
89
|
+
try {
|
|
90
|
+
await fn();
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(friendlyApiError(err));
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const defaultExec = (file, args, env) => execFileAsync(file, args, { env: env ?? process.env, maxBuffer: 64 * 1024 * 1024 });
|
|
98
|
+
export async function mintDogfoodGcpToken(exec = defaultExec) {
|
|
99
|
+
try {
|
|
100
|
+
const { stdout } = await exec('gcloud', [
|
|
101
|
+
'auth',
|
|
102
|
+
'print-access-token',
|
|
103
|
+
`--impersonate-service-account=${DOGFOOD_AGENT_ACCOUNT}`,
|
|
104
|
+
]);
|
|
105
|
+
const token = stdout.trim();
|
|
106
|
+
if (!token)
|
|
107
|
+
throw new Error('gcloud printed no token');
|
|
108
|
+
return token;
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
throw new Error(`could not impersonate ${DOGFOOD_AGENT_ACCOUNT}: ${errorText(err)}\n` +
|
|
112
|
+
'You need roles/iam.serviceAccountTokenCreator on it (eng-debuggers@natively.dev members have it) ' +
|
|
113
|
+
'and a current `gcloud auth login`.');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export async function readGithubToken(opts, exec = defaultExec) {
|
|
117
|
+
if (opts.tokenFile) {
|
|
118
|
+
const token = readFileSync(opts.tokenFile, 'utf8').trim();
|
|
119
|
+
if (!token)
|
|
120
|
+
throw new Error(`${opts.tokenFile} is empty`);
|
|
121
|
+
return { token, source: 'file' };
|
|
122
|
+
}
|
|
123
|
+
const env = opts.env ?? process.env;
|
|
124
|
+
const fromEnv = (env.GH_TOKEN ?? env.GITHUB_TOKEN ?? '').trim();
|
|
125
|
+
if (fromEnv)
|
|
126
|
+
return { token: fromEnv, source: 'env' };
|
|
127
|
+
try {
|
|
128
|
+
const { stdout } = await exec('gh', ['auth', 'token']);
|
|
129
|
+
const token = stdout.trim();
|
|
130
|
+
if (token)
|
|
131
|
+
return { token, source: 'gh-cli' };
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
}
|
|
135
|
+
throw new Error('no GitHub token: pass --github-token-file <path> (a fine-grained token on newly-app/newly with ' +
|
|
136
|
+
'Contents and Pull requests read/write is recommended), set GH_TOKEN, or `gh auth login`.');
|
|
137
|
+
}
|
|
138
|
+
export async function verifySopsBoundary(repoRoot, gcpToken, exec = defaultExec) {
|
|
139
|
+
const env = { ...process.env, GOOGLE_OAUTH_ACCESS_TOKEN: gcpToken };
|
|
140
|
+
delete env.GOOGLE_CREDENTIALS;
|
|
141
|
+
delete env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
142
|
+
const attempt = async (file) => {
|
|
143
|
+
try {
|
|
144
|
+
await exec('sops', ['decrypt', '--output', '/dev/null', join(repoRoot, file)], env);
|
|
145
|
+
return { ok: true, error: '' };
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
return { ok: false, error: errorText(err) };
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const dev = await attempt('secrets/dev.yaml');
|
|
152
|
+
const prod = await attempt('secrets/prod.yaml');
|
|
153
|
+
const detail = [
|
|
154
|
+
dev.ok ? 'secrets/dev.yaml: decrypts' : `secrets/dev.yaml: FAILED (${dev.error.split('\n')[0]})`,
|
|
155
|
+
prod.ok ? 'secrets/prod.yaml: DECRYPTS — this must not happen' : 'secrets/prod.yaml: refused',
|
|
156
|
+
].join('\n');
|
|
157
|
+
return { dev: dev.ok, prodRefused: !prod.ok, detail };
|
|
158
|
+
}
|
|
159
|
+
function errorText(err) {
|
|
160
|
+
if (err && typeof err === 'object' && 'stderr' in err && typeof err.stderr === 'string' && err.stderr.trim()) {
|
|
161
|
+
return err.stderr.trim();
|
|
162
|
+
}
|
|
163
|
+
return err instanceof Error ? err.message : String(err);
|
|
164
|
+
}
|
|
165
|
+
async function projectOrgId(client, projectId) {
|
|
166
|
+
const project = await client.get(`/projects/${encodeURIComponent(projectId)}`);
|
|
167
|
+
const orgId = project?.org_id ?? project?.orgId ?? project?.project?.org_id ?? project?.project?.orgId;
|
|
168
|
+
if (typeof orgId !== 'string' || !orgId)
|
|
169
|
+
throw new Error(`could not read the org of project ${projectId}`);
|
|
170
|
+
return orgId;
|
|
171
|
+
}
|
|
172
|
+
export async function pushDogfoodCreds(client, projectId, entries) {
|
|
173
|
+
const orgId = await projectOrgId(client, projectId);
|
|
174
|
+
await client.put(`/orgs/${encodeURIComponent(orgId)}/secret-groups/${DOGFOOD_SECRET_GROUP}`, {
|
|
175
|
+
entries,
|
|
176
|
+
exposeToSandbox: true,
|
|
177
|
+
force: true,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
async function credsOnce(opts) {
|
|
181
|
+
const { client, apiUrl } = api();
|
|
182
|
+
const projectId = projectIdFrom(opts.project, apiUrl);
|
|
183
|
+
const entries = {};
|
|
184
|
+
const github = await readGithubToken({ tokenFile: opts.githubTokenFile });
|
|
185
|
+
entries.GH_TOKEN = github.token;
|
|
186
|
+
if (github.source === 'gh-cli') {
|
|
187
|
+
console.log('GitHub: using your gh CLI token (all of its scopes). A fine-grained token is safer: --github-token-file.');
|
|
188
|
+
}
|
|
189
|
+
if (opts.gcp)
|
|
190
|
+
entries.GOOGLE_OAUTH_ACCESS_TOKEN = await mintDogfoodGcpToken();
|
|
191
|
+
await pushDogfoodCreds(client, projectId, entries);
|
|
192
|
+
console.log(`${new Date().toISOString()} credentials pushed to project ${projectId}: ${Object.keys(entries).join(', ')}` +
|
|
193
|
+
(opts.gcp ? ' (GCP token valid ~1h)' : ''));
|
|
194
|
+
}
|
|
195
|
+
export function dogfoodSessionBody(opts) {
|
|
196
|
+
const body = {
|
|
197
|
+
kind: 'interactive',
|
|
198
|
+
harness: 'claude-code',
|
|
199
|
+
dogfood: { baseRef: opts.baseRef },
|
|
200
|
+
agentModel: opts.model,
|
|
201
|
+
};
|
|
202
|
+
const prompt = opts.prompt.trim();
|
|
203
|
+
if (prompt)
|
|
204
|
+
body.initialPrompt = prompt;
|
|
205
|
+
return body;
|
|
206
|
+
}
|
|
207
|
+
export function renderEvent(raw) {
|
|
208
|
+
const type = raw.type ?? raw.event?.type;
|
|
209
|
+
const data = (raw.data ?? raw.event?.data ?? {});
|
|
210
|
+
switch (type) {
|
|
211
|
+
case 'text_delta':
|
|
212
|
+
return typeof data.delta === 'string' ? data.delta : null;
|
|
213
|
+
case 'user_message':
|
|
214
|
+
return typeof data.text === 'string' ? `\n\n› ${data.text}\n` : null;
|
|
215
|
+
case 'tool_call': {
|
|
216
|
+
const input = data.input ?? data.args;
|
|
217
|
+
const summary = input === undefined ? '' : JSON.stringify(input);
|
|
218
|
+
return `\n ▸ ${String(data.name ?? 'tool')} ${summary.length > 160 ? `${summary.slice(0, 157)}...` : summary}\n`;
|
|
219
|
+
}
|
|
220
|
+
case 'tool_result':
|
|
221
|
+
return data.isError === true || data.ok === false ? ` ✗ ${String(data.output ?? 'tool failed').slice(0, 300)}\n` : null;
|
|
222
|
+
case 'ask_user':
|
|
223
|
+
return `\n? ${String(data.question ?? 'The agent has a question')}\n`;
|
|
224
|
+
case 'error':
|
|
225
|
+
return `\n! ${String(data.message ?? 'error')}\n`;
|
|
226
|
+
case 'turn_complete': {
|
|
227
|
+
const cost = typeof data.costUsd === 'number' ? ` · $${data.costUsd.toFixed(2)}` : '';
|
|
228
|
+
return `\n— turn complete${cost}\n`;
|
|
229
|
+
}
|
|
230
|
+
case 'session_started':
|
|
231
|
+
return '— session started\n';
|
|
232
|
+
case 'run_parked':
|
|
233
|
+
return '— session parked (send a message to wake it)\n';
|
|
234
|
+
default:
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function eventsFrom(body) {
|
|
239
|
+
if (Array.isArray(body))
|
|
240
|
+
return body;
|
|
241
|
+
const events = body?.events;
|
|
242
|
+
return Array.isArray(events) ? events : [];
|
|
243
|
+
}
|
|
244
|
+
async function attach(client, sessionId, opts) {
|
|
245
|
+
let afterSeq = 0;
|
|
246
|
+
let stopped = false;
|
|
247
|
+
const rl = createInterface({ input: process.stdin });
|
|
248
|
+
rl.on('line', (line) => {
|
|
249
|
+
const text = line.trim();
|
|
250
|
+
if (!text)
|
|
251
|
+
return;
|
|
252
|
+
if (text === '/quit' || text === '/exit') {
|
|
253
|
+
stopped = true;
|
|
254
|
+
rl.close();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (text === '/cancel') {
|
|
258
|
+
void client.post(`/sessions/${sessionId}/cancel`, {}).catch((err) => console.error(friendlyApiError(err)));
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const body = { text };
|
|
262
|
+
if (opts.model)
|
|
263
|
+
body.agentModel = opts.model;
|
|
264
|
+
void client.post(`/sessions/${sessionId}/messages`, body).catch((err) => console.error(friendlyApiError(err)));
|
|
265
|
+
});
|
|
266
|
+
rl.on('close', () => {
|
|
267
|
+
stopped = true;
|
|
268
|
+
});
|
|
269
|
+
console.log(`attached to ${sessionId} — type a message and Enter to send; /cancel stops the turn; /quit detaches.`);
|
|
270
|
+
while (!stopped) {
|
|
271
|
+
try {
|
|
272
|
+
const body = await client.get(`/sessions/${sessionId}/events?after_seq=${afterSeq}&limit=500`);
|
|
273
|
+
for (const event of eventsFrom(body)) {
|
|
274
|
+
if (typeof event.seq === 'number')
|
|
275
|
+
afterSeq = Math.max(afterSeq, event.seq);
|
|
276
|
+
const text = renderEvent(event);
|
|
277
|
+
if (text)
|
|
278
|
+
process.stdout.write(text);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
console.error(friendlyApiError(err));
|
|
283
|
+
}
|
|
284
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function repoRoot() {
|
|
288
|
+
try {
|
|
289
|
+
const { stdout } = await defaultExec('git', ['rev-parse', '--show-toplevel']);
|
|
290
|
+
const root = stdout.trim();
|
|
291
|
+
return existsSync(join(root, 'secrets', 'dev.yaml')) ? root : null;
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
export function registerDogfood(program) {
|
|
298
|
+
const dogfood = program
|
|
299
|
+
.command('dogfood')
|
|
300
|
+
.description('Newly agent sessions that work on the Newly monorepo itself (staff, feature-flagged)');
|
|
301
|
+
dogfood
|
|
302
|
+
.command('login')
|
|
303
|
+
.description('Sign in to the control plane for dogfood commands (email code; separate from `newly login`)')
|
|
304
|
+
.option('--email <email>', 'your staff email (default: the `newly login` account)')
|
|
305
|
+
.option('--code <code>', 'finish a sign-in with the emailed code (when no terminal can prompt)')
|
|
306
|
+
.action((opts) => run(async () => {
|
|
307
|
+
const apiUrl = dogfoodApiUrl();
|
|
308
|
+
let email = opts.email;
|
|
309
|
+
if (!email) {
|
|
310
|
+
try {
|
|
311
|
+
email = requireCredentials().account;
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (!email)
|
|
317
|
+
email = (await ask('Email: ')).trim();
|
|
318
|
+
if (!email)
|
|
319
|
+
throw new Error('an email is required');
|
|
320
|
+
let code = opts.code;
|
|
321
|
+
if (!code) {
|
|
322
|
+
await sendSignInCode(apiUrl, email);
|
|
323
|
+
console.log(`Sent a sign-in code to ${email} (${apiUrl}).`);
|
|
324
|
+
if (!process.stdin.isTTY) {
|
|
325
|
+
console.log('Finish with: scripts/dogfood.sh login --code <code from the email>');
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
code = await ask('Code from the email: ');
|
|
329
|
+
}
|
|
330
|
+
const token = await verifySignInCode(apiUrl, email, code);
|
|
331
|
+
writeDogfoodSession({ apiUrl, token, account: email });
|
|
332
|
+
await new ApiClient(apiUrl, token).get('/projects');
|
|
333
|
+
console.log(`Signed in as ${email}. Next: \`newly dogfood setup\`.`);
|
|
334
|
+
}));
|
|
335
|
+
dogfood
|
|
336
|
+
.command('setup')
|
|
337
|
+
.description('Create or adopt your dogfood project and verify credentials end to end')
|
|
338
|
+
.option('--project <id>', 'adopt an existing project instead of creating one')
|
|
339
|
+
.option('--name <name>', 'name for a new project', 'Newly (dogfood)')
|
|
340
|
+
.option('--github-token-file <path>', 'GitHub token to give sessions (default: GH_TOKEN, then gh CLI)')
|
|
341
|
+
.action((opts) => run(async () => {
|
|
342
|
+
const { client, apiUrl } = api();
|
|
343
|
+
console.log(`control plane: ${apiUrl}`);
|
|
344
|
+
console.log('1/4 GCP: minting a dogfood-agent token by impersonation...');
|
|
345
|
+
const gcpToken = await mintDogfoodGcpToken();
|
|
346
|
+
console.log(' ok');
|
|
347
|
+
console.log('2/4 SOPS: dev must decrypt, prod must be refused...');
|
|
348
|
+
const root = await repoRoot();
|
|
349
|
+
if (root) {
|
|
350
|
+
const result = await verifySopsBoundary(root, gcpToken);
|
|
351
|
+
console.log(result.detail.replace(/^/gm, ' '));
|
|
352
|
+
if (!result.prodRefused)
|
|
353
|
+
throw new Error('the dogfood token can decrypt prod — stop and report this');
|
|
354
|
+
if (!result.dev)
|
|
355
|
+
throw new Error('the dogfood token cannot decrypt dev; see the error above');
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
console.log(' skipped: run setup from a monorepo checkout to verify (needs secrets/*.yaml and sops >= 3.10)');
|
|
359
|
+
}
|
|
360
|
+
console.log('3/4 GitHub: reading a token...');
|
|
361
|
+
const github = await readGithubToken({ tokenFile: opts.githubTokenFile });
|
|
362
|
+
console.log(` ok (${github.source})`);
|
|
363
|
+
console.log('4/4 Project...');
|
|
364
|
+
let projectId = opts.project ?? (readState()?.apiUrl === apiUrl ? readState()?.projectId : undefined);
|
|
365
|
+
if (!projectId) {
|
|
366
|
+
const listing = await client.get('/projects');
|
|
367
|
+
const orgId = listing?.defaultOrgId;
|
|
368
|
+
if (typeof orgId !== 'string' || !orgId)
|
|
369
|
+
throw new Error('could not find your workspace to create the project in');
|
|
370
|
+
const created = await client.post(`/orgs/${encodeURIComponent(orgId)}/projects`, { name: opts.name });
|
|
371
|
+
projectId = (created?.id ?? created?.projectId ?? created?.project?.id);
|
|
372
|
+
if (!projectId)
|
|
373
|
+
throw new Error('project created but no id came back');
|
|
374
|
+
console.log(` created ${projectId}`);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
console.log(` using ${projectId}`);
|
|
378
|
+
}
|
|
379
|
+
writeState({ projectId, apiUrl });
|
|
380
|
+
await pushDogfoodCreds(client, projectId, { GH_TOKEN: github.token, GOOGLE_OAUTH_ACCESS_TOKEN: gcpToken });
|
|
381
|
+
console.log(' credentials stored as the project\'s "newly-dogfood" secret group (dogfood sessions only)');
|
|
382
|
+
console.log('\nNext: `newly dogfood creds --watch` in a spare terminal (keeps the GCP token fresh),');
|
|
383
|
+
console.log('then `newly dogfood start "<what to do>"`.');
|
|
384
|
+
}));
|
|
385
|
+
dogfood
|
|
386
|
+
.command('creds')
|
|
387
|
+
.description('Mint fresh credentials and give them to your dogfood sessions')
|
|
388
|
+
.option('--project <id>', 'dogfood project (default: the one setup created)')
|
|
389
|
+
.option('--github-token-file <path>', 'GitHub token file (default: GH_TOKEN, then gh CLI)')
|
|
390
|
+
.option('--no-gcp', 'do not mint a GCP token (sessions then cannot use sops)')
|
|
391
|
+
.option('--watch', `keep refreshing every ${CREDS_REFRESH_MS / 60_000} minutes`, false)
|
|
392
|
+
.action((opts) => run(async () => {
|
|
393
|
+
await credsOnce(opts);
|
|
394
|
+
if (!opts.watch)
|
|
395
|
+
return;
|
|
396
|
+
for (;;) {
|
|
397
|
+
await new Promise((resolve) => setTimeout(resolve, CREDS_REFRESH_MS));
|
|
398
|
+
try {
|
|
399
|
+
await credsOnce(opts);
|
|
400
|
+
}
|
|
401
|
+
catch (err) {
|
|
402
|
+
console.error(`${new Date().toISOString()} refresh failed: ${friendlyApiError(err)}`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}));
|
|
406
|
+
dogfood
|
|
407
|
+
.command('start')
|
|
408
|
+
.description('Start a dogfood session on the Newly monorepo')
|
|
409
|
+
.argument('[prompt...]', 'what the agent should do')
|
|
410
|
+
.option('--project <id>', 'dogfood project (default: the one setup created)')
|
|
411
|
+
.option('--model <id>', 'agent model', DEFAULT_DOGFOOD_MODEL)
|
|
412
|
+
.option('--base-ref <ref>', 'branch of newly-app/newly to start from', 'main')
|
|
413
|
+
.option('--no-attach', 'print the session id and exit')
|
|
414
|
+
.action((promptWords, opts) => run(async () => {
|
|
415
|
+
const { client, apiUrl } = api();
|
|
416
|
+
const projectId = projectIdFrom(opts.project, apiUrl);
|
|
417
|
+
const body = dogfoodSessionBody({ model: opts.model, baseRef: opts.baseRef, prompt: promptWords.join(' ') });
|
|
418
|
+
const created = await client.post(`/projects/${encodeURIComponent(projectId)}/sessions`, body);
|
|
419
|
+
const sessionId = (created?.id ?? created?.sessionId ?? created?.session?.id);
|
|
420
|
+
if (!sessionId)
|
|
421
|
+
throw new Error('session created but no id came back');
|
|
422
|
+
console.log(`session ${sessionId} (project ${projectId}, model ${opts.model})`);
|
|
423
|
+
if (opts.attach)
|
|
424
|
+
await attach(client, sessionId, { model: opts.model });
|
|
425
|
+
}));
|
|
426
|
+
dogfood
|
|
427
|
+
.command('attach')
|
|
428
|
+
.description('Follow a session in the terminal and send it messages')
|
|
429
|
+
.argument('<sessionId>', 'session id')
|
|
430
|
+
.option('--model <id>', 'agent model for the messages you send')
|
|
431
|
+
.action((sessionId, opts) => run(async () => {
|
|
432
|
+
const { client } = api();
|
|
433
|
+
await attach(client, sessionId, opts);
|
|
434
|
+
}));
|
|
435
|
+
}
|
package/dist/commands/link.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { readProjectLink, writeProjectLink } from '../config.js';
|
|
1
|
+
import { readProjectLink, resolveProject, writeProjectLink } from '../config.js';
|
|
2
2
|
export function registerLink(program) {
|
|
3
3
|
program
|
|
4
4
|
.command('link')
|
|
5
5
|
.argument('<project-id>', 'Newly project id')
|
|
6
6
|
.description('Associate the current directory with a project (no download) so deploy/status/logs work here')
|
|
7
|
-
.action((
|
|
7
|
+
.action((projectRef) => {
|
|
8
8
|
const dir = process.cwd();
|
|
9
|
+
const projectId = resolveProject(dir, projectRef);
|
|
9
10
|
const existing = readProjectLink(dir);
|
|
10
11
|
writeProjectLink(dir, {
|
|
11
12
|
projectId,
|
package/dist/commands/pull.js
CHANGED
|
@@ -29,7 +29,7 @@ export function registerPull(program) {
|
|
|
29
29
|
const client = new ApiClient(creds.apiUrl, creds.token);
|
|
30
30
|
const query = opts.branch ? `?branch=${encodeURIComponent(opts.branch)}` : '';
|
|
31
31
|
console.log(`Downloading project ${projectId}${opts.branch ? ` (branch ${opts.branch})` : ''}…`);
|
|
32
|
-
const res = (await client.get(`/newly_backend/repo_archive/${projectId}${query}`));
|
|
32
|
+
const res = (await client.get(`/newly_backend/repo_archive/${encodeURIComponent(projectId)}${query}`));
|
|
33
33
|
const data = Buffer.from(await res.arrayBuffer());
|
|
34
34
|
if (opts.force) {
|
|
35
35
|
const keep = await snapshotTopLevelEntries(data);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Option } from 'commander';
|
|
1
|
+
import { InvalidArgumentError, Option } from 'commander';
|
|
2
2
|
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { basename, dirname, extname, join, resolve } from 'node:path';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
@@ -7,6 +7,22 @@ import { createHash, randomUUID } from 'node:crypto';
|
|
|
7
7
|
import { ApiClient, ApiError, ApiTransportError, friendlyApiError } from '../api.js';
|
|
8
8
|
import { requireCredentials } from '../config.js';
|
|
9
9
|
import { recordSimulatorAudio } from './run-cloud-audio.js';
|
|
10
|
+
export const IOS_SIMULATOR_CAPABILITIES = ['HealthKit', 'HomeKit', 'WidgetKit', 'SpeechSynthesis', 'Contacts', 'Calendars'];
|
|
11
|
+
export const IOS_PLATFORM_VERSIONS = ['26.5'];
|
|
12
|
+
export const IOS_DEVICE_NAMES = ['iPhone 17e'];
|
|
13
|
+
export function runCloudIosOptions(opts) {
|
|
14
|
+
const capabilities = [...new Set(opts.capability ?? [])];
|
|
15
|
+
if (!capabilities.length && !opts.platformVersion && !opts.deviceName)
|
|
16
|
+
return {};
|
|
17
|
+
return {
|
|
18
|
+
platformName: 'iOS',
|
|
19
|
+
'runcloud:options': {
|
|
20
|
+
...(capabilities.length ? { capabilities } : {}),
|
|
21
|
+
...(opts.platformVersion ? { platformVersion: opts.platformVersion } : {}),
|
|
22
|
+
...(opts.deviceName ? { deviceName: opts.deviceName } : {}),
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
10
26
|
export const SIMULATOR_KEYS = [
|
|
11
27
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
|
12
28
|
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
@@ -962,6 +978,7 @@ async function createSimulatorSession(platform, opts) {
|
|
|
962
978
|
autoDelete: opts.rm,
|
|
963
979
|
codec: requestedCodec(opts.codec),
|
|
964
980
|
...(opts.devHost ? { devHost: opts.devHost } : {}),
|
|
981
|
+
...(platform === 'ios' ? runCloudIosOptions(opts) : {}),
|
|
965
982
|
});
|
|
966
983
|
}
|
|
967
984
|
async function openSimulatorSessionUrl(platform, sessionId, url) {
|
|
@@ -1041,6 +1058,19 @@ function registerSimulatorCommands(program, platform) {
|
|
|
1041
1058
|
.option('--rm', 'release the session when this command exits', false)
|
|
1042
1059
|
.option('--json', 'output JSON', false)
|
|
1043
1060
|
.addOption(new Option('--dev-host <host>', 'dev-only: target a specific simulator fleet host').hideHelp());
|
|
1061
|
+
if (platform === 'ios') {
|
|
1062
|
+
createCommand
|
|
1063
|
+
.addOption(new Option('--capability <name>', 'iOS capability to turn on (repeatable); see run.cloud/docs/ios/capabilities')
|
|
1064
|
+
.choices(IOS_SIMULATOR_CAPABILITIES)
|
|
1065
|
+
.argParser((value, previous = []) => {
|
|
1066
|
+
if (!IOS_SIMULATOR_CAPABILITIES.includes(value)) {
|
|
1067
|
+
throw new InvalidArgumentError(`Allowed choices are ${IOS_SIMULATOR_CAPABILITIES.join(', ')}.`);
|
|
1068
|
+
}
|
|
1069
|
+
return [...previous, value];
|
|
1070
|
+
}))
|
|
1071
|
+
.addOption(new Option('--platform-version <version>', 'iOS runtime version').choices(IOS_PLATFORM_VERSIONS))
|
|
1072
|
+
.addOption(new Option('--device-name <name>', 'simulator device type').choices(IOS_DEVICE_NAMES));
|
|
1073
|
+
}
|
|
1044
1074
|
simulator.command('audio')
|
|
1045
1075
|
.description('Capture simulator speaker output as a WAV file')
|
|
1046
1076
|
.argument('<id>', 'session id')
|
package/dist/commands/website.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
-
import { basename, resolve } from 'node:path';
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, extname, join, relative, resolve } from 'node:path';
|
|
3
3
|
import { create as tarCreate } from 'tar';
|
|
4
4
|
import { ApiClient, friendlyApiError } from '../api.js';
|
|
5
5
|
import { createSnapshot } from '../archive.js';
|
|
6
6
|
import { requireCredentials, resolveProject } from '../config.js';
|
|
7
|
+
import { WEBSITE_TEMPLATE } from './websiteTemplate.generated.js';
|
|
7
8
|
import { isBundleDeployMode } from './deploy.js';
|
|
8
9
|
function makeClient(project) {
|
|
9
10
|
const creds = requireCredentials();
|
|
@@ -194,8 +195,93 @@ export async function runWebsiteRollback(client, projectId, deploymentId, log =
|
|
|
194
195
|
}));
|
|
195
196
|
log(`Rolled back to ${result.deployment.id}`);
|
|
196
197
|
}
|
|
198
|
+
const INTEGRATIONS = [
|
|
199
|
+
['@clerk/', 'Clerk', 'Email address and display name (via Clerk)'],
|
|
200
|
+
['firebase', 'Firebase', 'Account profile data (via Firebase)'],
|
|
201
|
+
['@supabase/', 'Supabase', 'Account profile data (via Supabase)'],
|
|
202
|
+
['@stripe/', 'Stripe', 'Payment metadata processed by Stripe; no card data stored locally'],
|
|
203
|
+
['react-native-purchases', 'RevenueCat', 'Subscription state (via RevenueCat)'],
|
|
204
|
+
['posthog-react-native', 'PostHog', 'Anonymous usage events (via PostHog)'],
|
|
205
|
+
['@amplitude/', 'Amplitude', 'Anonymous usage events (via Amplitude)'],
|
|
206
|
+
['mixpanel', 'Mixpanel', 'Anonymous usage events (via Mixpanel)'],
|
|
207
|
+
['@sentry/', 'Sentry', 'Crash reports including device model and OS version (via Sentry)'],
|
|
208
|
+
['bugsnag', 'Bugsnag', 'Crash reports including device model and OS version (via Bugsnag)'],
|
|
209
|
+
['@aws-sdk/', 'AWS S3', 'User-uploaded files (stored on AWS S3)'],
|
|
210
|
+
['expo-notifications', 'expo-notifications', 'Push notification tokens'],
|
|
211
|
+
['react-native-onesignal', 'OneSignal', 'Push notification tokens (via OneSignal)'],
|
|
212
|
+
];
|
|
213
|
+
function readJsonObject(path) {
|
|
214
|
+
try {
|
|
215
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
216
|
+
return parsed && typeof parsed === 'object' ? parsed : undefined;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
export function readAppFacts(projectDir) {
|
|
223
|
+
const expo = (readJsonObject(join(projectDir, 'app.json'))?.expo ?? {});
|
|
224
|
+
const deps = Object.keys((readJsonObject(join(projectDir, 'package.json'))?.dependencies ?? {}));
|
|
225
|
+
const found = INTEGRATIONS.filter(([marker]) => deps.some((d) => d.includes(marker)));
|
|
226
|
+
return {
|
|
227
|
+
appName: typeof expo.name === 'string' ? expo.name : basename(resolve(projectDir)),
|
|
228
|
+
iconPath: typeof expo.icon === 'string' ? expo.icon : '',
|
|
229
|
+
integrations: found.map(([, label]) => label),
|
|
230
|
+
collectedData: found.map(([, , line]) => line),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
export function runWebsiteInit(projectDir, opts = {}, log = console.log) {
|
|
234
|
+
const siteDir = join(projectDir, 'website');
|
|
235
|
+
if (existsSync(siteDir) && readdirSync(siteDir).length > 0 && !opts.force) {
|
|
236
|
+
throw new Error('website/ already has files. Pass --force to overwrite them with the starter files.');
|
|
237
|
+
}
|
|
238
|
+
for (const [file, base64] of Object.entries(WEBSITE_TEMPLATE)) {
|
|
239
|
+
const target = join(siteDir, file === 'gitignore' ? '.gitignore' : file);
|
|
240
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
241
|
+
writeFileSync(target, Buffer.from(base64, 'base64'));
|
|
242
|
+
}
|
|
243
|
+
const facts = readAppFacts(projectDir);
|
|
244
|
+
writeFileSync(join(siteDir, 'newly-facts.json'), `${JSON.stringify(facts, null, 2)}\n`);
|
|
245
|
+
const icon = facts.iconPath && resolve(projectDir, facts.iconPath);
|
|
246
|
+
if (icon && existsSync(icon)) {
|
|
247
|
+
const real = realpathSync(icon);
|
|
248
|
+
const inside = !relative(realpathSync(projectDir), real).startsWith('..');
|
|
249
|
+
if (inside && /\.(png|jpe?g|svg|ico)$/i.test(real) && statSync(real).isFile()) {
|
|
250
|
+
const ext = extname(real).toLowerCase();
|
|
251
|
+
copyFileSync(real, join(siteDir, 'app', `icon${ext}`));
|
|
252
|
+
copyFileSync(real, join(siteDir, 'public', `app-icon${ext}`));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const tsconfigPath = join(projectDir, 'tsconfig.json');
|
|
256
|
+
if (existsSync(tsconfigPath)) {
|
|
257
|
+
const tsconfig = readJsonObject(tsconfigPath);
|
|
258
|
+
if (!tsconfig) {
|
|
259
|
+
log('tsconfig.json has comments, so add "website" to its exclude list yourself.');
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
const exclude = Array.isArray(tsconfig.exclude) ? tsconfig.exclude : [];
|
|
263
|
+
if (!exclude.includes('website')) {
|
|
264
|
+
writeFileSync(tsconfigPath, `${JSON.stringify({ ...tsconfig, exclude: [...exclude, 'website'] }, null, 2)}\n`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
log('Website starter written to website/ (app facts in website/newly-facts.json).');
|
|
269
|
+
}
|
|
197
270
|
export function registerWebsite(program) {
|
|
198
271
|
const website = program.command('website').description('Publish and manage static website deployments');
|
|
272
|
+
website
|
|
273
|
+
.command('init')
|
|
274
|
+
.description('Scaffold the website starter into website/')
|
|
275
|
+
.option('--force', 'overwrite an existing website/ starter', false)
|
|
276
|
+
.action((opts) => {
|
|
277
|
+
try {
|
|
278
|
+
runWebsiteInit(process.cwd(), opts);
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
282
|
+
process.exitCode = 1;
|
|
283
|
+
}
|
|
284
|
+
});
|
|
199
285
|
website
|
|
200
286
|
.command('publish')
|
|
201
287
|
.description('Publish a static website directory to Cloudflare')
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const WEBSITE_TEMPLATE = {
|
|
2
|
+
"app/globals.css": "QHRhaWx3aW5kIGJhc2U7CkB0YWlsd2luZCBjb21wb25lbnRzOwpAdGFpbHdpbmQgdXRpbGl0aWVzOwoKQGxheWVyIGJhc2UgewogIDpyb290IHsKICAgIC0tYmFja2dyb3VuZDogMCAwJSAxMDAlOwogICAgLS1mb3JlZ3JvdW5kOiAyNDAgMTAlIDMuOSU7CiAgICAtLWNhcmQ6IDAgMCUgMTAwJTsKICAgIC0tY2FyZC1mb3JlZ3JvdW5kOiAyNDAgMTAlIDMuOSU7CiAgICAtLXByaW1hcnk6IDI0MCA1LjklIDEwJTsKICAgIC0tcHJpbWFyeS1mb3JlZ3JvdW5kOiAwIDAlIDk4JTsKICAgIC0tc2Vjb25kYXJ5OiAyNDAgNC44JSA5NS45JTsKICAgIC0tc2Vjb25kYXJ5LWZvcmVncm91bmQ6IDI0MCA1LjklIDEwJTsKICAgIC0tbXV0ZWQ6IDI0MCA0LjglIDk1LjklOwogICAgLS1tdXRlZC1mb3JlZ3JvdW5kOiAyNDAgMy44JSA0Ni4xJTsKICAgIC0tYWNjZW50OiAyNDAgNC44JSA5NS45JTsKICAgIC0tYWNjZW50LWZvcmVncm91bmQ6IDI0MCA1LjklIDEwJTsKICAgIC0tZGVzdHJ1Y3RpdmU6IDAgODQuMiUgNjAuMiU7CiAgICAtLWRlc3RydWN0aXZlLWZvcmVncm91bmQ6IDAgMCUgOTglOwogICAgLS1ib3JkZXI6IDI0MCA1LjklIDkwJTsKICAgIC0taW5wdXQ6IDI0MCA1LjklIDkwJTsKICAgIC0tcmluZzogMjQwIDUuOSUgMTAlOwogICAgLS1yYWRpdXM6IDAuNzVyZW07CiAgICAvKiBCcmFuZCBodWUgKDAtMzYwKS4gQWdlbnQgb3ZlcnJpZGVzIHBlciBwcm9qZWN0IGluIGFwcC9sYXlvdXQudHN4CiAgICAgICB2aWEgaW5saW5lIHN0eWxlIG9uIDxodG1sPjogZS5nLiBzdHlsZT17eyAiLS1icmFuZCI6ICIyNzgiIH19LgogICAgICAgVXNlZCBieSB0aGUgZ3JhZGllbnQvZ2xvdyB1dGlsaXRpZXMgYmVsb3cgc28gY29sb3VyIHNoaWZ0cyBpbgogICAgICAgb25lIHBsYWNlLiAqLwogICAgLS1icmFuZDogMjQwOwogIH0KCiAgKiB7CiAgICBib3JkZXItY29sb3I6IGhzbCh2YXIoLS1ib3JkZXIpKTsKICB9CiAgaHRtbCB7CiAgICAvKiBTbW9vdGggc2Nyb2xsIGZvciBpbi1wYWdlIGFuY2hvciBuYXYuICovCiAgICBzY3JvbGwtYmVoYXZpb3I6IHNtb290aDsKICB9CiAgYm9keSB7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiBoc2wodmFyKC0tYmFja2dyb3VuZCkpOwogICAgY29sb3I6IGhzbCh2YXIoLS1mb3JlZ3JvdW5kKSk7CiAgICBmb250LWZlYXR1cmUtc2V0dGluZ3M6ICJzczAxIiAxLCAiY3YxMSIgMSwgInJsaWciIDEsICJjYWx0IiAxOwogICAgdGV4dC1yZW5kZXJpbmc6IG9wdGltaXplTGVnaWJpbGl0eTsKICAgIC13ZWJraXQtZm9udC1zbW9vdGhpbmc6IGFudGlhbGlhc2VkOwogICAgLW1vei1vc3gtZm9udC1zbW9vdGhpbmc6IGdyYXlzY2FsZTsKICB9CiAgLyogVGlnaHRlbiBkaXNwbGF5IGhlYWRpbmdzIC0tIHNpbmdsZSBydWxlIHRoZSBhZ2VudCBkb2Vzbid0IGhhdmUgdG8KICAgICByZW1lbWJlci4gUGFpcnMgd2l0aCB0aGUgZGlzcGxheSBmb250IHNoaXBwZWQgdmlhIGxpYi9mb250cy50cy4gKi8KICBoMSwgaDIsIGgzIHsKICAgIGxldHRlci1zcGFjaW5nOiAtMC4wMjVlbTsKICB9Cn0KCkBsYXllciB1dGlsaXRpZXMgewogIC8qIFN1YnRsZSBkb3R0ZWQgYmFja2dyb3VuZCAtLSB3b3JrcyBvbiBhbnkgLS1iYWNrZ3JvdW5kLiBBZ2VudCB1c2VzCiAgICAgPGRpdiBjbGFzc05hbWU9ImJnLWRvdHMgLi4uIj4gb24gaGVybyBzZWN0aW9ucy4gKi8KICAuYmctZG90cyB7CiAgICBiYWNrZ3JvdW5kLWltYWdlOiByYWRpYWwtZ3JhZGllbnQoaHNsKHZhcigtLWZvcmVncm91bmQpIC8gMC4wOCkgMXB4LCB0cmFuc3BhcmVudCAxcHgpOwogICAgYmFja2dyb3VuZC1zaXplOiAyNHB4IDI0cHg7CiAgfQogIC8qIFNvZnQgc3F1YXJlZCBncmlkIGZvciB0ZWNoL1NhYVMgYWVzdGhldGljcy4gKi8KICAuYmctZ3JpZCB7CiAgICBiYWNrZ3JvdW5kLWltYWdlOgogICAgICBsaW5lYXItZ3JhZGllbnQodG8gcmlnaHQsIGhzbCh2YXIoLS1mb3JlZ3JvdW5kKSAvIDAuMDYpIDFweCwgdHJhbnNwYXJlbnQgMXB4KSwKICAgICAgbGluZWFyLWdyYWRpZW50KHRvIGJvdHRvbSwgaHNsKHZhcigtLWZvcmVncm91bmQpIC8gMC4wNikgMXB4LCB0cmFuc3BhcmVudCAxcHgpOwogICAgYmFja2dyb3VuZC1zaXplOiA0OHB4IDQ4cHg7CiAgfQogIC8qIEF1cm9yYSB3YXNoIC0tIHR3byBzb2Z0IGJyYW5kLXRpbnRlZCBibG9icywgaWRlYWwgZm9yIGhlcm8gYmVoaW5kIHR5cGUuCiAgICAgVXNlIHdpdGggYHJlbGF0aXZlIGlzb2xhdGUgb3ZlcmZsb3ctaGlkZGVuYCBhbmQgcGxhY2UgdHlwZSBhdCB6LTEwLiAqLwogIC5iZy1hdXJvcmEgewogICAgYmFja2dyb3VuZDoKICAgICAgcmFkaWFsLWdyYWRpZW50KDYwJSA1MCUgYXQgMjAlIDAlLCBoc2wodmFyKC0tYnJhbmQpIDkwJSA3MCUgLyAwLjM1KSAwJSwgdHJhbnNwYXJlbnQgNjAlKSwKICAgICAgcmFkaWFsLWdyYWRpZW50KDUwJSA0MCUgYXQgODAlIDMwJSwgaHNsKGNhbGModmFyKC0tYnJhbmQpICsgNDApIDkwJSA3NSUgLyAwLjI4KSAwJSwgdHJhbnNwYXJlbnQgNjAlKSwKICAgICAgcmFkaWFsLWdyYWRpZW50KDYwJSA1MCUgYXQgNTAlIDEwMCUsIGhzbChjYWxjKHZhcigtLWJyYW5kKSAtIDMwKSA5MCUgNzAlIC8gMC4yMikgMCUsIHRyYW5zcGFyZW50IDYwJSk7CiAgfQogIC8qIEJpZ2dlciwgbW9yZSBkcmFtYXRpYyBncmFkaWVudCBtZXNoIGZvciBsYW5kaW5nIGhlcm9lcy4gKi8KICAuYmctbWVzaCB7CiAgICBiYWNrZ3JvdW5kOgogICAgICByYWRpYWwtZ3JhZGllbnQoYXQgMjclIDM3JSwgaHNsKHZhcigtLWJyYW5kKSA4OSUgNzUlKSAwcHgsIHRyYW5zcGFyZW50IDUwJSksCiAgICAgIHJhZGlhbC1ncmFkaWVudChhdCA5NyUgMjElLCBoc2woY2FsYyh2YXIoLS1icmFuZCkgKyA2MCkgODAlIDcwJSkgMHB4LCB0cmFuc3BhcmVudCA1MCUpLAogICAgICByYWRpYWwtZ3JhZGllbnQoYXQgNTIlIDk5JSwgaHNsKGNhbGModmFyKC0tYnJhbmQpIC0gNDApIDgwJSA3MCUpIDBweCwgdHJhbnNwYXJlbnQgNTAlKSwKICAgICAgcmFkaWFsLWdyYWRpZW50KGF0IDEwJSAyOSUsIGhzbChjYWxjKHZhcigtLWJyYW5kKSArIDkwKSA3MCUgNzUlKSAwcHgsIHRyYW5zcGFyZW50IDUwJSksCiAgICAgIHJhZGlhbC1ncmFkaWVudChhdCA5NyUgOTYlLCBoc2woY2FsYyh2YXIoLS1icmFuZCkgLSA2MCkgOTAlIDc1JSkgMHB4LCB0cmFuc3BhcmVudCA1MCUpOwogIH0KICAvKiBTb2Z0IGdsb3cgaGFsby4gV3JhcCBhIGhlcm8gZWxlbWVudDogPGRpdiBjbGFzc05hbWU9Imdsb3ciPjxoMT4uLi48L2gxPjwvZGl2PiAqLwogIC5nbG93IHsKICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB9CiAgLmdsb3c6OmJlZm9yZSB7CiAgICBjb250ZW50OiAiIjsKICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICAgIGluc2V0OiAtMTAlOwogICAgYmFja2dyb3VuZDogcmFkaWFsLWdyYWRpZW50KGNsb3Nlc3Qtc2lkZSwgaHNsKHZhcigtLWJyYW5kKSA5MCUgNzAlIC8gMC4zNSksIHRyYW5zcGFyZW50KTsKICAgIGZpbHRlcjogYmx1cig0MHB4KTsKICAgIHotaW5kZXg6IC0xOwogIH0KICAvKiBDb25pYyBhY2NlbnQgcmluZyBmb3IgaWNvbnMgLyBiYWRnZXMuICovCiAgLnJpbmctY29uaWMgewogICAgYmFja2dyb3VuZDogY29uaWMtZ3JhZGllbnQoCiAgICAgIGZyb20gMTgwZGVnIGF0IDUwJSA1MCUsCiAgICAgIGhzbCh2YXIoLS1icmFuZCkgOTAlIDcwJSkgMGRlZywKICAgICAgaHNsKGNhbGModmFyKC0tYnJhbmQpICsgNjApIDgwJSA3NSUpIDEyMGRlZywKICAgICAgaHNsKGNhbGModmFyKC0tYnJhbmQpIC0gNDApIDgwJSA3MCUpIDI0MGRlZywKICAgICAgaHNsKHZhcigtLWJyYW5kKSA5MCUgNzAlKSAzNjBkZWcKICAgICk7CiAgfQogIC8qIEdyYWRpZW50IHRleHQgaGVscGVyLiAqLwogIC50ZXh0LWdyYWRpZW50IHsKICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgKICAgICAgMTM1ZGVnLAogICAgICBoc2wodmFyKC0tYnJhbmQpIDkwJSAzMCUpLAogICAgICBoc2woY2FsYyh2YXIoLS1icmFuZCkgKyA0MCkgOTAlIDU1JSkKICAgICk7CiAgICAtd2Via2l0LWJhY2tncm91bmQtY2xpcDogdGV4dDsKICAgIGJhY2tncm91bmQtY2xpcDogdGV4dDsKICAgIGNvbG9yOiB0cmFuc3BhcmVudDsKICB9CiAgLyogU2xvdyBkcmlmdGluZyBibG9iIC0tIHB1cmUgQ1NTIGFuaW1hdGlvbiBmb3IgaGVybyBhdG1vc3BoZXJlLiAqLwogIC5hbmltYXRlLWRyaWZ0IHsKICAgIGFuaW1hdGlvbjogZHJpZnQgMThzIGVhc2UtaW4tb3V0IGluZmluaXRlOwogIH0KICBAa2V5ZnJhbWVzIGRyaWZ0IHsKICAgIDAlLCAxMDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKSBzY2FsZSgxKTsgfQogICAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCg4JSwgLTYlLCAwKSBzY2FsZSgxLjA4KTsgfQogIH0KICAvKiBTdWJ0bGUgcmV2ZWFsIGZvciBoZXJvIGNvcHkuIFVzZSBvbiBoMS9wIHdpdGggYHN0eWxlPXt7YW5pbWF0aW9uRGVsYXk6JzAuMXMnfX1gLiAqLwogIC5hbmltYXRlLXJpc2UgewogICAgYW5pbWF0aW9uOiByaXNlIDAuOXMgY3ViaWMtYmV6aWVyKDAuMjIsIDEsIDAuMzYsIDEpIGJvdGg7CiAgfQogIEBrZXlmcmFtZXMgcmlzZSB7CiAgICBmcm9tIHsgb3BhY2l0eTogMDsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAxMnB4LCAwKTsgfQogICAgdG8gICB7IG9wYWNpdHk6IDE7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMCwgMCk7IH0KICB9CiAgLyogSGFpcmxpbmUgc2VwYXJhdG9yIHRoYXQgZmFkZXMgYXQgYm90aCBlbmRzLiAqLwogIC5oci1mYWRlIHsKICAgIGhlaWdodDogMXB4OwogICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KAogICAgICB0byByaWdodCwKICAgICAgdHJhbnNwYXJlbnQsCiAgICAgIGhzbCh2YXIoLS1mb3JlZ3JvdW5kKSAvIDAuMTgpLAogICAgICB0cmFuc3BhcmVudAogICAgKTsKICB9CiAgLyogVHlwZSBwYWlyaW5nIGhlbHBlcnMgd2lyZWQgdXAgdG8gbGliL2ZvbnRzLnRzIHZhcmlhYmxlcy4gKi8KICAuZm9udC1kaXNwbGF5IHsgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtZGlzcGxheSwgdWktc2VyaWYsIEdlb3JnaWEsIHNlcmlmKTsgfQogIC5mb250LWJvZHkgICAgeyBmb250LWZhbWlseTogdmFyKC0tZm9udC1ib2R5LCB1aS1zYW5zLXNlcmlmLCBzeXN0ZW0tdWksIHNhbnMtc2VyaWYpOyB9Cn0KCkBtZWRpYSAocHJlZmVycy1yZWR1Y2VkLW1vdGlvbjogcmVkdWNlKSB7CiAgLmFuaW1hdGUtZHJpZnQsCiAgLmFuaW1hdGUtcmlzZSB7CiAgICBhbmltYXRpb246IG5vbmU7CiAgfQp9Cg==",
|
|
3
|
+
"components/ui/accordion.tsx": "InVzZSBjbGllbnQiOwoKaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAicmVhY3QiOwppbXBvcnQgeyBBY2NvcmRpb24gYXMgQWNjb3JkaW9uUHJpbWl0aXZlIH0gZnJvbSAicmFkaXgtdWkiOwppbXBvcnQgeyBDaGV2cm9uRG93biB9IGZyb20gImx1Y2lkZS1yZWFjdCI7CgppbXBvcnQgeyBjbiB9IGZyb20gIkAvbGliL3V0aWxzIjsKCmNvbnN0IEFjY29yZGlvbiA9IEFjY29yZGlvblByaW1pdGl2ZS5Sb290OwoKY29uc3QgQWNjb3JkaW9uSXRlbSA9IFJlYWN0LmZvcndhcmRSZWY8CiAgUmVhY3QuRWxlbWVudFJlZjx0eXBlb2YgQWNjb3JkaW9uUHJpbWl0aXZlLkl0ZW0+LAogIFJlYWN0LkNvbXBvbmVudFByb3BzV2l0aG91dFJlZjx0eXBlb2YgQWNjb3JkaW9uUHJpbWl0aXZlLkl0ZW0+Cj4oKHsgY2xhc3NOYW1lLCAuLi5wcm9wcyB9LCByZWYpID0+ICgKICA8QWNjb3JkaW9uUHJpbWl0aXZlLkl0ZW0KICAgIHJlZj17cmVmfQogICAgY2xhc3NOYW1lPXtjbigiYm9yZGVyLWIiLCBjbGFzc05hbWUpfQogICAgey4uLnByb3BzfQogIC8+CikpOwpBY2NvcmRpb25JdGVtLmRpc3BsYXlOYW1lID0gIkFjY29yZGlvbkl0ZW0iOwoKY29uc3QgQWNjb3JkaW9uVHJpZ2dlciA9IFJlYWN0LmZvcndhcmRSZWY8CiAgUmVhY3QuRWxlbWVudFJlZjx0eXBlb2YgQWNjb3JkaW9uUHJpbWl0aXZlLlRyaWdnZXI+LAogIFJlYWN0LkNvbXBvbmVudFByb3BzV2l0aG91dFJlZjx0eXBlb2YgQWNjb3JkaW9uUHJpbWl0aXZlLlRyaWdnZXI+Cj4oKHsgY2xhc3NOYW1lLCBjaGlsZHJlbiwgLi4ucHJvcHMgfSwgcmVmKSA9PiAoCiAgPEFjY29yZGlvblByaW1pdGl2ZS5IZWFkZXIgY2xhc3NOYW1lPSJmbGV4Ij4KICAgIDxBY2NvcmRpb25QcmltaXRpdmUuVHJpZ2dlcgogICAgICByZWY9e3JlZn0KICAgICAgY2xhc3NOYW1lPXtjbigKICAgICAgICAiZmxleCBmbGV4LTEgaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBweS00IGZvbnQtbWVkaXVtIHRyYW5zaXRpb24tYWxsIGhvdmVyOnVuZGVybGluZSBbJltkYXRhLXN0YXRlPW9wZW5dPnN2Z106cm90YXRlLTE4MCIsCiAgICAgICAgY2xhc3NOYW1lCiAgICAgICl9CiAgICAgIHsuLi5wcm9wc30KICAgID4KICAgICAge2NoaWxkcmVufQogICAgICA8Q2hldnJvbkRvd24gY2xhc3NOYW1lPSJoLTQgdy00IHNocmluay0wIHRyYW5zaXRpb24tdHJhbnNmb3JtIGR1cmF0aW9uLTIwMCIgLz4KICAgIDwvQWNjb3JkaW9uUHJpbWl0aXZlLlRyaWdnZXI+CiAgPC9BY2NvcmRpb25QcmltaXRpdmUuSGVhZGVyPgopKTsKQWNjb3JkaW9uVHJpZ2dlci5kaXNwbGF5TmFtZSA9IEFjY29yZGlvblByaW1pdGl2ZS5UcmlnZ2VyLmRpc3BsYXlOYW1lOwoKY29uc3QgQWNjb3JkaW9uQ29udGVudCA9IFJlYWN0LmZvcndhcmRSZWY8CiAgUmVhY3QuRWxlbWVudFJlZjx0eXBlb2YgQWNjb3JkaW9uUHJpbWl0aXZlLkNvbnRlbnQ+LAogIFJlYWN0LkNvbXBvbmVudFByb3BzV2l0aG91dFJlZjx0eXBlb2YgQWNjb3JkaW9uUHJpbWl0aXZlLkNvbnRlbnQ+Cj4oKHsgY2xhc3NOYW1lLCBjaGlsZHJlbiwgLi4ucHJvcHMgfSwgcmVmKSA9PiAoCiAgPEFjY29yZGlvblByaW1pdGl2ZS5Db250ZW50CiAgICByZWY9e3JlZn0KICAgIGNsYXNzTmFtZT0ib3ZlcmZsb3ctaGlkZGVuIHRleHQtc20gZGF0YS1bc3RhdGU9Y2xvc2VkXTphbmltYXRlLWFjY29yZGlvbi11cCBkYXRhLVtzdGF0ZT1vcGVuXTphbmltYXRlLWFjY29yZGlvbi1kb3duIgogICAgey4uLnByb3BzfQogID4KICAgIDxkaXYgY2xhc3NOYW1lPXtjbigicGItNCBwdC0wIiwgY2xhc3NOYW1lKX0+e2NoaWxkcmVufTwvZGl2PgogIDwvQWNjb3JkaW9uUHJpbWl0aXZlLkNvbnRlbnQ+CikpOwpBY2NvcmRpb25Db250ZW50LmRpc3BsYXlOYW1lID0gQWNjb3JkaW9uUHJpbWl0aXZlLkNvbnRlbnQuZGlzcGxheU5hbWU7CgpleHBvcnQgeyBBY2NvcmRpb24sIEFjY29yZGlvbkl0ZW0sIEFjY29yZGlvblRyaWdnZXIsIEFjY29yZGlvbkNvbnRlbnQgfTsK",
|
|
4
|
+
"components/ui/alert.tsx": "aW1wb3J0ICogYXMgUmVhY3QgZnJvbSAicmVhY3QiOwppbXBvcnQgeyBjdmEsIHR5cGUgVmFyaWFudFByb3BzIH0gZnJvbSAiY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5IjsKCmltcG9ydCB7IGNuIH0gZnJvbSAiQC9saWIvdXRpbHMiOwoKY29uc3QgYWxlcnRWYXJpYW50cyA9IGN2YSgKICAicmVsYXRpdmUgdy1mdWxsIHJvdW5kZWQtbGcgYm9yZGVyIHAtNCBbJj5zdmd+Kl06cGwtNyBbJj5zdmcrZGl2XTp0cmFuc2xhdGUteS1bLTNweF0gWyY+c3ZnXTphYnNvbHV0ZSBbJj5zdmddOmxlZnQtNCBbJj5zdmddOnRvcC00IFsmPnN2Z106dGV4dC1mb3JlZ3JvdW5kIiwKICB7CiAgICB2YXJpYW50czogewogICAgICB2YXJpYW50OiB7CiAgICAgICAgZGVmYXVsdDogImJnLWJhY2tncm91bmQgdGV4dC1mb3JlZ3JvdW5kIiwKICAgICAgICBkZXN0cnVjdGl2ZToKICAgICAgICAgICJib3JkZXItZGVzdHJ1Y3RpdmUvNTAgdGV4dC1kZXN0cnVjdGl2ZSBkYXJrOmJvcmRlci1kZXN0cnVjdGl2ZSBbJj5zdmddOnRleHQtZGVzdHJ1Y3RpdmUiLAogICAgICB9LAogICAgfSwKICAgIGRlZmF1bHRWYXJpYW50czogewogICAgICB2YXJpYW50OiAiZGVmYXVsdCIsCiAgICB9LAogIH0KKTsKCmNvbnN0IEFsZXJ0ID0gUmVhY3QuZm9yd2FyZFJlZjwKICBIVE1MRGl2RWxlbWVudCwKICBSZWFjdC5IVE1MQXR0cmlidXRlczxIVE1MRGl2RWxlbWVudD4gJiBWYXJpYW50UHJvcHM8dHlwZW9mIGFsZXJ0VmFyaWFudHM+Cj4oKHsgY2xhc3NOYW1lLCB2YXJpYW50LCAuLi5wcm9wcyB9LCByZWYpID0+ICgKICA8ZGl2CiAgICByZWY9e3JlZn0KICAgIHJvbGU9ImFsZXJ0IgogICAgY2xhc3NOYW1lPXtjbihhbGVydFZhcmlhbnRzKHsgdmFyaWFudCB9KSwgY2xhc3NOYW1lKX0KICAgIHsuLi5wcm9wc30KICAvPgopKTsKQWxlcnQuZGlzcGxheU5hbWUgPSAiQWxlcnQiOwoKY29uc3QgQWxlcnRUaXRsZSA9IFJlYWN0LmZvcndhcmRSZWY8CiAgSFRNTFBhcmFncmFwaEVsZW1lbnQsCiAgUmVhY3QuSFRNTEF0dHJpYnV0ZXM8SFRNTEhlYWRpbmdFbGVtZW50Pgo+KCh7IGNsYXNzTmFtZSwgLi4ucHJvcHMgfSwgcmVmKSA9PiAoCiAgPGg1CiAgICByZWY9e3JlZn0KICAgIGNsYXNzTmFtZT17Y24oIm1iLTEgZm9udC1tZWRpdW0gbGVhZGluZy1ub25lIHRyYWNraW5nLXRpZ2h0IiwgY2xhc3NOYW1lKX0KICAgIHsuLi5wcm9wc30KICAvPgopKTsKQWxlcnRUaXRsZS5kaXNwbGF5TmFtZSA9ICJBbGVydFRpdGxlIjsKCmNvbnN0IEFsZXJ0RGVzY3JpcHRpb24gPSBSZWFjdC5mb3J3YXJkUmVmPAogIEhUTUxEaXZFbGVtZW50LAogIFJlYWN0LkhUTUxBdHRyaWJ1dGVzPEhUTUxEaXZFbGVtZW50Pgo+KCh7IGNsYXNzTmFtZSwgLi4ucHJvcHMgfSwgcmVmKSA9PiAoCiAgPGRpdgogICAgcmVmPXtyZWZ9CiAgICBjbGFzc05hbWU9e2NuKCJ0ZXh0LXNtIFsmX3BdOmxlYWRpbmctcmVsYXhlZCIsIGNsYXNzTmFtZSl9CiAgICB7Li4ucHJvcHN9CiAgLz4KKSk7CkFsZXJ0RGVzY3JpcHRpb24uZGlzcGxheU5hbWUgPSAiQWxlcnREZXNjcmlwdGlvbiI7CgpleHBvcnQgeyBBbGVydCwgQWxlcnRUaXRsZSwgQWxlcnREZXNjcmlwdGlvbiB9Owo=",
|
|
5
|
+
"components/ui/badge.tsx": "aW1wb3J0ICogYXMgUmVhY3QgZnJvbSAicmVhY3QiOwppbXBvcnQgeyBjdmEsIHR5cGUgVmFyaWFudFByb3BzIH0gZnJvbSAiY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5IjsKCmltcG9ydCB7IGNuIH0gZnJvbSAiQC9saWIvdXRpbHMiOwoKY29uc3QgYmFkZ2VWYXJpYW50cyA9IGN2YSgKICAiaW5saW5lLWZsZXggaXRlbXMtY2VudGVyIHJvdW5kZWQtZnVsbCBib3JkZXIgcHgtMi41IHB5LTAuNSB0ZXh0LXhzIGZvbnQtc2VtaWJvbGQgdHJhbnNpdGlvbi1jb2xvcnMgZm9jdXM6b3V0bGluZS1ub25lIGZvY3VzOnJpbmctMiBmb2N1czpyaW5nLXJpbmcgZm9jdXM6cmluZy1vZmZzZXQtMiIsCiAgewogICAgdmFyaWFudHM6IHsKICAgICAgdmFyaWFudDogewogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAiYm9yZGVyLXRyYW5zcGFyZW50IGJnLXByaW1hcnkgdGV4dC1wcmltYXJ5LWZvcmVncm91bmQgaG92ZXI6YmctcHJpbWFyeS84MCIsCiAgICAgICAgc2Vjb25kYXJ5OgogICAgICAgICAgImJvcmRlci10cmFuc3BhcmVudCBiZy1zZWNvbmRhcnkgdGV4dC1zZWNvbmRhcnktZm9yZWdyb3VuZCBob3ZlcjpiZy1zZWNvbmRhcnkvODAiLAogICAgICAgIGRlc3RydWN0aXZlOgogICAgICAgICAgImJvcmRlci10cmFuc3BhcmVudCBiZy1kZXN0cnVjdGl2ZSB0ZXh0LWRlc3RydWN0aXZlLWZvcmVncm91bmQgaG92ZXI6YmctZGVzdHJ1Y3RpdmUvODAiLAogICAgICAgIG91dGxpbmU6ICJ0ZXh0LWZvcmVncm91bmQiLAogICAgICB9LAogICAgfSwKICAgIGRlZmF1bHRWYXJpYW50czogewogICAgICB2YXJpYW50OiAiZGVmYXVsdCIsCiAgICB9LAogIH0KKTsKCmV4cG9ydCBpbnRlcmZhY2UgQmFkZ2VQcm9wcwogIGV4dGVuZHMgUmVhY3QuSFRNTEF0dHJpYnV0ZXM8SFRNTERpdkVsZW1lbnQ+LAogICAgVmFyaWFudFByb3BzPHR5cGVvZiBiYWRnZVZhcmlhbnRzPiB7fQoKZnVuY3Rpb24gQmFkZ2UoeyBjbGFzc05hbWUsIHZhcmlhbnQsIC4uLnByb3BzIH06IEJhZGdlUHJvcHMpIHsKICByZXR1cm4gPGRpdiBjbGFzc05hbWU9e2NuKGJhZGdlVmFyaWFudHMoeyB2YXJpYW50IH0pLCBjbGFzc05hbWUpfSB7Li4ucHJvcHN9IC8+Owp9CgpleHBvcnQgeyBCYWRnZSwgYmFkZ2VWYXJpYW50cyB9Owo=",
|
|
6
|
+
"components/ui/button.tsx": "aW1wb3J0ICogYXMgUmVhY3QgZnJvbSAicmVhY3QiOwppbXBvcnQgeyBTbG90IH0gZnJvbSAicmFkaXgtdWkiOwppbXBvcnQgeyBjdmEsIHR5cGUgVmFyaWFudFByb3BzIH0gZnJvbSAiY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5IjsKCmltcG9ydCB7IGNuIH0gZnJvbSAiQC9saWIvdXRpbHMiOwoKY29uc3QgYnV0dG9uVmFyaWFudHMgPSBjdmEoCiAgImlubGluZS1mbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBnYXAtMiB3aGl0ZXNwYWNlLW5vd3JhcCByb3VuZGVkLW1kIHRleHQtc20gZm9udC1tZWRpdW0gcmluZy1vZmZzZXQtYmFja2dyb3VuZCB0cmFuc2l0aW9uLWNvbG9ycyBmb2N1cy12aXNpYmxlOm91dGxpbmUtbm9uZSBmb2N1cy12aXNpYmxlOnJpbmctMiBmb2N1cy12aXNpYmxlOnJpbmctcmluZyBmb2N1cy12aXNpYmxlOnJpbmctb2Zmc2V0LTIgZGlzYWJsZWQ6cG9pbnRlci1ldmVudHMtbm9uZSBkaXNhYmxlZDpvcGFjaXR5LTUwIFsmX3N2Z106cG9pbnRlci1ldmVudHMtbm9uZSBbJl9zdmddOnNpemUtNCBbJl9zdmddOnNocmluay0wIiwKICB7CiAgICB2YXJpYW50czogewogICAgICB2YXJpYW50OiB7CiAgICAgICAgZGVmYXVsdDogImJnLXByaW1hcnkgdGV4dC1wcmltYXJ5LWZvcmVncm91bmQgaG92ZXI6YmctcHJpbWFyeS85MCIsCiAgICAgICAgZGVzdHJ1Y3RpdmU6CiAgICAgICAgICAiYmctZGVzdHJ1Y3RpdmUgdGV4dC1kZXN0cnVjdGl2ZS1mb3JlZ3JvdW5kIGhvdmVyOmJnLWRlc3RydWN0aXZlLzkwIiwKICAgICAgICBvdXRsaW5lOgogICAgICAgICAgImJvcmRlciBib3JkZXItaW5wdXQgYmctYmFja2dyb3VuZCBob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCIsCiAgICAgICAgc2Vjb25kYXJ5OgogICAgICAgICAgImJnLXNlY29uZGFyeSB0ZXh0LXNlY29uZGFyeS1mb3JlZ3JvdW5kIGhvdmVyOmJnLXNlY29uZGFyeS84MCIsCiAgICAgICAgZ2hvc3Q6ICJob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCIsCiAgICAgICAgbGluazogInRleHQtcHJpbWFyeSB1bmRlcmxpbmUtb2Zmc2V0LTQgaG92ZXI6dW5kZXJsaW5lIiwKICAgICAgfSwKICAgICAgc2l6ZTogewogICAgICAgIGRlZmF1bHQ6ICJoLTEwIHB4LTQgcHktMiIsCiAgICAgICAgc206ICJoLTkgcm91bmRlZC1tZCBweC0zIiwKICAgICAgICBsZzogImgtMTEgcm91bmRlZC1tZCBweC04IiwKICAgICAgICBpY29uOiAiaC0xMCB3LTEwIiwKICAgICAgfSwKICAgIH0sCiAgICBkZWZhdWx0VmFyaWFudHM6IHsKICAgICAgdmFyaWFudDogImRlZmF1bHQiLAogICAgICBzaXplOiAiZGVmYXVsdCIsCiAgICB9LAogIH0KKTsKCmV4cG9ydCBpbnRlcmZhY2UgQnV0dG9uUHJvcHMKICBleHRlbmRzIFJlYWN0LkJ1dHRvbkhUTUxBdHRyaWJ1dGVzPEhUTUxCdXR0b25FbGVtZW50PiwKICAgIFZhcmlhbnRQcm9wczx0eXBlb2YgYnV0dG9uVmFyaWFudHM+IHsKICBhc0NoaWxkPzogYm9vbGVhbjsKfQoKY29uc3QgQnV0dG9uID0gUmVhY3QuZm9yd2FyZFJlZjxIVE1MQnV0dG9uRWxlbWVudCwgQnV0dG9uUHJvcHM+KAogICh7IGNsYXNzTmFtZSwgdmFyaWFudCwgc2l6ZSwgYXNDaGlsZCA9IGZhbHNlLCAuLi5wcm9wcyB9LCByZWYpID0+IHsKICAgIGNvbnN0IENvbXAgPSBhc0NoaWxkID8gU2xvdC5Sb290IDogImJ1dHRvbiI7CiAgICByZXR1cm4gKAogICAgICA8Q29tcAogICAgICAgIGNsYXNzTmFtZT17Y24oYnV0dG9uVmFyaWFudHMoeyB2YXJpYW50LCBzaXplLCBjbGFzc05hbWUgfSkpfQogICAgICAgIHJlZj17cmVmfQogICAgICAgIHsuLi5wcm9wc30KICAgICAgLz4KICAgICk7CiAgfQopOwpCdXR0b24uZGlzcGxheU5hbWUgPSAiQnV0dG9uIjsKCmV4cG9ydCB7IEJ1dHRvbiwgYnV0dG9uVmFyaWFudHMgfTsK",
|
|
7
|
+
"components/ui/card.tsx": "aW1wb3J0ICogYXMgUmVhY3QgZnJvbSAicmVhY3QiOwoKaW1wb3J0IHsgY24gfSBmcm9tICJAL2xpYi91dGlscyI7Cgpjb25zdCBDYXJkID0gUmVhY3QuZm9yd2FyZFJlZjwKICBIVE1MRGl2RWxlbWVudCwKICBSZWFjdC5IVE1MQXR0cmlidXRlczxIVE1MRGl2RWxlbWVudD4KPigoeyBjbGFzc05hbWUsIC4uLnByb3BzIH0sIHJlZikgPT4gKAogIDxkaXYKICAgIHJlZj17cmVmfQogICAgY2xhc3NOYW1lPXtjbigKICAgICAgInJvdW5kZWQtbGcgYm9yZGVyIGJnLWNhcmQgdGV4dC1jYXJkLWZvcmVncm91bmQgc2hhZG93LXNtIiwKICAgICAgY2xhc3NOYW1lCiAgICApfQogICAgey4uLnByb3BzfQogIC8+CikpOwpDYXJkLmRpc3BsYXlOYW1lID0gIkNhcmQiOwoKY29uc3QgQ2FyZEhlYWRlciA9IFJlYWN0LmZvcndhcmRSZWY8CiAgSFRNTERpdkVsZW1lbnQsCiAgUmVhY3QuSFRNTEF0dHJpYnV0ZXM8SFRNTERpdkVsZW1lbnQ+Cj4oKHsgY2xhc3NOYW1lLCAuLi5wcm9wcyB9LCByZWYpID0+ICgKICA8ZGl2CiAgICByZWY9e3JlZn0KICAgIGNsYXNzTmFtZT17Y24oImZsZXggZmxleC1jb2wgc3BhY2UteS0xLjUgcC02IiwgY2xhc3NOYW1lKX0KICAgIHsuLi5wcm9wc30KICAvPgopKTsKQ2FyZEhlYWRlci5kaXNwbGF5TmFtZSA9ICJDYXJkSGVhZGVyIjsKCmNvbnN0IENhcmRUaXRsZSA9IFJlYWN0LmZvcndhcmRSZWY8CiAgSFRNTERpdkVsZW1lbnQsCiAgUmVhY3QuSFRNTEF0dHJpYnV0ZXM8SFRNTERpdkVsZW1lbnQ+Cj4oKHsgY2xhc3NOYW1lLCAuLi5wcm9wcyB9LCByZWYpID0+ICgKICA8ZGl2CiAgICByZWY9e3JlZn0KICAgIGNsYXNzTmFtZT17Y24oCiAgICAgICJ0ZXh0LTJ4bCBmb250LXNlbWlib2xkIGxlYWRpbmctbm9uZSB0cmFja2luZy10aWdodCIsCiAgICAgIGNsYXNzTmFtZQogICAgKX0KICAgIHsuLi5wcm9wc30KICAvPgopKTsKQ2FyZFRpdGxlLmRpc3BsYXlOYW1lID0gIkNhcmRUaXRsZSI7Cgpjb25zdCBDYXJkRGVzY3JpcHRpb24gPSBSZWFjdC5mb3J3YXJkUmVmPAogIEhUTUxEaXZFbGVtZW50LAogIFJlYWN0LkhUTUxBdHRyaWJ1dGVzPEhUTUxEaXZFbGVtZW50Pgo+KCh7IGNsYXNzTmFtZSwgLi4ucHJvcHMgfSwgcmVmKSA9PiAoCiAgPGRpdgogICAgcmVmPXtyZWZ9CiAgICBjbGFzc05hbWU9e2NuKCJ0ZXh0LXNtIHRleHQtbXV0ZWQtZm9yZWdyb3VuZCIsIGNsYXNzTmFtZSl9CiAgICB7Li4ucHJvcHN9CiAgLz4KKSk7CkNhcmREZXNjcmlwdGlvbi5kaXNwbGF5TmFtZSA9ICJDYXJkRGVzY3JpcHRpb24iOwoKY29uc3QgQ2FyZENvbnRlbnQgPSBSZWFjdC5mb3J3YXJkUmVmPAogIEhUTUxEaXZFbGVtZW50LAogIFJlYWN0LkhUTUxBdHRyaWJ1dGVzPEhUTUxEaXZFbGVtZW50Pgo+KCh7IGNsYXNzTmFtZSwgLi4ucHJvcHMgfSwgcmVmKSA9PiAoCiAgPGRpdiByZWY9e3JlZn0gY2xhc3NOYW1lPXtjbigicC02IHB0LTAiLCBjbGFzc05hbWUpfSB7Li4ucHJvcHN9IC8+CikpOwpDYXJkQ29udGVudC5kaXNwbGF5TmFtZSA9ICJDYXJkQ29udGVudCI7Cgpjb25zdCBDYXJkRm9vdGVyID0gUmVhY3QuZm9yd2FyZFJlZjwKICBIVE1MRGl2RWxlbWVudCwKICBSZWFjdC5IVE1MQXR0cmlidXRlczxIVE1MRGl2RWxlbWVudD4KPigoeyBjbGFzc05hbWUsIC4uLnByb3BzIH0sIHJlZikgPT4gKAogIDxkaXYKICAgIHJlZj17cmVmfQogICAgY2xhc3NOYW1lPXtjbigiZmxleCBpdGVtcy1jZW50ZXIgcC02IHB0LTAiLCBjbGFzc05hbWUpfQogICAgey4uLnByb3BzfQogIC8+CikpOwpDYXJkRm9vdGVyLmRpc3BsYXlOYW1lID0gIkNhcmRGb290ZXIiOwoKZXhwb3J0IHsKICBDYXJkLAogIENhcmRIZWFkZXIsCiAgQ2FyZEZvb3RlciwKICBDYXJkVGl0bGUsCiAgQ2FyZERlc2NyaXB0aW9uLAogIENhcmRDb250ZW50LAp9Owo=",
|
|
8
|
+
"components/ui/newly-attribution.tsx": "aW1wb3J0ICogYXMgUmVhY3QgZnJvbSAicmVhY3QiOwoKaW1wb3J0IHsgY24gfSBmcm9tICJAL2xpYi91dGlscyI7CgovLyBQbGF0Zm9ybSBhdHRyaWJ1dGlvbjogZXZlcnkgTmV3bHktZ2VuZXJhdGVkIHNpdGUgbGlua3MgYmFjayB0byB1cy4KLy8gU2NhZmZvbGQtb3duZWQgKHVuZGVyIGNvbXBvbmVudHMvdWkvKSBzbyB0aGUgYWdlbnQgaW1wb3J0cyBpdCBidXQKLy8gY2FuJ3QgZGVsZXRlIG9yIHJld3JpdGUgaXQuIFRoZSB2aXN1YWwgaXMgZGVsaWJlcmF0ZWx5IHNtYWxsIGFuZAovLyBtdXRlZCDigJQgYSBzaW5nbGUgbGluZSB0aGF0IGZpdHMgaW5zaWRlIHRoZSBwcm9qZWN0J3Mgb3duIGZvb3RlcgovLyB3aXRob3V0IGNvbXBldGluZyB3aXRoIHRoZSBzaXRlJ3MgYnJhbmQuCmZ1bmN0aW9uIE5ld2x5QXR0cmlidXRpb24oewogIGNsYXNzTmFtZSwKICAuLi5wcm9wcwp9OiBSZWFjdC5IVE1MQXR0cmlidXRlczxIVE1MQW5jaG9yRWxlbWVudD4pIHsKICByZXR1cm4gKAogICAgPGEKICAgICAgaHJlZj0iaHR0cHM6Ly9uZXdseS5hcHA/dXRtX3NvdXJjZT1zaXRlX2Zvb3RlciZ1dG1fbWVkaXVtPWF0dHJpYnV0aW9uIgogICAgICB0YXJnZXQ9Il9ibGFuayIKICAgICAgcmVsPSJub29wZW5lciBub3JlZmVycmVyIgogICAgICBjbGFzc05hbWU9e2NuKAogICAgICAgICJpbmxpbmUtZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTEgdGV4dC14cyB0ZXh0LW11dGVkLWZvcmVncm91bmQvNzAgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6dGV4dC1mb3JlZ3JvdW5kIiwKICAgICAgICBjbGFzc05hbWUsCiAgICAgICl9CiAgICAgIHsuLi5wcm9wc30KICAgID4KICAgICAgPHNwYW4+TWFkZSB3aXRoPC9zcGFuPgogICAgICA8c3BhbiBjbGFzc05hbWU9ImZvbnQtbWVkaXVtIj5OZXdseTwvc3Bhbj4KICAgIDwvYT4KICApOwp9CgpleHBvcnQgeyBOZXdseUF0dHJpYnV0aW9uIH07Cg==",
|
|
9
|
+
"components/ui/skeleton.tsx": "aW1wb3J0IHsgY24gfSBmcm9tICJAL2xpYi91dGlscyI7CgpmdW5jdGlvbiBTa2VsZXRvbih7CiAgY2xhc3NOYW1lLAogIC4uLnByb3BzCn06IFJlYWN0LkhUTUxBdHRyaWJ1dGVzPEhUTUxEaXZFbGVtZW50PikgewogIHJldHVybiAoCiAgICA8ZGl2CiAgICAgIGNsYXNzTmFtZT17Y24oImFuaW1hdGUtcHVsc2Ugcm91bmRlZC1tZCBiZy1tdXRlZCIsIGNsYXNzTmFtZSl9CiAgICAgIHsuLi5wcm9wc30KICAgIC8+CiAgKTsKfQoKZXhwb3J0IHsgU2tlbGV0b24gfTsK",
|
|
10
|
+
"gitignore": "bm9kZV9tb2R1bGVzCi5uZXh0Ci5uZXh0LWRldgpvdXQK",
|
|
11
|
+
"lib/fonts.ts": "aW1wb3J0IHsKICBJbnN0cnVtZW50X1NlcmlmLAogIEJyaWNvbGFnZV9Hcm90ZXNxdWUsCiAgRnJhdW5jZXMsCiAgRE1fU2VyaWZfRGlzcGxheSwKICBNYW5yb3BlLAogIEpldEJyYWluc19Nb25vLAogIEludGVyX1RpZ2h0LAp9IGZyb20gIm5leHQvZm9udC9nb29nbGUiOwoKLy8gRGlzcGxheSBmb250cyAtLSBwaWNrIG9uZSBwZXIgcHJvamVjdC4gRWFjaCBvcHRpb24gaXMgaW50ZW50aW9uYWxseQovLyBkaXN0aW5jdGl2ZTsgbm9uZSBvZiB0aGVtIGFyZSBJbnRlci4gUGFpciBlYWNoIHdpdGggYSBib2R5IGZvbnQuCmNvbnN0IGluc3RydW1lbnRTZXJpZiA9IEluc3RydW1lbnRfU2VyaWYoewogIHN1YnNldHM6IFsibGF0aW4iXSwKICB3ZWlnaHQ6ICI0MDAiLAogIGRpc3BsYXk6ICJzd2FwIiwKICB2YXJpYWJsZTogIi0tZm9udC1kaXNwbGF5IiwKfSk7CmNvbnN0IGJyaWNvbGFnZSA9IEJyaWNvbGFnZV9Hcm90ZXNxdWUoewogIHN1YnNldHM6IFsibGF0aW4iXSwKICBkaXNwbGF5OiAic3dhcCIsCiAgdmFyaWFibGU6ICItLWZvbnQtZGlzcGxheSIsCn0pOwpjb25zdCBmcmF1bmNlcyA9IEZyYXVuY2VzKHsKICBzdWJzZXRzOiBbImxhdGluIl0sCiAgZGlzcGxheTogInN3YXAiLAogIHZhcmlhYmxlOiAiLS1mb250LWRpc3BsYXkiLAp9KTsKY29uc3QgZG1TZXJpZiA9IERNX1NlcmlmX0Rpc3BsYXkoewogIHN1YnNldHM6IFsibGF0aW4iXSwKICB3ZWlnaHQ6ICI0MDAiLAogIGRpc3BsYXk6ICJzd2FwIiwKICB2YXJpYWJsZTogIi0tZm9udC1kaXNwbGF5IiwKfSk7CgovLyBCb2R5IGZvbnRzIC0tIGJvdGggbW9kZXJuLCBuZWl0aGVyIGdlbmVyaWMuCmNvbnN0IG1hbnJvcGUgPSBNYW5yb3BlKHsKICBzdWJzZXRzOiBbImxhdGluIl0sCiAgZGlzcGxheTogInN3YXAiLAogIHZhcmlhYmxlOiAiLS1mb250LWJvZHkiLAp9KTsKY29uc3QgaW50ZXJUaWdodCA9IEludGVyX1RpZ2h0KHsKICBzdWJzZXRzOiBbImxhdGluIl0sCiAgZGlzcGxheTogInN3YXAiLAogIHZhcmlhYmxlOiAiLS1mb250LWJvZHkiLAp9KTsKCi8vIEFsd2F5cyBhdmFpbGFibGUgZm9yIHN0YXRzIC8gbnVtZXJhbHMgLyBjb2RlLWlzaCBhY2NlbnRzLgpjb25zdCBqZXRicmFpbnNNb25vID0gSmV0QnJhaW5zX01vbm8oewogIHN1YnNldHM6IFsibGF0aW4iXSwKICBkaXNwbGF5OiAic3dhcCIsCiAgdmFyaWFibGU6ICItLWZvbnQtbW9ubyIsCn0pOwoKZXhwb3J0IHR5cGUgRm9udEROQSA9CiAgfCAiZWRpdG9yaWFsIiAgICAgIC8vIEluc3RydW1lbnQgU2VyaWYgKyBNYW5yb3BlICAgICAgICAocmVmaW5lZCAvIEFwcGxlLWlzaCkKICB8ICJib2xkIiAgICAgICAgICAgLy8gQnJpY29sYWdlIEdyb3Rlc3F1ZSArIEludGVyIFRpZ2h0IChib2xkIGxhdW5jaCAvIHBsYXlmdWwpCiAgfCAiZXhwcmVzc2l2ZSIgICAgIC8vIEZyYXVuY2VzICsgTWFucm9wZSAgICAgICAgICAgICAgICAodmFyaWFibGUgc2VyaWYgLyBjaGFyYWN0ZXJmdWwpCiAgfCAibHV4dXJ5IjsgICAgICAgIC8vIERNIFNlcmlmIERpc3BsYXkgKyBNYW5yb3BlICAgICAgICAoaGlnaC1lbmQgLyB3ZWxsbmVzcykKCi8qKgogKiBSZXR1cm5zIHRoZSBjbGFzc05hbWUgc3RyaW5nIHRvIHB1dCBvbiA8aHRtbD4gZm9yIGEgZ2l2ZW4gRE5BLiBDb21iaW5lcwogKiB0aGUgY2hvc2VuIGRpc3BsYXkgKyBib2R5ICsgbW9ubyB2YXJpYWJsZXMgc28gYWxsIHRocmVlIGFyZSBhdmFpbGFibGUKICogdmlhIGB2YXIoLS1mb250LSopYCBpbiBnbG9iYWxzLmNzcyBhbmQgdGhlIFRhaWx3aW5kIGBmb250LSpgIGhlbHBlcnMuCiAqCiAqIFVzYWdlIGluIGFwcC9sYXlvdXQudHN4OgogKiAgIDxodG1sIGxhbmc9ImVuIiBjbGFzc05hbWU9e3BhaXJGb3IoImVkaXRvcmlhbCIpfT4KICovCmV4cG9ydCBmdW5jdGlvbiBwYWlyRm9yKGRuYTogRm9udEROQSk6IHN0cmluZyB7CiAgY29uc3QgbW9ubyA9IGpldGJyYWluc01vbm8udmFyaWFibGU7CiAgc3dpdGNoIChkbmEpIHsKICAgIGNhc2UgImVkaXRvcmlhbCI6CiAgICAgIHJldHVybiBgJHtpbnN0cnVtZW50U2VyaWYudmFyaWFibGV9ICR7bWFucm9wZS52YXJpYWJsZX0gJHttb25vfWA7CiAgICBjYXNlICJib2xkIjoKICAgICAgcmV0dXJuIGAke2JyaWNvbGFnZS52YXJpYWJsZX0gJHtpbnRlclRpZ2h0LnZhcmlhYmxlfSAke21vbm99YDsKICAgIGNhc2UgImV4cHJlc3NpdmUiOgogICAgICByZXR1cm4gYCR7ZnJhdW5jZXMudmFyaWFibGV9ICR7bWFucm9wZS52YXJpYWJsZX0gJHttb25vfWA7CiAgICBjYXNlICJsdXh1cnkiOgogICAgICByZXR1cm4gYCR7ZG1TZXJpZi52YXJpYWJsZX0gJHttYW5yb3BlLnZhcmlhYmxlfSAke21vbm99YDsKICB9Cn0K",
|
|
12
|
+
"lib/utils.ts": "aW1wb3J0IHsgY2xzeCwgdHlwZSBDbGFzc1ZhbHVlIH0gZnJvbSAiY2xzeCI7CmltcG9ydCB7IHR3TWVyZ2UgfSBmcm9tICJ0YWlsd2luZC1tZXJnZSI7CgpleHBvcnQgZnVuY3Rpb24gY24oLi4uaW5wdXRzOiBDbGFzc1ZhbHVlW10pIHsKICByZXR1cm4gdHdNZXJnZShjbHN4KGlucHV0cykpOwp9Cg==",
|
|
13
|
+
"next-env.d.ts": "Ly8vIDxyZWZlcmVuY2UgdHlwZXM9Im5leHQiIC8+Ci8vLyA8cmVmZXJlbmNlIHR5cGVzPSJuZXh0L2ltYWdlLXR5cGVzL2dsb2JhbCIgLz4KCi8vIE5PVEU6IFRoaXMgZmlsZSBzaG91bGQgbm90IGJlIGVkaXRlZAovLyBzZWUgaHR0cHM6Ly9uZXh0anMub3JnL2RvY3MvYmFzaWMtZmVhdHVyZXMvdHlwZXNjcmlwdCBmb3IgbW9yZSBpbmZvcm1hdGlvbi4K",
|
|
14
|
+
"next.config.mjs": "aW1wb3J0IHsgUEhBU0VfREVWRUxPUE1FTlRfU0VSVkVSIH0gZnJvbSAnbmV4dC9jb25zdGFudHMuanMnOwoKLy8gQSBzdGF0aWMgZXhwb3J0IGxhbmRzIGluIGBvdXRgIG9ubHkgd2hpbGUgZGlzdERpciBpcyBgLm5leHRgLCBzbyB0aGUgZGV2IHNlcnZlciBpcyB0aGUgb25lIHRoYXQKLy8gbW92ZXM6IGEgYG5leHQgYnVpbGRgIGNhbiB0aGVuIHJ1biBiZXNpZGUgaXQgd2l0aG91dCBjbG9iYmVyaW5nIHRoZSBmaWxlcyBpdCBpcyBzZXJ2aW5nLgpleHBvcnQgZGVmYXVsdCAocGhhc2UpID0+ICh7CiAgb3V0cHV0OiAnZXhwb3J0JywKICB0cmFpbGluZ1NsYXNoOiB0cnVlLAogIC8vIFBsYWluIGA8aW1nPmAgaXMgdGhlIG5vcm0gaGVyZSBhbmQgdGhlIGV4cG9ydCBoYXMgbm8gaW1hZ2Ugc2VydmVyLgogIGltYWdlczogeyB1bm9wdGltaXplZDogdHJ1ZSB9LAogIGRpc3REaXI6IHBoYXNlID09PSBQSEFTRV9ERVZFTE9QTUVOVF9TRVJWRVIgPyAnLm5leHQtZGV2JyA6ICcubmV4dCcsCn0pOwo=",
|
|
15
|
+
"package.json": "ewogICJuYW1lIjogIm5ld2x5LXNpdGUiLAogICJwcml2YXRlIjogdHJ1ZSwKICAidmVyc2lvbiI6ICIwLjAuMSIsCiAgInNjcmlwdHMiOiB7CiAgICAiYnVpbGQiOiAibmV4dCBidWlsZCIKICB9LAogICJkZXBlbmRlbmNpZXMiOiB7CiAgICAibmV4dCI6ICJeMTQuMi4xOCIsCiAgICAicmVhY3QiOiAiXjE4LjMuMSIsCiAgICAicmVhY3QtZG9tIjogIl4xOC4zLjEiLAogICAgImx1Y2lkZS1yZWFjdCI6ICJeMC40NjAuMCIsCiAgICAiY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5IjogIl4wLjcuMSIsCiAgICAiY2xzeCI6ICJeMi4xLjEiLAogICAgInRhaWx3aW5kLW1lcmdlIjogIl4yLjUuNCIsCiAgICAidGFpbHdpbmRjc3MtYW5pbWF0ZSI6ICJeMS4wLjciLAogICAgInJhZGl4LXVpIjogIl4xLjQuMyIsCiAgICAiZnJhbWVyLW1vdGlvbiI6ICJeMTEuMTEuMTciCiAgfSwKICAiZGV2RGVwZW5kZW5jaWVzIjogewogICAgIkB0eXBlcy9ub2RlIjogIl4yMi45LjAiLAogICAgIkB0eXBlcy9yZWFjdCI6ICJeMTguMy4xMiIsCiAgICAiQHR5cGVzL3JlYWN0LWRvbSI6ICJeMTguMy4xIiwKICAgICJhdXRvcHJlZml4ZXIiOiAiXjEwLjQuMjAiLAogICAgInBvc3Rjc3MiOiAiXjguNC40OSIsCiAgICAidGFpbHdpbmRjc3MiOiAiXjMuNC4xNCIsCiAgICAidHlwZXNjcmlwdCI6ICJeNS42LjMiCiAgfQp9Cg==",
|
|
16
|
+
"postcss.config.mjs": "Y29uc3QgY29uZmlnID0gewogIHBsdWdpbnM6IHsKICAgIHRhaWx3aW5kY3NzOiB7fSwKICAgIGF1dG9wcmVmaXhlcjoge30sCiAgfSwKfTsKCmV4cG9ydCBkZWZhdWx0IGNvbmZpZzsK",
|
|
17
|
+
"public/app-store-icon.webp": "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",
|
|
18
|
+
"public/play-store-icon.png": "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",
|
|
19
|
+
"tailwind.config.ts": "aW1wb3J0IHR5cGUgeyBDb25maWcgfSBmcm9tICJ0YWlsd2luZGNzcyI7CmltcG9ydCBhbmltYXRlIGZyb20gInRhaWx3aW5kY3NzLWFuaW1hdGUiOwoKY29uc3QgY29uZmlnOiBDb25maWcgPSB7CiAgZGFya01vZGU6IFsiY2xhc3MiXSwKICBjb250ZW50OiBbIi4vYXBwLyoqLyoue3RzLHRzeH0iLCAiLi9jb21wb25lbnRzLyoqLyoue3RzLHRzeH0iXSwKICB0aGVtZTogewogICAgY29udGFpbmVyOiB7CiAgICAgIGNlbnRlcjogdHJ1ZSwKICAgICAgcGFkZGluZzogIjFyZW0iLAogICAgICBzY3JlZW5zOiB7ICIyeGwiOiAiMTQwMHB4IiB9LAogICAgfSwKICAgIGV4dGVuZDogewogICAgICBjb2xvcnM6IHsKICAgICAgICBib3JkZXI6ICJoc2wodmFyKC0tYm9yZGVyKSkiLAogICAgICAgIGlucHV0OiAiaHNsKHZhcigtLWlucHV0KSkiLAogICAgICAgIHJpbmc6ICJoc2wodmFyKC0tcmluZykpIiwKICAgICAgICBiYWNrZ3JvdW5kOiAiaHNsKHZhcigtLWJhY2tncm91bmQpKSIsCiAgICAgICAgZm9yZWdyb3VuZDogImhzbCh2YXIoLS1mb3JlZ3JvdW5kKSkiLAogICAgICAgIHByaW1hcnk6IHsKICAgICAgICAgIERFRkFVTFQ6ICJoc2wodmFyKC0tcHJpbWFyeSkpIiwKICAgICAgICAgIGZvcmVncm91bmQ6ICJoc2wodmFyKC0tcHJpbWFyeS1mb3JlZ3JvdW5kKSkiLAogICAgICAgIH0sCiAgICAgICAgc2Vjb25kYXJ5OiB7CiAgICAgICAgICBERUZBVUxUOiAiaHNsKHZhcigtLXNlY29uZGFyeSkpIiwKICAgICAgICAgIGZvcmVncm91bmQ6ICJoc2wodmFyKC0tc2Vjb25kYXJ5LWZvcmVncm91bmQpKSIsCiAgICAgICAgfSwKICAgICAgICBkZXN0cnVjdGl2ZTogewogICAgICAgICAgREVGQVVMVDogImhzbCh2YXIoLS1kZXN0cnVjdGl2ZSkpIiwKICAgICAgICAgIGZvcmVncm91bmQ6ICJoc2wodmFyKC0tZGVzdHJ1Y3RpdmUtZm9yZWdyb3VuZCkpIiwKICAgICAgICB9LAogICAgICAgIG11dGVkOiB7CiAgICAgICAgICBERUZBVUxUOiAiaHNsKHZhcigtLW11dGVkKSkiLAogICAgICAgICAgZm9yZWdyb3VuZDogImhzbCh2YXIoLS1tdXRlZC1mb3JlZ3JvdW5kKSkiLAogICAgICAgIH0sCiAgICAgICAgYWNjZW50OiB7CiAgICAgICAgICBERUZBVUxUOiAiaHNsKHZhcigtLWFjY2VudCkpIiwKICAgICAgICAgIGZvcmVncm91bmQ6ICJoc2wodmFyKC0tYWNjZW50LWZvcmVncm91bmQpKSIsCiAgICAgICAgfSwKICAgICAgICBjYXJkOiB7CiAgICAgICAgICBERUZBVUxUOiAiaHNsKHZhcigtLWNhcmQpKSIsCiAgICAgICAgICBmb3JlZ3JvdW5kOiAiaHNsKHZhcigtLWNhcmQtZm9yZWdyb3VuZCkpIiwKICAgICAgICB9LAogICAgICB9LAogICAgICBib3JkZXJSYWRpdXM6IHsKICAgICAgICBsZzogInZhcigtLXJhZGl1cykiLAogICAgICAgIG1kOiAiY2FsYyh2YXIoLS1yYWRpdXMpIC0gMnB4KSIsCiAgICAgICAgc206ICJjYWxjKHZhcigtLXJhZGl1cykgLSA0cHgpIiwKICAgICAgfSwKICAgICAgZm9udEZhbWlseTogewogICAgICAgIGRpc3BsYXk6IFsidmFyKC0tZm9udC1kaXNwbGF5KSIsICJ1aS1zZXJpZiIsICJHZW9yZ2lhIiwgInNlcmlmIl0sCiAgICAgICAgYm9keTogWyJ2YXIoLS1mb250LWJvZHkpIiwgInVpLXNhbnMtc2VyaWYiLCAic3lzdGVtLXVpIiwgInNhbnMtc2VyaWYiXSwKICAgICAgICBtb25vOiBbInZhcigtLWZvbnQtbW9ubykiLCAidWktbW9ub3NwYWNlIiwgIlNGTW9uby1SZWd1bGFyIiwgIm1vbm9zcGFjZSJdLAogICAgICB9LAogICAgICBrZXlmcmFtZXM6IHsKICAgICAgICAiYWNjb3JkaW9uLWRvd24iOiB7CiAgICAgICAgICBmcm9tOiB7IGhlaWdodDogIjAiIH0sCiAgICAgICAgICB0bzogeyBoZWlnaHQ6ICJ2YXIoLS1yYWRpeC1hY2NvcmRpb24tY29udGVudC1oZWlnaHQpIiB9LAogICAgICAgIH0sCiAgICAgICAgImFjY29yZGlvbi11cCI6IHsKICAgICAgICAgIGZyb206IHsgaGVpZ2h0OiAidmFyKC0tcmFkaXgtYWNjb3JkaW9uLWNvbnRlbnQtaGVpZ2h0KSIgfSwKICAgICAgICAgIHRvOiB7IGhlaWdodDogIjAiIH0sCiAgICAgICAgfSwKICAgICAgfSwKICAgICAgYW5pbWF0aW9uOiB7CiAgICAgICAgImFjY29yZGlvbi1kb3duIjogImFjY29yZGlvbi1kb3duIDAuMnMgZWFzZS1vdXQiLAogICAgICAgICJhY2NvcmRpb24tdXAiOiAiYWNjb3JkaW9uLXVwIDAuMnMgZWFzZS1vdXQiLAogICAgICB9LAogICAgfSwKICB9LAogIHBsdWdpbnM6IFthbmltYXRlXSwKfTsKCmV4cG9ydCBkZWZhdWx0IGNvbmZpZzsK",
|
|
20
|
+
"tsconfig.json": "ewogICJjb21waWxlck9wdGlvbnMiOiB7CiAgICAidGFyZ2V0IjogIkVTMjAyMiIsCiAgICAibGliIjogWyJkb20iLCAiZG9tLml0ZXJhYmxlIiwgImVzbmV4dCJdLAogICAgImFsbG93SnMiOiBmYWxzZSwKICAgICJza2lwTGliQ2hlY2siOiB0cnVlLAogICAgInN0cmljdCI6IHRydWUsCiAgICAibm9FbWl0IjogdHJ1ZSwKICAgICJlc01vZHVsZUludGVyb3AiOiB0cnVlLAogICAgIm1vZHVsZSI6ICJlc25leHQiLAogICAgIm1vZHVsZVJlc29sdXRpb24iOiAiYnVuZGxlciIsCiAgICAicmVzb2x2ZUpzb25Nb2R1bGUiOiB0cnVlLAogICAgImlzb2xhdGVkTW9kdWxlcyI6IHRydWUsCiAgICAianN4IjogInByZXNlcnZlIiwKICAgICJpbmNyZW1lbnRhbCI6IHRydWUsCiAgICAicGx1Z2lucyI6IFt7ICJuYW1lIjogIm5leHQiIH1dLAogICAgImJhc2VVcmwiOiAiLiIsCiAgICAicGF0aHMiOiB7ICJALyoiOiBbIi4vKiJdIH0KICB9LAogICJpbmNsdWRlIjogWyJuZXh0LWVudi5kLnRzIiwgIioqLyoudHMiLCAiKiovKi50c3giLCAiLm5leHQvdHlwZXMvKiovKi50cyJdLAogICJleGNsdWRlIjogWyJub2RlX21vZHVsZXMiXQp9Cg==",
|
|
21
|
+
};
|
package/dist/config.js
CHANGED
|
@@ -123,22 +123,33 @@ export function writeProjectLink(dir, link) {
|
|
|
123
123
|
const gitignorePath = join(linkDir, '.gitignore');
|
|
124
124
|
if (!existsSync(gitignorePath))
|
|
125
125
|
writeFileSync(gitignorePath, '*\n');
|
|
126
|
-
|
|
126
|
+
const clean = { ...link, projectId: projectIdFrom(link.projectId) };
|
|
127
|
+
writeFileSync(join(linkDir, 'project.json'), JSON.stringify(clean, null, 2) + '\n');
|
|
127
128
|
}
|
|
128
129
|
export function readProjectLink(dir) {
|
|
129
130
|
const path = join(dir, '.newly', 'project.json');
|
|
130
131
|
if (!existsSync(path))
|
|
131
132
|
return null;
|
|
132
133
|
try {
|
|
133
|
-
|
|
134
|
+
const link = JSON.parse(readFileSync(path, 'utf8'));
|
|
135
|
+
return typeof link.projectId === 'string' ? { ...link, projectId: projectIdFrom(link.projectId) } : link;
|
|
134
136
|
}
|
|
135
137
|
catch {
|
|
136
138
|
return null;
|
|
137
139
|
}
|
|
138
140
|
}
|
|
141
|
+
export function projectIdFrom(ref) {
|
|
142
|
+
const parts = ref.trim().split(/[?#]/)[0].split('/').filter(Boolean);
|
|
143
|
+
const at = parts.indexOf('projects');
|
|
144
|
+
return (at >= 0 ? parts[at + 1] : parts.at(-1)) ?? '';
|
|
145
|
+
}
|
|
139
146
|
export function resolveProject(dir, explicit) {
|
|
140
|
-
if (explicit)
|
|
141
|
-
|
|
147
|
+
if (explicit) {
|
|
148
|
+
const id = projectIdFrom(explicit);
|
|
149
|
+
if (!id)
|
|
150
|
+
throw new Error(`Not a project id: ${explicit}`);
|
|
151
|
+
return id;
|
|
152
|
+
}
|
|
142
153
|
const managedSessionProjectId = process.env['NEWLY_PROJECT_ID'];
|
|
143
154
|
if (managedSessionProjectId)
|
|
144
155
|
return managedSessionProjectId;
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ import { registerEnvironment } from './commands/environment.js';
|
|
|
24
24
|
import { registerAppStore } from './commands/appStore.js';
|
|
25
25
|
import { registerUpdate } from './commands/update.js';
|
|
26
26
|
import { registerToken } from './commands/token.js';
|
|
27
|
+
import { registerDogfood } from './commands/dogfood.js';
|
|
27
28
|
import { CLI_VERSION } from './version.js';
|
|
28
29
|
const program = new Command('newly')
|
|
29
30
|
.description('Develop, provision, and deploy Newly backends')
|
|
@@ -52,4 +53,5 @@ registerEnvironment(program);
|
|
|
52
53
|
registerAppStore(program);
|
|
53
54
|
registerUpdate(program);
|
|
54
55
|
registerToken(program);
|
|
56
|
+
registerDogfood(program);
|
|
55
57
|
await program.parseAsync(process.argv);
|
|
@@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
export const DEFAULT_BACKEND_SERVICES = [
|
|
4
4
|
{ name: 'api', path: 'api-service', type: 'worker', schema: 'api', secrets: 'api', public: true },
|
|
5
5
|
];
|
|
6
|
-
const SERVICE_NAME = /^[a-z][a-z0-9-]{0,31}$/;
|
|
6
|
+
const SERVICE_NAME = /^(?!prod-)[a-z][a-z0-9-]{0,31}$/;
|
|
7
7
|
export function readBackendServices(dir) {
|
|
8
8
|
const manifestPath = join(dir, 'backend', 'newly.services.json');
|
|
9
9
|
if (!existsSync(manifestPath))
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = '0.2.
|
|
1
|
+
export const CLI_VERSION = '0.2.188';
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -364,6 +364,7 @@ warm-parked and resumable is the most expensive mistake available here.
|
|
|
364
364
|
| `host-state-reconcile` | paused | the host had already parked it and the control plane caught up. The pause happened earlier than this event says |
|
|
365
365
|
| `host-reconcile` `reap-sweep` | destroyed | the platform reclaimed it |
|
|
366
366
|
| `boot-failure` `placement-timeout` `request-timeout` `scheduler` | never ran | capacity or image, not the workload |
|
|
367
|
+
| `orphaned-placement` | never ran | the control plane restarted while placing it (stuck in pending/starting); create it again |
|
|
367
368
|
| `image-built` `image-build-failure` | varies | an async image build finished or failed |
|
|
368
369
|
| `startup-recover` `volume-lease-invalid` `replica-fork-resume-failure` | varies | platform recovery paths |
|
|
369
370
|
|
package/runcloud-0.2.182.tgz
DELETED
|
Binary file
|