@expo/cli 55.0.24 → 55.0.26
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/build/bin/cli +1 -1
- package/build/src/events/index.js +2 -9
- package/build/src/events/index.js.map +1 -1
- package/build/src/events/stream.js +94 -24
- package/build/src/events/stream.js.map +1 -1
- package/build/src/prebuild/clearNativeFolder.js +38 -0
- package/build/src/prebuild/clearNativeFolder.js.map +1 -1
- package/build/src/prebuild/prebuildAsync.js +4 -0
- package/build/src/prebuild/prebuildAsync.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +9 -11
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/metroWatchTypeScriptFiles.js +48 -16
- package/build/src/start/server/metro/metroWatchTypeScriptFiles.js.map +1 -1
- package/build/src/start/server/metro/waitForMetroToObserveTypeScriptFile.js +32 -30
- package/build/src/start/server/metro/waitForMetroToObserveTypeScriptFile.js.map +1 -1
- package/build/src/start/server/metro/withMetroMultiPlatform.js +2 -0
- package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
- package/build/src/start/server/middleware/ManifestMiddleware.js +12 -3
- package/build/src/start/server/middleware/ManifestMiddleware.js.map +1 -1
- package/build/src/start/server/type-generation/routes.js +1 -0
- package/build/src/start/server/type-generation/routes.js.map +1 -1
- package/build/src/utils/tar.js +3 -2
- package/build/src/utils/tar.js.map +1 -1
- package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/package.json +10 -10
package/build/bin/cli
CHANGED
|
@@ -70,7 +70,7 @@ function getInitMetadata() {
|
|
|
70
70
|
return {
|
|
71
71
|
format: 'v0-jsonl',
|
|
72
72
|
// Version is added in the build script.
|
|
73
|
-
version: "55.0.
|
|
73
|
+
version: "55.0.26" ?? 'UNVERSIONED'
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
function installEventLogger(env = process.env.LOG_EVENTS) {
|
|
@@ -100,14 +100,7 @@ const shouldReduceLogs = ()=>!!logStream && _env.env.EXPO_UNSTABLE_HEADLESS;
|
|
|
100
100
|
const events = (category, _fn)=>{
|
|
101
101
|
function log(event, data) {
|
|
102
102
|
if (logStream) {
|
|
103
|
-
|
|
104
|
-
const _t = Date.now();
|
|
105
|
-
const payload = JSON.stringify({
|
|
106
|
-
_e,
|
|
107
|
-
_t,
|
|
108
|
-
...data
|
|
109
|
-
});
|
|
110
|
-
logStream._write(payload + '\n');
|
|
103
|
+
(0, _stream.writeEvent)(logStream, category, event, data);
|
|
111
104
|
}
|
|
112
105
|
}
|
|
113
106
|
log.category = category;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/events/index.ts"],"sourcesContent":["import { Console } from 'node:console';\nimport path from 'node:path';\n\nimport type { EventBuilder, EventLoggerBuilder, EventShape } from './builder';\nimport { LogStream } from './stream';\nimport { env } from '../utils/env';\n\ninterface InitMetadata {\n format: 'v0-jsonl' | (string & {});\n version: string;\n}\n\nlet logPath = process.cwd();\nlet logStream: LogStream | undefined;\n\nfunction parseLogTarget(env: string | undefined) {\n let logDestination: string | number | undefined;\n if (env) {\n const fd = parseInt(env, 10);\n if (fd > 0 && Number.isSafeInteger(fd)) {\n logDestination = fd;\n } else {\n try {\n const parsedPath = path.parse(env);\n logDestination = path.format(parsedPath);\n logPath = parsedPath.dir;\n } catch {\n logDestination = undefined;\n }\n }\n }\n return logDestination;\n}\n\nfunction getInitMetadata(): InitMetadata {\n return {\n format: 'v0-jsonl',\n // Version is added in the build script.\n version: process.env.__EXPO_VERSION ?? 'UNVERSIONED',\n };\n}\n\n/** Activates the event logger based on the input env var\n * @param env - The target to write the logs to; defaults to `$LOG_EVENTS`\n */\nexport function installEventLogger(env = process.env.LOG_EVENTS) {\n const eventLogDestination = parseLogTarget(env);\n if (eventLogDestination) {\n if (eventLogDestination === 1) {\n // Reuse Node's existing stdio streams so redirected or piped terminals don't\n // attempt TTY-only initialization when LOG_EVENTS swaps console output.\n const output = process.stderr;\n Object.defineProperty(process, 'stdout', { get: () => output });\n globalThis.console = new Console(output, output);\n } else if (eventLogDestination === 2) {\n const output = process.stdout;\n Object.defineProperty(process, 'stderr', { get: () => output });\n globalThis.console = new Console(output, output);\n }\n logStream = new LogStream(eventLogDestination);\n rootEvent('init', getInitMetadata());\n }\n}\n\n/** Returns whether the event logger is active */\nexport const isEventLoggerActive = () => !!logStream?.writable;\n\n/** Whether logs shown in the terminal should be reduced.\n * @remarks\n * We indicate that we're in an automated tool (e.g. E2E tests) with `EXPO_UNSTABLE_HEADLESS`.\n * If the event logger is activate and we're running in a headless tool, we should reduce\n * interactive or noisy logs, in favour of the event logger.\n */\nexport const shouldReduceLogs = () => !!logStream && env.EXPO_UNSTABLE_HEADLESS;\n\n/** Used to create an event logger for structured JSONL logs activated with the `LOG_EVENTS` environment variable.\n *\n * @remarks\n * Structured logs are streamed to a JSONL output file or file descriptor, and are meant for automated tooling\n * or normal usage to document what happened during a user session. When creating a module that outputs errors,\n * events, or captures what the user was doing, create a new event logger category for them and add structured\n * log events.\n * For example, `../start/server/metro/MetroTerminalReporter` captures most of Metro's logged events.\n * Structured JSONL logs don't have a large performance impact, unlike `DEBUG` logs, and are easily parseable\n * and filterable, including by wrapper processes.\n *\n * After adding a new event category, don't forget to add it to `./types.ts` to collect all event shape types\n * in one place.\n *\n * @example\n * ```ts\n * export const event = events('test', (t) => [\n * t.event<'my_event', {\n * myValue: string | null;\n * }>(),\n * ]);\n *\n * event('my_event', { myValue: 'test' });\n * ```\n *\n * This will log a `{ _e: 'test:my_event', _t: 0, myValue: 'test' }` entry in the event log.\n */\nexport const events: EventLoggerBuilder = ((\n category: string,\n _fn: (builder: EventBuilder) => readonly EventShape<string>[]\n) => {\n function log(event: string, data: any) {\n if (logStream) {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/events/index.ts"],"sourcesContent":["import { Console } from 'node:console';\nimport path from 'node:path';\n\nimport type { EventBuilder, EventLoggerBuilder, EventShape } from './builder';\nimport { LogStream, writeEvent } from './stream';\nimport { env } from '../utils/env';\n\ninterface InitMetadata {\n format: 'v0-jsonl' | (string & {});\n version: string;\n}\n\nlet logPath = process.cwd();\nlet logStream: LogStream | undefined;\n\nfunction parseLogTarget(env: string | undefined) {\n let logDestination: string | number | undefined;\n if (env) {\n const fd = parseInt(env, 10);\n if (fd > 0 && Number.isSafeInteger(fd)) {\n logDestination = fd;\n } else {\n try {\n const parsedPath = path.parse(env);\n logDestination = path.format(parsedPath);\n logPath = parsedPath.dir;\n } catch {\n logDestination = undefined;\n }\n }\n }\n return logDestination;\n}\n\nfunction getInitMetadata(): InitMetadata {\n return {\n format: 'v0-jsonl',\n // Version is added in the build script.\n version: process.env.__EXPO_VERSION ?? 'UNVERSIONED',\n };\n}\n\n/** Activates the event logger based on the input env var\n * @param env - The target to write the logs to; defaults to `$LOG_EVENTS`\n */\nexport function installEventLogger(env = process.env.LOG_EVENTS) {\n const eventLogDestination = parseLogTarget(env);\n if (eventLogDestination) {\n if (eventLogDestination === 1) {\n // Reuse Node's existing stdio streams so redirected or piped terminals don't\n // attempt TTY-only initialization when LOG_EVENTS swaps console output.\n const output = process.stderr;\n Object.defineProperty(process, 'stdout', { get: () => output });\n globalThis.console = new Console(output, output);\n } else if (eventLogDestination === 2) {\n const output = process.stdout;\n Object.defineProperty(process, 'stderr', { get: () => output });\n globalThis.console = new Console(output, output);\n }\n logStream = new LogStream(eventLogDestination);\n rootEvent('init', getInitMetadata());\n }\n}\n\n/** Returns whether the event logger is active */\nexport const isEventLoggerActive = () => !!logStream?.writable;\n\n/** Whether logs shown in the terminal should be reduced.\n * @remarks\n * We indicate that we're in an automated tool (e.g. E2E tests) with `EXPO_UNSTABLE_HEADLESS`.\n * If the event logger is activate and we're running in a headless tool, we should reduce\n * interactive or noisy logs, in favour of the event logger.\n */\nexport const shouldReduceLogs = () => !!logStream && env.EXPO_UNSTABLE_HEADLESS;\n\n/** Used to create an event logger for structured JSONL logs activated with the `LOG_EVENTS` environment variable.\n *\n * @remarks\n * Structured logs are streamed to a JSONL output file or file descriptor, and are meant for automated tooling\n * or normal usage to document what happened during a user session. When creating a module that outputs errors,\n * events, or captures what the user was doing, create a new event logger category for them and add structured\n * log events.\n * For example, `../start/server/metro/MetroTerminalReporter` captures most of Metro's logged events.\n * Structured JSONL logs don't have a large performance impact, unlike `DEBUG` logs, and are easily parseable\n * and filterable, including by wrapper processes.\n *\n * After adding a new event category, don't forget to add it to `./types.ts` to collect all event shape types\n * in one place.\n *\n * @example\n * ```ts\n * export const event = events('test', (t) => [\n * t.event<'my_event', {\n * myValue: string | null;\n * }>(),\n * ]);\n *\n * event('my_event', { myValue: 'test' });\n * ```\n *\n * This will log a `{ _e: 'test:my_event', _t: 0, myValue: 'test' }` entry in the event log.\n */\nexport const events: EventLoggerBuilder = ((\n category: string,\n _fn: (builder: EventBuilder) => readonly EventShape<string>[]\n) => {\n function log(event: string, data: any) {\n if (logStream) {\n writeEvent(logStream, category, event, data);\n }\n }\n log.category = category;\n\n log.path = function relativePath(target: string | undefined | null): string | null {\n try {\n return target != null && path.isAbsolute(target)\n ? path.relative(logPath, target).replace(/\\\\/, '/') || '.'\n : (target ?? null);\n } catch {\n return target || null;\n }\n };\n\n return log;\n}) as EventLoggerBuilder;\n\n// These are built-in events: We choose an ambiguous name on purpose,\n// since we don't assume this implementation will necessarily only be in `@expo/cli`\nexport const rootEvent = events('root', (t) => [t.event<'init', InitMetadata>()]);\n\nexport type { EventLogger } from './builder';\n"],"names":["events","installEventLogger","isEventLoggerActive","rootEvent","shouldReduceLogs","logPath","process","cwd","logStream","parseLogTarget","env","logDestination","fd","parseInt","Number","isSafeInteger","parsedPath","path","parse","format","dir","undefined","getInitMetadata","version","__EXPO_VERSION","LOG_EVENTS","eventLogDestination","output","stderr","Object","defineProperty","get","globalThis","console","Console","stdout","LogStream","writable","EXPO_UNSTABLE_HEADLESS","category","_fn","log","event","data","writeEvent","relativePath","target","isAbsolute","relative","replace","t"],"mappings":";;;;;;;;;;;IAsGaA,MAAM;eAANA;;IAzDGC,kBAAkB;eAAlBA;;IAoBHC,mBAAmB;eAAnBA;;IA+DAC,SAAS;eAATA;;IAvDAC,gBAAgB;eAAhBA;;;;yBAzEW;;;;;;;gEACP;;;;;;wBAGqB;qBAClB;;;;;;AAOpB,IAAIC,UAAUC,QAAQC,GAAG;AACzB,IAAIC;AAEJ,SAASC,eAAeC,GAAuB;IAC7C,IAAIC;IACJ,IAAID,KAAK;QACP,MAAME,KAAKC,SAASH,KAAK;QACzB,IAAIE,KAAK,KAAKE,OAAOC,aAAa,CAACH,KAAK;YACtCD,iBAAiBC;QACnB,OAAO;YACL,IAAI;gBACF,MAAMI,aAAaC,mBAAI,CAACC,KAAK,CAACR;gBAC9BC,iBAAiBM,mBAAI,CAACE,MAAM,CAACH;gBAC7BX,UAAUW,WAAWI,GAAG;YAC1B,EAAE,OAAM;gBACNT,iBAAiBU;YACnB;QACF;IACF;IACA,OAAOV;AACT;AAEA,SAASW;IACP,OAAO;QACLH,QAAQ;QACR,wCAAwC;QACxCI,SAASjB,QAAQI,GAAG,CAACc,cAAc,IAAI;IACzC;AACF;AAKO,SAASvB,mBAAmBS,MAAMJ,QAAQI,GAAG,CAACe,UAAU;IAC7D,MAAMC,sBAAsBjB,eAAeC;IAC3C,IAAIgB,qBAAqB;QACvB,IAAIA,wBAAwB,GAAG;YAC7B,6EAA6E;YAC7E,wEAAwE;YACxE,MAAMC,SAASrB,QAAQsB,MAAM;YAC7BC,OAAOC,cAAc,CAACxB,SAAS,UAAU;gBAAEyB,KAAK,IAAMJ;YAAO;YAC7DK,WAAWC,OAAO,GAAG,IAAIC,CAAAA,cAAM,SAAC,CAACP,QAAQA;QAC3C,OAAO,IAAID,wBAAwB,GAAG;YACpC,MAAMC,SAASrB,QAAQ6B,MAAM;YAC7BN,OAAOC,cAAc,CAACxB,SAAS,UAAU;gBAAEyB,KAAK,IAAMJ;YAAO;YAC7DK,WAAWC,OAAO,GAAG,IAAIC,CAAAA,cAAM,SAAC,CAACP,QAAQA;QAC3C;QACAnB,YAAY,IAAI4B,iBAAS,CAACV;QAC1BvB,UAAU,QAAQmB;IACpB;AACF;AAGO,MAAMpB,sBAAsB,IAAM,CAAC,EAACM,6BAAAA,UAAW6B,QAAQ;AAQvD,MAAMjC,mBAAmB,IAAM,CAAC,CAACI,aAAaE,QAAG,CAAC4B,sBAAsB;AA6BxE,MAAMtC,SAA8B,CACzCuC,UACAC;IAEA,SAASC,IAAIC,KAAa,EAAEC,IAAS;QACnC,IAAInC,WAAW;YACboC,IAAAA,kBAAU,EAACpC,WAAW+B,UAAUG,OAAOC;QACzC;IACF;IACAF,IAAIF,QAAQ,GAAGA;IAEfE,IAAIxB,IAAI,GAAG,SAAS4B,aAAaC,MAAiC;QAChE,IAAI;YACF,OAAOA,UAAU,QAAQ7B,mBAAI,CAAC8B,UAAU,CAACD,UACrC7B,mBAAI,CAAC+B,QAAQ,CAAC3C,SAASyC,QAAQG,OAAO,CAAC,MAAM,QAAQ,MACpDH,UAAU;QACjB,EAAE,OAAM;YACN,OAAOA,UAAU;QACnB;IACF;IAEA,OAAOL;AACT;AAIO,MAAMtC,YAAYH,OAAO,QAAQ,CAACkD,IAAM;QAACA,EAAER,KAAK;KAAyB"}
|
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
LogStream: function() {
|
|
8
13
|
return LogStream;
|
|
14
|
+
},
|
|
15
|
+
writeEvent: function() {
|
|
16
|
+
return writeEvent;
|
|
9
17
|
}
|
|
10
18
|
});
|
|
11
19
|
function _nodebuffer() {
|
|
@@ -43,6 +51,12 @@ function _interop_require_default(obj) {
|
|
|
43
51
|
}
|
|
44
52
|
const BUSY_WRITE_TIMEOUT = 100;
|
|
45
53
|
const HIGH_WATER_MARK = 16387; /*16KB*/
|
|
54
|
+
function writeEvent(dest, category, kind, payload) {
|
|
55
|
+
const timestamp = Date.now();
|
|
56
|
+
const rest = JSON.stringify(payload).slice(1);
|
|
57
|
+
const line = rest.length > 1 ? `{"_e":"${category}:${kind}","_t":${timestamp},${rest}\n` : `{"_e":"${category}:${kind}","_t":${timestamp}}\n`;
|
|
58
|
+
dest._writeln(line);
|
|
59
|
+
}
|
|
46
60
|
class LogStream extends _nodeevents().EventEmitter {
|
|
47
61
|
#fd;
|
|
48
62
|
#file;
|
|
@@ -54,9 +68,11 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
54
68
|
#output;
|
|
55
69
|
#len;
|
|
56
70
|
#lines;
|
|
71
|
+
#head;
|
|
57
72
|
#partialLine;
|
|
73
|
+
#onRelease;
|
|
58
74
|
constructor(dest){
|
|
59
|
-
super(), this.#fd = -1, this.#file = null, this.#writing = false, this.#ending = false, this.#flushPending = false, this.#destroyed = false, this.#opening = false, this.#output = '', this.#len = 0, this.#lines = [], this.#partialLine = 0;
|
|
75
|
+
super(), this.#fd = -1, this.#file = null, this.#writing = false, this.#ending = false, this.#flushPending = false, this.#destroyed = false, this.#opening = false, this.#output = '', this.#len = 0, this.#lines = [], this.#head = 0, this.#partialLine = 0, this.#onRelease = (err, written)=>this.#release(err, written);
|
|
60
76
|
if (typeof dest === 'number') {
|
|
61
77
|
_nodefs().default.fsyncSync(dest);
|
|
62
78
|
this.#fd = dest;
|
|
@@ -87,23 +103,43 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
87
103
|
}
|
|
88
104
|
} else {
|
|
89
105
|
this.emit('write', written);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const output = _nodebuffer().Buffer.from(this.#output).subarray(written).toString();
|
|
93
|
-
this.#len -= this.#output.length - output.length;
|
|
94
|
-
this.#output = output;
|
|
95
|
-
} else {
|
|
106
|
+
if (written === this.#output.length) {
|
|
107
|
+
// Fast path: complete write (exact for ASCII, the common case for JSONL)
|
|
96
108
|
this.#len -= this.#output.length;
|
|
97
109
|
this.#output = '';
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.#
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
110
|
+
if (this.#lines.length - this.#head > this.#partialLine) {
|
|
111
|
+
this.#writeLine();
|
|
112
|
+
} else if (this.#ending) {
|
|
113
|
+
this.#writing = false;
|
|
114
|
+
this.#close();
|
|
115
|
+
} else {
|
|
116
|
+
this.#writing = false;
|
|
117
|
+
if (this.#flushPending) {
|
|
118
|
+
this.emit('drain');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
104
121
|
} else {
|
|
105
|
-
|
|
106
|
-
|
|
122
|
+
// Multi-byte complete write (written > length) or partial write (written < length)
|
|
123
|
+
const outputLength = _nodebuffer().Buffer.byteLength(this.#output);
|
|
124
|
+
if (outputLength > written) {
|
|
125
|
+
const output = _nodebuffer().Buffer.from(this.#output).toString('utf8', written);
|
|
126
|
+
this.#len -= this.#output.length - output.length;
|
|
127
|
+
this.#output = output;
|
|
128
|
+
} else {
|
|
129
|
+
this.#len -= this.#output.length;
|
|
130
|
+
this.#output = '';
|
|
131
|
+
}
|
|
132
|
+
if (this.#output || this.#lines.length - this.#head > this.#partialLine) {
|
|
133
|
+
this.#writeLine();
|
|
134
|
+
} else if (this.#ending) {
|
|
135
|
+
this.#writing = false;
|
|
136
|
+
this.#close();
|
|
137
|
+
} else {
|
|
138
|
+
this.#writing = false;
|
|
139
|
+
if (this.#flushPending) {
|
|
140
|
+
this.emit('drain');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
107
143
|
}
|
|
108
144
|
}
|
|
109
145
|
}
|
|
@@ -123,7 +159,7 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
123
159
|
this.emit('ready');
|
|
124
160
|
if (this.#destroyed) {
|
|
125
161
|
// do nothing when we're already closing the file
|
|
126
|
-
} else if (!this.writing && this.#lines.length > this.#partialLine || this.#flushPending) {
|
|
162
|
+
} else if (!this.writing && this.#lines.length - this.#head > this.#partialLine || this.#flushPending) {
|
|
127
163
|
this.#writeLine();
|
|
128
164
|
}
|
|
129
165
|
}
|
|
@@ -143,6 +179,7 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
143
179
|
this.#destroyed = true;
|
|
144
180
|
this.#partialLine = 0;
|
|
145
181
|
this.#lines.length = 0;
|
|
182
|
+
this.#head = 0;
|
|
146
183
|
const onClose = (error)=>{
|
|
147
184
|
if (error) {
|
|
148
185
|
this.emit('error', error);
|
|
@@ -162,8 +199,22 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
162
199
|
}
|
|
163
200
|
#writeLine() {
|
|
164
201
|
this.#writing = true;
|
|
165
|
-
this.#output
|
|
166
|
-
|
|
202
|
+
if (!this.#output) {
|
|
203
|
+
const end = this.#lines.length - this.#partialLine;
|
|
204
|
+
if (end > this.#head) {
|
|
205
|
+
this.#output = this.#lines[this.#head++] || '';
|
|
206
|
+
// Batch multiple lines into one write call below HWM, to avoid
|
|
207
|
+
// excessive syscalls after when lines accumulated during a previous write
|
|
208
|
+
while(this.#head < end && this.#output.length < HIGH_WATER_MARK){
|
|
209
|
+
this.#output += this.#lines[this.#head++];
|
|
210
|
+
}
|
|
211
|
+
if (this.#head === this.#lines.length) {
|
|
212
|
+
this.#lines.length = 0;
|
|
213
|
+
this.#head = 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
_nodefs().default.write(this.#fd, this.#output, this.#onRelease);
|
|
167
218
|
}
|
|
168
219
|
_end() {
|
|
169
220
|
if (!this.#destroyed && !this.#ending) {
|
|
@@ -171,7 +222,7 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
171
222
|
if (this.#opening) {
|
|
172
223
|
this.once('ready', ()=>this._end());
|
|
173
224
|
} else if (!this.#writing && this.#fd >= 0) {
|
|
174
|
-
if (this.#lines.length > this.#partialLine) {
|
|
225
|
+
if (this.#lines.length - this.#head > this.#partialLine) {
|
|
175
226
|
this.#writeLine();
|
|
176
227
|
} else {
|
|
177
228
|
this.#close();
|
|
@@ -225,7 +276,7 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
225
276
|
this.once('drain', onDrain);
|
|
226
277
|
this.once('error', onError);
|
|
227
278
|
if (!this.#writing) {
|
|
228
|
-
if (this.#lines.length > this.#partialLine || this.#output) {
|
|
279
|
+
if (this.#lines.length - this.#head > this.#partialLine || this.#output) {
|
|
229
280
|
// There are complete lines or remaining output to write
|
|
230
281
|
this.#writeLine();
|
|
231
282
|
} else {
|
|
@@ -235,11 +286,30 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
235
286
|
}
|
|
236
287
|
}
|
|
237
288
|
}
|
|
289
|
+
_writeln(data) {
|
|
290
|
+
this.#len += data.length;
|
|
291
|
+
if (!this.#writing && this.#lines.length === this.#head && !this.#output) {
|
|
292
|
+
// Fast path: When no write is pending, directly write the line
|
|
293
|
+
this.#writing = true;
|
|
294
|
+
this.#output = data;
|
|
295
|
+
_nodefs().default.write(this.#fd, data, this.#onRelease);
|
|
296
|
+
} else {
|
|
297
|
+
this.#lines.push(data);
|
|
298
|
+
if (!this.#writing) {
|
|
299
|
+
this.#writeLine();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return this.#len < HIGH_WATER_MARK;
|
|
303
|
+
}
|
|
238
304
|
_write(data) {
|
|
239
305
|
if (this.#destroyed) {
|
|
240
306
|
return false;
|
|
241
307
|
}
|
|
242
308
|
this.#len += data.length;
|
|
309
|
+
// Fast path: For complete lines with no pending partial we can skip the work below
|
|
310
|
+
if (this.#partialLine === 0 && data.charCodeAt(data.length - 1) === 10 /*'\n'*/ ) {
|
|
311
|
+
return this._writeln(data);
|
|
312
|
+
}
|
|
243
313
|
let startIdx = 0;
|
|
244
314
|
let endIdx = -1;
|
|
245
315
|
while((endIdx = data.indexOf('\n', startIdx)) > -1){
|
|
@@ -261,7 +331,7 @@ class LogStream extends _nodeevents().EventEmitter {
|
|
|
261
331
|
}
|
|
262
332
|
this.#partialLine = 1;
|
|
263
333
|
}
|
|
264
|
-
if (!this.#writing && this.#lines.length > this.#partialLine) {
|
|
334
|
+
if (!this.#writing && this.#lines.length - this.#head > this.#partialLine) {
|
|
265
335
|
this.#writeLine();
|
|
266
336
|
}
|
|
267
337
|
return this.#len < HIGH_WATER_MARK;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/events/stream.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { EventEmitter } from 'node:events';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst BUSY_WRITE_TIMEOUT = 100;\nconst HIGH_WATER_MARK = 16_387; /*16KB*/\n\nexport class LogStream extends EventEmitter implements NodeJS.WritableStream {\n #fd = -1;\n #file: string | null = null;\n\n #writing = false;\n #ending = false;\n #flushPending = false;\n #destroyed = false;\n #opening = false;\n\n #output = '';\n #len = 0;\n #lines: string[] = [];\n #partialLine = 0;\n\n constructor(dest: string | number) {\n super();\n if (typeof dest === 'number') {\n fs.fsyncSync(dest);\n this.#fd = dest;\n process.nextTick(() => this.emit('ready'));\n } else if (typeof dest === 'string') {\n this.#openFile(dest);\n }\n }\n\n get file(): string | null {\n return this.#file;\n }\n\n get fd(): number {\n return this.#fd;\n }\n\n get writing(): boolean {\n return this.#writing;\n }\n\n get writable(): boolean {\n return !this.#destroyed && !this.#ending;\n }\n\n #release(error: NodeJS.ErrnoException | null, written: number) {\n if (error) {\n if (error.code === 'EAGAIN' || error.code === 'EBUSY') {\n setTimeout(() => this.#writeLine(), BUSY_WRITE_TIMEOUT);\n } else {\n this.#writing = false;\n this.emit('error', error);\n }\n } else {\n this.emit('write', written);\n\n const outputLength = Buffer.byteLength(this.#output);\n if (outputLength > written) {\n const output = Buffer.from(this.#output).subarray(written).toString();\n this.#len -= this.#output.length - output.length;\n this.#output = output;\n } else {\n this.#len -= this.#output.length;\n this.#output = '';\n }\n\n if (this.#output || this.#lines.length > this.#partialLine) {\n this.#writeLine();\n } else if (this.#ending) {\n this.#writing = false;\n this.#close();\n } else {\n this.#writing = false;\n this.emit('drain');\n }\n }\n }\n\n #openFile(file: string) {\n this.#opening = true;\n this.#writing = true;\n\n const onOpened = (error: Error | null, fd?: number | null) => {\n if (error) {\n this.#writing = false;\n this.#opening = false;\n this.emit('error', error);\n } else {\n this.#fd = fd!;\n this.#file = file;\n this.#opening = false;\n this.#writing = false;\n this.emit('ready');\n if (this.#destroyed) {\n // do nothing when we're already closing the file\n } else if (\n (!this.writing && this.#lines.length > this.#partialLine) ||\n this.#flushPending\n ) {\n this.#writeLine();\n }\n }\n };\n\n fs.mkdir(path.dirname(file), { recursive: true }, (err) => {\n if (err) return onOpened(err);\n fs.open(file, 'a', 0o666, onOpened);\n });\n }\n\n #close() {\n if (this.#fd === -1) {\n this.once('ready', () => this.#close());\n return;\n }\n\n this.#destroyed = true;\n this.#partialLine = 0;\n this.#lines.length = 0;\n\n const onClose = (error?: NodeJS.ErrnoException | null) => {\n if (error) {\n this.emit('error', error);\n this.emit('close', error);\n } else {\n if (this.#ending && !this.#writing) this.emit('finish');\n this.emit('close');\n }\n };\n\n fsFsync(this.#fd, (error) => {\n if (!error && !isStdFd(this.#fd)) {\n fs.close(this.#fd, onClose);\n } else {\n onClose(); // Error intentionally ignored, assume closed\n }\n });\n }\n\n #writeLine() {\n this.#writing = true;\n this.#output ||= this.#lines.length > this.#partialLine ? this.#lines.shift() || '' : '';\n fs.write(this.#fd, this.#output, (err, written) => this.#release(err, written));\n }\n\n _end() {\n if (!this.#destroyed && !this.#ending) {\n this.#ending = true;\n if (this.#opening) {\n this.once('ready', () => this._end());\n } else if (!this.#writing && this.#fd >= 0) {\n if (this.#lines.length > this.#partialLine) {\n this.#writeLine();\n } else {\n this.#close();\n }\n }\n }\n return this;\n }\n\n end(cb?: () => void): this;\n end(data: string | Uint8Array, cb?: () => void): this;\n end(str: string, encoding?: BufferEncoding, cb?: () => void): this;\n\n end(\n arg1?: Uint8Array | string | (() => void),\n arg2?: BufferEncoding | (() => void),\n arg3?: () => void\n ) {\n const maybeCb = arg3 || arg2 || arg1;\n const input = typeof arg1 !== 'function' ? arg1 : undefined;\n const encoding = typeof arg2 === 'string' ? arg2 : 'utf8';\n const cb = typeof maybeCb === 'function' ? maybeCb : undefined;\n if (typeof input === 'string') {\n this.write(input, encoding);\n } else if (input != null) {\n this.write(input);\n }\n if (cb) this.once('close', cb);\n return this._end();\n }\n\n destroy() {\n if (!this.#destroyed) this.#close();\n }\n\n flush(cb?: (error?: Error | null) => void) {\n if (this.#destroyed) {\n cb?.();\n } else {\n const onDrain = () => {\n if (!this.#destroyed) {\n fsFsync(this.#fd, (error) => {\n this.#flushPending = false;\n if (error?.code === 'EBADF') {\n cb?.(); // If fd is closed, ignore the error\n } else {\n cb?.(error);\n }\n });\n } else {\n this.#flushPending = false;\n cb?.();\n }\n this.off('error', onError);\n };\n\n const onError = (err: Error) => {\n this.#flushPending = false;\n this.off('drain', onDrain);\n cb?.(err);\n };\n\n this.#flushPending = true;\n this.once('drain', onDrain);\n this.once('error', onError);\n\n if (!this.#writing) {\n if (this.#lines.length > this.#partialLine || this.#output) {\n // There are complete lines or remaining output to write\n this.#writeLine();\n } else {\n // Nothing complete to write, emit drain immediately\n process.nextTick(() => this.emit('drain'));\n }\n }\n }\n }\n\n _write(data: string): boolean {\n if (this.#destroyed) {\n return false;\n }\n\n this.#len += data.length;\n\n let startIdx = 0;\n let endIdx = -1;\n while ((endIdx = data.indexOf('\\n', startIdx)) > -1) {\n const line = data.slice(startIdx, endIdx + 1);\n if (this.#partialLine > 0) {\n this.#lines[this.#lines.length - 1] += line;\n } else {\n this.#lines.push(line);\n }\n this.#partialLine = 0;\n startIdx = ++endIdx;\n }\n\n if (startIdx < data.length) {\n const line = data.slice(startIdx);\n if (this.#partialLine > 0) {\n this.#lines[this.#lines.length - 1] += line;\n } else {\n this.#lines.push(data.slice(startIdx));\n }\n this.#partialLine = 1;\n }\n\n if (!this.#writing && this.#lines.length > this.#partialLine) {\n this.#writeLine();\n }\n\n return this.#len < HIGH_WATER_MARK;\n }\n\n write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean;\n write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean;\n\n write(\n input: Uint8Array | string,\n arg2?: BufferEncoding | ((err?: Error | null) => void),\n arg3?: (err?: Error | null) => void\n ): boolean {\n const maybeCb = arg3 || arg2;\n const encoding = typeof arg2 === 'string' ? arg2 : 'utf8';\n const data = typeof input === 'string' ? input : Buffer.from(input).toString(encoding);\n const cb = typeof maybeCb === 'function' ? maybeCb : undefined;\n try {\n return this._write(data);\n } finally {\n cb?.();\n }\n }\n\n [Symbol.dispose]() {\n this.destroy();\n }\n}\n\nconst isStdFd = (fd: number) => {\n switch (fd) {\n case 1:\n case 2:\n case process.stdout.fd:\n case process.stderr.fd:\n return true;\n default:\n return false;\n }\n};\n\nconst fsFsync = (fd: number, cb: (error?: NodeJS.ErrnoException | null) => void) => {\n try {\n fs.fsync(fd, cb);\n } catch (error: any) {\n cb(error);\n }\n};\n"],"names":["LogStream","BUSY_WRITE_TIMEOUT","HIGH_WATER_MARK","EventEmitter","constructor","dest","fs","fsyncSync","process","nextTick","emit","file","fd","writing","writable","error","written","code","setTimeout","outputLength","Buffer","byteLength","output","from","subarray","toString","length","onOpened","mkdir","path","dirname","recursive","err","open","once","onClose","fsFsync","isStdFd","close","shift","write","_end","end","arg1","arg2","arg3","maybeCb","input","undefined","encoding","cb","destroy","flush","onDrain","off","onError","_write","data","startIdx","endIdx","indexOf","line","slice","push","Symbol","dispose","stdout","stderr","fsync"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/events/stream.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { EventEmitter } from 'node:events';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst BUSY_WRITE_TIMEOUT = 100;\nconst HIGH_WATER_MARK = 16_387; /*16KB*/\n\nexport function writeEvent(dest: LogStream, category: string, kind: string, payload: any) {\n const timestamp = Date.now();\n const rest = JSON.stringify(payload).slice(1);\n const line =\n rest.length > 1\n ? `{\"_e\":\"${category}:${kind}\",\"_t\":${timestamp},${rest}\\n`\n : `{\"_e\":\"${category}:${kind}\",\"_t\":${timestamp}}\\n`;\n dest._writeln(line);\n}\n\nexport class LogStream extends EventEmitter implements NodeJS.WritableStream {\n #fd = -1;\n #file: string | null = null;\n\n #writing = false;\n #ending = false;\n #flushPending = false;\n #destroyed = false;\n #opening = false;\n\n #output = '';\n #len = 0;\n #lines: string[] = [];\n #head = 0;\n #partialLine = 0;\n #onRelease = (err: NodeJS.ErrnoException | null, written: number) => this.#release(err, written);\n\n constructor(dest: string | number) {\n super();\n if (typeof dest === 'number') {\n fs.fsyncSync(dest);\n this.#fd = dest;\n process.nextTick(() => this.emit('ready'));\n } else if (typeof dest === 'string') {\n this.#openFile(dest);\n }\n }\n\n get file(): string | null {\n return this.#file;\n }\n\n get fd(): number {\n return this.#fd;\n }\n\n get writing(): boolean {\n return this.#writing;\n }\n\n get writable(): boolean {\n return !this.#destroyed && !this.#ending;\n }\n\n #release(error: NodeJS.ErrnoException | null, written: number) {\n if (error) {\n if (error.code === 'EAGAIN' || error.code === 'EBUSY') {\n setTimeout(() => this.#writeLine(), BUSY_WRITE_TIMEOUT);\n } else {\n this.#writing = false;\n this.emit('error', error);\n }\n } else {\n this.emit('write', written);\n\n if (written === this.#output.length) {\n // Fast path: complete write (exact for ASCII, the common case for JSONL)\n this.#len -= this.#output.length;\n this.#output = '';\n\n if (this.#lines.length - this.#head > this.#partialLine) {\n this.#writeLine();\n } else if (this.#ending) {\n this.#writing = false;\n this.#close();\n } else {\n this.#writing = false;\n if (this.#flushPending) {\n this.emit('drain');\n }\n }\n } else {\n // Multi-byte complete write (written > length) or partial write (written < length)\n const outputLength = Buffer.byteLength(this.#output);\n if (outputLength > written) {\n const output = Buffer.from(this.#output).toString('utf8', written);\n this.#len -= this.#output.length - output.length;\n this.#output = output;\n } else {\n this.#len -= this.#output.length;\n this.#output = '';\n }\n\n if (this.#output || this.#lines.length - this.#head > this.#partialLine) {\n this.#writeLine();\n } else if (this.#ending) {\n this.#writing = false;\n this.#close();\n } else {\n this.#writing = false;\n if (this.#flushPending) {\n this.emit('drain');\n }\n }\n }\n }\n }\n\n #openFile(file: string) {\n this.#opening = true;\n this.#writing = true;\n\n const onOpened = (error: Error | null, fd?: number | null) => {\n if (error) {\n this.#writing = false;\n this.#opening = false;\n this.emit('error', error);\n } else {\n this.#fd = fd!;\n this.#file = file;\n this.#opening = false;\n this.#writing = false;\n this.emit('ready');\n if (this.#destroyed) {\n // do nothing when we're already closing the file\n } else if (\n (!this.writing && this.#lines.length - this.#head > this.#partialLine) ||\n this.#flushPending\n ) {\n this.#writeLine();\n }\n }\n };\n\n fs.mkdir(path.dirname(file), { recursive: true }, (err) => {\n if (err) return onOpened(err);\n fs.open(file, 'a', 0o666, onOpened);\n });\n }\n\n #close() {\n if (this.#fd === -1) {\n this.once('ready', () => this.#close());\n return;\n }\n\n this.#destroyed = true;\n this.#partialLine = 0;\n this.#lines.length = 0;\n this.#head = 0;\n\n const onClose = (error?: NodeJS.ErrnoException | null) => {\n if (error) {\n this.emit('error', error);\n this.emit('close', error);\n } else {\n if (this.#ending && !this.#writing) this.emit('finish');\n this.emit('close');\n }\n };\n\n fsFsync(this.#fd, (error) => {\n if (!error && !isStdFd(this.#fd)) {\n fs.close(this.#fd, onClose);\n } else {\n onClose(); // Error intentionally ignored, assume closed\n }\n });\n }\n\n #writeLine() {\n this.#writing = true;\n if (!this.#output) {\n const end = this.#lines.length - this.#partialLine;\n if (end > this.#head) {\n this.#output = this.#lines[this.#head++] || '';\n // Batch multiple lines into one write call below HWM, to avoid\n // excessive syscalls after when lines accumulated during a previous write\n while (this.#head < end && this.#output.length < HIGH_WATER_MARK) {\n this.#output += this.#lines[this.#head++];\n }\n if (this.#head === this.#lines.length) {\n this.#lines.length = 0;\n this.#head = 0;\n }\n }\n }\n fs.write(this.#fd, this.#output, this.#onRelease);\n }\n\n _end() {\n if (!this.#destroyed && !this.#ending) {\n this.#ending = true;\n if (this.#opening) {\n this.once('ready', () => this._end());\n } else if (!this.#writing && this.#fd >= 0) {\n if (this.#lines.length - this.#head > this.#partialLine) {\n this.#writeLine();\n } else {\n this.#close();\n }\n }\n }\n return this;\n }\n\n end(cb?: () => void): this;\n end(data: string | Uint8Array, cb?: () => void): this;\n end(str: string, encoding?: BufferEncoding, cb?: () => void): this;\n\n end(\n arg1?: Uint8Array | string | (() => void),\n arg2?: BufferEncoding | (() => void),\n arg3?: () => void\n ) {\n const maybeCb = arg3 || arg2 || arg1;\n const input = typeof arg1 !== 'function' ? arg1 : undefined;\n const encoding = typeof arg2 === 'string' ? arg2 : 'utf8';\n const cb = typeof maybeCb === 'function' ? maybeCb : undefined;\n if (typeof input === 'string') {\n this.write(input, encoding);\n } else if (input != null) {\n this.write(input);\n }\n if (cb) this.once('close', cb);\n return this._end();\n }\n\n destroy() {\n if (!this.#destroyed) this.#close();\n }\n\n flush(cb?: (error?: Error | null) => void) {\n if (this.#destroyed) {\n cb?.();\n } else {\n const onDrain = () => {\n if (!this.#destroyed) {\n fsFsync(this.#fd, (error) => {\n this.#flushPending = false;\n if (error?.code === 'EBADF') {\n cb?.(); // If fd is closed, ignore the error\n } else {\n cb?.(error);\n }\n });\n } else {\n this.#flushPending = false;\n cb?.();\n }\n this.off('error', onError);\n };\n\n const onError = (err: Error) => {\n this.#flushPending = false;\n this.off('drain', onDrain);\n cb?.(err);\n };\n\n this.#flushPending = true;\n this.once('drain', onDrain);\n this.once('error', onError);\n\n if (!this.#writing) {\n if (this.#lines.length - this.#head > this.#partialLine || this.#output) {\n // There are complete lines or remaining output to write\n this.#writeLine();\n } else {\n // Nothing complete to write, emit drain immediately\n process.nextTick(() => this.emit('drain'));\n }\n }\n }\n }\n\n _writeln(data: string): boolean {\n this.#len += data.length;\n if (!this.#writing && this.#lines.length === this.#head && !this.#output) {\n // Fast path: When no write is pending, directly write the line\n this.#writing = true;\n this.#output = data;\n fs.write(this.#fd, data, this.#onRelease);\n } else {\n this.#lines.push(data);\n if (!this.#writing) {\n this.#writeLine();\n }\n }\n return this.#len < HIGH_WATER_MARK;\n }\n\n _write(data: string): boolean {\n if (this.#destroyed) {\n return false;\n }\n\n this.#len += data.length;\n\n // Fast path: For complete lines with no pending partial we can skip the work below\n if (this.#partialLine === 0 && data.charCodeAt(data.length - 1) === 10 /*'\\n'*/) {\n return this._writeln(data);\n }\n\n let startIdx = 0;\n let endIdx = -1;\n while ((endIdx = data.indexOf('\\n', startIdx)) > -1) {\n const line = data.slice(startIdx, endIdx + 1);\n if (this.#partialLine > 0) {\n this.#lines[this.#lines.length - 1] += line;\n } else {\n this.#lines.push(line);\n }\n this.#partialLine = 0;\n startIdx = ++endIdx;\n }\n\n if (startIdx < data.length) {\n const line = data.slice(startIdx);\n if (this.#partialLine > 0) {\n this.#lines[this.#lines.length - 1] += line;\n } else {\n this.#lines.push(data.slice(startIdx));\n }\n this.#partialLine = 1;\n }\n\n if (!this.#writing && this.#lines.length - this.#head > this.#partialLine) {\n this.#writeLine();\n }\n\n return this.#len < HIGH_WATER_MARK;\n }\n\n write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean;\n write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean;\n\n write(\n input: Uint8Array | string,\n arg2?: BufferEncoding | ((err?: Error | null) => void),\n arg3?: (err?: Error | null) => void\n ): boolean {\n const maybeCb = arg3 || arg2;\n const encoding = typeof arg2 === 'string' ? arg2 : 'utf8';\n const data = typeof input === 'string' ? input : Buffer.from(input).toString(encoding);\n const cb = typeof maybeCb === 'function' ? maybeCb : undefined;\n try {\n return this._write(data);\n } finally {\n cb?.();\n }\n }\n\n [Symbol.dispose]() {\n this.destroy();\n }\n}\n\nconst isStdFd = (fd: number) => {\n switch (fd) {\n case 1:\n case 2:\n case process.stdout.fd:\n case process.stderr.fd:\n return true;\n default:\n return false;\n }\n};\n\nconst fsFsync = (fd: number, cb: (error?: NodeJS.ErrnoException | null) => void) => {\n try {\n fs.fsync(fd, cb);\n } catch (error: any) {\n cb(error);\n }\n};\n"],"names":["LogStream","writeEvent","BUSY_WRITE_TIMEOUT","HIGH_WATER_MARK","dest","category","kind","payload","timestamp","Date","now","rest","JSON","stringify","slice","line","length","_writeln","EventEmitter","constructor","err","written","fs","fsyncSync","process","nextTick","emit","file","fd","writing","writable","error","code","setTimeout","outputLength","Buffer","byteLength","output","from","toString","onOpened","mkdir","path","dirname","recursive","open","once","onClose","fsFsync","isStdFd","close","end","write","_end","arg1","arg2","arg3","maybeCb","input","undefined","encoding","cb","destroy","flush","onDrain","off","onError","data","push","_write","charCodeAt","startIdx","endIdx","indexOf","Symbol","dispose","stdout","stderr","fsync"],"mappings":"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"}
|
|
@@ -21,6 +21,9 @@ _export(exports, {
|
|
|
21
21
|
hasRequiredIOSFilesAsync: function() {
|
|
22
22
|
return hasRequiredIOSFilesAsync;
|
|
23
23
|
},
|
|
24
|
+
maybeBailOnNativeModuleAsync: function() {
|
|
25
|
+
return maybeBailOnNativeModuleAsync;
|
|
26
|
+
},
|
|
24
27
|
promptToClearMalformedNativeProjectsAsync: function() {
|
|
25
28
|
return promptToClearMalformedNativeProjectsAsync;
|
|
26
29
|
}
|
|
@@ -39,6 +42,13 @@ function _chalk() {
|
|
|
39
42
|
};
|
|
40
43
|
return data;
|
|
41
44
|
}
|
|
45
|
+
function _unstableautolinkingexports() {
|
|
46
|
+
const data = require("expo/internal/unstable-autolinking-exports");
|
|
47
|
+
_unstableautolinkingexports = function() {
|
|
48
|
+
return data;
|
|
49
|
+
};
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
42
52
|
function _fs() {
|
|
43
53
|
const data = /*#__PURE__*/ _interop_require_default(require("fs"));
|
|
44
54
|
_fs = function() {
|
|
@@ -178,6 +188,8 @@ async function promptToClearMalformedNativeProjectsAsync(projectRoot, checkPlatf
|
|
|
178
188
|
const platforms = await getMalformedNativeProjectsAsync(projectRoot, checkPlatforms);
|
|
179
189
|
if (!platforms.length) {
|
|
180
190
|
return;
|
|
191
|
+
} else if (await maybeBailOnNativeModuleAsync(projectRoot)) {
|
|
192
|
+
return;
|
|
181
193
|
}
|
|
182
194
|
const displayPlatforms = platforms.map((platform)=>_chalk().default.cyan(platform));
|
|
183
195
|
// Prompt which platforms to reset.
|
|
@@ -198,5 +210,31 @@ async function promptToClearMalformedNativeProjectsAsync(projectRoot, checkPlatf
|
|
|
198
210
|
_log.warn('Continuing with malformed native projects');
|
|
199
211
|
}
|
|
200
212
|
}
|
|
213
|
+
async function maybeBailOnNativeModuleAsync(projectRoot) {
|
|
214
|
+
let isNativeModule = false;
|
|
215
|
+
try {
|
|
216
|
+
isNativeModule = await (0, _unstableautolinkingexports().isNativeModuleAsync)(projectRoot);
|
|
217
|
+
} catch {
|
|
218
|
+
// We don't care too much about a failure here
|
|
219
|
+
// TODO(@kitten): Remove try/catch; this is only to protect against version misalignment
|
|
220
|
+
// Remove this when we're bumping to SDK 56
|
|
221
|
+
}
|
|
222
|
+
if (isNativeModule) {
|
|
223
|
+
if (!(0, _interactive.isInteractive)()) {
|
|
224
|
+
_log.warn(`Current project was detected as a native module, but the command will continue because the terminal is not interactive.`);
|
|
225
|
+
return false;
|
|
226
|
+
} else {
|
|
227
|
+
_log.warn('Current project was detected as a native module and not an Expo app.');
|
|
228
|
+
}
|
|
229
|
+
const answer = await (0, _prompts.confirmAsync)({
|
|
230
|
+
message: `Continue anyway?`
|
|
231
|
+
});
|
|
232
|
+
if (!answer) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
_log.log();
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
201
239
|
|
|
202
240
|
//# sourceMappingURL=clearNativeFolder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/prebuild/clearNativeFolder.ts"],"sourcesContent":["import { AndroidConfig, IOSConfig, ModPlatform } from '@expo/config-plugins';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\n\nimport * as Log from '../log';\nimport { directoryExistsAsync } from '../utils/dir';\nimport { isInteractive } from '../utils/interactive';\nimport { logNewSection } from '../utils/ora';\nimport { confirmAsync } from '../utils/prompts';\n\ntype ArbitraryPlatform = ModPlatform | string;\n\n/** Delete the input native folders and print a loading step. */\nexport async function clearNativeFolder(projectRoot: string, folders: string[]) {\n const step = logNewSection(`Clearing ${folders.join(', ')}`);\n try {\n await Promise.all(\n folders.map((folderName) =>\n fs.promises.rm(path.join(projectRoot, folderName), {\n recursive: true,\n force: true,\n })\n )\n );\n step.succeed(`Cleared ${folders.join(', ')} code`);\n } catch (error: any) {\n step.fail(`Failed to delete ${folders.join(', ')} code: ${error.message}`);\n throw error;\n }\n}\n\n/**\n * Returns `true` if a certain subset of required Android project files are intact.\n *\n * This isn't perfect but it serves the purpose of indicating that the user should\n * be warned to nuke the project files, most commonly when git is cleared and the root folder\n * remains in memory.\n */\nexport async function hasRequiredAndroidFilesAsync(projectRoot: string): Promise<boolean> {\n try {\n await Promise.all([\n AndroidConfig.Paths.getAppBuildGradleAsync(projectRoot),\n AndroidConfig.Paths.getProjectBuildGradleAsync(projectRoot),\n AndroidConfig.Paths.getAndroidManifestAsync(projectRoot),\n AndroidConfig.Paths.getMainApplicationAsync(projectRoot),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Returns `true` if a certain subset of required iOS project files are intact. */\nexport async function hasRequiredIOSFilesAsync(projectRoot: string) {\n try {\n // If any of the following required files are missing, then the project is malformed.\n await Promise.all([\n IOSConfig.Paths.getAllXcodeProjectPaths(projectRoot),\n IOSConfig.Paths.getAllPBXProjectPaths(projectRoot),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Filter out platforms that do not have an existing platform folder.\n * If the user wants to validate that neither of ['ios', 'android'] are malformed then we should\n * first check that both `ios` and `android` folders exist.\n *\n * This optimization prevents us from prompting to clear a \"malformed\" project that doesn't exist yet.\n */\nasync function filterPlatformsThatDoNotExistAsync(\n projectRoot: string,\n platforms: ArbitraryPlatform[]\n): Promise<ArbitraryPlatform[]> {\n const valid = await Promise.all(\n platforms.map(async (platform) => {\n if (await directoryExistsAsync(path.join(projectRoot, platform))) {\n return platform;\n }\n return null;\n })\n );\n return valid.filter(Boolean) as ArbitraryPlatform[];\n}\n\n/** Get a list of native platforms that have existing directories which contain malformed projects. */\nexport async function getMalformedNativeProjectsAsync(\n projectRoot: string,\n platforms: ArbitraryPlatform[]\n): Promise<ArbitraryPlatform[]> {\n const VERIFIERS: Record<ArbitraryPlatform, (root: string) => Promise<boolean>> = {\n android: hasRequiredAndroidFilesAsync,\n ios: hasRequiredIOSFilesAsync,\n };\n\n const checkablePlatforms = platforms.filter((platform) => platform in VERIFIERS);\n const checkPlatforms = await filterPlatformsThatDoNotExistAsync(projectRoot, checkablePlatforms);\n return (\n await Promise.all(\n checkPlatforms.map(async (platform) => {\n if (!VERIFIERS[platform]) {\n return false;\n }\n if (await VERIFIERS[platform](projectRoot)) {\n return false;\n }\n return platform;\n })\n )\n ).filter(Boolean) as ArbitraryPlatform[];\n}\n\nexport async function promptToClearMalformedNativeProjectsAsync(\n projectRoot: string,\n checkPlatforms: ArbitraryPlatform[]\n) {\n const platforms = await getMalformedNativeProjectsAsync(projectRoot, checkPlatforms);\n\n if (!platforms.length) {\n return;\n }\n\n const displayPlatforms = platforms.map((platform) => chalk.cyan(platform));\n // Prompt which platforms to reset.\n const message =\n platforms.length > 1\n ? `The ${displayPlatforms[0]} and ${displayPlatforms[1]} projects are malformed`\n : `The ${displayPlatforms[0]} project is malformed`;\n\n if (\n // If the process is non-interactive, default to clearing the malformed native project.\n // This would only happen on re-running prebuild.\n !isInteractive() ||\n // Prompt to clear the native folders.\n (await confirmAsync({\n message: `${message}, would you like to clear the project files and reinitialize them?`,\n initial: true,\n }))\n ) {\n if (!isInteractive()) {\n Log.warn(`${message}, project files will be cleared and reinitialized.`);\n }\n await clearNativeFolder(projectRoot, platforms);\n } else {\n // Warn the user that the process may fail.\n Log.warn('Continuing with malformed native projects');\n }\n}\n"],"names":["clearNativeFolder","getMalformedNativeProjectsAsync","hasRequiredAndroidFilesAsync","hasRequiredIOSFilesAsync","promptToClearMalformedNativeProjectsAsync","projectRoot","folders","step","logNewSection","join","Promise","all","map","folderName","fs","promises","rm","path","recursive","force","succeed","error","fail","message","AndroidConfig","Paths","getAppBuildGradleAsync","getProjectBuildGradleAsync","getAndroidManifestAsync","getMainApplicationAsync","IOSConfig","getAllXcodeProjectPaths","getAllPBXProjectPaths","filterPlatformsThatDoNotExistAsync","platforms","valid","platform","directoryExistsAsync","filter","Boolean","VERIFIERS","android","ios","checkablePlatforms","checkPlatforms","length","displayPlatforms","chalk","cyan","isInteractive","confirmAsync","initial","Log","warn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/prebuild/clearNativeFolder.ts"],"sourcesContent":["import { AndroidConfig, IOSConfig, ModPlatform } from '@expo/config-plugins';\nimport chalk from 'chalk';\nimport { isNativeModuleAsync } from 'expo/internal/unstable-autolinking-exports';\nimport fs from 'fs';\nimport path from 'path';\n\nimport * as Log from '../log';\nimport { directoryExistsAsync } from '../utils/dir';\nimport { isInteractive } from '../utils/interactive';\nimport { logNewSection } from '../utils/ora';\nimport { confirmAsync } from '../utils/prompts';\n\ntype ArbitraryPlatform = ModPlatform | string;\n\n/** Delete the input native folders and print a loading step. */\nexport async function clearNativeFolder(projectRoot: string, folders: string[]) {\n const step = logNewSection(`Clearing ${folders.join(', ')}`);\n try {\n await Promise.all(\n folders.map((folderName) =>\n fs.promises.rm(path.join(projectRoot, folderName), {\n recursive: true,\n force: true,\n })\n )\n );\n step.succeed(`Cleared ${folders.join(', ')} code`);\n } catch (error: any) {\n step.fail(`Failed to delete ${folders.join(', ')} code: ${error.message}`);\n throw error;\n }\n}\n\n/**\n * Returns `true` if a certain subset of required Android project files are intact.\n *\n * This isn't perfect but it serves the purpose of indicating that the user should\n * be warned to nuke the project files, most commonly when git is cleared and the root folder\n * remains in memory.\n */\nexport async function hasRequiredAndroidFilesAsync(projectRoot: string): Promise<boolean> {\n try {\n await Promise.all([\n AndroidConfig.Paths.getAppBuildGradleAsync(projectRoot),\n AndroidConfig.Paths.getProjectBuildGradleAsync(projectRoot),\n AndroidConfig.Paths.getAndroidManifestAsync(projectRoot),\n AndroidConfig.Paths.getMainApplicationAsync(projectRoot),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Returns `true` if a certain subset of required iOS project files are intact. */\nexport async function hasRequiredIOSFilesAsync(projectRoot: string) {\n try {\n // If any of the following required files are missing, then the project is malformed.\n await Promise.all([\n IOSConfig.Paths.getAllXcodeProjectPaths(projectRoot),\n IOSConfig.Paths.getAllPBXProjectPaths(projectRoot),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Filter out platforms that do not have an existing platform folder.\n * If the user wants to validate that neither of ['ios', 'android'] are malformed then we should\n * first check that both `ios` and `android` folders exist.\n *\n * This optimization prevents us from prompting to clear a \"malformed\" project that doesn't exist yet.\n */\nasync function filterPlatformsThatDoNotExistAsync(\n projectRoot: string,\n platforms: ArbitraryPlatform[]\n): Promise<ArbitraryPlatform[]> {\n const valid = await Promise.all(\n platforms.map(async (platform) => {\n if (await directoryExistsAsync(path.join(projectRoot, platform))) {\n return platform;\n }\n return null;\n })\n );\n return valid.filter(Boolean) as ArbitraryPlatform[];\n}\n\n/** Get a list of native platforms that have existing directories which contain malformed projects. */\nexport async function getMalformedNativeProjectsAsync(\n projectRoot: string,\n platforms: ArbitraryPlatform[]\n): Promise<ArbitraryPlatform[]> {\n const VERIFIERS: Record<ArbitraryPlatform, (root: string) => Promise<boolean>> = {\n android: hasRequiredAndroidFilesAsync,\n ios: hasRequiredIOSFilesAsync,\n };\n\n const checkablePlatforms = platforms.filter((platform) => platform in VERIFIERS);\n const checkPlatforms = await filterPlatformsThatDoNotExistAsync(projectRoot, checkablePlatforms);\n return (\n await Promise.all(\n checkPlatforms.map(async (platform) => {\n if (!VERIFIERS[platform]) {\n return false;\n }\n if (await VERIFIERS[platform](projectRoot)) {\n return false;\n }\n return platform;\n })\n )\n ).filter(Boolean) as ArbitraryPlatform[];\n}\n\nexport async function promptToClearMalformedNativeProjectsAsync(\n projectRoot: string,\n checkPlatforms: ArbitraryPlatform[]\n) {\n const platforms = await getMalformedNativeProjectsAsync(projectRoot, checkPlatforms);\n\n if (!platforms.length) {\n return;\n } else if (await maybeBailOnNativeModuleAsync(projectRoot)) {\n return;\n }\n\n const displayPlatforms = platforms.map((platform) => chalk.cyan(platform));\n // Prompt which platforms to reset.\n const message =\n platforms.length > 1\n ? `The ${displayPlatforms[0]} and ${displayPlatforms[1]} projects are malformed`\n : `The ${displayPlatforms[0]} project is malformed`;\n\n if (\n // If the process is non-interactive, default to clearing the malformed native project.\n // This would only happen on re-running prebuild.\n !isInteractive() ||\n // Prompt to clear the native folders.\n (await confirmAsync({\n message: `${message}, would you like to clear the project files and reinitialize them?`,\n initial: true,\n }))\n ) {\n if (!isInteractive()) {\n Log.warn(`${message}, project files will be cleared and reinitialized.`);\n }\n await clearNativeFolder(projectRoot, platforms);\n } else {\n // Warn the user that the process may fail.\n Log.warn('Continuing with malformed native projects');\n }\n}\n\nexport async function maybeBailOnNativeModuleAsync(projectRoot: string) {\n let isNativeModule = false;\n try {\n isNativeModule = await isNativeModuleAsync(projectRoot);\n } catch {\n // We don't care too much about a failure here\n // TODO(@kitten): Remove try/catch; this is only to protect against version misalignment\n // Remove this when we're bumping to SDK 56\n }\n if (isNativeModule) {\n if (!isInteractive()) {\n Log.warn(\n `Current project was detected as a native module, but the command will continue because the terminal is not interactive.`\n );\n return false;\n } else {\n Log.warn('Current project was detected as a native module and not an Expo app.');\n }\n\n const answer = await confirmAsync({\n message: `Continue anyway?`,\n });\n if (!answer) {\n return true;\n }\n\n Log.log();\n }\n\n return false;\n}\n"],"names":["clearNativeFolder","getMalformedNativeProjectsAsync","hasRequiredAndroidFilesAsync","hasRequiredIOSFilesAsync","maybeBailOnNativeModuleAsync","promptToClearMalformedNativeProjectsAsync","projectRoot","folders","step","logNewSection","join","Promise","all","map","folderName","fs","promises","rm","path","recursive","force","succeed","error","fail","message","AndroidConfig","Paths","getAppBuildGradleAsync","getProjectBuildGradleAsync","getAndroidManifestAsync","getMainApplicationAsync","IOSConfig","getAllXcodeProjectPaths","getAllPBXProjectPaths","filterPlatformsThatDoNotExistAsync","platforms","valid","platform","directoryExistsAsync","filter","Boolean","VERIFIERS","android","ios","checkablePlatforms","checkPlatforms","length","displayPlatforms","chalk","cyan","isInteractive","confirmAsync","initial","Log","warn","isNativeModule","isNativeModuleAsync","answer","log"],"mappings":"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"}
|
|
@@ -102,6 +102,10 @@ async function prebuildAsync(projectRoot, options) {
|
|
|
102
102
|
if (await maybeBailOnGitStatusAsync()) {
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
|
+
// Check if the target project is actually a native module, which we don't want to erase
|
|
106
|
+
if (await (0, _clearNativeFolder.maybeBailOnNativeModuleAsync)(projectRoot)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
105
109
|
// Clear the native folders before syncing
|
|
106
110
|
await (0, _clearNativeFolder.clearNativeFolder)(projectRoot, options.platforms);
|
|
107
111
|
} else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/prebuild/prebuildAsync.ts"],"sourcesContent":["import { ExpoConfig, getConfig } from '@expo/config';\nimport { ModPlatform } from '@expo/config-plugins';\nimport chalk from 'chalk';\n\nimport { clearNativeFolder, promptToClearMalformedNativeProjectsAsync } from './clearNativeFolder';\nimport { configureProjectAsync } from './configureProjectAsync';\nimport { ensureConfigAsync } from './ensureConfigAsync';\nimport { assertPlatforms, ensureValidPlatforms, resolveTemplateOption } from './resolveOptions';\nimport { updateFromTemplateAsync } from './updateFromTemplate';\nimport { installAsync } from '../install/installAsync';\nimport { Log } from '../log';\nimport { env } from '../utils/env';\nimport { setNodeEnv, loadEnvFiles } from '../utils/nodeEnv';\nimport { clearNodeModulesAsync } from '../utils/nodeModules';\nimport { logNewSection } from '../utils/ora';\nimport { profile } from '../utils/profile';\nimport { confirmAsync } from '../utils/prompts';\n\nconst debug = require('debug')('expo:prebuild') as typeof console.log;\n\nexport type PrebuildResults = {\n /** Expo config. */\n exp: ExpoConfig;\n /** Indicates if the process created new files. */\n hasNewProjectFiles: boolean;\n /** The platforms that were prebuilt. */\n platforms: ModPlatform[];\n /** Indicates if pod install was run. */\n podInstall: boolean;\n /** Indicates if node modules were installed. */\n nodeInstall: boolean;\n};\n\n/**\n * Entry point into the prebuild process, delegates to other helpers to perform various steps.\n *\n * 0. Attempt to clean the project folders.\n * 1. Create native projects (ios, android).\n * 2. Install node modules.\n * 3. Apply config to native projects.\n * 4. Install CocoaPods.\n */\nexport async function prebuildAsync(\n projectRoot: string,\n options: {\n /** Should install node modules and cocoapods. */\n install?: boolean;\n /** List of platforms to prebuild. */\n platforms: ModPlatform[];\n /** Should delete the native folders before attempting to prebuild. */\n clean?: boolean;\n /** URL or file path to the prebuild template. */\n template?: string;\n /** Name of the node package manager to install with. */\n packageManager?: {\n npm?: boolean;\n yarn?: boolean;\n pnpm?: boolean;\n bun?: boolean;\n };\n /** List of node modules to skip updating. */\n skipDependencyUpdate?: string[];\n }\n): Promise<PrebuildResults | null> {\n setNodeEnv('development');\n loadEnvFiles(projectRoot);\n\n const { platforms } = getConfig(projectRoot).exp;\n if (platforms?.length) {\n // Filter out platforms that aren't in the app.json.\n const finalPlatforms = options.platforms.filter((platform) => platforms.includes(platform));\n if (finalPlatforms.length > 0) {\n options.platforms = finalPlatforms;\n } else {\n const requestedPlatforms = options.platforms.join(', ');\n Log.warn(\n chalk`⚠️ Requested prebuild for \"${requestedPlatforms}\", but only \"${platforms.join(', ')}\" is present in app config (\"expo.platforms\" entry). Continuing with \"${requestedPlatforms}\".`\n );\n }\n }\n if (options.clean) {\n const { maybeBailOnGitStatusAsync } = await import('../utils/git.js');\n // Clean the project folders...\n if (await maybeBailOnGitStatusAsync()) {\n return null;\n }\n // Clear the native folders before syncing\n await clearNativeFolder(projectRoot, options.platforms);\n } else {\n // Check if the existing project folders are malformed.\n await promptToClearMalformedNativeProjectsAsync(projectRoot, options.platforms);\n }\n\n // Warn if the project is attempting to prebuild an unsupported platform (iOS on Windows).\n options.platforms = ensureValidPlatforms(options.platforms);\n // Assert if no platforms are left over after filtering.\n assertPlatforms(options.platforms);\n\n // Get the Expo config, create it if missing.\n const { exp, pkg } = await ensureConfigAsync(projectRoot, { platforms: options.platforms });\n\n // Create native projects from template.\n const { hasNewProjectFiles, needsPodInstall, templateChecksum, changedDependencies } =\n await updateFromTemplateAsync(projectRoot, {\n exp,\n pkg,\n template: options.template != null ? resolveTemplateOption(options.template) : undefined,\n platforms: options.platforms,\n skipDependencyUpdate: options.skipDependencyUpdate,\n });\n\n // Install node modules\n if (options.install) {\n if (changedDependencies.length) {\n if (options.packageManager?.npm) {\n await clearNodeModulesAsync(projectRoot);\n }\n\n Log.log(chalk.gray(chalk`Dependencies in the {bold package.json} changed:`));\n Log.log(chalk.gray(' ' + changedDependencies.join(', ')));\n\n // Installing dependencies is a legacy feature from the unversioned\n // command. We know opt to not change dependencies unless a template\n // indicates a new dependency is required, or if the core dependencies are wrong.\n if (\n await confirmAsync({\n message: `Install the updated dependencies?`,\n initial: true,\n })\n ) {\n await installAsync([], {\n npm: !!options.packageManager?.npm,\n yarn: !!options.packageManager?.yarn,\n pnpm: !!options.packageManager?.pnpm,\n bun: !!options.packageManager?.bun,\n silent: !(env.EXPO_DEBUG || env.CI),\n });\n }\n }\n }\n\n // Apply Expo config to native projects. Prevent log-spew from ora when running in debug mode.\n const configSyncingStep: { succeed(text?: string): unknown; fail(text?: string): unknown } =\n env.EXPO_DEBUG\n ? {\n succeed(text) {\n Log.log(text!);\n },\n fail(text) {\n Log.error(text!);\n },\n }\n : logNewSection('Running prebuild');\n try {\n await profile(configureProjectAsync)(projectRoot, {\n platforms: options.platforms,\n exp,\n templateChecksum,\n });\n configSyncingStep.succeed('Finished prebuild');\n } catch (error) {\n configSyncingStep.fail('Prebuild failed');\n throw error;\n }\n\n // Install CocoaPods\n let podsInstalled: boolean = false;\n // err towards running pod install less because it's slow and users can easily run npx pod-install afterwards.\n if (options.platforms.includes('ios') && options.install && needsPodInstall) {\n const { installCocoaPodsAsync } = await import('../utils/cocoapods.js');\n\n podsInstalled = await installCocoaPodsAsync(projectRoot);\n } else {\n debug('Skipped pod install');\n }\n\n return {\n nodeInstall: !!options.install,\n podInstall: !podsInstalled,\n platforms: options.platforms,\n hasNewProjectFiles,\n exp,\n };\n}\n"],"names":["prebuildAsync","debug","require","projectRoot","options","setNodeEnv","loadEnvFiles","platforms","getConfig","exp","length","finalPlatforms","filter","platform","includes","requestedPlatforms","join","Log","warn","chalk","clean","maybeBailOnGitStatusAsync","clearNativeFolder","promptToClearMalformedNativeProjectsAsync","ensureValidPlatforms","assertPlatforms","pkg","ensureConfigAsync","hasNewProjectFiles","needsPodInstall","templateChecksum","changedDependencies","updateFromTemplateAsync","template","resolveTemplateOption","undefined","skipDependencyUpdate","install","packageManager","npm","clearNodeModulesAsync","log","gray","confirmAsync","message","initial","installAsync","yarn","pnpm","bun","silent","env","EXPO_DEBUG","CI","configSyncingStep","succeed","text","fail","error","logNewSection","profile","configureProjectAsync","podsInstalled","installCocoaPodsAsync","nodeInstall","podInstall"],"mappings":";;;;+BA0CsBA;;;eAAAA;;;;yBA1CgB;;;;;;;gEAEpB;;;;;;mCAE2D;uCACvC;mCACJ;gCAC2C;oCACrC;8BACX;qBACT;qBACA;yBACqB;6BACH;qBACR;yBACN;yBACK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE7B,MAAMC,QAAQC,QAAQ,SAAS;AAwBxB,eAAeF,cACpBG,WAAmB,EACnBC,OAkBC;IAEDC,IAAAA,mBAAU,EAAC;IACXC,IAAAA,qBAAY,EAACH;IAEb,MAAM,EAAEI,SAAS,EAAE,GAAGC,IAAAA,mBAAS,EAACL,aAAaM,GAAG;IAChD,IAAIF,6BAAAA,UAAWG,MAAM,EAAE;QACrB,oDAAoD;QACpD,MAAMC,iBAAiBP,QAAQG,SAAS,CAACK,MAAM,CAAC,CAACC,WAAaN,UAAUO,QAAQ,CAACD;QACjF,IAAIF,eAAeD,MAAM,GAAG,GAAG;YAC7BN,QAAQG,SAAS,GAAGI;QACtB,OAAO;YACL,MAAMI,qBAAqBX,QAAQG,SAAS,CAACS,IAAI,CAAC;YAClDC,QAAG,CAACC,IAAI,CACNC,IAAAA,gBAAK,CAAA,CAAC,4BAA4B,EAAEJ,mBAAmB,aAAa,EAAER,UAAUS,IAAI,CAAC,MAAM,sEAAsE,EAAED,mBAAmB,EAAE,CAAC;QAE7L;IACF;IACA,IAAIX,QAAQgB,KAAK,EAAE;QACjB,MAAM,EAAEC,yBAAyB,EAAE,GAAG,MAAM,mEAAA,QAAO;QACnD,+BAA+B;QAC/B,IAAI,MAAMA,6BAA6B;YACrC,OAAO;QACT;QACA,0CAA0C;QAC1C,MAAMC,IAAAA,oCAAiB,EAACnB,aAAaC,QAAQG,SAAS;IACxD,OAAO;QACL,uDAAuD;QACvD,MAAMgB,IAAAA,4DAAyC,EAACpB,aAAaC,QAAQG,SAAS;IAChF;IAEA,0FAA0F;IAC1FH,QAAQG,SAAS,GAAGiB,IAAAA,oCAAoB,EAACpB,QAAQG,SAAS;IAC1D,wDAAwD;IACxDkB,IAAAA,+BAAe,EAACrB,QAAQG,SAAS;IAEjC,6CAA6C;IAC7C,MAAM,EAAEE,GAAG,EAAEiB,GAAG,EAAE,GAAG,MAAMC,IAAAA,oCAAiB,EAACxB,aAAa;QAAEI,WAAWH,QAAQG,SAAS;IAAC;IAEzF,wCAAwC;IACxC,MAAM,EAAEqB,kBAAkB,EAAEC,eAAe,EAAEC,gBAAgB,EAAEC,mBAAmB,EAAE,GAClF,MAAMC,IAAAA,2CAAuB,EAAC7B,aAAa;QACzCM;QACAiB;QACAO,UAAU7B,QAAQ6B,QAAQ,IAAI,OAAOC,IAAAA,qCAAqB,EAAC9B,QAAQ6B,QAAQ,IAAIE;QAC/E5B,WAAWH,QAAQG,SAAS;QAC5B6B,sBAAsBhC,QAAQgC,oBAAoB;IACpD;IAEF,uBAAuB;IACvB,IAAIhC,QAAQiC,OAAO,EAAE;QACnB,IAAIN,oBAAoBrB,MAAM,EAAE;gBAC1BN;YAAJ,KAAIA,0BAAAA,QAAQkC,cAAc,qBAAtBlC,wBAAwBmC,GAAG,EAAE;gBAC/B,MAAMC,IAAAA,kCAAqB,EAACrC;YAC9B;YAEAc,QAAG,CAACwB,GAAG,CAACtB,gBAAK,CAACuB,IAAI,CAACvB,IAAAA,gBAAK,CAAA,CAAC,gDAAgD,CAAC;YAC1EF,QAAG,CAACwB,GAAG,CAACtB,gBAAK,CAACuB,IAAI,CAAC,OAAOX,oBAAoBf,IAAI,CAAC;YAEnD,mEAAmE;YACnE,oEAAoE;YACpE,iFAAiF;YACjF,IACE,MAAM2B,IAAAA,qBAAY,EAAC;gBACjBC,SAAS,CAAC,iCAAiC,CAAC;gBAC5CC,SAAS;YACX,IACA;oBAESzC,0BACCA,0BACAA,0BACDA;gBAJT,MAAM0C,IAAAA,0BAAY,EAAC,EAAE,EAAE;oBACrBP,KAAK,CAAC,GAACnC,2BAAAA,QAAQkC,cAAc,qBAAtBlC,yBAAwBmC,GAAG;oBAClCQ,MAAM,CAAC,GAAC3C,2BAAAA,QAAQkC,cAAc,qBAAtBlC,yBAAwB2C,IAAI;oBACpCC,MAAM,CAAC,GAAC5C,2BAAAA,QAAQkC,cAAc,qBAAtBlC,yBAAwB4C,IAAI;oBACpCC,KAAK,CAAC,GAAC7C,2BAAAA,QAAQkC,cAAc,qBAAtBlC,yBAAwB6C,GAAG;oBAClCC,QAAQ,CAAEC,CAAAA,QAAG,CAACC,UAAU,IAAID,QAAG,CAACE,EAAE,AAAD;gBACnC;YACF;QACF;IACF;IAEA,8FAA8F;IAC9F,MAAMC,oBACJH,QAAG,CAACC,UAAU,GACV;QACEG,SAAQC,IAAI;YACVvC,QAAG,CAACwB,GAAG,CAACe;QACV;QACAC,MAAKD,IAAI;YACPvC,QAAG,CAACyC,KAAK,CAACF;QACZ;IACF,IACAG,IAAAA,kBAAa,EAAC;IACpB,IAAI;QACF,MAAMC,IAAAA,gBAAO,EAACC,4CAAqB,EAAE1D,aAAa;YAChDI,WAAWH,QAAQG,SAAS;YAC5BE;YACAqB;QACF;QACAwB,kBAAkBC,OAAO,CAAC;IAC5B,EAAE,OAAOG,OAAO;QACdJ,kBAAkBG,IAAI,CAAC;QACvB,MAAMC;IACR;IAEA,oBAAoB;IACpB,IAAII,gBAAyB;IAC7B,8GAA8G;IAC9G,IAAI1D,QAAQG,SAAS,CAACO,QAAQ,CAAC,UAAUV,QAAQiC,OAAO,IAAIR,iBAAiB;QAC3E,MAAM,EAAEkC,qBAAqB,EAAE,GAAG,MAAM,mEAAA,QAAO;QAE/CD,gBAAgB,MAAMC,sBAAsB5D;IAC9C,OAAO;QACLF,MAAM;IACR;IAEA,OAAO;QACL+D,aAAa,CAAC,CAAC5D,QAAQiC,OAAO;QAC9B4B,YAAY,CAACH;QACbvD,WAAWH,QAAQG,SAAS;QAC5BqB;QACAnB;IACF;AACF"}
|
|
1
|
+
{"version":3,"sources":["../../../src/prebuild/prebuildAsync.ts"],"sourcesContent":["import { ExpoConfig, getConfig } from '@expo/config';\nimport { ModPlatform } from '@expo/config-plugins';\nimport chalk from 'chalk';\n\nimport {\n clearNativeFolder,\n promptToClearMalformedNativeProjectsAsync,\n maybeBailOnNativeModuleAsync,\n} from './clearNativeFolder';\nimport { configureProjectAsync } from './configureProjectAsync';\nimport { ensureConfigAsync } from './ensureConfigAsync';\nimport { assertPlatforms, ensureValidPlatforms, resolveTemplateOption } from './resolveOptions';\nimport { updateFromTemplateAsync } from './updateFromTemplate';\nimport { installAsync } from '../install/installAsync';\nimport { Log } from '../log';\nimport { env } from '../utils/env';\nimport { setNodeEnv, loadEnvFiles } from '../utils/nodeEnv';\nimport { clearNodeModulesAsync } from '../utils/nodeModules';\nimport { logNewSection } from '../utils/ora';\nimport { profile } from '../utils/profile';\nimport { confirmAsync } from '../utils/prompts';\n\nconst debug = require('debug')('expo:prebuild') as typeof console.log;\n\nexport type PrebuildResults = {\n /** Expo config. */\n exp: ExpoConfig;\n /** Indicates if the process created new files. */\n hasNewProjectFiles: boolean;\n /** The platforms that were prebuilt. */\n platforms: ModPlatform[];\n /** Indicates if pod install was run. */\n podInstall: boolean;\n /** Indicates if node modules were installed. */\n nodeInstall: boolean;\n};\n\n/**\n * Entry point into the prebuild process, delegates to other helpers to perform various steps.\n *\n * 0. Attempt to clean the project folders.\n * 1. Create native projects (ios, android).\n * 2. Install node modules.\n * 3. Apply config to native projects.\n * 4. Install CocoaPods.\n */\nexport async function prebuildAsync(\n projectRoot: string,\n options: {\n /** Should install node modules and cocoapods. */\n install?: boolean;\n /** List of platforms to prebuild. */\n platforms: ModPlatform[];\n /** Should delete the native folders before attempting to prebuild. */\n clean?: boolean;\n /** URL or file path to the prebuild template. */\n template?: string;\n /** Name of the node package manager to install with. */\n packageManager?: {\n npm?: boolean;\n yarn?: boolean;\n pnpm?: boolean;\n bun?: boolean;\n };\n /** List of node modules to skip updating. */\n skipDependencyUpdate?: string[];\n }\n): Promise<PrebuildResults | null> {\n setNodeEnv('development');\n loadEnvFiles(projectRoot);\n\n const { platforms } = getConfig(projectRoot).exp;\n if (platforms?.length) {\n // Filter out platforms that aren't in the app.json.\n const finalPlatforms = options.platforms.filter((platform) => platforms.includes(platform));\n if (finalPlatforms.length > 0) {\n options.platforms = finalPlatforms;\n } else {\n const requestedPlatforms = options.platforms.join(', ');\n Log.warn(\n chalk`⚠️ Requested prebuild for \"${requestedPlatforms}\", but only \"${platforms.join(', ')}\" is present in app config (\"expo.platforms\" entry). Continuing with \"${requestedPlatforms}\".`\n );\n }\n }\n if (options.clean) {\n const { maybeBailOnGitStatusAsync } = await import('../utils/git.js');\n // Clean the project folders...\n if (await maybeBailOnGitStatusAsync()) {\n return null;\n }\n // Check if the target project is actually a native module, which we don't want to erase\n if (await maybeBailOnNativeModuleAsync(projectRoot)) {\n return null;\n }\n // Clear the native folders before syncing\n await clearNativeFolder(projectRoot, options.platforms);\n } else {\n // Check if the existing project folders are malformed.\n await promptToClearMalformedNativeProjectsAsync(projectRoot, options.platforms);\n }\n\n // Warn if the project is attempting to prebuild an unsupported platform (iOS on Windows).\n options.platforms = ensureValidPlatforms(options.platforms);\n // Assert if no platforms are left over after filtering.\n assertPlatforms(options.platforms);\n\n // Get the Expo config, create it if missing.\n const { exp, pkg } = await ensureConfigAsync(projectRoot, { platforms: options.platforms });\n\n // Create native projects from template.\n const { hasNewProjectFiles, needsPodInstall, templateChecksum, changedDependencies } =\n await updateFromTemplateAsync(projectRoot, {\n exp,\n pkg,\n template: options.template != null ? resolveTemplateOption(options.template) : undefined,\n platforms: options.platforms,\n skipDependencyUpdate: options.skipDependencyUpdate,\n });\n\n // Install node modules\n if (options.install) {\n if (changedDependencies.length) {\n if (options.packageManager?.npm) {\n await clearNodeModulesAsync(projectRoot);\n }\n\n Log.log(chalk.gray(chalk`Dependencies in the {bold package.json} changed:`));\n Log.log(chalk.gray(' ' + changedDependencies.join(', ')));\n\n // Installing dependencies is a legacy feature from the unversioned\n // command. We know opt to not change dependencies unless a template\n // indicates a new dependency is required, or if the core dependencies are wrong.\n if (\n await confirmAsync({\n message: `Install the updated dependencies?`,\n initial: true,\n })\n ) {\n await installAsync([], {\n npm: !!options.packageManager?.npm,\n yarn: !!options.packageManager?.yarn,\n pnpm: !!options.packageManager?.pnpm,\n bun: !!options.packageManager?.bun,\n silent: !(env.EXPO_DEBUG || env.CI),\n });\n }\n }\n }\n\n // Apply Expo config to native projects. Prevent log-spew from ora when running in debug mode.\n const configSyncingStep: { succeed(text?: string): unknown; fail(text?: string): unknown } =\n env.EXPO_DEBUG\n ? {\n succeed(text) {\n Log.log(text!);\n },\n fail(text) {\n Log.error(text!);\n },\n }\n : logNewSection('Running prebuild');\n try {\n await profile(configureProjectAsync)(projectRoot, {\n platforms: options.platforms,\n exp,\n templateChecksum,\n });\n configSyncingStep.succeed('Finished prebuild');\n } catch (error) {\n configSyncingStep.fail('Prebuild failed');\n throw error;\n }\n\n // Install CocoaPods\n let podsInstalled: boolean = false;\n // err towards running pod install less because it's slow and users can easily run npx pod-install afterwards.\n if (options.platforms.includes('ios') && options.install && needsPodInstall) {\n const { installCocoaPodsAsync } = await import('../utils/cocoapods.js');\n\n podsInstalled = await installCocoaPodsAsync(projectRoot);\n } else {\n debug('Skipped pod install');\n }\n\n return {\n nodeInstall: !!options.install,\n podInstall: !podsInstalled,\n platforms: options.platforms,\n hasNewProjectFiles,\n exp,\n };\n}\n"],"names":["prebuildAsync","debug","require","projectRoot","options","setNodeEnv","loadEnvFiles","platforms","getConfig","exp","length","finalPlatforms","filter","platform","includes","requestedPlatforms","join","Log","warn","chalk","clean","maybeBailOnGitStatusAsync","maybeBailOnNativeModuleAsync","clearNativeFolder","promptToClearMalformedNativeProjectsAsync","ensureValidPlatforms","assertPlatforms","pkg","ensureConfigAsync","hasNewProjectFiles","needsPodInstall","templateChecksum","changedDependencies","updateFromTemplateAsync","template","resolveTemplateOption","undefined","skipDependencyUpdate","install","packageManager","npm","clearNodeModulesAsync","log","gray","confirmAsync","message","initial","installAsync","yarn","pnpm","bun","silent","env","EXPO_DEBUG","CI","configSyncingStep","succeed","text","fail","error","logNewSection","profile","configureProjectAsync","podsInstalled","installCocoaPodsAsync","nodeInstall","podInstall"],"mappings":"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"}
|
|
@@ -950,7 +950,7 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
|
|
|
950
950
|
(0, _waitForMetroToObserveTypeScriptFile.observeAnyFileChanges)({
|
|
951
951
|
metro,
|
|
952
952
|
server
|
|
953
|
-
}, (
|
|
953
|
+
}, ({ changes })=>{
|
|
954
954
|
var _exp_extra_router, _exp_extra;
|
|
955
955
|
if (hasApiRoutes) {
|
|
956
956
|
// NOTE(EvanBacon): We aren't sure what files the API routes are using so we'll just invalidate
|
|
@@ -960,23 +960,19 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
|
|
|
960
960
|
// up for a lot of the overhead.
|
|
961
961
|
this.invalidateApiRouteCache();
|
|
962
962
|
} else if (!(0, _router.hasWarnedAboutApiRoutes)()) {
|
|
963
|
-
for (const
|
|
964
|
-
|
|
963
|
+
for (const change of changes.addedFiles){
|
|
964
|
+
if (// If the user did not delete a file that matches the Expo Router API Route convention, then we should warn that
|
|
965
965
|
// API Routes are not enabled in the project.
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
event.filePath.startsWith(appDir) && (0, _router.isApiRouteConvention)(event.filePath)) {
|
|
966
|
+
// Ensure the file is in the project's routes directory to prevent false positives in monorepos.
|
|
967
|
+
change[0].startsWith(appDir) && (0, _router.isApiRouteConvention)(change[0])) {
|
|
969
968
|
(0, _router.warnInvalidWebOutput)();
|
|
970
969
|
}
|
|
971
970
|
}
|
|
972
971
|
}
|
|
973
972
|
// Handle loader file changes for HMR
|
|
974
973
|
if ((_exp_extra = exp.extra) == null ? void 0 : (_exp_extra_router = _exp_extra.router) == null ? void 0 : _exp_extra_router.unstable_useServerDataLoaders) {
|
|
975
|
-
for (const
|
|
976
|
-
|
|
977
|
-
if (((_event_metadata1 = event.metadata) == null ? void 0 : _event_metadata1.type) !== 'd') {
|
|
978
|
-
this.handleLoaderFileChange(event.filePath);
|
|
979
|
-
}
|
|
974
|
+
for (const change of changes.modifiedFiles){
|
|
975
|
+
this.handleLoaderFileChange(change[0]);
|
|
980
976
|
}
|
|
981
977
|
}
|
|
982
978
|
});
|
|
@@ -1157,6 +1153,8 @@ class MetroBundlerDevServer extends _BundlerDevServer.BundlerDevServer {
|
|
|
1157
1153
|
debug('Skipping TypeScript check because Metro is not running (headless).');
|
|
1158
1154
|
return resolve(false);
|
|
1159
1155
|
}
|
|
1156
|
+
// TODO(@kitten): This is highly inefficient. We shouldn't watch all changes to determine this
|
|
1157
|
+
// and instead use startup heuristic and do a pre-bundling check
|
|
1160
1158
|
const off = (0, _metroWatchTypeScriptFiles.metroWatchTypeScriptFiles)({
|
|
1161
1159
|
projectRoot: this.projectRoot,
|
|
1162
1160
|
server: this.instance.server,
|