@astrale-os/cli 1.0.0-beta.4 → 1.0.0-beta.5
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/astrale.js +29682 -35214
- package/dist/public/connect-core.js +24198 -30085
- package/dist/public/keys/index.js +24086 -30014
- package/dist/public/paths/index.js +23680 -29365
- package/dist/types/lib/idp.d.ts +1 -0
- package/dist/types/lib/update.d.ts +30 -0
- package/package.json +8 -5
- package/src/admin/__tests__/binding.test.ts +3 -3
- package/src/admin/binding.ts +4 -4
- package/src/admin/catalog/.spec/api.d.ts +1 -1
- package/src/admin/instance/.spec/api.d.ts +1 -1
- package/src/commands/__tests__/update.test.ts +25 -3
- package/src/commands/update.ts +31 -11
- package/src/lib/__tests__/idp.test.ts +25 -0
- package/src/lib/__tests__/update.test.ts +101 -8
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +1 -1
- package/src/lib/__tests__/view-session.test.ts +1 -1
- package/src/lib/idp.ts +29 -1
- package/src/lib/update.ts +120 -26
- package/studio/client/dist/assets/{elk-api-lwhFo7vB.js → elk-api-YEDvaNU-.js} +1 -1
- package/studio/client/dist/assets/{index-BckHuAWk.js → index-C-PvAXV4.js} +2 -2
- package/studio/client/dist/assets/{index-B-c-smo9.js → index-CzpmJD0j.js} +4 -4
- package/studio/client/dist/index.html +1 -1
- package/studio/package.json +7 -9
- package/studio/server/introspect/runtime.test.ts +2 -2
- package/studio/shared/contracts/surface.test.ts +1 -0
- package/viewer/dist/main.js +27 -51
package/src/lib/update.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
chmod,
|
|
4
|
+
copyFile,
|
|
5
|
+
mkdir,
|
|
6
|
+
mkdtemp,
|
|
7
|
+
readFile,
|
|
8
|
+
realpath,
|
|
9
|
+
rename,
|
|
10
|
+
rm,
|
|
11
|
+
writeFile,
|
|
12
|
+
} from 'node:fs/promises'
|
|
3
13
|
import { tmpdir } from 'node:os'
|
|
4
14
|
import { dirname, join } from 'node:path'
|
|
5
15
|
import { z } from 'zod'
|
|
@@ -61,9 +71,26 @@ export type UpdateRequest = {
|
|
|
61
71
|
currentVersion: string
|
|
62
72
|
platform?: Platform
|
|
63
73
|
installPath?: string
|
|
74
|
+
execution?: UpdateExecution
|
|
64
75
|
}
|
|
65
76
|
|
|
77
|
+
export type UpdateExecution =
|
|
78
|
+
| { kind: 'standalone'; executable: string }
|
|
79
|
+
| { kind: 'package-managed'; executable: string }
|
|
80
|
+
|
|
81
|
+
const admittedScriptInstall = Symbol('admittedScriptInstall')
|
|
82
|
+
export type AdmittedScriptInstall = Readonly<{
|
|
83
|
+
metadata: InstallMetadata
|
|
84
|
+
executable: string
|
|
85
|
+
[admittedScriptInstall]: true
|
|
86
|
+
}>
|
|
87
|
+
|
|
66
88
|
export type UpdateResult =
|
|
89
|
+
| {
|
|
90
|
+
status: 'managed'
|
|
91
|
+
currentVersion: string
|
|
92
|
+
executable: string
|
|
93
|
+
}
|
|
67
94
|
| {
|
|
68
95
|
status: 'up-to-date'
|
|
69
96
|
currentVersion: string
|
|
@@ -106,42 +133,99 @@ export function platformKey(platform: Platform): string {
|
|
|
106
133
|
return `${platform.os}-${platform.arch}`
|
|
107
134
|
}
|
|
108
135
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
136
|
+
export function classifyUpdateExecution(input: {
|
|
137
|
+
bunVersion?: string
|
|
138
|
+
executable: string
|
|
139
|
+
entry?: string
|
|
140
|
+
}): UpdateExecution {
|
|
141
|
+
return input.bunVersion && input.entry?.startsWith('/$bunfs/')
|
|
142
|
+
? { kind: 'standalone', executable: input.executable }
|
|
143
|
+
: { kind: 'package-managed', executable: input.executable }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function detectUpdateExecution(): UpdateExecution {
|
|
147
|
+
return classifyUpdateExecution({
|
|
148
|
+
bunVersion: (process.versions as { bun?: string }).bun,
|
|
149
|
+
executable: process.execPath,
|
|
150
|
+
entry: process.argv[1],
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function packageManagedUpdateError(executable: string): AstraleError {
|
|
155
|
+
return new AstraleError(
|
|
156
|
+
'UPDATE_PACKAGE_MANAGED',
|
|
157
|
+
'This Astrale build is managed by your package manager.',
|
|
158
|
+
`Active binary: ${executable}. Update it with npm, pnpm, or bun; or put the official script installation first on PATH.`,
|
|
159
|
+
)
|
|
116
160
|
}
|
|
117
161
|
|
|
118
162
|
export async function readInstallMetadata(path = INSTALL_PATH): Promise<InstallMetadata> {
|
|
119
163
|
let raw: string
|
|
120
164
|
try {
|
|
121
165
|
raw = await readFile(path, 'utf8')
|
|
122
|
-
} catch {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
: new AstraleError(
|
|
130
|
-
'UPDATE_PACKAGE_MANAGED',
|
|
131
|
-
'This Astrale build is managed by your package manager.',
|
|
132
|
-
'Update with: npm install -g @astrale-os/cli@latest (or pnpm/bun)',
|
|
133
|
-
)
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (!isMissingFile(error)) throw error
|
|
168
|
+
throw new AstraleError(
|
|
169
|
+
'UPDATE_NOT_SCRIPT_INSTALLED',
|
|
170
|
+
'Astrale was not installed by the official install script.',
|
|
171
|
+
'Reinstall with: curl -fsSL https://raw.githubusercontent.com/astrale-os/cli/main/install.sh | sh',
|
|
172
|
+
)
|
|
134
173
|
}
|
|
135
174
|
|
|
136
|
-
|
|
175
|
+
let decoded: unknown
|
|
176
|
+
try {
|
|
177
|
+
decoded = JSON.parse(raw)
|
|
178
|
+
} catch {
|
|
179
|
+
throw badInstallMetadata(path)
|
|
180
|
+
}
|
|
181
|
+
const parsed = InstallMetadataSchema.safeParse(decoded)
|
|
137
182
|
if (!parsed.success) {
|
|
183
|
+
throw badInstallMetadata(path)
|
|
184
|
+
}
|
|
185
|
+
return parsed.data
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isMissingFile(error: unknown): error is NodeJS.ErrnoException {
|
|
189
|
+
return error instanceof Error && 'code' in error && error.code === 'ENOENT'
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function badInstallMetadata(path: string): AstraleError {
|
|
193
|
+
return new AstraleError(
|
|
194
|
+
'UPDATE_BAD_INSTALL_METADATA',
|
|
195
|
+
`Invalid install metadata at ${path}.`,
|
|
196
|
+
'Reinstall with: curl -fsSL https://raw.githubusercontent.com/astrale-os/cli/main/install.sh | sh',
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export async function admitScriptInstall(
|
|
201
|
+
meta: InstallMetadata,
|
|
202
|
+
execution: Extract<UpdateExecution, { kind: 'standalone' }>,
|
|
203
|
+
): Promise<AdmittedScriptInstall> {
|
|
204
|
+
const [running, recorded] = await Promise.all([
|
|
205
|
+
realpathIfExists(execution.executable),
|
|
206
|
+
realpathIfExists(meta.bin),
|
|
207
|
+
])
|
|
208
|
+
if (running === undefined || recorded === undefined || running !== recorded) {
|
|
138
209
|
throw new AstraleError(
|
|
139
|
-
'
|
|
140
|
-
|
|
141
|
-
|
|
210
|
+
'UPDATE_INSTALL_MISMATCH',
|
|
211
|
+
'The running Astrale binary does not own the recorded script installation.',
|
|
212
|
+
`Running binary: ${execution.executable}; recorded binary: ${meta.bin}. Refusing to replace a different installation.`,
|
|
142
213
|
)
|
|
143
214
|
}
|
|
144
|
-
return
|
|
215
|
+
return Object.freeze({
|
|
216
|
+
metadata: meta,
|
|
217
|
+
executable: running,
|
|
218
|
+
[admittedScriptInstall]: true as const,
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function realpathIfExists(path: string): Promise<string | undefined> {
|
|
223
|
+
try {
|
|
224
|
+
return await realpath(path)
|
|
225
|
+
} catch (error) {
|
|
226
|
+
if (isMissingFile(error)) return undefined
|
|
227
|
+
throw error
|
|
228
|
+
}
|
|
145
229
|
}
|
|
146
230
|
|
|
147
231
|
export async function writeInstallMetadata(
|
|
@@ -175,7 +259,17 @@ export function shouldUpdate(currentVersion: string, manifestVersion: string): b
|
|
|
175
259
|
}
|
|
176
260
|
|
|
177
261
|
export async function updateAstrale(req: UpdateRequest): Promise<UpdateResult> {
|
|
178
|
-
const
|
|
262
|
+
const execution = req.execution ?? detectUpdateExecution()
|
|
263
|
+
if (execution.kind === 'package-managed') {
|
|
264
|
+
return {
|
|
265
|
+
status: 'managed',
|
|
266
|
+
currentVersion: req.currentVersion,
|
|
267
|
+
executable: execution.executable,
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const install = await admitScriptInstall(await readInstallMetadata(req.installPath), execution)
|
|
272
|
+
const meta = install.metadata
|
|
179
273
|
const currentVersion = meta.version ?? req.currentVersion
|
|
180
274
|
const channel = req.channel ?? meta.channel ?? DEFAULT_UPDATE_CHANNEL
|
|
181
275
|
const platform = req.platform ?? detectPlatform()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as L}from"./index-
|
|
1
|
+
import{m as L}from"./index-C-PvAXV4.js";function S(y,b){for(var u=0;u<b.length;u++){const a=b[u];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in y)){const n=Object.getOwnPropertyDescriptor(a,i);n&&Object.defineProperty(y,i,n.get?n:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(y,Symbol.toStringTag,{value:"Module"}))}function w(y){throw new Error('Could not dynamically require "'+y+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var O={exports:{}},j;function C(){return j||(j=1,(function(y,b){(function(u){y.exports=u()})(function(){return(function(){function u(a,i,n){function d(f,_){if(!i[f]){if(!a[f]){var h=typeof w=="function"&&w;if(!_&&h)return h(f,!0);if(g)return g(f,!0);var o=new Error("Cannot find module '"+f+"'");throw o.code="MODULE_NOT_FOUND",o}var e=i[f]={exports:{}};a[f][0].call(e.exports,function(r){var t=a[f][1][r];return d(t||r)},e,e.exports,u,a,i,n)}return i[f].exports}for(var g=typeof w=="function"&&w,m=0;m<n.length;m++)d(n[m]);return d}return u})()({1:[function(u,a,i){Object.defineProperty(i,"__esModule",{value:!0}),i.default=void 0;function n(o){"@babel/helpers - typeof";return n=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(o)}function d(o,e){if(!(o instanceof e))throw new TypeError("Cannot call a class as a function")}function g(o,e){for(var r=0;r<e.length;r++){var t=e[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(o,f(t.key),t)}}function m(o,e,r){return e&&g(o.prototype,e),Object.defineProperty(o,"prototype",{writable:!1}),o}function f(o){var e=_(o,"string");return n(e)=="symbol"?e:e+""}function _(o,e){if(n(o)!="object"||!o)return o;var r=o[Symbol.toPrimitive];if(r!==void 0){var t=r.call(o,e);if(n(t)!="object")return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(o)}i.default=(function(){function o(){var e=this,r=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=r.defaultLayoutOptions,s=t===void 0?{}:t,l=r.algorithms,v=l===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:l,c=r.workerFactory,p=r.workerUrl;if(d(this,o),this.defaultLayoutOptions=s,this.initialized=!1,typeof p>"u"&&typeof c>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var k=c;typeof p<"u"&&typeof c>"u"&&(k=function(M){return new Worker(M)});var E=k(p);if(typeof E.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new h(E),this.worker.postMessage({cmd:"register",algorithms:v}).then(function(P){return e.initialized=!0}).catch(console.err)}return m(o,[{key:"layout",value:function(r){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},s=t.layoutOptions,l=s===void 0?this.defaultLayoutOptions:s,v=t.logging,c=v===void 0?!1:v,p=t.measureExecutionTime,k=p===void 0?!1:p;return r?this.worker.postMessage({cmd:"layout",graph:r,layoutOptions:l,options:{logging:c,measureExecutionTime:k}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker&&this.worker.terminate()}}])})();var h=(function(){function o(e){var r=this;if(d(this,o),e===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=e,this.worker.onmessage=function(t){setTimeout(function(){r.receive(r,t)},0)}}return m(o,[{key:"postMessage",value:function(r){var t=this.id||0;this.id=t+1,r.id=t;var s=this;return new Promise(function(l,v){s.resolvers[t]=function(c,p){c?(s.convertGwtStyleError(c),v(c)):l(p)},s.worker.postMessage(r)})}},{key:"receive",value:function(r,t){var s=t.data,l=r.resolvers[s.id];l&&(delete r.resolvers[s.id],s.error?l(s.error):l(null,s.data))}},{key:"terminate",value:function(){this.worker&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(r){if(r){var t=r.__java$exception;t&&(t.cause&&t.cause.backingJsObject&&(r.cause=t.cause.backingJsObject,this.convertGwtStyleError(r.cause)),delete r.__java$exception)}}}])})()},{}],2:[function(u,a,i){var n=u("./elk-api.js").default;Object.defineProperty(a.exports,"__esModule",{value:!0}),a.exports=n,n.default=n},{"./elk-api.js":1}]},{},[2])(2)})})(O)),O.exports}var x=C();const A=L(x),q=S({__proto__:null,default:A},[x]);export{q as e};
|