@absolutejs/absolute 0.20.0-beta.77 → 0.20.0-beta.79

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.
Files changed (35) hide show
  1. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  2. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  3. package/dist/build.js +41 -27
  4. package/dist/build.js.map +5 -5
  5. package/dist/cli/{buildDepVendor-521faxfs.js → buildDepVendor-rz5w5cp0.js} +18 -9
  6. package/dist/cli/{compile-1gkn94ek.js → compile-ee32zv39.js} +3 -3
  7. package/dist/cli/{dev-p8403w4q.js → dev-b1m7jp2t.js} +8 -8
  8. package/dist/cli/{expoDevController-787dw9bz.js → expoDevController-bdm4cq6m.js} +12 -6
  9. package/dist/cli/{expoProject-7mdpssp7.js → expoProject-c6tpj156.js} +2 -2
  10. package/dist/cli/{index-sghxp2cp.js → index-7q7wjgkq.js} +1 -1
  11. package/dist/cli/{index-jqc26p92.js → index-ar4gz15x.js} +3 -3
  12. package/dist/cli/{index-1twzwcga.js → index-eyx1hnm6.js} +23 -10
  13. package/dist/cli/{index-v0mxg0na.js → index-wt6kdy5f.js} +2 -2
  14. package/dist/cli/index.js +11 -6
  15. package/dist/cli/migrate-p4rp5r6b.js +521 -0
  16. package/dist/cli/{mobile-nymyq2t8.js → mobile-hyxr0n58.js} +4 -4
  17. package/dist/cli/{nativeAuth-kq81zgy3.js → nativeAuth-zx4tsb1f.js} +1 -1
  18. package/dist/cli/{start-yrhe9s4e.js → start-ty8jjzn8.js} +4 -4
  19. package/dist/cli/{workspace-weacygfv.js → workspace-h7czpaqh.js} +29 -2
  20. package/dist/index.js +41 -27
  21. package/dist/index.js.map +5 -5
  22. package/dist/mobile/index.js +49 -22
  23. package/dist/mobile/index.js.map +6 -6
  24. package/dist/mobile/remoteMacAgentEntry.js +62 -49
  25. package/dist/src/build/buildDepVendor.d.ts +1 -0
  26. package/dist/src/cli/scripts/migrate.d.ts +2 -0
  27. package/dist/src/cli/scripts/workspace.d.ts +14 -0
  28. package/dist/src/dev/moduleServer.d.ts +4 -0
  29. package/dist/src/migrate/detect.d.ts +25 -0
  30. package/dist/src/migrate/scan.d.ts +14 -0
  31. package/dist/src/migrate/substitutions.d.ts +37 -0
  32. package/dist/src/migrate/types.d.ts +40 -0
  33. package/dist/src/mobile/androidUpgradeConformance.d.ts +2 -0
  34. package/dist/src/mobile/nativeAuth.d.ts +3 -3
  35. package/package.json +3 -2
