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.
@@ -481,7 +481,7 @@ export function registerBuild(program) {
481
481
  }
482
482
  const { client } = makeClient();
483
483
  const projectId = opts.remoteSource
484
- ? opts.project || readProjectLink(opts.sourcePath ?? '.')?.projectId
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
+ }
@@ -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((projectId) => {
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,
@@ -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')
@@ -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
- writeFileSync(join(linkDir, 'project.json'), JSON.stringify(link, null, 2) + '\n');
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
- return JSON.parse(readFileSync(path, 'utf8'));
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
- return explicit;
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.182';
1
+ export const CLI_VERSION = '0.2.188';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.2.182",
3
+ "version": "0.2.188",
4
4
  "description": "Create and control run.cloud remote mobile simulators and cloud sandboxes",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
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
 
Binary file