@stacksjs/actions 0.75.275 → 0.75.277
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/project-scripts.js +78 -7
- package/package.json +41 -41
package/dist/project-scripts.js
CHANGED
|
@@ -57,6 +57,8 @@ public static class StacksOwnedCheck {
|
|
|
57
57
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
58
58
|
static extern bool PeekNamedPipe(IntPtr pipe, IntPtr buffer, uint size, IntPtr read,
|
|
59
59
|
out uint available, IntPtr remaining);
|
|
60
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
61
|
+
static extern bool ReadFile(IntPtr pipe, byte[] buffer, uint count, out uint read, IntPtr overlapped);
|
|
60
62
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
61
63
|
static extern bool CreateProcessW(string application, StringBuilder command, IntPtr processSecurity,
|
|
62
64
|
IntPtr threadSecurity, bool inherit, uint flags, IntPtr environment, string directory,
|
|
@@ -91,6 +93,27 @@ public static class StacksOwnedCheck {
|
|
|
91
93
|
if (error == 109 || error == 232) return true; // Closed control pipe.
|
|
92
94
|
throw new Win32Exception(error);
|
|
93
95
|
}
|
|
96
|
+
static bool AwaitStart() {
|
|
97
|
+
// No consumer can exist until the live Bun host grants permission. It may
|
|
98
|
+
// safely kill a compiling or waiting helper when cancellation wins first.
|
|
99
|
+
Console.Out.WriteLine("STACKS_OWNED_CHECK_READY");
|
|
100
|
+
Console.Out.Flush();
|
|
101
|
+
while (true) {
|
|
102
|
+
uint available;
|
|
103
|
+
if (!PeekNamedPipe(GetStdHandle(-10), IntPtr.Zero, 0, IntPtr.Zero, out available, IntPtr.Zero)) {
|
|
104
|
+
int error = Marshal.GetLastWin32Error();
|
|
105
|
+
if (error == 109 || error == 232) return false;
|
|
106
|
+
throw new Win32Exception(error);
|
|
107
|
+
}
|
|
108
|
+
if (available != 0) {
|
|
109
|
+
byte[] command = new byte[1];
|
|
110
|
+
uint read;
|
|
111
|
+
Require(ReadFile(GetStdHandle(-10), command, 1, out read, IntPtr.Zero));
|
|
112
|
+
return read == 1 && command[0] == 1;
|
|
113
|
+
}
|
|
114
|
+
Thread.Sleep(10);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
94
117
|
static IntPtr Job() {
|
|
95
118
|
IntPtr job = CreateJobObjectW(IntPtr.Zero, null);
|
|
96
119
|
Require(job != IntPtr.Zero);
|
|
@@ -101,8 +124,8 @@ public static class StacksOwnedCheck {
|
|
|
101
124
|
return job;
|
|
102
125
|
}
|
|
103
126
|
public static int Run(string bun, string script) {
|
|
104
|
-
//
|
|
105
|
-
//
|
|
127
|
+
// The control pipe is never inherited as consumer stdin. Prepare both
|
|
128
|
+
// ownership jobs before reporting readiness or accepting startup permission.
|
|
106
129
|
if (StopRequested()) return 1;
|
|
107
130
|
// The outer job owns this host before it creates anything. If cancellation
|
|
108
131
|
// races suspended-child assignment below, host death still kills that child.
|
|
@@ -113,6 +136,7 @@ public static class StacksOwnedCheck {
|
|
|
113
136
|
IntPtr commandJob = Job();
|
|
114
137
|
ProcessInfo child = new ProcessInfo();
|
|
115
138
|
try {
|
|
139
|
+
if (!AwaitStart() || StopRequested()) return 1;
|
|
116
140
|
Startup startup = new Startup();
|
|
117
141
|
startup.Size = (uint)Marshal.SizeOf(typeof(Startup));
|
|
118
142
|
startup.Flags = 0x100; // STARTF_USESTDHANDLES
|
|
@@ -175,6 +199,7 @@ exit [StacksOwnedCheck]::Run('${bun.replaceAll("'","''")}', '${script}')
|
|
|
175
199
|
setInterval(() => {}, 60_000)
|
|
176
200
|
let command
|
|
177
201
|
let stopRequested = false
|
|
202
|
+
let consumerPermitted = false
|
|
178
203
|
let start
|
|
179
204
|
const permitted = new Promise(resolve => { start = resolve })
|
|
180
205
|
process.on('message', async (message) => {
|
|
@@ -183,8 +208,16 @@ process.on('message', async (message) => {
|
|
|
183
208
|
start()
|
|
184
209
|
if (command) {
|
|
185
210
|
try {
|
|
186
|
-
|
|
187
|
-
|
|
211
|
+
if (!consumerPermitted) {
|
|
212
|
+
// Preparation may itself spawn the C# compiler. Before permission,
|
|
213
|
+
// the entire helper tree is disposable without interrupting user code.
|
|
214
|
+
const killed = Bun.spawnSync([${JSON.stringify(windowsTaskkill)}, '/PID', String(command.pid), '/T', '/F'], { stdout: 'ignore', stderr: 'ignore', timeout: 2000 })
|
|
215
|
+
if (killed.exitCode !== 0 && command.exitCode === null) throw new Error('Native preparation cleanup failed')
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
command.stdin.write(new Uint8Array([2]))
|
|
219
|
+
await command.stdin.flush()
|
|
220
|
+
}
|
|
188
221
|
} catch (error) { process.send({ error: String(error) }) }
|
|
189
222
|
}
|
|
190
223
|
} else if (message?.start) start()
|
|
@@ -194,10 +227,48 @@ await permitted
|
|
|
194
227
|
if (stopRequested) process.send({ exitCode: 1 })
|
|
195
228
|
else {
|
|
196
229
|
try {
|
|
197
|
-
command = Bun.spawn(${JSON.stringify(command)}, { stdin: 'pipe', stdout: '
|
|
230
|
+
command = Bun.spawn(${JSON.stringify(command)}, { stdin: 'pipe', stdout: 'pipe', stderr: 'inherit' })
|
|
198
231
|
process.send({ helperPid: command.pid })
|
|
199
|
-
|
|
200
|
-
|
|
232
|
+
const forward = async () => {
|
|
233
|
+
const reader = command.stdout.getReader()
|
|
234
|
+
let prefix = Buffer.alloc(0)
|
|
235
|
+
let ready = false
|
|
236
|
+
try {
|
|
237
|
+
while (true) {
|
|
238
|
+
const next = await reader.read()
|
|
239
|
+
if (next.done) break
|
|
240
|
+
if (ready) { await Bun.write(Bun.stdout, next.value); continue }
|
|
241
|
+
prefix = Buffer.concat([prefix, Buffer.from(next.value)])
|
|
242
|
+
const line = prefix.indexOf(10)
|
|
243
|
+
if (line < 0) {
|
|
244
|
+
if (prefix.length > 128) throw new Error('Native ownership readiness was malformed')
|
|
245
|
+
continue
|
|
246
|
+
}
|
|
247
|
+
if (prefix.subarray(0, line).toString().trimEnd() !== 'STACKS_OWNED_CHECK_READY')
|
|
248
|
+
throw new Error('Native ownership readiness was malformed')
|
|
249
|
+
ready = true
|
|
250
|
+
if (!stopRequested) {
|
|
251
|
+
// This assignment and write share one event-loop turn. A later
|
|
252
|
+
// stop therefore uses cooperative Job Object cleanup, never the
|
|
253
|
+
// preparation-only kill once user code could be running.
|
|
254
|
+
consumerPermitted = true
|
|
255
|
+
command.stdin.write(new Uint8Array([1]))
|
|
256
|
+
await command.stdin.flush()
|
|
257
|
+
}
|
|
258
|
+
if (prefix.length > line + 1) await Bun.write(Bun.stdout, prefix.subarray(line + 1))
|
|
259
|
+
prefix = Buffer.alloc(0)
|
|
260
|
+
}
|
|
261
|
+
if (!ready && !stopRequested) throw new Error('Native ownership readiness was not received')
|
|
262
|
+
} finally { reader.releaseLock() }
|
|
263
|
+
}
|
|
264
|
+
const [code] = await Promise.all([command.exited, forward()])
|
|
265
|
+
process.send({ exitCode: code })
|
|
266
|
+
} catch (error) {
|
|
267
|
+
if (command && !consumerPermitted) {
|
|
268
|
+
try { command.kill('SIGKILL'); await command.exited } catch {}
|
|
269
|
+
}
|
|
270
|
+
process.send({ error: String(error) })
|
|
271
|
+
}
|
|
201
272
|
}
|
|
202
273
|
`:`
|
|
203
274
|
setInterval(() => {}, 60_000)
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/actions",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.277",
|
|
6
6
|
"description": "The Stacks actions.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -66,58 +66,58 @@
|
|
|
66
66
|
"prepublishOnly": "bun run build"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@stacksjs/action-runner": "0.75.
|
|
70
|
-
"@stacksjs/ai": "0.75.
|
|
71
|
-
"@stacksjs/analytics": "0.75.
|
|
72
|
-
"@stacksjs/api": "0.75.
|
|
73
|
-
"@stacksjs/auth": "0.75.
|
|
74
|
-
"@stacksjs/build": "0.75.
|
|
69
|
+
"@stacksjs/action-runner": "0.75.277",
|
|
70
|
+
"@stacksjs/ai": "0.75.277",
|
|
71
|
+
"@stacksjs/analytics": "0.75.277",
|
|
72
|
+
"@stacksjs/api": "0.75.277",
|
|
73
|
+
"@stacksjs/auth": "0.75.277",
|
|
74
|
+
"@stacksjs/build": "0.75.277",
|
|
75
75
|
"@stacksjs/bumpx": "^0.2.26",
|
|
76
76
|
"@stacksjs/bunpress": "^0.2.15",
|
|
77
|
-
"@stacksjs/cli": "0.75.
|
|
78
|
-
"@stacksjs/cloud": "0.75.
|
|
79
|
-
"@stacksjs/cms": "0.75.
|
|
77
|
+
"@stacksjs/cli": "0.75.277",
|
|
78
|
+
"@stacksjs/cloud": "0.75.277",
|
|
79
|
+
"@stacksjs/cms": "0.75.277",
|
|
80
80
|
"@stacksjs/components": "0.2.670",
|
|
81
|
-
"@stacksjs/config": "0.75.
|
|
82
|
-
"@stacksjs/database": "0.75.
|
|
83
|
-
"@stacksjs/desktop-build": "0.75.
|
|
84
|
-
"@stacksjs/dns": "0.75.
|
|
85
|
-
"@stacksjs/enums": "0.75.
|
|
86
|
-
"@stacksjs/env": "0.75.
|
|
87
|
-
"@stacksjs/error-handling": "0.75.
|
|
88
|
-
"@stacksjs/github": "0.75.
|
|
81
|
+
"@stacksjs/config": "0.75.277",
|
|
82
|
+
"@stacksjs/database": "0.75.277",
|
|
83
|
+
"@stacksjs/desktop-build": "0.75.277",
|
|
84
|
+
"@stacksjs/dns": "0.75.277",
|
|
85
|
+
"@stacksjs/enums": "0.75.277",
|
|
86
|
+
"@stacksjs/env": "0.75.277",
|
|
87
|
+
"@stacksjs/error-handling": "0.75.277",
|
|
88
|
+
"@stacksjs/github": "0.75.277",
|
|
89
89
|
"@stacksjs/gitit": "^0.2.5",
|
|
90
|
-
"@stacksjs/i18n": "0.75.
|
|
91
|
-
"@stacksjs/image": "0.75.
|
|
92
|
-
"@stacksjs/logging": "0.75.
|
|
90
|
+
"@stacksjs/i18n": "0.75.277",
|
|
91
|
+
"@stacksjs/image": "0.75.277",
|
|
92
|
+
"@stacksjs/logging": "0.75.277",
|
|
93
93
|
"@stacksjs/logsmith": "^0.2.11",
|
|
94
|
-
"@stacksjs/mobile": "0.75.
|
|
95
|
-
"@stacksjs/orm": "0.75.
|
|
96
|
-
"@stacksjs/path": "0.75.
|
|
97
|
-
"@stacksjs/payments": "0.75.
|
|
98
|
-
"@stacksjs/queue": "0.75.
|
|
99
|
-
"@stacksjs/registry": "0.75.
|
|
100
|
-
"@stacksjs/router": "0.75.
|
|
94
|
+
"@stacksjs/mobile": "0.75.277",
|
|
95
|
+
"@stacksjs/orm": "0.75.277",
|
|
96
|
+
"@stacksjs/path": "0.75.277",
|
|
97
|
+
"@stacksjs/payments": "0.75.277",
|
|
98
|
+
"@stacksjs/queue": "0.75.277",
|
|
99
|
+
"@stacksjs/registry": "0.75.277",
|
|
100
|
+
"@stacksjs/router": "0.75.277",
|
|
101
101
|
"@stacksjs/rpx": "^0.11.54",
|
|
102
|
-
"@stacksjs/scheduler": "0.75.
|
|
103
|
-
"@stacksjs/search-engine": "0.75.
|
|
104
|
-
"@stacksjs/security": "0.75.
|
|
105
|
-
"@stacksjs/server": "0.75.
|
|
106
|
-
"@stacksjs/sites": "0.75.
|
|
107
|
-
"@stacksjs/storage": "0.75.
|
|
108
|
-
"@stacksjs/strings": "0.75.
|
|
102
|
+
"@stacksjs/scheduler": "0.75.277",
|
|
103
|
+
"@stacksjs/search-engine": "0.75.277",
|
|
104
|
+
"@stacksjs/security": "0.75.277",
|
|
105
|
+
"@stacksjs/server": "0.75.277",
|
|
106
|
+
"@stacksjs/sites": "0.75.277",
|
|
107
|
+
"@stacksjs/storage": "0.75.277",
|
|
108
|
+
"@stacksjs/strings": "0.75.277",
|
|
109
109
|
"@stacksjs/stx": "0.2.670",
|
|
110
110
|
"@stacksjs/tlsx": "^0.13.19",
|
|
111
111
|
"@stacksjs/ts-cloud": "^0.16.58",
|
|
112
112
|
"@stacksjs/ts-md": "^0.1.1",
|
|
113
|
-
"@stacksjs/tunnel": "0.75.
|
|
114
|
-
"@stacksjs/types": "0.75.
|
|
115
|
-
"@stacksjs/utils": "0.75.
|
|
116
|
-
"@stacksjs/whois": "0.75.
|
|
113
|
+
"@stacksjs/tunnel": "0.75.277",
|
|
114
|
+
"@stacksjs/types": "0.75.277",
|
|
115
|
+
"@stacksjs/utils": "0.75.277",
|
|
116
|
+
"@stacksjs/whois": "0.75.277",
|
|
117
117
|
"bun-plugin-stx": "0.2.670"
|
|
118
118
|
},
|
|
119
119
|
"peerDependencies": {
|
|
120
|
-
"craft-native": ">=0.0.
|
|
120
|
+
"craft-native": ">=0.0.301",
|
|
121
121
|
"pickier": "^0.1.75"
|
|
122
122
|
},
|
|
123
123
|
"peerDependenciesMeta": {
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
}
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
|
-
"@stacksjs/validation": "0.75.
|
|
132
|
+
"@stacksjs/validation": "0.75.277",
|
|
133
133
|
"better-dx": "^0.2.24"
|
|
134
134
|
}
|
|
135
135
|
}
|