@@ -0,0 +1,521 @@
1
+ // @bun
2
+ import {
3
+ colors
4
+ } from "./index-8nym68py.js";
5
+ import"./index-czwrxgdj.js";
6
+ import"./index-mywsk201.js";
7
+
8
+ // src/migrate/detect.ts
9
+ var CONFIDENT = 0.7;
10
+ var DEPENDENCY_SIGNALS = [
11
+ ["@absolutejs/absolute", "absolutejs"],
12
+ ["next", "nextjs"],
13
+ ["nuxt", "nuxt"],
14
+ ["@remix-run/react", "remix"],
15
+ ["@remix-run/node", "remix"],
16
+ ["@sveltejs/kit", "sveltekit"],
17
+ ["astro", "astro"],
18
+ ["react-scripts", "create-react-app"],
19
+ ["vite", "vite"]
20
+ ];
21
+ var FILE_SIGNALS = [
22
+ ["absolute.config.ts", "absolutejs"],
23
+ ["absolute.config.js", "absolutejs"],
24
+ ["next.config.js", "nextjs"],
25
+ ["next.config.mjs", "nextjs"],
26
+ ["next.config.ts", "nextjs"],
27
+ ["nuxt.config.ts", "nuxt"],
28
+ ["remix.config.js", "remix"],
29
+ ["svelte.config.js", "sveltekit"],
30
+ ["astro.config.mjs", "astro"],
31
+ ["vite.config.ts", "vite"],
32
+ ["vite.config.js", "vite"]
33
+ ];
34
+ var DEPENDENCY_WEIGHT = 0.75;
35
+ var FILE_WEIGHT = 0.3;
36
+ var CERTAIN = 1;
37
+ var STACK_PRECEDENCE = [
38
+ "absolutejs",
39
+ "nextjs",
40
+ "nuxt",
41
+ "remix",
42
+ "sveltekit",
43
+ "astro",
44
+ "create-react-app",
45
+ "vite",
46
+ "unknown"
47
+ ];
48
+ var AMBIGUITY_PENALTY = 0.3;
49
+ var dependencyNames = (manifest) => {
50
+ if (!manifest)
51
+ return new Set;
52
+ return new Set([
53
+ ...Object.keys(manifest.dependencies ?? {}),
54
+ ...Object.keys(manifest.devDependencies ?? {}),
55
+ ...Object.keys(manifest.peerDependencies ?? {})
56
+ ]);
57
+ };
58
+ var SUBSUMED_BY_OTHERS = new Set(["vite"]);
59
+ var scoreSignals = (present, signals, weight, label) => {
60
+ const scores = new Map;
61
+ const evidence = [];
62
+ for (const [name, kind] of signals) {
63
+ if (!present(name))
64
+ continue;
65
+ scores.set(kind, (scores.get(kind) ?? 0) + weight);
66
+ evidence.push(label(name));
67
+ }
68
+ return { evidence, scores };
69
+ };
70
+ var merge = (into, from) => {
71
+ for (const [kind, score] of from) {
72
+ into.set(kind, (into.get(kind) ?? 0) + score);
73
+ }
74
+ return into;
75
+ };
76
+ var detectStack = ({
77
+ manifest,
78
+ files
79
+ }) => {
80
+ const dependencies = dependencyNames(manifest);
81
+ const names = new Set(files.map((file) => file.split("/").pop() ?? file));
82
+ const fromDependencies = scoreSignals((name) => dependencies.has(name), DEPENDENCY_SIGNALS, DEPENDENCY_WEIGHT, (name) => ({
83
+ detail: `depends on ${name}`,
84
+ source: "package.json"
85
+ }));
86
+ const fromFiles = scoreSignals((name) => names.has(name), FILE_SIGNALS, FILE_WEIGHT, (name) => ({ detail: "config file present", source: name }));
87
+ const scores = merge(new Map(fromDependencies.scores), fromFiles.scores);
88
+ const decisive = [...scores.keys()].some((kind2) => !SUBSUMED_BY_OTHERS.has(kind2));
89
+ if (decisive) {
90
+ for (const kind2 of SUBSUMED_BY_OTHERS)
91
+ scores.delete(kind2);
92
+ }
93
+ const rank = (kind2) => {
94
+ const index = STACK_PRECEDENCE.indexOf(kind2);
95
+ return index === -1 ? STACK_PRECEDENCE.length : index;
96
+ };
97
+ const ranked = [...scores.entries()].sort(([leftKind, left], [rightKind, right]) => right - left || rank(leftKind) - rank(rightKind));
98
+ const [top] = ranked;
99
+ if (!top) {
100
+ return {
101
+ alternates: [],
102
+ confidence: 0,
103
+ evidence: [],
104
+ kind: "unknown"
105
+ };
106
+ }
107
+ const [kind, score] = top;
108
+ const [, runnerUpScore] = ranked[1] ?? [];
109
+ const ambiguous = runnerUpScore === score;
110
+ return {
111
+ alternates: ranked.slice(1).map(([alternate]) => alternate),
112
+ confidence: Math.max(0, Math.min(score, CERTAIN) - (ambiguous ? AMBIGUITY_PENALTY : 0)),
113
+ evidence: [...fromDependencies.evidence, ...fromFiles.evidence],
114
+ kind
115
+ };
116
+ };
117
+
118
+ // src/migrate/scan.ts
119
+ import { existsSync, readdirSync, readFileSync, statSync } from "fs";
120
+ import { join, relative } from "path";
121
+ // src/migrate/catalogSnapshot.json
122
+ var catalogSnapshot_default = {
123
+ comment: "Snapshot of first-party package names, used to validate migration suggestions offline. Studio passes its live catalog instead; regenerate with scripts/generateCatalog.ts in the Studio repo.",
124
+ generatedFrom: "@absolutejs/studio packageCatalog.json contract 2",
125
+ names: [
126
+ "@absolutejs/a2a",
127
+ "@absolutejs/agency",
128
+ "@absolutejs/agent",
129
+ "@absolutejs/agent-conformance",
130
+ "@absolutejs/agent-control",
131
+ "@absolutejs/agent-discovery",
132
+ "@absolutejs/agent-inbox",
133
+ "@absolutejs/agent-memory",
134
+ "@absolutejs/agent-reputation",
135
+ "@absolutejs/agent-runtime",
136
+ "@absolutejs/agent-sandbox",
137
+ "@absolutejs/agent-trust",
138
+ "@absolutejs/agents-mcp",
139
+ "@absolutejs/arazzo",
140
+ "@absolutejs/artifacts",
141
+ "@absolutejs/audience",
142
+ "@absolutejs/audit",
143
+ "@absolutejs/audit-elysia",
144
+ "@absolutejs/audit-postgres",
145
+ "@absolutejs/audit-s3",
146
+ "@absolutejs/auth",
147
+ "@absolutejs/beacon",
148
+ "@absolutejs/billing",
149
+ "@absolutejs/blob",
150
+ "@absolutejs/collectibles",
151
+ "@absolutejs/commerce",
152
+ "@absolutejs/commerce-customcat",
153
+ "@absolutejs/commerce-easypost",
154
+ "@absolutejs/commerce-resend",
155
+ "@absolutejs/commerce-stripe",
156
+ "@absolutejs/compliance",
157
+ "@absolutejs/crm",
158
+ "@absolutejs/discover",
159
+ "@absolutejs/dispatch",
160
+ "@absolutejs/dispatch-apns",
161
+ "@absolutejs/dispatch-fcm",
162
+ "@absolutejs/dispatch-postmark",
163
+ "@absolutejs/dispatch-resend",
164
+ "@absolutejs/dispatch-telnyx",
165
+ "@absolutejs/dispatch-twilio",
166
+ "@absolutejs/egress",
167
+ "@absolutejs/email",
168
+ "@absolutejs/engagement",
169
+ "@absolutejs/engagement-apollo",
170
+ "@absolutejs/enrich",
171
+ "@absolutejs/errors",
172
+ "@absolutejs/errors-postgres",
173
+ "@absolutejs/execution",
174
+ "@absolutejs/git",
175
+ "@absolutejs/health",
176
+ "@absolutejs/incidents",
177
+ "@absolutejs/logs",
178
+ "@absolutejs/marketplace",
179
+ "@absolutejs/mcp",
180
+ "@absolutejs/media",
181
+ "@absolutejs/meeting",
182
+ "@absolutejs/meeting-discord",
183
+ "@absolutejs/meeting-recall",
184
+ "@absolutejs/metering",
185
+ "@absolutejs/metrics",
186
+ "@absolutejs/observability",
187
+ "@absolutejs/onchain",
188
+ "@absolutejs/onchain-base",
189
+ "@absolutejs/outcomes",
190
+ "@absolutejs/partnership",
191
+ "@absolutejs/policy",
192
+ "@absolutejs/pwa",
193
+ "@absolutejs/queue",
194
+ "@absolutejs/queue-postgres",
195
+ "@absolutejs/queue-redis",
196
+ "@absolutejs/rag",
197
+ "@absolutejs/rag-pinecone",
198
+ "@absolutejs/rag-postgres",
199
+ "@absolutejs/rag-sqlite",
200
+ "@absolutejs/rate-limit",
201
+ "@absolutejs/reliability",
202
+ "@absolutejs/renown",
203
+ "@absolutejs/replay",
204
+ "@absolutejs/rules",
205
+ "@absolutejs/scoped-state",
206
+ "@absolutejs/secrets",
207
+ "@absolutejs/site-admin",
208
+ "@absolutejs/sync",
209
+ "@absolutejs/sync-automerge",
210
+ "@absolutejs/sync-bus-pg",
211
+ "@absolutejs/sync-bus-redis",
212
+ "@absolutejs/sync-loro",
213
+ "@absolutejs/sync-pack-comments",
214
+ "@absolutejs/sync-pack-counters",
215
+ "@absolutejs/sync-pack-digest",
216
+ "@absolutejs/sync-pack-favorites",
217
+ "@absolutejs/sync-pack-mentions",
218
+ "@absolutejs/sync-pack-notifications",
219
+ "@absolutejs/sync-pack-presence",
220
+ "@absolutejs/sync-pack-utils",
221
+ "@absolutejs/sync-yjs",
222
+ "@absolutejs/tour",
223
+ "@absolutejs/voice",
224
+ "@absolutejs/voice-assemblyai",
225
+ "@absolutejs/voice-azure",
226
+ "@absolutejs/voice-cartesia",
227
+ "@absolutejs/voice-deepgram",
228
+ "@absolutejs/voice-elevenlabs",
229
+ "@absolutejs/voice-gemini",
230
+ "@absolutejs/voice-gladia",
231
+ "@absolutejs/voice-google-speech",
232
+ "@absolutejs/voice-lmnt",
233
+ "@absolutejs/voice-neets",
234
+ "@absolutejs/voice-openai",
235
+ "@absolutejs/voice-openai-whisper",
236
+ "@absolutejs/voice-playht",
237
+ "@absolutejs/voice-rime",
238
+ "@absolutejs/voice-smallest",
239
+ "@absolutejs/voice-soniox",
240
+ "@absolutejs/voice-speechmatics",
241
+ "@absolutejs/vulnerabilities",
242
+ "@absolutejs/vulnerabilities-epss",
243
+ "@absolutejs/vulnerabilities-kev",
244
+ "@absolutejs/vulnerabilities-osv",
245
+ "@absolutejs/vulnerabilities-postgres",
246
+ "@absolutejs/vulnerabilities-report",
247
+ "@absolutejs/vulnerabilities-ubuntu",
248
+ "@absolutejs/vulnerabilities-witness",
249
+ "@absolutejs/vulnerabilities-worker",
250
+ "@absolutejs/wallet",
251
+ "@absolutejs/wallet-stripe",
252
+ "@absolutejs/webmcp"
253
+ ]
254
+ };
255
+
256
+ // src/migrate/substitutions.ts
257
+ var DEFAULT_SUBSTITUTION_RULES = [
258
+ {
259
+ from: "next-auth",
260
+ rationale: "Sessions, OAuth providers, MFA and passkeys, wired to the same request context.",
261
+ to: "@absolutejs/auth"
262
+ },
263
+ {
264
+ from: "bullmq",
265
+ rationale: "Durable job queue with a Postgres or Redis adapter instead of a required Redis.",
266
+ to: "@absolutejs/queue"
267
+ },
268
+ {
269
+ from: "bull",
270
+ rationale: "Durable job queue with first-party adapters.",
271
+ to: "@absolutejs/queue"
272
+ },
273
+ {
274
+ from: "@sentry/node",
275
+ rationale: "Error capture, session replay and symbolication without a third-party account.",
276
+ to: "@absolutejs/errors"
277
+ },
278
+ {
279
+ from: "@sentry/browser",
280
+ rationale: "Browser error capture reported through the same pipeline.",
281
+ to: "@absolutejs/beacon"
282
+ },
283
+ {
284
+ from: "web-vitals",
285
+ rationale: "Real-user vitals already collected by the framework client.",
286
+ to: "@absolutejs/beacon"
287
+ },
288
+ {
289
+ from: "nodemailer",
290
+ rationale: "Transactional send with swappable Resend, Postmark or SMTP adapters.",
291
+ to: "@absolutejs/dispatch"
292
+ },
293
+ {
294
+ from: "resend",
295
+ rationale: "Same provider, behind an adapter you can change without touching call sites.",
296
+ to: "@absolutejs/dispatch-resend"
297
+ },
298
+ {
299
+ from: "stripe",
300
+ rationale: "Checkout, subscriptions and webhooks with the ledger already modelled.",
301
+ to: "@absolutejs/commerce-stripe"
302
+ },
303
+ {
304
+ from: "@aws-sdk/client-s3",
305
+ rationale: "Object storage with presigning and lifecycle handled for you.",
306
+ to: "@absolutejs/blob"
307
+ },
308
+ {
309
+ from: "yjs",
310
+ rationale: "Collaborative state with presence, comments and history packs included.",
311
+ to: "@absolutejs/sync"
312
+ },
313
+ {
314
+ from: "zustand",
315
+ rationale: "Scoped client state that survives island boundaries.",
316
+ to: "@absolutejs/scoped-state"
317
+ },
318
+ {
319
+ from: "express-rate-limit",
320
+ rationale: "Rate limiting applied at the route contract.",
321
+ to: "@absolutejs/rate-limit"
322
+ },
323
+ {
324
+ from: "pino",
325
+ rationale: "Structured logging that joins the observability pipeline.",
326
+ to: "@absolutejs/logs"
327
+ },
328
+ {
329
+ from: "winston",
330
+ rationale: "Structured logging that joins the observability pipeline.",
331
+ to: "@absolutejs/logs"
332
+ }
333
+ ];
334
+ var planSubstitutions = ({
335
+ dependencies,
336
+ importsByPackage = {},
337
+ catalog,
338
+ rules = DEFAULT_SUBSTITUTION_RULES
339
+ }) => {
340
+ const declared = new Set(dependencies);
341
+ const available = new Set(catalog.map((entry) => entry.name));
342
+ return rules.filter((rule) => declared.has(rule.from) && available.has(rule.to)).map((rule) => ({
343
+ from: rule.from,
344
+ rationale: rule.rationale,
345
+ to: rule.to,
346
+ usedIn: [...importsByPackage[rule.from] ?? []]
347
+ })).sort((left, right) => right.usedIn.length - left.usedIn.length || left.from.localeCompare(right.from));
348
+ };
349
+
350
+ // src/migrate/scan.ts
351
+ var SKIP_DIRECTORIES = new Set([
352
+ ".git",
353
+ ".next",
354
+ ".turbo",
355
+ "build",
356
+ "coverage",
357
+ "dist",
358
+ "node_modules",
359
+ "out"
360
+ ]);
361
+ var SOURCE_EXTENSIONS = [
362
+ ".ts",
363
+ ".tsx",
364
+ ".js",
365
+ ".jsx",
366
+ ".mjs",
367
+ ".vue",
368
+ ".svelte"
369
+ ];
370
+ var MAX_FILES = 5000;
371
+ var isSource = (file) => SOURCE_EXTENSIONS.some((extension) => file.endsWith(extension));
372
+ var entriesOf = (directory) => {
373
+ try {
374
+ return readdirSync(directory);
375
+ } catch {
376
+ return [];
377
+ }
378
+ };
379
+ var isDirectory = (path) => {
380
+ try {
381
+ return statSync(path).isDirectory();
382
+ } catch {
383
+ return false;
384
+ }
385
+ };
386
+ var textOf = (path) => {
387
+ try {
388
+ return readFileSync(path, "utf-8");
389
+ } catch {
390
+ return "";
391
+ }
392
+ };
393
+ var walkOne = (root, directory) => entriesOf(directory).reduce((carry, entry) => {
394
+ if (SKIP_DIRECTORIES.has(entry))
395
+ return carry;
396
+ const absolute = join(directory, entry);
397
+ if (isDirectory(absolute)) {
398
+ carry.directories.push(absolute);
399
+ return carry;
400
+ }
401
+ carry.files.push(relative(root, absolute));
402
+ return carry;
403
+ }, { directories: [], files: [] });
404
+ var listProjectFiles = (root, limit = MAX_FILES) => {
405
+ const found = [];
406
+ const queue = [root];
407
+ while (queue.length > 0 && found.length < limit) {
408
+ const directory = queue.shift();
409
+ if (directory === undefined)
410
+ break;
411
+ const walk = walkOne(root, directory);
412
+ queue.push(...walk.directories);
413
+ found.push(...walk.files.slice(0, limit - found.length));
414
+ }
415
+ return found;
416
+ };
417
+ var isRecord = (value) => typeof value === "object" && value !== null;
418
+ var sectionNames = (value) => isRecord(value) ? Object.keys(value) : [];
419
+ var readManifest = (root) => {
420
+ const path = join(root, "package.json");
421
+ if (!existsSync(path))
422
+ return null;
423
+ const parsed = JSON.parse(textOf(path) || "null");
424
+ if (!isRecord(parsed))
425
+ return null;
426
+ return parsed;
427
+ };
428
+ var declaredDependencies = (manifest) => {
429
+ if (!manifest)
430
+ return [];
431
+ const source = manifest;
432
+ return ["dependencies", "devDependencies", "peerDependencies"].flatMap((section) => sectionNames(source[section]));
433
+ };
434
+ var importsInFile = (text, packages) => packages.filter((name) => text.includes(`'${name}`) || text.includes(`"${name}`));
435
+ var findImporters = (root, files, packages) => files.filter(isSource).reduce((carry, file) => {
436
+ for (const name of importsInFile(textOf(join(root, file)), packages)) {
437
+ carry[name] = [...carry[name] ?? [], file];
438
+ }
439
+ return carry;
440
+ }, {});
441
+ var scanProject = (root, { catalog, rules } = {}) => {
442
+ const manifest = readManifest(root);
443
+ const files = listProjectFiles(root);
444
+ const dependencies = declaredDependencies(manifest);
445
+ const resolvedCatalog = catalog ?? catalogSnapshot_default.names.map((name) => ({ name }));
446
+ return {
447
+ detection: detectStack({ files, manifest }),
448
+ substitutions: planSubstitutions({
449
+ catalog: resolvedCatalog,
450
+ dependencies,
451
+ importsByPackage: findImporters(root, files, dependencies),
452
+ rules
453
+ })
454
+ };
455
+ };
456
+
457
+ // src/cli/scripts/migrate.ts
458
+ var PERCENT = 100;
459
+ var paint = (code, text) => `${code}${text}${colors.reset}`;
460
+ var bold = (text) => paint(colors.bold, text);
461
+ var dim = (text) => paint(colors.dim, text);
462
+ var warn = (text) => paint(colors.yellow, text);
463
+ var stackLabel = {
464
+ absolutejs: "AbsoluteJS",
465
+ astro: "Astro",
466
+ "create-react-app": "Create React App",
467
+ nextjs: "Next.js",
468
+ nuxt: "Nuxt",
469
+ remix: "Remix",
470
+ sveltekit: "SvelteKit",
471
+ unknown: "not recognised",
472
+ vite: "Vite"
473
+ };
474
+ var renderDetection = (plan) => {
475
+ const { detection } = plan;
476
+ const percent = Math.round(detection.confidence * PERCENT);
477
+ const label = stackLabel[detection.kind] ?? detection.kind;
478
+ const lines = [`
479
+ Stack: ${bold(label)} (${percent}% confident)`];
480
+ for (const item of detection.evidence.slice(0, 4)) {
481
+ lines.push(dim(` ${item.source} \u2014 ${item.detail}`));
482
+ }
483
+ if (detection.alternates.length > 0) {
484
+ lines.push(dim(` also matched: ${detection.alternates.join(", ")}`));
485
+ }
486
+ if (detection.confidence < CONFIDENT && detection.kind !== "unknown") {
487
+ lines.push(warn(" Low confidence \u2014 confirm the stack before migrating."));
488
+ }
489
+ return lines.join(`
490
+ `);
491
+ };
492
+ var renderSubstitutions = (plan) => {
493
+ const { substitutions } = plan;
494
+ if (substitutions.length === 0) {
495
+ return `
496
+ ${dim("No first-party substitutions found.")}`;
497
+ }
498
+ const lines = [
499
+ `
500
+ ${bold(String(substitutions.length))} dependencies have a first-party equivalent:`
501
+ ];
502
+ for (const item of substitutions) {
503
+ const where = item.usedIn.length > 0 ? `${item.usedIn.length} file${item.usedIn.length === 1 ? "" : "s"}` : "declared, never imported";
504
+ lines.push(` ${item.from} \u2192 ${bold(item.to)} ${dim(`(${where})`)}`);
505
+ lines.push(dim(` ${item.rationale}`));
506
+ }
507
+ lines.push(dim(`
508
+ Nothing was changed. This command only reports; apply the swaps yourself
509
+ or let Studio propose them as a reviewable diff.`));
510
+ return lines.join(`
511
+ `);
512
+ };
513
+ var migrate = (root = process.cwd()) => {
514
+ const plan = scanProject(root);
515
+ console.log(renderDetection(plan));
516
+ console.log(renderSubstitutions(plan));
517
+ console.log("");
518
+ };
519
+ export {
520
+ migrate
521
+ };
@@ -4,12 +4,12 @@ import {
4
4
  } from "./index-zh6hhrwy.js";
5
5
  import {
6
6
  start
7
- } from "./index-v0mxg0na.js";
7
+ } from "./index-wt6kdy5f.js";
8
8
  import {
9
9
  ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
10
10
  ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
11
11
  resolveAbsoluteMobileRoute
12
- } from "./index-sghxp2cp.js";
12
+ } from "./index-7q7wjgkq.js";
13
13
  import"./index-bzs19w3r.js";
14
14
  import"./index-s2tazax7.js";
15
15
  import {
@@ -63,14 +63,14 @@ import {
63
63
  syncAbsoluteExpoWebAssets,
64
64
  unsignedAbsoluteMobileUpdate,
65
65
  writeAbsoluteExpoProject
66
- } from "./index-1twzwcga.js";
66
+ } from "./index-eyx1hnm6.js";
67
67
  import {
68
68
  normalizeAbsoluteIosDeviceIdentifier
69
69
  } from "./index-j66p8hn5.js";
70
70
  import {
71
71
  projectUsesAbsoluteAuth,
72
72
  projectUsesAbsoluteSync
73
- } from "./index-jqc26p92.js";
73
+ } from "./index-ar4gz15x.js";
74
74
  import {
75
75
  buildAbsoluteAndroidGradleArtifact,
76
76
  fingerprintAbsoluteAndroidNativeProject,
@@ -16,7 +16,7 @@ import {
16
16
  projectUsesAbsoluteSync,
17
17
  resolveAbsoluteMobileAuthManifest,
18
18
  serializeAbsoluteMobileAuthEnvironment
19
- } from "./index-jqc26p92.js";
19
+ } from "./index-ar4gz15x.js";
20
20
  import"./index-mywsk201.js";
21
21
  export {
22
22
  ABSOLUTE_AUTH_PACKAGE,
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  start
4
- } from "./index-v0mxg0na.js";
5
- import"./index-sghxp2cp.js";
4
+ } from "./index-wt6kdy5f.js";
5
+ import"./index-7q7wjgkq.js";
6
6
  import"./index-bzs19w3r.js";
7
7
  import"./index-s2tazax7.js";
8
8
  import"./index-fc9vxw56.js";
@@ -11,8 +11,8 @@ import"./index-06cmrcdq.js";
11
11
  import"./index-9kwmb3c0.js";
12
12
  import"./index-w5vswatm.js";
13
13
  import"./index-6fb7k6dg.js";
14
- import"./index-1twzwcga.js";
15
- import"./index-jqc26p92.js";
14
+ import"./index-eyx1hnm6.js";
15
+ import"./index-ar4gz15x.js";
16
16
  import"./index-t84wxk1p.js";
17
17
  import"./index-wtfnv3n2.js";
18
18
  import"./index-prwyfnn3.js";
@@ -1104,6 +1104,20 @@ var warnForSharedBuildDirectories = (services, addLog) => {
1104
1104
  addLog("workspace", `Services ${names.map((name) => `"${name}"`).join(" and ")} resolve to the same buildDirectory: ${buildDirectory}. Builds will be serialized and the last completed build will own that directory.`, "warn");
1105
1105
  }
1106
1106
  };
1107
+ var startWorkspaceOrShutDown = async ({
1108
+ onFailure,
1109
+ shutdown,
1110
+ start
1111
+ }) => {
1112
+ try {
1113
+ await start();
1114
+ return true;
1115
+ } catch (error) {
1116
+ onFailure(error instanceof Error ? error.message : String(error));
1117
+ await shutdown(1);
1118
+ return false;
1119
+ }
1120
+ };
1107
1121
  var workspace = async (subcommand, options) => {
1108
1122
  if (subcommand !== "dev") {
1109
1123
  throw new Error(subcommand ? `Unknown workspace command: ${subcommand}` : "No workspace subcommand specified. Use `absolute workspace dev`.");
@@ -1337,7 +1351,13 @@ var workspace = async (subcommand, options) => {
1337
1351
  await killProcesses();
1338
1352
  restarting = false;
1339
1353
  workspaceBootStartedAt = performance.now();
1340
- await startServices();
1354
+ const restarted = await startWorkspaceOrShutDown({
1355
+ shutdown,
1356
+ start: startServices,
1357
+ onFailure: (message) => addLog("workspace", `Workspace failed to restart: ${message}`, "error")
1358
+ });
1359
+ if (!restarted)
1360
+ return;
1341
1361
  tui.setReadyDuration(performance.now() - workspaceBootStartedAt);
1342
1362
  };
1343
1363
  const togglePause = () => {
@@ -1402,12 +1422,19 @@ var workspace = async (subcommand, options) => {
1402
1422
  shutdown(0);
1403
1423
  });
1404
1424
  tui.start();
1405
- await startServices();
1425
+ const started = await startWorkspaceOrShutDown({
1426
+ shutdown,
1427
+ start: startServices,
1428
+ onFailure: (message) => addLog("workspace", `Workspace failed to start: ${message}`, "error")
1429
+ });
1430
+ if (!started)
1431
+ return;
1406
1432
  tui.setReadyDuration(performance.now() - workspaceBootStartedAt);
1407
1433
  await Promise.withResolvers().promise;
1408
1434
  };
1409
1435
  export {
1410
1436
  findSharedWorkspaceBuildDirectories,
1411
1437
  resolveWorkspaceServicePort,
1438
+ startWorkspaceOrShutDown,
1412
1439
  workspace
1413
1440
  };