@arcote.tech/arc-cli 0.7.16 → 0.7.18
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/index.js +638 -711
- package/package.json +9 -9
- package/src/builder/chunk-planner.ts +92 -8
- package/src/platform/server.ts +14 -11
- package/src/platform/shared.ts +5 -1
package/dist/index.js
CHANGED
|
@@ -14004,6 +14004,38 @@ class AuthAdapter {
|
|
|
14004
14004
|
this.scopes.clear();
|
|
14005
14005
|
}
|
|
14006
14006
|
}
|
|
14007
|
+
function triggerModuleSync(scope, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
14008
|
+
if (!provider) {
|
|
14009
|
+
latestSync = Promise.resolve();
|
|
14010
|
+
return latestSync;
|
|
14011
|
+
}
|
|
14012
|
+
const seq = ++syncSeq;
|
|
14013
|
+
const run = (async () => {
|
|
14014
|
+
try {
|
|
14015
|
+
await provider(scope);
|
|
14016
|
+
} catch (err3) {
|
|
14017
|
+
console.warn("[arc] module sync failed during setToken:", err3);
|
|
14018
|
+
}
|
|
14019
|
+
})();
|
|
14020
|
+
const guarded = new Promise((resolve) => {
|
|
14021
|
+
let settled = false;
|
|
14022
|
+
const done = () => {
|
|
14023
|
+
if (settled)
|
|
14024
|
+
return;
|
|
14025
|
+
settled = true;
|
|
14026
|
+
resolve();
|
|
14027
|
+
};
|
|
14028
|
+
const timer = setTimeout(() => {
|
|
14029
|
+
console.warn(`[arc] module sync did not complete within ${timeoutMs}ms; proceeding anyway.`);
|
|
14030
|
+
done();
|
|
14031
|
+
}, timeoutMs);
|
|
14032
|
+
timer?.unref?.();
|
|
14033
|
+
run.then(done, done).finally(() => clearTimeout(timer));
|
|
14034
|
+
});
|
|
14035
|
+
if (seq === syncSeq)
|
|
14036
|
+
latestSync = guarded;
|
|
14037
|
+
return guarded;
|
|
14038
|
+
}
|
|
14007
14039
|
|
|
14008
14040
|
class EventWire {
|
|
14009
14041
|
baseUrl;
|
|
@@ -14017,7 +14049,8 @@ class EventWire {
|
|
|
14017
14049
|
onSyncedCallback;
|
|
14018
14050
|
reconnectTimeout;
|
|
14019
14051
|
syncRequested = false;
|
|
14020
|
-
|
|
14052
|
+
querySubscriptions = new Map;
|
|
14053
|
+
querySubCounter = 0;
|
|
14021
14054
|
enableEventSync;
|
|
14022
14055
|
constructor(baseUrl, options) {
|
|
14023
14056
|
this.baseUrl = baseUrl;
|
|
@@ -14072,7 +14105,7 @@ class EventWire {
|
|
|
14072
14105
|
this.requestSync();
|
|
14073
14106
|
}
|
|
14074
14107
|
this.flushPendingEvents();
|
|
14075
|
-
this.
|
|
14108
|
+
this.sendAllQuerySubscriptions();
|
|
14076
14109
|
} else {
|
|
14077
14110
|
console.log(`[EventWire] onopen called but ws is not OPEN, readyState:`, this.ws?.readyState);
|
|
14078
14111
|
}
|
|
@@ -14148,24 +14181,29 @@ class EventWire {
|
|
|
14148
14181
|
onSynced(callback) {
|
|
14149
14182
|
this.onSyncedCallback = callback;
|
|
14150
14183
|
}
|
|
14151
|
-
|
|
14152
|
-
const
|
|
14153
|
-
this.
|
|
14184
|
+
subscribeQuery(descriptor, scope, callbacks) {
|
|
14185
|
+
const subscriptionId = `qs_${this.instanceId}_${++this.querySubCounter}`;
|
|
14186
|
+
this.querySubscriptions.set(subscriptionId, {
|
|
14187
|
+
descriptor,
|
|
14188
|
+
scope,
|
|
14189
|
+
callbacks
|
|
14190
|
+
});
|
|
14154
14191
|
if (this.state === "connected" && this.ws) {
|
|
14155
14192
|
this.ws.send(JSON.stringify({
|
|
14156
|
-
type: "subscribe-
|
|
14157
|
-
|
|
14193
|
+
type: "subscribe-query",
|
|
14194
|
+
subscriptionId,
|
|
14195
|
+
descriptor,
|
|
14158
14196
|
scope
|
|
14159
14197
|
}));
|
|
14160
14198
|
}
|
|
14199
|
+
return subscriptionId;
|
|
14161
14200
|
}
|
|
14162
|
-
|
|
14163
|
-
this.
|
|
14201
|
+
unsubscribeQuery(subscriptionId) {
|
|
14202
|
+
this.querySubscriptions.delete(subscriptionId);
|
|
14164
14203
|
if (this.state === "connected" && this.ws) {
|
|
14165
14204
|
this.ws.send(JSON.stringify({
|
|
14166
|
-
type: "unsubscribe-
|
|
14167
|
-
|
|
14168
|
-
scope
|
|
14205
|
+
type: "unsubscribe-query",
|
|
14206
|
+
subscriptionId
|
|
14169
14207
|
}));
|
|
14170
14208
|
}
|
|
14171
14209
|
}
|
|
@@ -14200,17 +14238,17 @@ class EventWire {
|
|
|
14200
14238
|
this.lastHostEventId = message.lastHostEventId;
|
|
14201
14239
|
}
|
|
14202
14240
|
break;
|
|
14203
|
-
case "
|
|
14204
|
-
const sub = this.
|
|
14241
|
+
case "query-snapshot": {
|
|
14242
|
+
const sub = this.querySubscriptions.get(message.subscriptionId);
|
|
14205
14243
|
if (sub) {
|
|
14206
|
-
sub.onSnapshot(message.
|
|
14244
|
+
sub.callbacks.onSnapshot(message.result ?? null);
|
|
14207
14245
|
}
|
|
14208
14246
|
break;
|
|
14209
14247
|
}
|
|
14210
|
-
case "
|
|
14211
|
-
const sub = this.
|
|
14248
|
+
case "query-changes": {
|
|
14249
|
+
const sub = this.querySubscriptions.get(message.subscriptionId);
|
|
14212
14250
|
if (sub && Array.isArray(message.changes)) {
|
|
14213
|
-
sub.onChanges(message.changes);
|
|
14251
|
+
sub.callbacks.onChanges(message.changes);
|
|
14214
14252
|
}
|
|
14215
14253
|
break;
|
|
14216
14254
|
}
|
|
@@ -14238,17 +14276,15 @@ class EventWire {
|
|
|
14238
14276
|
this.pendingEvents = [];
|
|
14239
14277
|
}
|
|
14240
14278
|
}
|
|
14241
|
-
|
|
14279
|
+
sendAllQuerySubscriptions() {
|
|
14242
14280
|
if (!this.ws || this.state !== "connected")
|
|
14243
14281
|
return;
|
|
14244
|
-
for (const
|
|
14245
|
-
const sepIdx = key.indexOf(":");
|
|
14246
|
-
const scope = key.slice(0, sepIdx);
|
|
14247
|
-
const element = key.slice(sepIdx + 1);
|
|
14282
|
+
for (const [subscriptionId, sub] of this.querySubscriptions) {
|
|
14248
14283
|
this.ws.send(JSON.stringify({
|
|
14249
|
-
type: "subscribe-
|
|
14250
|
-
|
|
14251
|
-
|
|
14284
|
+
type: "subscribe-query",
|
|
14285
|
+
subscriptionId,
|
|
14286
|
+
descriptor: sub.descriptor,
|
|
14287
|
+
scope: sub.scope
|
|
14252
14288
|
}));
|
|
14253
14289
|
}
|
|
14254
14290
|
}
|
|
@@ -14267,19 +14303,12 @@ class LocalEventPublisher2 {
|
|
|
14267
14303
|
views = [];
|
|
14268
14304
|
syncCallback;
|
|
14269
14305
|
subscribers = new Map;
|
|
14270
|
-
viewChangesCallbacks = new Set;
|
|
14271
14306
|
constructor(dataStorage) {
|
|
14272
14307
|
this.dataStorage = dataStorage;
|
|
14273
14308
|
}
|
|
14274
14309
|
onPublish(callback) {
|
|
14275
14310
|
this.syncCallback = callback;
|
|
14276
14311
|
}
|
|
14277
|
-
onViewChanges(callback) {
|
|
14278
|
-
this.viewChangesCallbacks.add(callback);
|
|
14279
|
-
return () => {
|
|
14280
|
-
this.viewChangesCallbacks.delete(callback);
|
|
14281
|
-
};
|
|
14282
|
-
}
|
|
14283
14312
|
registerViews(views) {
|
|
14284
14313
|
this.views = views;
|
|
14285
14314
|
}
|
|
@@ -14347,19 +14376,7 @@ class LocalEventPublisher2 {
|
|
|
14347
14376
|
});
|
|
14348
14377
|
const viewChanges = await this.collectViewChanges(event);
|
|
14349
14378
|
allChanges.push(...viewChanges);
|
|
14350
|
-
|
|
14351
|
-
const committed = await this.dataStorage.commitChanges(allChanges, {
|
|
14352
|
-
captureRowsFor: viewStoreNames
|
|
14353
|
-
});
|
|
14354
|
-
if (committed.length > 0 && this.viewChangesCallbacks.size > 0) {
|
|
14355
|
-
for (const callback of this.viewChangesCallbacks) {
|
|
14356
|
-
try {
|
|
14357
|
-
callback(committed);
|
|
14358
|
-
} catch (error) {
|
|
14359
|
-
console.error(`[EventPublisher] onViewChanges callback error:`, error);
|
|
14360
|
-
}
|
|
14361
|
-
}
|
|
14362
|
-
}
|
|
14379
|
+
await this.dataStorage.commitChanges(allChanges);
|
|
14363
14380
|
await this.notifySubscribers(event);
|
|
14364
14381
|
if (this.syncCallback) {
|
|
14365
14382
|
this.syncCallback(event);
|
|
@@ -14740,9 +14757,8 @@ function typeValidatorBuilder(typeName, comparatorStrategy) {
|
|
|
14740
14757
|
}
|
|
14741
14758
|
|
|
14742
14759
|
class DataStorage {
|
|
14743
|
-
async commitChanges(changes
|
|
14760
|
+
async commitChanges(changes) {
|
|
14744
14761
|
await Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
|
|
14745
|
-
return [];
|
|
14746
14762
|
}
|
|
14747
14763
|
}
|
|
14748
14764
|
|
|
@@ -15099,6 +15115,47 @@ function deepMerge(target, source) {
|
|
|
15099
15115
|
function isPlainObject(item) {
|
|
15100
15116
|
return item && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && Object.prototype.toString.call(item) === "[object Object]";
|
|
15101
15117
|
}
|
|
15118
|
+
function murmurHash(key, seed = 0) {
|
|
15119
|
+
let remainder, bytes, h1, h1b, c1, c2, k1, i;
|
|
15120
|
+
remainder = key.length & 3;
|
|
15121
|
+
bytes = key.length - remainder;
|
|
15122
|
+
h1 = seed;
|
|
15123
|
+
c1 = 3432918353;
|
|
15124
|
+
c2 = 461845907;
|
|
15125
|
+
i = 0;
|
|
15126
|
+
while (i < bytes) {
|
|
15127
|
+
k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
|
|
15128
|
+
++i;
|
|
15129
|
+
k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
|
|
15130
|
+
k1 = k1 << 15 | k1 >>> 17;
|
|
15131
|
+
k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
|
|
15132
|
+
h1 ^= k1;
|
|
15133
|
+
h1 = h1 << 13 | h1 >>> 19;
|
|
15134
|
+
h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
|
|
15135
|
+
h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
|
|
15136
|
+
}
|
|
15137
|
+
k1 = 0;
|
|
15138
|
+
if (remainder >= 3) {
|
|
15139
|
+
k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
|
|
15140
|
+
}
|
|
15141
|
+
if (remainder >= 2) {
|
|
15142
|
+
k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
|
|
15143
|
+
}
|
|
15144
|
+
if (remainder >= 1) {
|
|
15145
|
+
k1 ^= key.charCodeAt(i) & 255;
|
|
15146
|
+
k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
|
|
15147
|
+
k1 = k1 << 15 | k1 >>> 17;
|
|
15148
|
+
k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
|
|
15149
|
+
h1 ^= k1;
|
|
15150
|
+
}
|
|
15151
|
+
h1 ^= key.length;
|
|
15152
|
+
h1 ^= h1 >>> 16;
|
|
15153
|
+
h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
|
|
15154
|
+
h1 ^= h1 >>> 13;
|
|
15155
|
+
h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
|
|
15156
|
+
h1 ^= h1 >>> 16;
|
|
15157
|
+
return h1 >>> 0;
|
|
15158
|
+
}
|
|
15102
15159
|
function resolveQueryChange(currentResult, event3, options) {
|
|
15103
15160
|
const index = currentResult.findIndex((e2) => e2._id === event3.id);
|
|
15104
15161
|
const isInCurrentResult = index !== -1;
|
|
@@ -15200,8 +15257,8 @@ class ObservableDataStorage {
|
|
|
15200
15257
|
getReadWriteTransaction() {
|
|
15201
15258
|
return this.source.getReadWriteTransaction();
|
|
15202
15259
|
}
|
|
15203
|
-
commitChanges(changes
|
|
15204
|
-
return this.source.commitChanges(changes
|
|
15260
|
+
commitChanges(changes) {
|
|
15261
|
+
return this.source.commitChanges(changes);
|
|
15205
15262
|
}
|
|
15206
15263
|
trackQuery(storeName, options, result, listener4) {
|
|
15207
15264
|
const key = this.getQueryKey(storeName, options);
|
|
@@ -15214,7 +15271,8 @@ class ObservableDataStorage {
|
|
|
15214
15271
|
}
|
|
15215
15272
|
handleStoreChange(storeName, events) {
|
|
15216
15273
|
let hasChanges = false;
|
|
15217
|
-
|
|
15274
|
+
const staleKeys = [];
|
|
15275
|
+
for (const [key, query] of this.trackedQueries) {
|
|
15218
15276
|
if (query.storeName !== storeName)
|
|
15219
15277
|
continue;
|
|
15220
15278
|
let currentResult = query.result;
|
|
@@ -15226,10 +15284,20 @@ class ObservableDataStorage {
|
|
|
15226
15284
|
queryChanged = true;
|
|
15227
15285
|
}
|
|
15228
15286
|
}
|
|
15229
|
-
if (queryChanged)
|
|
15230
|
-
|
|
15287
|
+
if (!queryChanged)
|
|
15288
|
+
continue;
|
|
15289
|
+
if (query.options.limit !== undefined && query.result.length === query.options.limit && currentResult.length < query.options.limit) {
|
|
15290
|
+
staleKeys.push(key);
|
|
15231
15291
|
hasChanges = true;
|
|
15292
|
+
continue;
|
|
15232
15293
|
}
|
|
15294
|
+
query.result = currentResult;
|
|
15295
|
+
hasChanges = true;
|
|
15296
|
+
}
|
|
15297
|
+
for (const key of staleKeys) {
|
|
15298
|
+
const query = this.trackedQueries.get(key);
|
|
15299
|
+
this.source.getStore(query.storeName).unsubscribe(query.listener);
|
|
15300
|
+
this.trackedQueries.delete(key);
|
|
15233
15301
|
}
|
|
15234
15302
|
if (hasChanges) {
|
|
15235
15303
|
this.onChange();
|
|
@@ -15402,6 +15470,7 @@ class ScopedModel3 {
|
|
|
15402
15470
|
for (const listener4 of this.tokenListeners) {
|
|
15403
15471
|
listener4();
|
|
15404
15472
|
}
|
|
15473
|
+
return triggerModuleSync(this.scopeName);
|
|
15405
15474
|
}
|
|
15406
15475
|
getToken() {
|
|
15407
15476
|
return this.authAdapter.getToken();
|
|
@@ -15499,243 +15568,136 @@ class Model2 {
|
|
|
15499
15568
|
return s;
|
|
15500
15569
|
}
|
|
15501
15570
|
}
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
storeKey(viewName, scope) {
|
|
15510
|
-
return `${scope ?? DEFAULT_SCOPE}:${viewName}`;
|
|
15511
|
-
}
|
|
15512
|
-
registerViews(views) {
|
|
15513
|
-
this.views = views;
|
|
15514
|
-
}
|
|
15515
|
-
getStore(viewName, scope) {
|
|
15516
|
-
const key = this.storeKey(viewName, scope);
|
|
15517
|
-
if (!this.stores.has(key)) {
|
|
15518
|
-
this.stores.set(key, new StreamingStore);
|
|
15571
|
+
function applyQueryChanges(result, changes) {
|
|
15572
|
+
const next = [...result];
|
|
15573
|
+
for (const change of changes) {
|
|
15574
|
+
if (change.type === "delete") {
|
|
15575
|
+
const idx = next.findIndex((it) => it._id === change.id);
|
|
15576
|
+
if (idx !== -1)
|
|
15577
|
+
next.splice(idx, 1);
|
|
15519
15578
|
}
|
|
15520
|
-
return this.stores.get(key);
|
|
15521
|
-
}
|
|
15522
|
-
hasData(viewName, scope) {
|
|
15523
|
-
const store = this.stores.get(this.storeKey(viewName, scope));
|
|
15524
|
-
return store ? store.hasData() : false;
|
|
15525
15579
|
}
|
|
15526
|
-
|
|
15527
|
-
|
|
15528
|
-
|
|
15529
|
-
|
|
15530
|
-
|
|
15580
|
+
for (const change of changes) {
|
|
15581
|
+
if (change.type === "set") {
|
|
15582
|
+
const idx = next.findIndex((it) => it._id === change.id);
|
|
15583
|
+
if (idx !== -1)
|
|
15584
|
+
next.splice(idx, 1);
|
|
15585
|
+
next.splice(change.index, 0, change.item);
|
|
15531
15586
|
}
|
|
15532
|
-
|
|
15533
|
-
|
|
15534
|
-
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15587
|
+
}
|
|
15588
|
+
return next;
|
|
15589
|
+
}
|
|
15590
|
+
|
|
15591
|
+
class StreamingQueryCache {
|
|
15592
|
+
entries = new Map;
|
|
15593
|
+
static UNSUBSCRIBE_DELAY_MS = 5000;
|
|
15594
|
+
entryKey(descriptor, scope) {
|
|
15595
|
+
return `${scope ?? "default"}:${murmurHash(JSON.stringify(descriptor))}`;
|
|
15596
|
+
}
|
|
15597
|
+
subscribe(descriptor, scope, eventWire, onChange) {
|
|
15598
|
+
const key = this.entryKey(descriptor, scope);
|
|
15599
|
+
let entry = this.entries.get(key);
|
|
15600
|
+
if (entry) {
|
|
15601
|
+
if (entry.pendingUnsub) {
|
|
15602
|
+
clearTimeout(entry.pendingUnsub);
|
|
15603
|
+
entry.pendingUnsub = undefined;
|
|
15604
|
+
}
|
|
15605
|
+
entry.refCount++;
|
|
15606
|
+
} else {
|
|
15607
|
+
const newEntry = {
|
|
15608
|
+
result: undefined,
|
|
15609
|
+
hasResult: false,
|
|
15610
|
+
listeners: new Set,
|
|
15611
|
+
refCount: 1,
|
|
15612
|
+
subscriptionId: ""
|
|
15538
15613
|
};
|
|
15614
|
+
newEntry.subscriptionId = eventWire.subscribeQuery(descriptor, scope, {
|
|
15615
|
+
onSnapshot: (result) => {
|
|
15616
|
+
newEntry.result = result;
|
|
15617
|
+
newEntry.hasResult = true;
|
|
15618
|
+
this.notify(newEntry);
|
|
15619
|
+
},
|
|
15620
|
+
onChanges: (changes) => {
|
|
15621
|
+
if (!newEntry.hasResult || !Array.isArray(newEntry.result)) {
|
|
15622
|
+
return;
|
|
15623
|
+
}
|
|
15624
|
+
newEntry.result = applyQueryChanges(newEntry.result, changes);
|
|
15625
|
+
this.notify(newEntry);
|
|
15626
|
+
}
|
|
15627
|
+
});
|
|
15628
|
+
this.entries.set(key, newEntry);
|
|
15629
|
+
entry = newEntry;
|
|
15539
15630
|
}
|
|
15540
|
-
const
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
refCount: 1
|
|
15544
|
-
});
|
|
15631
|
+
const subscribed = entry;
|
|
15632
|
+
subscribed.listeners.add(onChange);
|
|
15633
|
+
let active = true;
|
|
15545
15634
|
return {
|
|
15546
|
-
|
|
15547
|
-
|
|
15635
|
+
read: () => ({
|
|
15636
|
+
result: subscribed.result,
|
|
15637
|
+
loading: !subscribed.hasResult
|
|
15638
|
+
}),
|
|
15639
|
+
unsubscribe: () => {
|
|
15640
|
+
if (!active)
|
|
15641
|
+
return;
|
|
15642
|
+
active = false;
|
|
15643
|
+
subscribed.listeners.delete(onChange);
|
|
15644
|
+
subscribed.refCount--;
|
|
15645
|
+
if (subscribed.refCount > 0)
|
|
15646
|
+
return;
|
|
15647
|
+
subscribed.pendingUnsub = setTimeout(() => {
|
|
15648
|
+
subscribed.pendingUnsub = undefined;
|
|
15649
|
+
if (subscribed.refCount > 0)
|
|
15650
|
+
return;
|
|
15651
|
+
eventWire.unsubscribeQuery(subscribed.subscriptionId);
|
|
15652
|
+
this.entries.delete(key);
|
|
15653
|
+
}, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
|
|
15654
|
+
}
|
|
15548
15655
|
};
|
|
15549
15656
|
}
|
|
15550
|
-
|
|
15551
|
-
const stream2 = this.activeStreams.get(key);
|
|
15552
|
-
if (!stream2)
|
|
15553
|
-
return;
|
|
15554
|
-
stream2.refCount--;
|
|
15555
|
-
if (stream2.refCount <= 0) {
|
|
15556
|
-
const timeout = setTimeout(() => {
|
|
15557
|
-
this.pendingUnsubscribes.delete(key);
|
|
15558
|
-
const current2 = this.activeStreams.get(key);
|
|
15559
|
-
if (current2 && current2.refCount <= 0) {
|
|
15560
|
-
current2.unsubscribe();
|
|
15561
|
-
this.activeStreams.delete(key);
|
|
15562
|
-
}
|
|
15563
|
-
}, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
|
|
15564
|
-
this.pendingUnsubscribes.set(key, timeout);
|
|
15565
|
-
}
|
|
15566
|
-
}
|
|
15567
|
-
subscribeView(viewName, eventWire, scope) {
|
|
15568
|
-
const key = this.storeKey(viewName, scope);
|
|
15569
|
-
const { unsubscribe } = this.registerStream(key, () => {
|
|
15570
|
-
const store = this.stores.get(key) ?? new StreamingStore;
|
|
15571
|
-
this.stores.set(key, store);
|
|
15572
|
-
eventWire.subscribeView(viewName, scope ?? DEFAULT_SCOPE, {
|
|
15573
|
-
onSnapshot: (items) => store.setAll(items),
|
|
15574
|
-
onChanges: (changes) => store.applyChanges(changes)
|
|
15575
|
-
});
|
|
15576
|
-
return {
|
|
15577
|
-
unsubscribe: () => eventWire.unsubscribeView(viewName, scope ?? DEFAULT_SCOPE)
|
|
15578
|
-
};
|
|
15579
|
-
});
|
|
15580
|
-
return unsubscribe;
|
|
15581
|
-
}
|
|
15582
|
-
invalidateScope(scope) {
|
|
15657
|
+
invalidateScope(scope, eventWire) {
|
|
15583
15658
|
const prefix = `${scope}:`;
|
|
15584
|
-
for (const [key,
|
|
15659
|
+
for (const [key, entry] of this.entries) {
|
|
15585
15660
|
if (!key.startsWith(prefix))
|
|
15586
15661
|
continue;
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
stream2.unsubscribe();
|
|
15595
|
-
} catch {}
|
|
15596
|
-
this.activeStreams.delete(key);
|
|
15597
|
-
}
|
|
15598
|
-
for (const [key, store] of this.stores) {
|
|
15599
|
-
if (!key.startsWith(prefix))
|
|
15600
|
-
continue;
|
|
15601
|
-
store.clear();
|
|
15602
|
-
}
|
|
15603
|
-
}
|
|
15604
|
-
async applyEvent(event3) {
|
|
15605
|
-
for (const view3 of this.views) {
|
|
15606
|
-
const handlers = view3.getHandlers();
|
|
15607
|
-
const handler = handlers[event3.type];
|
|
15608
|
-
if (!handler)
|
|
15609
|
-
continue;
|
|
15610
|
-
const suffix = `:${view3.name}`;
|
|
15611
|
-
for (const [key, store] of this.stores) {
|
|
15612
|
-
if (!key.endsWith(suffix))
|
|
15613
|
-
continue;
|
|
15614
|
-
const ctx = {
|
|
15615
|
-
set: async (id3, data) => {
|
|
15616
|
-
store.set(String(id3), { _id: String(id3), ...data });
|
|
15617
|
-
},
|
|
15618
|
-
modify: async (id3, data) => {
|
|
15619
|
-
store.modify(String(id3), data);
|
|
15620
|
-
},
|
|
15621
|
-
remove: async (id3) => {
|
|
15622
|
-
store.remove(String(id3));
|
|
15623
|
-
},
|
|
15624
|
-
find: async (options) => {
|
|
15625
|
-
return store.find(options);
|
|
15626
|
-
},
|
|
15627
|
-
findOne: async (where) => {
|
|
15628
|
-
return store.findOne(where);
|
|
15629
|
-
},
|
|
15630
|
-
$auth: {}
|
|
15631
|
-
};
|
|
15632
|
-
await handler(ctx, event3);
|
|
15633
|
-
}
|
|
15662
|
+
if (entry.pendingUnsub)
|
|
15663
|
+
clearTimeout(entry.pendingUnsub);
|
|
15664
|
+
eventWire?.unsubscribeQuery(entry.subscriptionId);
|
|
15665
|
+
this.entries.delete(key);
|
|
15666
|
+
entry.result = undefined;
|
|
15667
|
+
entry.hasResult = false;
|
|
15668
|
+
this.notify(entry);
|
|
15634
15669
|
}
|
|
15635
15670
|
}
|
|
15636
|
-
clear() {
|
|
15637
|
-
for (const
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
for (const timeout of this.pendingUnsubscribes.values()) {
|
|
15642
|
-
clearTimeout(timeout);
|
|
15643
|
-
}
|
|
15644
|
-
this.pendingUnsubscribes.clear();
|
|
15645
|
-
for (const store of this.stores.values()) {
|
|
15646
|
-
store.clear();
|
|
15671
|
+
clear(eventWire) {
|
|
15672
|
+
for (const entry of this.entries.values()) {
|
|
15673
|
+
if (entry.pendingUnsub)
|
|
15674
|
+
clearTimeout(entry.pendingUnsub);
|
|
15675
|
+
eventWire?.unsubscribeQuery(entry.subscriptionId);
|
|
15647
15676
|
}
|
|
15677
|
+
this.entries.clear();
|
|
15648
15678
|
}
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
hasData() {
|
|
15656
|
-
return this.initialized;
|
|
15657
|
-
}
|
|
15658
|
-
setAll(items) {
|
|
15659
|
-
this.initialized = true;
|
|
15660
|
-
this.data.clear();
|
|
15661
|
-
for (const item of items) {
|
|
15662
|
-
this.data.set(item._id, item);
|
|
15663
|
-
}
|
|
15664
|
-
this.notifyListeners(null);
|
|
15665
|
-
}
|
|
15666
|
-
applyChanges(events) {
|
|
15667
|
-
if (events.length === 0)
|
|
15668
|
-
return;
|
|
15669
|
-
for (const event3 of events) {
|
|
15670
|
-
if (event3.type === "set" && event3.item) {
|
|
15671
|
-
this.data.set(event3.id, event3.item);
|
|
15672
|
-
} else if (event3.type === "delete") {
|
|
15673
|
-
this.data.delete(event3.id);
|
|
15679
|
+
notify(entry) {
|
|
15680
|
+
for (const listener4 of entry.listeners) {
|
|
15681
|
+
try {
|
|
15682
|
+
listener4();
|
|
15683
|
+
} catch (err3) {
|
|
15684
|
+
console.error(`[Arc] Query cache listener error:`, err3);
|
|
15674
15685
|
}
|
|
15675
15686
|
}
|
|
15676
|
-
this.notifyListeners(events);
|
|
15677
|
-
}
|
|
15678
|
-
set(id3, item) {
|
|
15679
|
-
this.data.set(id3, item);
|
|
15680
|
-
this.notifyListeners([{ type: "set", id: id3, item }]);
|
|
15681
|
-
}
|
|
15682
|
-
modify(id3, updates) {
|
|
15683
|
-
const existing = this.data.get(id3);
|
|
15684
|
-
if (existing) {
|
|
15685
|
-
const updated = { ...existing, ...updates };
|
|
15686
|
-
this.data.set(id3, updated);
|
|
15687
|
-
this.notifyListeners([{ type: "set", id: id3, item: updated }]);
|
|
15688
|
-
}
|
|
15689
|
-
}
|
|
15690
|
-
remove(id3) {
|
|
15691
|
-
if (this.data.delete(id3)) {
|
|
15692
|
-
this.notifyListeners([{ type: "delete", id: id3, item: null }]);
|
|
15693
|
-
}
|
|
15694
|
-
}
|
|
15695
|
-
clear() {
|
|
15696
|
-
this.initialized = false;
|
|
15697
|
-
this.data.clear();
|
|
15698
|
-
this.notifyListeners(null);
|
|
15699
|
-
}
|
|
15700
|
-
find(options = {}) {
|
|
15701
|
-
let results = Array.from(this.data.values());
|
|
15702
|
-
if (options.where) {
|
|
15703
|
-
results = results.filter((item) => checkItemMatchesWhere(item, options.where));
|
|
15704
|
-
}
|
|
15705
|
-
return applyOrderByAndLimit(results, options);
|
|
15706
|
-
}
|
|
15707
|
-
findOne(where) {
|
|
15708
|
-
const results = this.find({ where });
|
|
15709
|
-
return results[0];
|
|
15710
|
-
}
|
|
15711
|
-
subscribe(listener4) {
|
|
15712
|
-
this.listeners.add(listener4);
|
|
15713
|
-
return () => {
|
|
15714
|
-
this.listeners.delete(listener4);
|
|
15715
|
-
};
|
|
15716
|
-
}
|
|
15717
|
-
notifyListeners(events) {
|
|
15718
|
-
for (const listener4 of this.listeners) {
|
|
15719
|
-
listener4(events);
|
|
15720
|
-
}
|
|
15721
15687
|
}
|
|
15722
15688
|
}
|
|
15723
15689
|
|
|
15724
15690
|
class StreamingEventPublisher {
|
|
15725
|
-
cache;
|
|
15726
15691
|
eventWire;
|
|
15727
15692
|
views = [];
|
|
15728
15693
|
subscribers = new Map;
|
|
15729
|
-
constructor(
|
|
15730
|
-
this.cache = cache;
|
|
15694
|
+
constructor(eventWire) {
|
|
15731
15695
|
this.eventWire = eventWire;
|
|
15732
15696
|
}
|
|
15733
15697
|
registerViews(views) {
|
|
15734
15698
|
this.views = views;
|
|
15735
|
-
this.cache.registerViews(views);
|
|
15736
15699
|
}
|
|
15737
15700
|
async publish(event3) {
|
|
15738
|
-
await this.cache.applyEvent(event3);
|
|
15739
15701
|
await this.notifySubscribers(event3);
|
|
15740
15702
|
this.eventWire.syncEvents([
|
|
15741
15703
|
{
|
|
@@ -18142,7 +18104,7 @@ var Operation, PROXY_DRAFT, RAW_RETURN_SYMBOL, iteratorSymbol, dataTypes, intern
|
|
|
18142
18104
|
}
|
|
18143
18105
|
return returnValue(result);
|
|
18144
18106
|
};
|
|
18145
|
-
}, create, constructorString, TOKEN_PREFIX = "arc:token:", eventWireInstanceCounter = 0, EVENT_TABLES, arrayValidator, ArcArray, objectValidator, ArcObject, ScopedDataStorage, ArcPrimitive, stringValidator, ArcString, ArcContextElement, ArcBoolean, ArcId, numberValidator, ArcNumber, ArcEvent, ArcCommand, ArcListener, ArcRoute, ForkedStoreState, ForkedDataStorage, MasterStoreState, MasterDataStorage2, dateValidator,
|
|
18107
|
+
}, create, constructorString, TOKEN_PREFIX = "arc:token:", DEFAULT_TIMEOUT_MS = 8000, provider = null, latestSync = null, syncSeq = 0, eventWireInstanceCounter = 0, EVENT_TABLES, arrayValidator, ArcArray, objectValidator, ArcObject, ScopedDataStorage, ArcPrimitive, stringValidator, ArcString, ArcContextElement, ArcBoolean, ArcId, numberValidator, ArcNumber, ArcEvent, ArcCommand, ArcListener, ArcRoute, ForkedStoreState, ForkedDataStorage, MasterStoreState, MasterDataStorage2, dateValidator, originCache, originStackCache, originError, CLOSE, Query, PostgresError, Errors, types2, Identifier, Parameter, Builder, defaultHandlers, builders, serializers, parsers, mergeUserTypes = function(types22) {
|
|
18146
18108
|
const user = typeHandlers(types22 || {});
|
|
18147
18109
|
return {
|
|
18148
18110
|
serializers: Object.assign({}, serializers, user.serializers),
|
|
@@ -19748,12 +19710,8 @@ var init_dist = __esm(() => {
|
|
|
19748
19710
|
}
|
|
19749
19711
|
return transaction.find(this.storeName, { where: { _id: id2 } }).then((results) => results[0]);
|
|
19750
19712
|
}
|
|
19751
|
-
async applyChangeAndReturnEvent(transaction, change, transactionCache
|
|
19713
|
+
async applyChangeAndReturnEvent(transaction, change, transactionCache) {
|
|
19752
19714
|
if (change.type === "set") {
|
|
19753
|
-
let existing;
|
|
19754
|
-
if (options?.captureRows) {
|
|
19755
|
-
existing = await this.readExisting(transaction, change.data._id, transactionCache);
|
|
19756
|
-
}
|
|
19757
19715
|
await transaction.set(this.storeName, change.data);
|
|
19758
19716
|
const item = this.deserialize ? this.deserialize(change.data) : change.data;
|
|
19759
19717
|
if (transactionCache) {
|
|
@@ -19766,16 +19724,10 @@ var init_dist = __esm(() => {
|
|
|
19766
19724
|
type: "set",
|
|
19767
19725
|
item: change.data,
|
|
19768
19726
|
id: change.data._id
|
|
19769
|
-
}
|
|
19770
|
-
oldRow: existing ?? null,
|
|
19771
|
-
newRow: change.data
|
|
19727
|
+
}
|
|
19772
19728
|
};
|
|
19773
19729
|
}
|
|
19774
19730
|
if (change.type === "delete") {
|
|
19775
|
-
let existing;
|
|
19776
|
-
if (options?.captureRows) {
|
|
19777
|
-
existing = await this.readExisting(transaction, change.id, transactionCache);
|
|
19778
|
-
}
|
|
19779
19731
|
await transaction.remove(this.storeName, change.id);
|
|
19780
19732
|
if (transactionCache) {
|
|
19781
19733
|
transactionCache.delete(`${this.storeName}:${change.id}`);
|
|
@@ -19787,9 +19739,7 @@ var init_dist = __esm(() => {
|
|
|
19787
19739
|
type: "delete",
|
|
19788
19740
|
item: null,
|
|
19789
19741
|
id: change.id
|
|
19790
|
-
}
|
|
19791
|
-
oldRow: existing ?? null,
|
|
19792
|
-
newRow: null
|
|
19742
|
+
}
|
|
19793
19743
|
};
|
|
19794
19744
|
}
|
|
19795
19745
|
if (change.type === "modify") {
|
|
@@ -19807,9 +19757,7 @@ var init_dist = __esm(() => {
|
|
|
19807
19757
|
type: "set",
|
|
19808
19758
|
item,
|
|
19809
19759
|
id: change.id
|
|
19810
|
-
}
|
|
19811
|
-
oldRow: existing ?? null,
|
|
19812
|
-
newRow: updated
|
|
19760
|
+
}
|
|
19813
19761
|
};
|
|
19814
19762
|
}
|
|
19815
19763
|
if (change.type === "mutate") {
|
|
@@ -19827,9 +19775,7 @@ var init_dist = __esm(() => {
|
|
|
19827
19775
|
type: "set",
|
|
19828
19776
|
item,
|
|
19829
19777
|
id: change.id
|
|
19830
|
-
}
|
|
19831
|
-
oldRow: existing ?? null,
|
|
19832
|
-
newRow: updated
|
|
19778
|
+
}
|
|
19833
19779
|
};
|
|
19834
19780
|
}
|
|
19835
19781
|
throw new Error("Unknown change type");
|
|
@@ -19906,22 +19852,17 @@ var init_dist = __esm(() => {
|
|
|
19906
19852
|
applySerializedChanges(changes) {
|
|
19907
19853
|
return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applySerializedChanges(changes2)));
|
|
19908
19854
|
}
|
|
19909
|
-
async commitChanges(changes
|
|
19855
|
+
async commitChanges(changes) {
|
|
19910
19856
|
const transaction = await this.getReadWriteTransaction();
|
|
19911
19857
|
const transactionCache = new Map;
|
|
19912
19858
|
const eventsByStore = new Map;
|
|
19913
|
-
const committed = [];
|
|
19914
19859
|
for (const { store, changes: storeChanges } of changes) {
|
|
19915
19860
|
const storeState = this.getStore(store);
|
|
19916
19861
|
const storeEvents = [];
|
|
19917
|
-
const capture = options?.captureRowsFor?.has(store) ?? false;
|
|
19918
19862
|
for (const change of storeChanges) {
|
|
19919
|
-
const { event: event3
|
|
19863
|
+
const { event: event3 } = await storeState.applyChangeAndReturnEvent(transaction, change, transactionCache);
|
|
19920
19864
|
if (event3)
|
|
19921
19865
|
storeEvents.push(event3);
|
|
19922
|
-
if (capture) {
|
|
19923
|
-
committed.push({ store, id: event3.id, oldRow, newRow });
|
|
19924
|
-
}
|
|
19925
19866
|
}
|
|
19926
19867
|
if (storeEvents.length > 0) {
|
|
19927
19868
|
eventsByStore.set(store, storeEvents);
|
|
@@ -19932,7 +19873,6 @@ var init_dist = __esm(() => {
|
|
|
19932
19873
|
const storeState = this.getStore(store);
|
|
19933
19874
|
storeState.notifyListenersPublic(events);
|
|
19934
19875
|
}
|
|
19935
|
-
return committed;
|
|
19936
19876
|
}
|
|
19937
19877
|
fork() {
|
|
19938
19878
|
return new ForkedDataStorage(this);
|
|
@@ -21435,6 +21375,38 @@ class AuthAdapter2 {
|
|
|
21435
21375
|
this.scopes.clear();
|
|
21436
21376
|
}
|
|
21437
21377
|
}
|
|
21378
|
+
function triggerModuleSync2(scope, timeoutMs = DEFAULT_TIMEOUT_MS2) {
|
|
21379
|
+
if (!provider2) {
|
|
21380
|
+
latestSync2 = Promise.resolve();
|
|
21381
|
+
return latestSync2;
|
|
21382
|
+
}
|
|
21383
|
+
const seq = ++syncSeq2;
|
|
21384
|
+
const run = (async () => {
|
|
21385
|
+
try {
|
|
21386
|
+
await provider2(scope);
|
|
21387
|
+
} catch (err3) {
|
|
21388
|
+
console.warn("[arc] module sync failed during setToken:", err3);
|
|
21389
|
+
}
|
|
21390
|
+
})();
|
|
21391
|
+
const guarded = new Promise((resolve) => {
|
|
21392
|
+
let settled = false;
|
|
21393
|
+
const done = () => {
|
|
21394
|
+
if (settled)
|
|
21395
|
+
return;
|
|
21396
|
+
settled = true;
|
|
21397
|
+
resolve();
|
|
21398
|
+
};
|
|
21399
|
+
const timer2 = setTimeout(() => {
|
|
21400
|
+
console.warn(`[arc] module sync did not complete within ${timeoutMs}ms; proceeding anyway.`);
|
|
21401
|
+
done();
|
|
21402
|
+
}, timeoutMs);
|
|
21403
|
+
timer2?.unref?.();
|
|
21404
|
+
run.then(done, done).finally(() => clearTimeout(timer2));
|
|
21405
|
+
});
|
|
21406
|
+
if (seq === syncSeq2)
|
|
21407
|
+
latestSync2 = guarded;
|
|
21408
|
+
return guarded;
|
|
21409
|
+
}
|
|
21438
21410
|
|
|
21439
21411
|
class EventWire2 {
|
|
21440
21412
|
baseUrl;
|
|
@@ -21448,7 +21420,8 @@ class EventWire2 {
|
|
|
21448
21420
|
onSyncedCallback;
|
|
21449
21421
|
reconnectTimeout;
|
|
21450
21422
|
syncRequested = false;
|
|
21451
|
-
|
|
21423
|
+
querySubscriptions = new Map;
|
|
21424
|
+
querySubCounter = 0;
|
|
21452
21425
|
enableEventSync;
|
|
21453
21426
|
constructor(baseUrl, options) {
|
|
21454
21427
|
this.baseUrl = baseUrl;
|
|
@@ -21503,7 +21476,7 @@ class EventWire2 {
|
|
|
21503
21476
|
this.requestSync();
|
|
21504
21477
|
}
|
|
21505
21478
|
this.flushPendingEvents();
|
|
21506
|
-
this.
|
|
21479
|
+
this.sendAllQuerySubscriptions();
|
|
21507
21480
|
} else {
|
|
21508
21481
|
console.log(`[EventWire] onopen called but ws is not OPEN, readyState:`, this.ws?.readyState);
|
|
21509
21482
|
}
|
|
@@ -21579,24 +21552,29 @@ class EventWire2 {
|
|
|
21579
21552
|
onSynced(callback) {
|
|
21580
21553
|
this.onSyncedCallback = callback;
|
|
21581
21554
|
}
|
|
21582
|
-
|
|
21583
|
-
const
|
|
21584
|
-
this.
|
|
21555
|
+
subscribeQuery(descriptor, scope, callbacks) {
|
|
21556
|
+
const subscriptionId = `qs_${this.instanceId}_${++this.querySubCounter}`;
|
|
21557
|
+
this.querySubscriptions.set(subscriptionId, {
|
|
21558
|
+
descriptor,
|
|
21559
|
+
scope,
|
|
21560
|
+
callbacks
|
|
21561
|
+
});
|
|
21585
21562
|
if (this.state === "connected" && this.ws) {
|
|
21586
21563
|
this.ws.send(JSON.stringify({
|
|
21587
|
-
type: "subscribe-
|
|
21588
|
-
|
|
21564
|
+
type: "subscribe-query",
|
|
21565
|
+
subscriptionId,
|
|
21566
|
+
descriptor,
|
|
21589
21567
|
scope
|
|
21590
21568
|
}));
|
|
21591
21569
|
}
|
|
21570
|
+
return subscriptionId;
|
|
21592
21571
|
}
|
|
21593
|
-
|
|
21594
|
-
this.
|
|
21572
|
+
unsubscribeQuery(subscriptionId) {
|
|
21573
|
+
this.querySubscriptions.delete(subscriptionId);
|
|
21595
21574
|
if (this.state === "connected" && this.ws) {
|
|
21596
21575
|
this.ws.send(JSON.stringify({
|
|
21597
|
-
type: "unsubscribe-
|
|
21598
|
-
|
|
21599
|
-
scope
|
|
21576
|
+
type: "unsubscribe-query",
|
|
21577
|
+
subscriptionId
|
|
21600
21578
|
}));
|
|
21601
21579
|
}
|
|
21602
21580
|
}
|
|
@@ -21631,17 +21609,17 @@ class EventWire2 {
|
|
|
21631
21609
|
this.lastHostEventId = message.lastHostEventId;
|
|
21632
21610
|
}
|
|
21633
21611
|
break;
|
|
21634
|
-
case "
|
|
21635
|
-
const sub = this.
|
|
21612
|
+
case "query-snapshot": {
|
|
21613
|
+
const sub = this.querySubscriptions.get(message.subscriptionId);
|
|
21636
21614
|
if (sub) {
|
|
21637
|
-
sub.onSnapshot(message.
|
|
21615
|
+
sub.callbacks.onSnapshot(message.result ?? null);
|
|
21638
21616
|
}
|
|
21639
21617
|
break;
|
|
21640
21618
|
}
|
|
21641
|
-
case "
|
|
21642
|
-
const sub = this.
|
|
21619
|
+
case "query-changes": {
|
|
21620
|
+
const sub = this.querySubscriptions.get(message.subscriptionId);
|
|
21643
21621
|
if (sub && Array.isArray(message.changes)) {
|
|
21644
|
-
sub.onChanges(message.changes);
|
|
21622
|
+
sub.callbacks.onChanges(message.changes);
|
|
21645
21623
|
}
|
|
21646
21624
|
break;
|
|
21647
21625
|
}
|
|
@@ -21669,17 +21647,15 @@ class EventWire2 {
|
|
|
21669
21647
|
this.pendingEvents = [];
|
|
21670
21648
|
}
|
|
21671
21649
|
}
|
|
21672
|
-
|
|
21650
|
+
sendAllQuerySubscriptions() {
|
|
21673
21651
|
if (!this.ws || this.state !== "connected")
|
|
21674
21652
|
return;
|
|
21675
|
-
for (const
|
|
21676
|
-
const sepIdx = key.indexOf(":");
|
|
21677
|
-
const scope = key.slice(0, sepIdx);
|
|
21678
|
-
const element = key.slice(sepIdx + 1);
|
|
21653
|
+
for (const [subscriptionId, sub] of this.querySubscriptions) {
|
|
21679
21654
|
this.ws.send(JSON.stringify({
|
|
21680
|
-
type: "subscribe-
|
|
21681
|
-
|
|
21682
|
-
|
|
21655
|
+
type: "subscribe-query",
|
|
21656
|
+
subscriptionId,
|
|
21657
|
+
descriptor: sub.descriptor,
|
|
21658
|
+
scope: sub.scope
|
|
21683
21659
|
}));
|
|
21684
21660
|
}
|
|
21685
21661
|
}
|
|
@@ -21698,19 +21674,12 @@ class LocalEventPublisher3 {
|
|
|
21698
21674
|
views = [];
|
|
21699
21675
|
syncCallback;
|
|
21700
21676
|
subscribers = new Map;
|
|
21701
|
-
viewChangesCallbacks = new Set;
|
|
21702
21677
|
constructor(dataStorage) {
|
|
21703
21678
|
this.dataStorage = dataStorage;
|
|
21704
21679
|
}
|
|
21705
21680
|
onPublish(callback) {
|
|
21706
21681
|
this.syncCallback = callback;
|
|
21707
21682
|
}
|
|
21708
|
-
onViewChanges(callback) {
|
|
21709
|
-
this.viewChangesCallbacks.add(callback);
|
|
21710
|
-
return () => {
|
|
21711
|
-
this.viewChangesCallbacks.delete(callback);
|
|
21712
|
-
};
|
|
21713
|
-
}
|
|
21714
21683
|
registerViews(views) {
|
|
21715
21684
|
this.views = views;
|
|
21716
21685
|
}
|
|
@@ -21778,19 +21747,7 @@ class LocalEventPublisher3 {
|
|
|
21778
21747
|
});
|
|
21779
21748
|
const viewChanges = await this.collectViewChanges(event);
|
|
21780
21749
|
allChanges.push(...viewChanges);
|
|
21781
|
-
|
|
21782
|
-
const committed = await this.dataStorage.commitChanges(allChanges, {
|
|
21783
|
-
captureRowsFor: viewStoreNames
|
|
21784
|
-
});
|
|
21785
|
-
if (committed.length > 0 && this.viewChangesCallbacks.size > 0) {
|
|
21786
|
-
for (const callback of this.viewChangesCallbacks) {
|
|
21787
|
-
try {
|
|
21788
|
-
callback(committed);
|
|
21789
|
-
} catch (error) {
|
|
21790
|
-
console.error(`[EventPublisher] onViewChanges callback error:`, error);
|
|
21791
|
-
}
|
|
21792
|
-
}
|
|
21793
|
-
}
|
|
21750
|
+
await this.dataStorage.commitChanges(allChanges);
|
|
21794
21751
|
await this.notifySubscribers(event);
|
|
21795
21752
|
if (this.syncCallback) {
|
|
21796
21753
|
this.syncCallback(event);
|
|
@@ -22171,9 +22128,8 @@ function typeValidatorBuilder2(typeName, comparatorStrategy) {
|
|
|
22171
22128
|
}
|
|
22172
22129
|
|
|
22173
22130
|
class DataStorage2 {
|
|
22174
|
-
async commitChanges(changes
|
|
22131
|
+
async commitChanges(changes) {
|
|
22175
22132
|
await Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
|
|
22176
|
-
return [];
|
|
22177
22133
|
}
|
|
22178
22134
|
}
|
|
22179
22135
|
|
|
@@ -22530,6 +22486,47 @@ function deepMerge2(target, source) {
|
|
|
22530
22486
|
function isPlainObject2(item) {
|
|
22531
22487
|
return item && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && Object.prototype.toString.call(item) === "[object Object]";
|
|
22532
22488
|
}
|
|
22489
|
+
function murmurHash2(key, seed = 0) {
|
|
22490
|
+
let remainder, bytes, h1, h1b, c1, c2, k1, i;
|
|
22491
|
+
remainder = key.length & 3;
|
|
22492
|
+
bytes = key.length - remainder;
|
|
22493
|
+
h1 = seed;
|
|
22494
|
+
c1 = 3432918353;
|
|
22495
|
+
c2 = 461845907;
|
|
22496
|
+
i = 0;
|
|
22497
|
+
while (i < bytes) {
|
|
22498
|
+
k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
|
|
22499
|
+
++i;
|
|
22500
|
+
k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
|
|
22501
|
+
k1 = k1 << 15 | k1 >>> 17;
|
|
22502
|
+
k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
|
|
22503
|
+
h1 ^= k1;
|
|
22504
|
+
h1 = h1 << 13 | h1 >>> 19;
|
|
22505
|
+
h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
|
|
22506
|
+
h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
|
|
22507
|
+
}
|
|
22508
|
+
k1 = 0;
|
|
22509
|
+
if (remainder >= 3) {
|
|
22510
|
+
k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
|
|
22511
|
+
}
|
|
22512
|
+
if (remainder >= 2) {
|
|
22513
|
+
k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
|
|
22514
|
+
}
|
|
22515
|
+
if (remainder >= 1) {
|
|
22516
|
+
k1 ^= key.charCodeAt(i) & 255;
|
|
22517
|
+
k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
|
|
22518
|
+
k1 = k1 << 15 | k1 >>> 17;
|
|
22519
|
+
k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
|
|
22520
|
+
h1 ^= k1;
|
|
22521
|
+
}
|
|
22522
|
+
h1 ^= key.length;
|
|
22523
|
+
h1 ^= h1 >>> 16;
|
|
22524
|
+
h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
|
|
22525
|
+
h1 ^= h1 >>> 13;
|
|
22526
|
+
h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
|
|
22527
|
+
h1 ^= h1 >>> 16;
|
|
22528
|
+
return h1 >>> 0;
|
|
22529
|
+
}
|
|
22533
22530
|
function resolveQueryChange2(currentResult, event3, options) {
|
|
22534
22531
|
const index = currentResult.findIndex((e2) => e2._id === event3.id);
|
|
22535
22532
|
const isInCurrentResult = index !== -1;
|
|
@@ -22631,8 +22628,8 @@ class ObservableDataStorage2 {
|
|
|
22631
22628
|
getReadWriteTransaction() {
|
|
22632
22629
|
return this.source.getReadWriteTransaction();
|
|
22633
22630
|
}
|
|
22634
|
-
commitChanges(changes
|
|
22635
|
-
return this.source.commitChanges(changes
|
|
22631
|
+
commitChanges(changes) {
|
|
22632
|
+
return this.source.commitChanges(changes);
|
|
22636
22633
|
}
|
|
22637
22634
|
trackQuery(storeName, options, result, listener4) {
|
|
22638
22635
|
const key = this.getQueryKey(storeName, options);
|
|
@@ -22645,7 +22642,8 @@ class ObservableDataStorage2 {
|
|
|
22645
22642
|
}
|
|
22646
22643
|
handleStoreChange(storeName, events) {
|
|
22647
22644
|
let hasChanges = false;
|
|
22648
|
-
|
|
22645
|
+
const staleKeys = [];
|
|
22646
|
+
for (const [key, query] of this.trackedQueries) {
|
|
22649
22647
|
if (query.storeName !== storeName)
|
|
22650
22648
|
continue;
|
|
22651
22649
|
let currentResult = query.result;
|
|
@@ -22657,10 +22655,20 @@ class ObservableDataStorage2 {
|
|
|
22657
22655
|
queryChanged = true;
|
|
22658
22656
|
}
|
|
22659
22657
|
}
|
|
22660
|
-
if (queryChanged)
|
|
22661
|
-
|
|
22658
|
+
if (!queryChanged)
|
|
22659
|
+
continue;
|
|
22660
|
+
if (query.options.limit !== undefined && query.result.length === query.options.limit && currentResult.length < query.options.limit) {
|
|
22661
|
+
staleKeys.push(key);
|
|
22662
22662
|
hasChanges = true;
|
|
22663
|
+
continue;
|
|
22663
22664
|
}
|
|
22665
|
+
query.result = currentResult;
|
|
22666
|
+
hasChanges = true;
|
|
22667
|
+
}
|
|
22668
|
+
for (const key of staleKeys) {
|
|
22669
|
+
const query = this.trackedQueries.get(key);
|
|
22670
|
+
this.source.getStore(query.storeName).unsubscribe(query.listener);
|
|
22671
|
+
this.trackedQueries.delete(key);
|
|
22664
22672
|
}
|
|
22665
22673
|
if (hasChanges) {
|
|
22666
22674
|
this.onChange();
|
|
@@ -22833,6 +22841,7 @@ class ScopedModel4 {
|
|
|
22833
22841
|
for (const listener4 of this.tokenListeners) {
|
|
22834
22842
|
listener4();
|
|
22835
22843
|
}
|
|
22844
|
+
return triggerModuleSync2(this.scopeName);
|
|
22836
22845
|
}
|
|
22837
22846
|
getToken() {
|
|
22838
22847
|
return this.authAdapter.getToken();
|
|
@@ -22930,243 +22939,136 @@ class Model3 {
|
|
|
22930
22939
|
return s;
|
|
22931
22940
|
}
|
|
22932
22941
|
}
|
|
22933
|
-
|
|
22934
|
-
|
|
22935
|
-
|
|
22936
|
-
|
|
22937
|
-
|
|
22938
|
-
|
|
22939
|
-
|
|
22940
|
-
storeKey(viewName, scope) {
|
|
22941
|
-
return `${scope ?? DEFAULT_SCOPE2}:${viewName}`;
|
|
22942
|
-
}
|
|
22943
|
-
registerViews(views) {
|
|
22944
|
-
this.views = views;
|
|
22945
|
-
}
|
|
22946
|
-
getStore(viewName, scope) {
|
|
22947
|
-
const key = this.storeKey(viewName, scope);
|
|
22948
|
-
if (!this.stores.has(key)) {
|
|
22949
|
-
this.stores.set(key, new StreamingStore2);
|
|
22942
|
+
function applyQueryChanges2(result, changes) {
|
|
22943
|
+
const next = [...result];
|
|
22944
|
+
for (const change of changes) {
|
|
22945
|
+
if (change.type === "delete") {
|
|
22946
|
+
const idx = next.findIndex((it) => it._id === change.id);
|
|
22947
|
+
if (idx !== -1)
|
|
22948
|
+
next.splice(idx, 1);
|
|
22950
22949
|
}
|
|
22951
|
-
return this.stores.get(key);
|
|
22952
|
-
}
|
|
22953
|
-
hasData(viewName, scope) {
|
|
22954
|
-
const store = this.stores.get(this.storeKey(viewName, scope));
|
|
22955
|
-
return store ? store.hasData() : false;
|
|
22956
22950
|
}
|
|
22957
|
-
|
|
22958
|
-
|
|
22959
|
-
|
|
22960
|
-
|
|
22961
|
-
|
|
22951
|
+
for (const change of changes) {
|
|
22952
|
+
if (change.type === "set") {
|
|
22953
|
+
const idx = next.findIndex((it) => it._id === change.id);
|
|
22954
|
+
if (idx !== -1)
|
|
22955
|
+
next.splice(idx, 1);
|
|
22956
|
+
next.splice(change.index, 0, change.item);
|
|
22962
22957
|
}
|
|
22963
|
-
|
|
22964
|
-
|
|
22965
|
-
|
|
22966
|
-
|
|
22967
|
-
|
|
22968
|
-
|
|
22958
|
+
}
|
|
22959
|
+
return next;
|
|
22960
|
+
}
|
|
22961
|
+
|
|
22962
|
+
class StreamingQueryCache2 {
|
|
22963
|
+
entries = new Map;
|
|
22964
|
+
static UNSUBSCRIBE_DELAY_MS = 5000;
|
|
22965
|
+
entryKey(descriptor, scope) {
|
|
22966
|
+
return `${scope ?? "default"}:${murmurHash2(JSON.stringify(descriptor))}`;
|
|
22967
|
+
}
|
|
22968
|
+
subscribe(descriptor, scope, eventWire, onChange) {
|
|
22969
|
+
const key = this.entryKey(descriptor, scope);
|
|
22970
|
+
let entry = this.entries.get(key);
|
|
22971
|
+
if (entry) {
|
|
22972
|
+
if (entry.pendingUnsub) {
|
|
22973
|
+
clearTimeout(entry.pendingUnsub);
|
|
22974
|
+
entry.pendingUnsub = undefined;
|
|
22975
|
+
}
|
|
22976
|
+
entry.refCount++;
|
|
22977
|
+
} else {
|
|
22978
|
+
const newEntry = {
|
|
22979
|
+
result: undefined,
|
|
22980
|
+
hasResult: false,
|
|
22981
|
+
listeners: new Set,
|
|
22982
|
+
refCount: 1,
|
|
22983
|
+
subscriptionId: ""
|
|
22969
22984
|
};
|
|
22985
|
+
newEntry.subscriptionId = eventWire.subscribeQuery(descriptor, scope, {
|
|
22986
|
+
onSnapshot: (result) => {
|
|
22987
|
+
newEntry.result = result;
|
|
22988
|
+
newEntry.hasResult = true;
|
|
22989
|
+
this.notify(newEntry);
|
|
22990
|
+
},
|
|
22991
|
+
onChanges: (changes) => {
|
|
22992
|
+
if (!newEntry.hasResult || !Array.isArray(newEntry.result)) {
|
|
22993
|
+
return;
|
|
22994
|
+
}
|
|
22995
|
+
newEntry.result = applyQueryChanges2(newEntry.result, changes);
|
|
22996
|
+
this.notify(newEntry);
|
|
22997
|
+
}
|
|
22998
|
+
});
|
|
22999
|
+
this.entries.set(key, newEntry);
|
|
23000
|
+
entry = newEntry;
|
|
22970
23001
|
}
|
|
22971
|
-
const
|
|
22972
|
-
|
|
22973
|
-
|
|
22974
|
-
refCount: 1
|
|
22975
|
-
});
|
|
23002
|
+
const subscribed = entry;
|
|
23003
|
+
subscribed.listeners.add(onChange);
|
|
23004
|
+
let active = true;
|
|
22976
23005
|
return {
|
|
22977
|
-
|
|
22978
|
-
|
|
23006
|
+
read: () => ({
|
|
23007
|
+
result: subscribed.result,
|
|
23008
|
+
loading: !subscribed.hasResult
|
|
23009
|
+
}),
|
|
23010
|
+
unsubscribe: () => {
|
|
23011
|
+
if (!active)
|
|
23012
|
+
return;
|
|
23013
|
+
active = false;
|
|
23014
|
+
subscribed.listeners.delete(onChange);
|
|
23015
|
+
subscribed.refCount--;
|
|
23016
|
+
if (subscribed.refCount > 0)
|
|
23017
|
+
return;
|
|
23018
|
+
subscribed.pendingUnsub = setTimeout(() => {
|
|
23019
|
+
subscribed.pendingUnsub = undefined;
|
|
23020
|
+
if (subscribed.refCount > 0)
|
|
23021
|
+
return;
|
|
23022
|
+
eventWire.unsubscribeQuery(subscribed.subscriptionId);
|
|
23023
|
+
this.entries.delete(key);
|
|
23024
|
+
}, StreamingQueryCache2.UNSUBSCRIBE_DELAY_MS);
|
|
23025
|
+
}
|
|
22979
23026
|
};
|
|
22980
23027
|
}
|
|
22981
|
-
|
|
22982
|
-
const stream2 = this.activeStreams.get(key);
|
|
22983
|
-
if (!stream2)
|
|
22984
|
-
return;
|
|
22985
|
-
stream2.refCount--;
|
|
22986
|
-
if (stream2.refCount <= 0) {
|
|
22987
|
-
const timeout = setTimeout(() => {
|
|
22988
|
-
this.pendingUnsubscribes.delete(key);
|
|
22989
|
-
const current22 = this.activeStreams.get(key);
|
|
22990
|
-
if (current22 && current22.refCount <= 0) {
|
|
22991
|
-
current22.unsubscribe();
|
|
22992
|
-
this.activeStreams.delete(key);
|
|
22993
|
-
}
|
|
22994
|
-
}, StreamingQueryCache2.UNSUBSCRIBE_DELAY_MS);
|
|
22995
|
-
this.pendingUnsubscribes.set(key, timeout);
|
|
22996
|
-
}
|
|
22997
|
-
}
|
|
22998
|
-
subscribeView(viewName, eventWire, scope) {
|
|
22999
|
-
const key = this.storeKey(viewName, scope);
|
|
23000
|
-
const { unsubscribe } = this.registerStream(key, () => {
|
|
23001
|
-
const store = this.stores.get(key) ?? new StreamingStore2;
|
|
23002
|
-
this.stores.set(key, store);
|
|
23003
|
-
eventWire.subscribeView(viewName, scope ?? DEFAULT_SCOPE2, {
|
|
23004
|
-
onSnapshot: (items) => store.setAll(items),
|
|
23005
|
-
onChanges: (changes) => store.applyChanges(changes)
|
|
23006
|
-
});
|
|
23007
|
-
return {
|
|
23008
|
-
unsubscribe: () => eventWire.unsubscribeView(viewName, scope ?? DEFAULT_SCOPE2)
|
|
23009
|
-
};
|
|
23010
|
-
});
|
|
23011
|
-
return unsubscribe;
|
|
23012
|
-
}
|
|
23013
|
-
invalidateScope(scope) {
|
|
23028
|
+
invalidateScope(scope, eventWire) {
|
|
23014
23029
|
const prefix = `${scope}:`;
|
|
23015
|
-
for (const [key,
|
|
23030
|
+
for (const [key, entry] of this.entries) {
|
|
23016
23031
|
if (!key.startsWith(prefix))
|
|
23017
23032
|
continue;
|
|
23018
|
-
|
|
23019
|
-
|
|
23020
|
-
|
|
23021
|
-
|
|
23022
|
-
|
|
23023
|
-
|
|
23024
|
-
|
|
23025
|
-
stream2.unsubscribe();
|
|
23026
|
-
} catch {}
|
|
23027
|
-
this.activeStreams.delete(key);
|
|
23028
|
-
}
|
|
23029
|
-
for (const [key, store] of this.stores) {
|
|
23030
|
-
if (!key.startsWith(prefix))
|
|
23031
|
-
continue;
|
|
23032
|
-
store.clear();
|
|
23033
|
-
}
|
|
23034
|
-
}
|
|
23035
|
-
async applyEvent(event3) {
|
|
23036
|
-
for (const view3 of this.views) {
|
|
23037
|
-
const handlers = view3.getHandlers();
|
|
23038
|
-
const handler = handlers[event3.type];
|
|
23039
|
-
if (!handler)
|
|
23040
|
-
continue;
|
|
23041
|
-
const suffix = `:${view3.name}`;
|
|
23042
|
-
for (const [key, store] of this.stores) {
|
|
23043
|
-
if (!key.endsWith(suffix))
|
|
23044
|
-
continue;
|
|
23045
|
-
const ctx = {
|
|
23046
|
-
set: async (id3, data) => {
|
|
23047
|
-
store.set(String(id3), { _id: String(id3), ...data });
|
|
23048
|
-
},
|
|
23049
|
-
modify: async (id3, data) => {
|
|
23050
|
-
store.modify(String(id3), data);
|
|
23051
|
-
},
|
|
23052
|
-
remove: async (id3) => {
|
|
23053
|
-
store.remove(String(id3));
|
|
23054
|
-
},
|
|
23055
|
-
find: async (options) => {
|
|
23056
|
-
return store.find(options);
|
|
23057
|
-
},
|
|
23058
|
-
findOne: async (where) => {
|
|
23059
|
-
return store.findOne(where);
|
|
23060
|
-
},
|
|
23061
|
-
$auth: {}
|
|
23062
|
-
};
|
|
23063
|
-
await handler(ctx, event3);
|
|
23064
|
-
}
|
|
23065
|
-
}
|
|
23066
|
-
}
|
|
23067
|
-
clear() {
|
|
23068
|
-
for (const stream2 of this.activeStreams.values()) {
|
|
23069
|
-
stream2.unsubscribe();
|
|
23070
|
-
}
|
|
23071
|
-
this.activeStreams.clear();
|
|
23072
|
-
for (const timeout of this.pendingUnsubscribes.values()) {
|
|
23073
|
-
clearTimeout(timeout);
|
|
23074
|
-
}
|
|
23075
|
-
this.pendingUnsubscribes.clear();
|
|
23076
|
-
for (const store of this.stores.values()) {
|
|
23077
|
-
store.clear();
|
|
23033
|
+
if (entry.pendingUnsub)
|
|
23034
|
+
clearTimeout(entry.pendingUnsub);
|
|
23035
|
+
eventWire?.unsubscribeQuery(entry.subscriptionId);
|
|
23036
|
+
this.entries.delete(key);
|
|
23037
|
+
entry.result = undefined;
|
|
23038
|
+
entry.hasResult = false;
|
|
23039
|
+
this.notify(entry);
|
|
23078
23040
|
}
|
|
23079
23041
|
}
|
|
23080
|
-
|
|
23081
|
-
|
|
23082
|
-
|
|
23083
|
-
|
|
23084
|
-
|
|
23085
|
-
initialized = false;
|
|
23086
|
-
hasData() {
|
|
23087
|
-
return this.initialized;
|
|
23088
|
-
}
|
|
23089
|
-
setAll(items) {
|
|
23090
|
-
this.initialized = true;
|
|
23091
|
-
this.data.clear();
|
|
23092
|
-
for (const item of items) {
|
|
23093
|
-
this.data.set(item._id, item);
|
|
23042
|
+
clear(eventWire) {
|
|
23043
|
+
for (const entry of this.entries.values()) {
|
|
23044
|
+
if (entry.pendingUnsub)
|
|
23045
|
+
clearTimeout(entry.pendingUnsub);
|
|
23046
|
+
eventWire?.unsubscribeQuery(entry.subscriptionId);
|
|
23094
23047
|
}
|
|
23095
|
-
this.
|
|
23048
|
+
this.entries.clear();
|
|
23096
23049
|
}
|
|
23097
|
-
|
|
23098
|
-
|
|
23099
|
-
|
|
23100
|
-
|
|
23101
|
-
|
|
23102
|
-
|
|
23103
|
-
} else if (event3.type === "delete") {
|
|
23104
|
-
this.data.delete(event3.id);
|
|
23050
|
+
notify(entry) {
|
|
23051
|
+
for (const listener4 of entry.listeners) {
|
|
23052
|
+
try {
|
|
23053
|
+
listener4();
|
|
23054
|
+
} catch (err3) {
|
|
23055
|
+
console.error(`[Arc] Query cache listener error:`, err3);
|
|
23105
23056
|
}
|
|
23106
23057
|
}
|
|
23107
|
-
this.notifyListeners(events);
|
|
23108
|
-
}
|
|
23109
|
-
set(id3, item) {
|
|
23110
|
-
this.data.set(id3, item);
|
|
23111
|
-
this.notifyListeners([{ type: "set", id: id3, item }]);
|
|
23112
|
-
}
|
|
23113
|
-
modify(id3, updates) {
|
|
23114
|
-
const existing = this.data.get(id3);
|
|
23115
|
-
if (existing) {
|
|
23116
|
-
const updated = { ...existing, ...updates };
|
|
23117
|
-
this.data.set(id3, updated);
|
|
23118
|
-
this.notifyListeners([{ type: "set", id: id3, item: updated }]);
|
|
23119
|
-
}
|
|
23120
|
-
}
|
|
23121
|
-
remove(id3) {
|
|
23122
|
-
if (this.data.delete(id3)) {
|
|
23123
|
-
this.notifyListeners([{ type: "delete", id: id3, item: null }]);
|
|
23124
|
-
}
|
|
23125
|
-
}
|
|
23126
|
-
clear() {
|
|
23127
|
-
this.initialized = false;
|
|
23128
|
-
this.data.clear();
|
|
23129
|
-
this.notifyListeners(null);
|
|
23130
|
-
}
|
|
23131
|
-
find(options = {}) {
|
|
23132
|
-
let results = Array.from(this.data.values());
|
|
23133
|
-
if (options.where) {
|
|
23134
|
-
results = results.filter((item) => checkItemMatchesWhere2(item, options.where));
|
|
23135
|
-
}
|
|
23136
|
-
return applyOrderByAndLimit2(results, options);
|
|
23137
|
-
}
|
|
23138
|
-
findOne(where) {
|
|
23139
|
-
const results = this.find({ where });
|
|
23140
|
-
return results[0];
|
|
23141
|
-
}
|
|
23142
|
-
subscribe(listener4) {
|
|
23143
|
-
this.listeners.add(listener4);
|
|
23144
|
-
return () => {
|
|
23145
|
-
this.listeners.delete(listener4);
|
|
23146
|
-
};
|
|
23147
|
-
}
|
|
23148
|
-
notifyListeners(events) {
|
|
23149
|
-
for (const listener4 of this.listeners) {
|
|
23150
|
-
listener4(events);
|
|
23151
|
-
}
|
|
23152
23058
|
}
|
|
23153
23059
|
}
|
|
23154
23060
|
|
|
23155
23061
|
class StreamingEventPublisher2 {
|
|
23156
|
-
cache;
|
|
23157
23062
|
eventWire;
|
|
23158
23063
|
views = [];
|
|
23159
23064
|
subscribers = new Map;
|
|
23160
|
-
constructor(
|
|
23161
|
-
this.cache = cache;
|
|
23065
|
+
constructor(eventWire) {
|
|
23162
23066
|
this.eventWire = eventWire;
|
|
23163
23067
|
}
|
|
23164
23068
|
registerViews(views) {
|
|
23165
23069
|
this.views = views;
|
|
23166
|
-
this.cache.registerViews(views);
|
|
23167
23070
|
}
|
|
23168
23071
|
async publish(event3) {
|
|
23169
|
-
await this.cache.applyEvent(event3);
|
|
23170
23072
|
await this.notifySubscribers(event3);
|
|
23171
23073
|
this.eventWire.syncEvents([
|
|
23172
23074
|
{
|
|
@@ -24049,7 +23951,7 @@ var Operation2, PROXY_DRAFT2, RAW_RETURN_SYMBOL2, iteratorSymbol2, dataTypes2, i
|
|
|
24049
23951
|
}
|
|
24050
23952
|
return returnValue(result);
|
|
24051
23953
|
};
|
|
24052
|
-
}, create2, constructorString2, TOKEN_PREFIX2 = "arc:token:", eventWireInstanceCounter2 = 0, EVENT_TABLES2, arrayValidator2, ArcArray2, objectValidator2, ArcObject2, ScopedDataStorage2, ArcPrimitive2, stringValidator2, ArcString2, ArcContextElement2, ArcBoolean2, ArcId2, numberValidator2, ArcNumber2, ArcEvent2, ArcCommand2, ArcListener2, ArcRoute2, ForkedStoreState2, ForkedDataStorage2, MasterStoreState2, MasterDataStorage3, dateValidator2,
|
|
23954
|
+
}, create2, constructorString2, TOKEN_PREFIX2 = "arc:token:", DEFAULT_TIMEOUT_MS2 = 8000, provider2 = null, latestSync2 = null, syncSeq2 = 0, eventWireInstanceCounter2 = 0, EVENT_TABLES2, arrayValidator2, ArcArray2, objectValidator2, ArcObject2, ScopedDataStorage2, ArcPrimitive2, stringValidator2, ArcString2, ArcContextElement2, ArcBoolean2, ArcId2, numberValidator2, ArcNumber2, ArcEvent2, ArcCommand2, ArcListener2, ArcRoute2, ForkedStoreState2, ForkedDataStorage2, MasterStoreState2, MasterDataStorage3, dateValidator2, SQLiteReadWriteTransaction, createSQLiteAdapterFactory = (db) => {
|
|
24053
23955
|
return async (context) => {
|
|
24054
23956
|
const adapter = new SQLiteAdapter(db, context);
|
|
24055
23957
|
await adapter.initialize();
|
|
@@ -25614,12 +25516,8 @@ var init_dist2 = __esm(() => {
|
|
|
25614
25516
|
}
|
|
25615
25517
|
return transaction.find(this.storeName, { where: { _id: id22 } }).then((results) => results[0]);
|
|
25616
25518
|
}
|
|
25617
|
-
async applyChangeAndReturnEvent(transaction, change, transactionCache
|
|
25519
|
+
async applyChangeAndReturnEvent(transaction, change, transactionCache) {
|
|
25618
25520
|
if (change.type === "set") {
|
|
25619
|
-
let existing;
|
|
25620
|
-
if (options?.captureRows) {
|
|
25621
|
-
existing = await this.readExisting(transaction, change.data._id, transactionCache);
|
|
25622
|
-
}
|
|
25623
25521
|
await transaction.set(this.storeName, change.data);
|
|
25624
25522
|
const item = this.deserialize ? this.deserialize(change.data) : change.data;
|
|
25625
25523
|
if (transactionCache) {
|
|
@@ -25632,16 +25530,10 @@ var init_dist2 = __esm(() => {
|
|
|
25632
25530
|
type: "set",
|
|
25633
25531
|
item: change.data,
|
|
25634
25532
|
id: change.data._id
|
|
25635
|
-
}
|
|
25636
|
-
oldRow: existing ?? null,
|
|
25637
|
-
newRow: change.data
|
|
25533
|
+
}
|
|
25638
25534
|
};
|
|
25639
25535
|
}
|
|
25640
25536
|
if (change.type === "delete") {
|
|
25641
|
-
let existing;
|
|
25642
|
-
if (options?.captureRows) {
|
|
25643
|
-
existing = await this.readExisting(transaction, change.id, transactionCache);
|
|
25644
|
-
}
|
|
25645
25537
|
await transaction.remove(this.storeName, change.id);
|
|
25646
25538
|
if (transactionCache) {
|
|
25647
25539
|
transactionCache.delete(`${this.storeName}:${change.id}`);
|
|
@@ -25653,9 +25545,7 @@ var init_dist2 = __esm(() => {
|
|
|
25653
25545
|
type: "delete",
|
|
25654
25546
|
item: null,
|
|
25655
25547
|
id: change.id
|
|
25656
|
-
}
|
|
25657
|
-
oldRow: existing ?? null,
|
|
25658
|
-
newRow: null
|
|
25548
|
+
}
|
|
25659
25549
|
};
|
|
25660
25550
|
}
|
|
25661
25551
|
if (change.type === "modify") {
|
|
@@ -25673,9 +25563,7 @@ var init_dist2 = __esm(() => {
|
|
|
25673
25563
|
type: "set",
|
|
25674
25564
|
item,
|
|
25675
25565
|
id: change.id
|
|
25676
|
-
}
|
|
25677
|
-
oldRow: existing ?? null,
|
|
25678
|
-
newRow: updated
|
|
25566
|
+
}
|
|
25679
25567
|
};
|
|
25680
25568
|
}
|
|
25681
25569
|
if (change.type === "mutate") {
|
|
@@ -25693,9 +25581,7 @@ var init_dist2 = __esm(() => {
|
|
|
25693
25581
|
type: "set",
|
|
25694
25582
|
item,
|
|
25695
25583
|
id: change.id
|
|
25696
|
-
}
|
|
25697
|
-
oldRow: existing ?? null,
|
|
25698
|
-
newRow: updated
|
|
25584
|
+
}
|
|
25699
25585
|
};
|
|
25700
25586
|
}
|
|
25701
25587
|
throw new Error("Unknown change type");
|
|
@@ -25772,22 +25658,17 @@ var init_dist2 = __esm(() => {
|
|
|
25772
25658
|
applySerializedChanges(changes) {
|
|
25773
25659
|
return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applySerializedChanges(changes2)));
|
|
25774
25660
|
}
|
|
25775
|
-
async commitChanges(changes
|
|
25661
|
+
async commitChanges(changes) {
|
|
25776
25662
|
const transaction = await this.getReadWriteTransaction();
|
|
25777
25663
|
const transactionCache = new Map;
|
|
25778
25664
|
const eventsByStore = new Map;
|
|
25779
|
-
const committed = [];
|
|
25780
25665
|
for (const { store, changes: storeChanges } of changes) {
|
|
25781
25666
|
const storeState = this.getStore(store);
|
|
25782
25667
|
const storeEvents = [];
|
|
25783
|
-
const capture = options?.captureRowsFor?.has(store) ?? false;
|
|
25784
25668
|
for (const change of storeChanges) {
|
|
25785
|
-
const { event: event3
|
|
25669
|
+
const { event: event3 } = await storeState.applyChangeAndReturnEvent(transaction, change, transactionCache);
|
|
25786
25670
|
if (event3)
|
|
25787
25671
|
storeEvents.push(event3);
|
|
25788
|
-
if (capture) {
|
|
25789
|
-
committed.push({ store, id: event3.id, oldRow, newRow });
|
|
25790
|
-
}
|
|
25791
25672
|
}
|
|
25792
25673
|
if (storeEvents.length > 0) {
|
|
25793
25674
|
eventsByStore.set(store, storeEvents);
|
|
@@ -25798,7 +25679,6 @@ var init_dist2 = __esm(() => {
|
|
|
25798
25679
|
const storeState = this.getStore(store);
|
|
25799
25680
|
storeState.notifyListenersPublic(events);
|
|
25800
25681
|
}
|
|
25801
|
-
return committed;
|
|
25802
25682
|
}
|
|
25803
25683
|
fork() {
|
|
25804
25684
|
return new ForkedDataStorage2(this);
|
|
@@ -34582,8 +34462,8 @@ ${colors3.yellow}Type declaration errors:${colors3.reset}`);
|
|
|
34582
34462
|
}
|
|
34583
34463
|
|
|
34584
34464
|
// src/platform/shared.ts
|
|
34585
|
-
import { copyFileSync, existsSync as existsSync10, mkdirSync as mkdirSync9, readdirSync as
|
|
34586
|
-
import { dirname as dirname8, join as
|
|
34465
|
+
import { copyFileSync, existsSync as existsSync10, mkdirSync as mkdirSync9, readdirSync as readdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
34466
|
+
import { dirname as dirname8, join as join12 } from "path";
|
|
34587
34467
|
|
|
34588
34468
|
// src/builder/module-builder.ts
|
|
34589
34469
|
import { execSync } from "child_process";
|
|
@@ -35378,7 +35258,8 @@ writeFileSync(out, JSON.stringify(result, null, 2) + "\\n");
|
|
|
35378
35258
|
`.trim();
|
|
35379
35259
|
|
|
35380
35260
|
// src/builder/chunk-planner.ts
|
|
35381
|
-
import {
|
|
35261
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
|
|
35262
|
+
import { basename as basename3, join as join10 } from "path";
|
|
35382
35263
|
var PUBLIC_CHUNK = "public";
|
|
35383
35264
|
function planChunks(packages, accessMap) {
|
|
35384
35265
|
const assignments = new Map;
|
|
@@ -35410,6 +35291,53 @@ function planChunks(packages, accessMap) {
|
|
|
35410
35291
|
});
|
|
35411
35292
|
return { assignments, groups, chunks };
|
|
35412
35293
|
}
|
|
35294
|
+
var MODULE_CALL = /\bmodule\(\s*["'`]([a-zA-Z0-9_-]+)["'`]/g;
|
|
35295
|
+
function collectModuleNames(dir, acc) {
|
|
35296
|
+
let entries;
|
|
35297
|
+
try {
|
|
35298
|
+
entries = readdirSync5(dir);
|
|
35299
|
+
} catch {
|
|
35300
|
+
return;
|
|
35301
|
+
}
|
|
35302
|
+
for (const e of entries) {
|
|
35303
|
+
if (e === "node_modules" || e === "dist")
|
|
35304
|
+
continue;
|
|
35305
|
+
const full = join10(dir, e);
|
|
35306
|
+
let isDir = false;
|
|
35307
|
+
try {
|
|
35308
|
+
isDir = statSync2(full).isDirectory();
|
|
35309
|
+
} catch {
|
|
35310
|
+
continue;
|
|
35311
|
+
}
|
|
35312
|
+
if (isDir) {
|
|
35313
|
+
collectModuleNames(full, acc);
|
|
35314
|
+
} else if (e.endsWith(".ts") || e.endsWith(".tsx")) {
|
|
35315
|
+
const src = readFileSync9(full, "utf-8");
|
|
35316
|
+
MODULE_CALL.lastIndex = 0;
|
|
35317
|
+
let m;
|
|
35318
|
+
while (m = MODULE_CALL.exec(src))
|
|
35319
|
+
acc.add(m[1]);
|
|
35320
|
+
}
|
|
35321
|
+
}
|
|
35322
|
+
}
|
|
35323
|
+
function assertOneModulePerPackage(packages) {
|
|
35324
|
+
const offenders = [];
|
|
35325
|
+
for (const pkg of packages) {
|
|
35326
|
+
const names = new Set;
|
|
35327
|
+
collectModuleNames(join10(pkg.path, "src"), names);
|
|
35328
|
+
if (names.size > 1) {
|
|
35329
|
+
offenders.push({ pkg: pkg.name, modules: [...names].sort() });
|
|
35330
|
+
}
|
|
35331
|
+
}
|
|
35332
|
+
if (offenders.length === 0)
|
|
35333
|
+
return;
|
|
35334
|
+
const detail = offenders.map((o) => ` \u2022 ${o.pkg} declares ${o.modules.length}: ${o.modules.join(", ")}`).join(`
|
|
35335
|
+
`);
|
|
35336
|
+
throw new Error(`Arc build: a workspace package must declare at most ONE module().
|
|
35337
|
+
` + `Chunk grouping is per-package \u2014 a second module() silently inherits the ` + `first module's token protection and chunk, so e.g. a public onboarding ` + `page sharing a package with a workspaceToken-gated module becomes ` + `unreachable for users without that token.
|
|
35338
|
+
${detail}
|
|
35339
|
+
` + `Fix: move each extra module() into its own workspace package ` + `(declare its own protectedBy there).`);
|
|
35340
|
+
}
|
|
35413
35341
|
function moduleNameOf(pkgName) {
|
|
35414
35342
|
return pkgName.includes("/") ? pkgName.split("/").pop() : pkgName;
|
|
35415
35343
|
}
|
|
@@ -35417,17 +35345,19 @@ function resolveChunk(moduleName, access) {
|
|
|
35417
35345
|
if (!access || access.rules.length === 0)
|
|
35418
35346
|
return PUBLIC_CHUNK;
|
|
35419
35347
|
const tokenNames = new Set(access.rules.map((r) => r.token.name));
|
|
35420
|
-
if (tokenNames.size
|
|
35421
|
-
|
|
35348
|
+
if (tokenNames.size > 1) {
|
|
35349
|
+
const list = [...tokenNames].sort().join(", ");
|
|
35350
|
+
throw new Error(`Module "${moduleName}" has access rules for multiple tokens [${list}]. ` + `Multi-token modules are not supported \u2014 split the module or unify on a single token type.`);
|
|
35422
35351
|
}
|
|
35423
|
-
const
|
|
35424
|
-
|
|
35352
|
+
const tokenName = [...tokenNames][0];
|
|
35353
|
+
const hasCheck = access.rules.some((r) => r.hasCheck);
|
|
35354
|
+
return hasCheck ? `${tokenName}__${moduleName}` : tokenName;
|
|
35425
35355
|
}
|
|
35426
35356
|
|
|
35427
35357
|
// src/builder/dependency-collector.ts
|
|
35428
35358
|
import { createHash } from "crypto";
|
|
35429
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as
|
|
35430
|
-
import { basename as basename4, dirname as dirname7, join as
|
|
35359
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
35360
|
+
import { basename as basename4, dirname as dirname7, join as join11 } from "path";
|
|
35431
35361
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
35432
35362
|
function collectFrameworkDeps(arcDir, rootDir, packages, sharedDeps = []) {
|
|
35433
35363
|
mkdirSync8(arcDir, { recursive: true });
|
|
@@ -35438,7 +35368,7 @@ function collectFrameworkDeps(arcDir, rootDir, packages, sharedDeps = []) {
|
|
|
35438
35368
|
try {
|
|
35439
35369
|
const cliDir = dirname7(fileURLToPath6(import.meta.url));
|
|
35440
35370
|
const arcOtelPkgPath = Bun.resolveSync("@arcote.tech/arc-otel/package.json", cliDir);
|
|
35441
|
-
const arcOtelPkg = JSON.parse(
|
|
35371
|
+
const arcOtelPkg = JSON.parse(readFileSync10(arcOtelPkgPath, "utf-8"));
|
|
35442
35372
|
for (const [name, spec] of Object.entries(arcOtelPkg.dependencies ?? {})) {
|
|
35443
35373
|
if (name.startsWith("@opentelemetry/")) {
|
|
35444
35374
|
versions[name] = spec;
|
|
@@ -35449,10 +35379,10 @@ function collectFrameworkDeps(arcDir, rootDir, packages, sharedDeps = []) {
|
|
|
35449
35379
|
console.warn(`[arc-otel] could not resolve @arcote.tech/arc-otel \u2014 image will run without telemetry deps: ${e.message}`);
|
|
35450
35380
|
}
|
|
35451
35381
|
let rootArc;
|
|
35452
|
-
const rootPkgPath =
|
|
35382
|
+
const rootPkgPath = join11(rootDir, "package.json");
|
|
35453
35383
|
if (existsSync9(rootPkgPath)) {
|
|
35454
35384
|
try {
|
|
35455
|
-
const rootPkg = JSON.parse(
|
|
35385
|
+
const rootPkg = JSON.parse(readFileSync10(rootPkgPath, "utf-8"));
|
|
35456
35386
|
if (rootPkg.arc && typeof rootPkg.arc === "object")
|
|
35457
35387
|
rootArc = rootPkg.arc;
|
|
35458
35388
|
} catch {}
|
|
@@ -35464,11 +35394,11 @@ function collectFrameworkDeps(arcDir, rootDir, packages, sharedDeps = []) {
|
|
|
35464
35394
|
dependencies: versions,
|
|
35465
35395
|
...rootArc ? { arc: rootArc } : {}
|
|
35466
35396
|
};
|
|
35467
|
-
const manifestPath =
|
|
35397
|
+
const manifestPath = join11(arcDir, "package.json");
|
|
35468
35398
|
writeFileSync8(manifestPath, JSON.stringify(manifest, null, 2) + `
|
|
35469
35399
|
`);
|
|
35470
|
-
const hash = sha256Hex2(
|
|
35471
|
-
writeFileSync8(
|
|
35400
|
+
const hash = sha256Hex2(readFileSync10(manifestPath));
|
|
35401
|
+
writeFileSync8(join11(arcDir, ".deps-hash"), hash + `
|
|
35472
35402
|
`);
|
|
35473
35403
|
return { hash, manifestPath };
|
|
35474
35404
|
}
|
|
@@ -35476,7 +35406,7 @@ function sha256Hex2(bytes) {
|
|
|
35476
35406
|
return createHash("sha256").update(bytes).digest("hex");
|
|
35477
35407
|
}
|
|
35478
35408
|
function resolveFrameworkVersions(rootDir, packages) {
|
|
35479
|
-
const rootPkg = JSON.parse(
|
|
35409
|
+
const rootPkg = JSON.parse(readFileSync10(join11(rootDir, "package.json"), "utf-8"));
|
|
35480
35410
|
const rootDeps = rootPkg.dependencies ?? {};
|
|
35481
35411
|
const rootDevDeps = rootPkg.devDependencies ?? {};
|
|
35482
35412
|
const required = new Set(FRAMEWORK_PEERS);
|
|
@@ -35535,9 +35465,9 @@ function resolveWorkspace() {
|
|
|
35535
35465
|
process.exit(1);
|
|
35536
35466
|
}
|
|
35537
35467
|
const rootDir = dirname8(packageJsonPath);
|
|
35538
|
-
const rootPkg = JSON.parse(
|
|
35468
|
+
const rootPkg = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
|
|
35539
35469
|
const appName = rootPkg.name ?? "Arc App";
|
|
35540
|
-
const arcDir =
|
|
35470
|
+
const arcDir = join12(rootDir, ".arc", "platform");
|
|
35541
35471
|
log2("Scanning workspaces...");
|
|
35542
35472
|
const packages = discoverPackages(rootDir);
|
|
35543
35473
|
if (packages.length > 0) {
|
|
@@ -35547,10 +35477,10 @@ function resolveWorkspace() {
|
|
|
35547
35477
|
}
|
|
35548
35478
|
let manifest;
|
|
35549
35479
|
for (const name of ["manifest.json", "manifest.webmanifest"]) {
|
|
35550
|
-
const manifestPath =
|
|
35480
|
+
const manifestPath = join12(rootDir, name);
|
|
35551
35481
|
if (existsSync10(manifestPath)) {
|
|
35552
35482
|
try {
|
|
35553
|
-
const data = JSON.parse(
|
|
35483
|
+
const data = JSON.parse(readFileSync11(manifestPath, "utf-8"));
|
|
35554
35484
|
const icons = data.icons;
|
|
35555
35485
|
manifest = {
|
|
35556
35486
|
path: manifestPath,
|
|
@@ -35569,9 +35499,9 @@ function resolveWorkspace() {
|
|
|
35569
35499
|
rootPkg,
|
|
35570
35500
|
appName,
|
|
35571
35501
|
arcDir,
|
|
35572
|
-
browserDir:
|
|
35573
|
-
assetsDir:
|
|
35574
|
-
publicDir:
|
|
35502
|
+
browserDir: join12(arcDir, "browser"),
|
|
35503
|
+
assetsDir: join12(arcDir, "assets"),
|
|
35504
|
+
publicDir: join12(rootDir, "public"),
|
|
35575
35505
|
packages,
|
|
35576
35506
|
manifest
|
|
35577
35507
|
};
|
|
@@ -35581,11 +35511,12 @@ async function buildAll(ws, opts = {}) {
|
|
|
35581
35511
|
const noCache = opts.noCache ?? false;
|
|
35582
35512
|
const themePath = ws.rootPkg.arc?.theme;
|
|
35583
35513
|
log2(`Building (concurrency parallel${noCache ? ", no-cache" : ""})...`);
|
|
35514
|
+
assertOneModulePerPackage(ws.packages);
|
|
35584
35515
|
await buildContextPackages(ws.rootDir, ws.packages, cache, noCache);
|
|
35585
35516
|
copyContextServerBundles(ws);
|
|
35586
35517
|
const accessMap = await extractAccessMap(ws.rootDir, ws.packages);
|
|
35587
35518
|
mkdirSync9(ws.arcDir, { recursive: true });
|
|
35588
|
-
writeFileSync9(
|
|
35519
|
+
writeFileSync9(join12(ws.arcDir, "access.json"), JSON.stringify(accessMap, null, 2) + `
|
|
35589
35520
|
`);
|
|
35590
35521
|
const plan = planChunks(ws.packages, accessMap);
|
|
35591
35522
|
ok(`Chunks: ${plan.chunks.map((c) => `${c}(${plan.groups.get(c)?.length ?? 0})`).join(", ")}`);
|
|
@@ -35601,7 +35532,7 @@ async function buildAll(ws, opts = {}) {
|
|
|
35601
35532
|
collectFrameworkDeps(ws.arcDir, ws.rootDir, ws.packages);
|
|
35602
35533
|
saveBuildCache(ws.arcDir, cache);
|
|
35603
35534
|
const finalManifest = assembleManifest(ws, browserResult, cache);
|
|
35604
|
-
writeFileSync9(
|
|
35535
|
+
writeFileSync9(join12(ws.arcDir, "manifest.json"), JSON.stringify(finalManifest, null, 2));
|
|
35605
35536
|
return finalManifest;
|
|
35606
35537
|
}
|
|
35607
35538
|
function assembleManifest(ws, browser, cache) {
|
|
@@ -35615,40 +35546,40 @@ function assembleManifest(ws, browser, cache) {
|
|
|
35615
35546
|
};
|
|
35616
35547
|
}
|
|
35617
35548
|
function copyContextServerBundles(ws) {
|
|
35618
|
-
const outDir =
|
|
35549
|
+
const outDir = join12(ws.arcDir, "server");
|
|
35619
35550
|
mkdirSync9(outDir, { recursive: true });
|
|
35620
35551
|
for (const pkg of ws.packages) {
|
|
35621
35552
|
if (!isContextPackage(pkg.packageJson))
|
|
35622
35553
|
continue;
|
|
35623
|
-
const src =
|
|
35554
|
+
const src = join12(pkg.path, "dist", "server", "main", "index.js");
|
|
35624
35555
|
if (!existsSync10(src)) {
|
|
35625
35556
|
err(`Server bundle missing for ${pkg.name}: ${src}`);
|
|
35626
35557
|
continue;
|
|
35627
35558
|
}
|
|
35628
35559
|
const safeName = pkg.path.split("/").pop();
|
|
35629
|
-
const dst =
|
|
35560
|
+
const dst = join12(outDir, `${safeName}.js`);
|
|
35630
35561
|
copyFileSync(src, dst);
|
|
35631
35562
|
}
|
|
35632
35563
|
}
|
|
35633
35564
|
function resolveAssetSource(from, pkgDir, rootDir) {
|
|
35634
35565
|
if (from.startsWith("./") || from.startsWith("../")) {
|
|
35635
|
-
const resolved =
|
|
35566
|
+
const resolved = join12(pkgDir, from);
|
|
35636
35567
|
return existsSync10(resolved) ? resolved : null;
|
|
35637
35568
|
}
|
|
35638
35569
|
const candidates = [
|
|
35639
|
-
|
|
35640
|
-
|
|
35570
|
+
join12(rootDir, "node_modules", from),
|
|
35571
|
+
join12(pkgDir, "node_modules", from)
|
|
35641
35572
|
];
|
|
35642
35573
|
for (const c of candidates) {
|
|
35643
35574
|
if (existsSync10(c))
|
|
35644
35575
|
return c;
|
|
35645
35576
|
}
|
|
35646
|
-
const bunCacheDir =
|
|
35577
|
+
const bunCacheDir = join12(rootDir, "node_modules", ".bun");
|
|
35647
35578
|
if (existsSync10(bunCacheDir)) {
|
|
35648
|
-
for (const entry of
|
|
35579
|
+
for (const entry of readdirSync6(bunCacheDir, { withFileTypes: true })) {
|
|
35649
35580
|
if (!entry.isDirectory())
|
|
35650
35581
|
continue;
|
|
35651
|
-
const candidate =
|
|
35582
|
+
const candidate = join12(bunCacheDir, entry.name, "node_modules", from);
|
|
35652
35583
|
if (existsSync10(candidate))
|
|
35653
35584
|
return candidate;
|
|
35654
35585
|
}
|
|
@@ -35656,11 +35587,11 @@ function resolveAssetSource(from, pkgDir, rootDir) {
|
|
|
35656
35587
|
return null;
|
|
35657
35588
|
}
|
|
35658
35589
|
function readBrowserAssets(pkgDir) {
|
|
35659
|
-
const pkgJsonPath =
|
|
35590
|
+
const pkgJsonPath = join12(pkgDir, "package.json");
|
|
35660
35591
|
if (!existsSync10(pkgJsonPath))
|
|
35661
35592
|
return [];
|
|
35662
35593
|
try {
|
|
35663
|
-
const pkg = JSON.parse(
|
|
35594
|
+
const pkg = JSON.parse(readFileSync11(pkgJsonPath, "utf-8"));
|
|
35664
35595
|
const assets = pkg.arc?.browserAssets;
|
|
35665
35596
|
if (!Array.isArray(assets))
|
|
35666
35597
|
return [];
|
|
@@ -35670,14 +35601,14 @@ function readBrowserAssets(pkgDir) {
|
|
|
35670
35601
|
}
|
|
35671
35602
|
}
|
|
35672
35603
|
function discoverBrowserAssets(ws) {
|
|
35673
|
-
const arcDir =
|
|
35604
|
+
const arcDir = join12(ws.rootDir, "node_modules", "@arcote.tech");
|
|
35674
35605
|
if (!existsSync10(arcDir))
|
|
35675
35606
|
return [];
|
|
35676
35607
|
const out = [];
|
|
35677
|
-
for (const entry of
|
|
35608
|
+
for (const entry of readdirSync6(arcDir, { withFileTypes: true })) {
|
|
35678
35609
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
35679
35610
|
continue;
|
|
35680
|
-
const pkgDir =
|
|
35611
|
+
const pkgDir = join12(arcDir, entry.name);
|
|
35681
35612
|
const assets = readBrowserAssets(pkgDir);
|
|
35682
35613
|
for (const asset of assets) {
|
|
35683
35614
|
const src = resolveAssetSource(asset.from, pkgDir, ws.rootDir);
|
|
@@ -35702,7 +35633,7 @@ async function copyBrowserAssets(ws, cache, noCache) {
|
|
|
35702
35633
|
to: a.to,
|
|
35703
35634
|
mtime: mtimeOf(a.src)
|
|
35704
35635
|
})));
|
|
35705
|
-
const requiredOutputs = assets.map((a) =>
|
|
35636
|
+
const requiredOutputs = assets.map((a) => join12(ws.assetsDir, a.to));
|
|
35706
35637
|
if (!noCache && isCacheHit(cache, unitId, inputHash, requiredOutputs)) {
|
|
35707
35638
|
console.log(` \u2713 cached: browser-assets (${assets.length})`);
|
|
35708
35639
|
return;
|
|
@@ -35710,10 +35641,10 @@ async function copyBrowserAssets(ws, cache, noCache) {
|
|
|
35710
35641
|
console.log(` building: browser-assets (${assets.length})`);
|
|
35711
35642
|
const outputHashes = {};
|
|
35712
35643
|
for (const asset of assets) {
|
|
35713
|
-
const dest =
|
|
35644
|
+
const dest = join12(ws.assetsDir, asset.to);
|
|
35714
35645
|
mkdirSync9(dirname8(dest), { recursive: true });
|
|
35715
35646
|
copyFileSync(asset.src, dest);
|
|
35716
|
-
outputHashes[asset.to] = sha256Hex(
|
|
35647
|
+
outputHashes[asset.to] = sha256Hex(readFileSync11(dest));
|
|
35717
35648
|
}
|
|
35718
35649
|
updateCache(cache, unitId, inputHash, { outputHashes });
|
|
35719
35650
|
}
|
|
@@ -35721,15 +35652,15 @@ async function loadServerContext(ws) {
|
|
|
35721
35652
|
globalThis.ONLY_SERVER = true;
|
|
35722
35653
|
globalThis.ONLY_BROWSER = false;
|
|
35723
35654
|
globalThis.ONLY_CLIENT = false;
|
|
35724
|
-
const platformDir =
|
|
35725
|
-
const platformPkg = JSON.parse(
|
|
35726
|
-
const platformEntry =
|
|
35655
|
+
const platformDir = join12(process.cwd(), "node_modules", "@arcote.tech", "platform");
|
|
35656
|
+
const platformPkg = JSON.parse(readFileSync11(join12(platformDir, "package.json"), "utf-8"));
|
|
35657
|
+
const platformEntry = join12(platformDir, platformPkg.main ?? "src/index.ts");
|
|
35727
35658
|
await import(platformEntry);
|
|
35728
|
-
const serverDir =
|
|
35729
|
-
const bundles = existsSync10(serverDir) ?
|
|
35659
|
+
const serverDir = join12(ws.arcDir, "server");
|
|
35660
|
+
const bundles = existsSync10(serverDir) ? readdirSync6(serverDir).filter((f) => f.endsWith(".js")) : [];
|
|
35730
35661
|
if (bundles.length > 0) {
|
|
35731
35662
|
for (const file of bundles) {
|
|
35732
|
-
const bundlePath =
|
|
35663
|
+
const bundlePath = join12(serverDir, file);
|
|
35733
35664
|
try {
|
|
35734
35665
|
await import(bundlePath);
|
|
35735
35666
|
} catch (e) {
|
|
@@ -35739,7 +35670,7 @@ async function loadServerContext(ws) {
|
|
|
35739
35670
|
} else if (ws.packages.length > 0) {
|
|
35740
35671
|
const ctxPackages = ws.packages.filter((p) => isContextPackage(p.packageJson));
|
|
35741
35672
|
for (const ctx of ctxPackages) {
|
|
35742
|
-
const serverDist =
|
|
35673
|
+
const serverDist = join12(ctx.path, "dist", "server", "main", "index.js");
|
|
35743
35674
|
if (!existsSync10(serverDist)) {
|
|
35744
35675
|
err(`Context server dist not found: ${serverDist}`);
|
|
35745
35676
|
continue;
|
|
@@ -35769,21 +35700,21 @@ async function platformBuild(opts = {}) {
|
|
|
35769
35700
|
}
|
|
35770
35701
|
|
|
35771
35702
|
// src/commands/platform-deploy.ts
|
|
35772
|
-
import { existsSync as existsSync17, readFileSync as
|
|
35773
|
-
import { dirname as dirname11, join as
|
|
35703
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
|
|
35704
|
+
import { dirname as dirname11, join as join20 } from "path";
|
|
35774
35705
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
35775
35706
|
|
|
35776
35707
|
// src/deploy/bootstrap.ts
|
|
35777
35708
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
35778
35709
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
35779
35710
|
import { tmpdir as tmpdir2 } from "os";
|
|
35780
|
-
import { dirname as dirname9, join as
|
|
35711
|
+
import { dirname as dirname9, join as join18 } from "path";
|
|
35781
35712
|
|
|
35782
35713
|
// src/deploy/ansible.ts
|
|
35783
35714
|
import { spawn as nodeSpawn } from "child_process";
|
|
35784
35715
|
import { existsSync as existsSync11, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
35785
35716
|
import { homedir, tmpdir } from "os";
|
|
35786
|
-
import { join as
|
|
35717
|
+
import { join as join13 } from "path";
|
|
35787
35718
|
|
|
35788
35719
|
// src/deploy/assets.ts
|
|
35789
35720
|
var TERRAFORM_MAIN_TF = `terraform {
|
|
@@ -36057,28 +35988,28 @@ var ASSETS = {
|
|
|
36057
35988
|
};
|
|
36058
35989
|
async function materializeAssets(targetDir, files) {
|
|
36059
35990
|
const { mkdirSync: mkdirSync10, writeFileSync: writeFileSync10 } = await import("fs");
|
|
36060
|
-
const { join:
|
|
35991
|
+
const { join: join13 } = await import("path");
|
|
36061
35992
|
mkdirSync10(targetDir, { recursive: true });
|
|
36062
35993
|
for (const [name, content] of Object.entries(files)) {
|
|
36063
|
-
writeFileSync10(
|
|
35994
|
+
writeFileSync10(join13(targetDir, name), content);
|
|
36064
35995
|
}
|
|
36065
35996
|
}
|
|
36066
35997
|
|
|
36067
35998
|
// src/deploy/ansible.ts
|
|
36068
35999
|
function pickSshKeyForAnsible(configured) {
|
|
36069
36000
|
if (configured) {
|
|
36070
|
-
const expanded = configured.startsWith("~") ?
|
|
36001
|
+
const expanded = configured.startsWith("~") ? join13(homedir(), configured.slice(1)) : configured;
|
|
36071
36002
|
return existsSync11(expanded) ? expanded : null;
|
|
36072
36003
|
}
|
|
36073
36004
|
for (const name of ["id_ed25519", "id_ecdsa", "id_rsa"]) {
|
|
36074
|
-
const path4 =
|
|
36005
|
+
const path4 = join13(homedir(), ".ssh", name);
|
|
36075
36006
|
if (existsSync11(path4))
|
|
36076
36007
|
return path4;
|
|
36077
36008
|
}
|
|
36078
36009
|
return null;
|
|
36079
36010
|
}
|
|
36080
36011
|
async function runAnsible(inputs) {
|
|
36081
|
-
const workDir =
|
|
36012
|
+
const workDir = join13(tmpdir(), "arc-deploy", `ansible-${Date.now()}`);
|
|
36082
36013
|
mkdirSync10(workDir, { recursive: true });
|
|
36083
36014
|
await materializeAssets(workDir, ASSETS.ansible);
|
|
36084
36015
|
const user = inputs.asRoot ? "root" : inputs.target.user;
|
|
@@ -36095,7 +36026,7 @@ async function runAnsible(inputs) {
|
|
|
36095
36026
|
""
|
|
36096
36027
|
].join(`
|
|
36097
36028
|
`);
|
|
36098
|
-
writeFileSync10(
|
|
36029
|
+
writeFileSync10(join13(workDir, "inventory.ini"), inventory);
|
|
36099
36030
|
const extraVarsJson = JSON.stringify({
|
|
36100
36031
|
username: inputs.target.user,
|
|
36101
36032
|
ssh_port: port,
|
|
@@ -37143,10 +37074,10 @@ import { spawn as nodeSpawn2 } from "child_process";
|
|
|
37143
37074
|
import { createHash as createHash2 } from "crypto";
|
|
37144
37075
|
import { existsSync as existsSync12, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
37145
37076
|
import { homedir as homedir2 } from "os";
|
|
37146
|
-
import { join as
|
|
37077
|
+
import { join as join14 } from "path";
|
|
37147
37078
|
async function runTerraform(inputs) {
|
|
37148
37079
|
const wsHash = createHash2("sha256").update(inputs.workspaceDir).digest("hex").slice(0, 16);
|
|
37149
|
-
const workDir =
|
|
37080
|
+
const workDir = join14(homedir2(), ".arc-deploy", wsHash, "tf");
|
|
37150
37081
|
mkdirSync11(workDir, { recursive: true });
|
|
37151
37082
|
await materializeAssets(workDir, ASSETS.terraform);
|
|
37152
37083
|
const sshPubKey = inputs.tf.sshPublicKey ?? expandHome("~/.ssh/id_ed25519.pub");
|
|
@@ -37163,7 +37094,7 @@ async function runTerraform(inputs) {
|
|
|
37163
37094
|
].join(`
|
|
37164
37095
|
`) + `
|
|
37165
37096
|
`;
|
|
37166
|
-
writeFileSync11(
|
|
37097
|
+
writeFileSync11(join14(workDir, "terraform.tfvars"), tfvars);
|
|
37167
37098
|
await runTf(workDir, ["init", "-input=false", "-no-color"]);
|
|
37168
37099
|
await runTf(workDir, [
|
|
37169
37100
|
"apply",
|
|
@@ -37221,20 +37152,20 @@ function expandHome(p) {
|
|
|
37221
37152
|
}
|
|
37222
37153
|
|
|
37223
37154
|
// src/deploy/config.ts
|
|
37224
|
-
import { existsSync as existsSync14, readFileSync as
|
|
37225
|
-
import { join as
|
|
37155
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
37156
|
+
import { join as join16 } from "path";
|
|
37226
37157
|
|
|
37227
37158
|
// src/deploy/env-file.ts
|
|
37228
|
-
import { appendFileSync, existsSync as existsSync13, readFileSync as
|
|
37229
|
-
import { join as
|
|
37159
|
+
import { appendFileSync, existsSync as existsSync13, readFileSync as readFileSync12 } from "fs";
|
|
37160
|
+
import { join as join15 } from "path";
|
|
37230
37161
|
function loadDeployEnvFiles(rootDir, envNames) {
|
|
37231
|
-
const globalsPath =
|
|
37232
|
-
const globals = existsSync13(globalsPath) ? parseEnvFile(
|
|
37162
|
+
const globalsPath = join15(rootDir, "deploy.arc.env");
|
|
37163
|
+
const globals = existsSync13(globalsPath) ? parseEnvFile(readFileSync12(globalsPath, "utf-8"), globalsPath) : {};
|
|
37233
37164
|
const perEnv = {};
|
|
37234
37165
|
for (const name of envNames) {
|
|
37235
|
-
const envPath =
|
|
37166
|
+
const envPath = join15(rootDir, `deploy.arc.${name}.env`);
|
|
37236
37167
|
if (existsSync13(envPath)) {
|
|
37237
|
-
perEnv[name] = parseEnvFile(
|
|
37168
|
+
perEnv[name] = parseEnvFile(readFileSync12(envPath, "utf-8"), envPath);
|
|
37238
37169
|
}
|
|
37239
37170
|
}
|
|
37240
37171
|
return { globals, perEnv };
|
|
@@ -37250,16 +37181,16 @@ function ensurePersistedSecret(rootDir, scope, key, generate) {
|
|
|
37250
37181
|
if (process.env[key])
|
|
37251
37182
|
return process.env[key];
|
|
37252
37183
|
const fileName = scope === "globals" ? "deploy.arc.env" : `deploy.arc.${scope}.env`;
|
|
37253
|
-
const path4 =
|
|
37184
|
+
const path4 = join15(rootDir, fileName);
|
|
37254
37185
|
if (existsSync13(path4)) {
|
|
37255
|
-
const existing = parseEnvFile(
|
|
37186
|
+
const existing = parseEnvFile(readFileSync12(path4, "utf-8"), path4);
|
|
37256
37187
|
if (existing[key]) {
|
|
37257
37188
|
process.env[key] = existing[key];
|
|
37258
37189
|
return existing[key];
|
|
37259
37190
|
}
|
|
37260
37191
|
}
|
|
37261
37192
|
const value = generate();
|
|
37262
|
-
const prefix = existsSync13(path4) && !
|
|
37193
|
+
const prefix = existsSync13(path4) && !readFileSync12(path4, "utf-8").endsWith(`
|
|
37263
37194
|
`) ? `
|
|
37264
37195
|
` : "";
|
|
37265
37196
|
appendFileSync(path4, `${prefix}${key}=${value}
|
|
@@ -37295,7 +37226,7 @@ function parseEnvFile(content, pathForErrors) {
|
|
|
37295
37226
|
// src/deploy/config.ts
|
|
37296
37227
|
var DEPLOY_CONFIG_FILE = "deploy.arc.json";
|
|
37297
37228
|
function deployConfigPath(rootDir) {
|
|
37298
|
-
return
|
|
37229
|
+
return join16(rootDir, DEPLOY_CONFIG_FILE);
|
|
37299
37230
|
}
|
|
37300
37231
|
function deployConfigExists(rootDir) {
|
|
37301
37232
|
return existsSync14(deployConfigPath(rootDir));
|
|
@@ -37305,7 +37236,7 @@ function loadDeployConfig(rootDir) {
|
|
|
37305
37236
|
if (!existsSync14(path4)) {
|
|
37306
37237
|
throw new Error(`Missing ${DEPLOY_CONFIG_FILE} at ${path4}`);
|
|
37307
37238
|
}
|
|
37308
|
-
const raw =
|
|
37239
|
+
const raw = readFileSync13(path4, "utf-8");
|
|
37309
37240
|
let parsed;
|
|
37310
37241
|
try {
|
|
37311
37242
|
parsed = JSON.parse(raw);
|
|
@@ -37328,7 +37259,7 @@ function loadDeployConfig(rootDir) {
|
|
|
37328
37259
|
}
|
|
37329
37260
|
function saveDeployConfig(rootDir, cfg) {
|
|
37330
37261
|
const path4 = deployConfigPath(rootDir);
|
|
37331
|
-
const raw = existsSync14(path4) ? JSON.parse(
|
|
37262
|
+
const raw = existsSync14(path4) ? JSON.parse(readFileSync13(path4, "utf-8")) : {};
|
|
37332
37263
|
raw.target = { ...raw.target, ...cfg.target };
|
|
37333
37264
|
writeFileSync12(path4, JSON.stringify(raw, null, 2) + `
|
|
37334
37265
|
`);
|
|
@@ -37541,14 +37472,14 @@ function cfgErr(path4, expected) {
|
|
|
37541
37472
|
var {spawn: spawn3 } = globalThis.Bun;
|
|
37542
37473
|
import { existsSync as existsSync15 } from "fs";
|
|
37543
37474
|
import { homedir as homedir3 } from "os";
|
|
37544
|
-
import { join as
|
|
37475
|
+
import { join as join17 } from "path";
|
|
37545
37476
|
function pickSshKey(target) {
|
|
37546
37477
|
if (target.sshKey) {
|
|
37547
|
-
const expanded = target.sshKey.startsWith("~") ?
|
|
37478
|
+
const expanded = target.sshKey.startsWith("~") ? join17(homedir3(), target.sshKey.slice(1)) : target.sshKey;
|
|
37548
37479
|
return existsSync15(expanded) ? expanded : null;
|
|
37549
37480
|
}
|
|
37550
37481
|
for (const name of ["id_ed25519", "id_ecdsa", "id_rsa"]) {
|
|
37551
|
-
const path4 =
|
|
37482
|
+
const path4 = join17(homedir3(), ".ssh", name);
|
|
37552
37483
|
if (existsSync15(path4))
|
|
37553
37484
|
return path4;
|
|
37554
37485
|
}
|
|
@@ -37784,7 +37715,7 @@ async function isRegistryRunning(cfg) {
|
|
|
37784
37715
|
}
|
|
37785
37716
|
async function upStack(inputs) {
|
|
37786
37717
|
const { cfg } = inputs;
|
|
37787
|
-
const workDir =
|
|
37718
|
+
const workDir = join18(tmpdir2(), "arc-deploy", `stack-${Date.now()}`);
|
|
37788
37719
|
mkdirSync12(workDir, { recursive: true });
|
|
37789
37720
|
await assertRegistryDnsResolves(cfg);
|
|
37790
37721
|
const password = process.env[cfg.registry.passwordEnv];
|
|
@@ -37792,9 +37723,9 @@ async function upStack(inputs) {
|
|
|
37792
37723
|
throw new Error(`Registry password env var ${cfg.registry.passwordEnv} is not set. ` + `Set it (e.g. \`export ${cfg.registry.passwordEnv}=...\`) before bootstrap.`);
|
|
37793
37724
|
}
|
|
37794
37725
|
const htpasswdLine = await generateHtpasswd(cfg.registry.username, password);
|
|
37795
|
-
writeFileSync13(
|
|
37796
|
-
writeFileSync13(
|
|
37797
|
-
writeFileSync13(
|
|
37726
|
+
writeFileSync13(join18(workDir, "htpasswd"), htpasswdLine);
|
|
37727
|
+
writeFileSync13(join18(workDir, "Caddyfile"), generateCaddyfile(cfg));
|
|
37728
|
+
writeFileSync13(join18(workDir, "docker-compose.yml"), generateCompose({ cfg }));
|
|
37798
37729
|
let observabilityFiles = null;
|
|
37799
37730
|
let observabilityHtpasswd = null;
|
|
37800
37731
|
if (cfg.observability?.enabled) {
|
|
@@ -37806,30 +37737,30 @@ async function upStack(inputs) {
|
|
|
37806
37737
|
}
|
|
37807
37738
|
observabilityHtpasswd = await generateCaddyBasicAuthLine("admin", adminPassword);
|
|
37808
37739
|
for (const [relPath, contents] of Object.entries(observabilityFiles)) {
|
|
37809
|
-
const fullPath =
|
|
37740
|
+
const fullPath = join18(workDir, relPath);
|
|
37810
37741
|
mkdirSync12(dirname9(fullPath), { recursive: true });
|
|
37811
37742
|
writeFileSync13(fullPath, contents);
|
|
37812
37743
|
}
|
|
37813
|
-
writeFileSync13(
|
|
37744
|
+
writeFileSync13(join18(workDir, "observability-htpasswd"), observabilityHtpasswd);
|
|
37814
37745
|
}
|
|
37815
37746
|
await assertExec(cfg.target, `sudo mkdir -p ${cfg.target.remoteDir} && sudo chown ${cfg.target.user}:${cfg.target.user} ${cfg.target.remoteDir}`);
|
|
37816
37747
|
for (const name of Object.keys(cfg.envs)) {
|
|
37817
37748
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/${name}`);
|
|
37818
37749
|
}
|
|
37819
37750
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/registry-auth`);
|
|
37820
|
-
await scpUpload(cfg.target,
|
|
37821
|
-
await scpUpload(cfg.target,
|
|
37822
|
-
await scpUpload(cfg.target,
|
|
37751
|
+
await scpUpload(cfg.target, join18(workDir, "Caddyfile"), `${cfg.target.remoteDir}/Caddyfile`);
|
|
37752
|
+
await scpUpload(cfg.target, join18(workDir, "docker-compose.yml"), `${cfg.target.remoteDir}/docker-compose.yml`);
|
|
37753
|
+
await scpUpload(cfg.target, join18(workDir, "htpasswd"), `${cfg.target.remoteDir}/registry-auth/htpasswd`);
|
|
37823
37754
|
if (observabilityFiles && observabilityHtpasswd) {
|
|
37824
37755
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/observability/grafana-dashboards`);
|
|
37825
37756
|
for (const relPath of Object.keys(observabilityFiles)) {
|
|
37826
|
-
const localDir = dirname9(
|
|
37757
|
+
const localDir = dirname9(join18(workDir, relPath));
|
|
37827
37758
|
mkdirSync12(localDir, { recursive: true });
|
|
37828
37759
|
}
|
|
37829
37760
|
for (const relPath of Object.keys(observabilityFiles)) {
|
|
37830
|
-
await scpUpload(cfg.target,
|
|
37761
|
+
await scpUpload(cfg.target, join18(workDir, relPath), `${cfg.target.remoteDir}/${relPath}`);
|
|
37831
37762
|
}
|
|
37832
|
-
await scpUpload(cfg.target,
|
|
37763
|
+
await scpUpload(cfg.target, join18(workDir, "observability-htpasswd"), `${cfg.target.remoteDir}/observability-htpasswd`);
|
|
37833
37764
|
}
|
|
37834
37765
|
await assertExec(cfg.target, `touch ${cfg.target.remoteDir}/.env`);
|
|
37835
37766
|
if (cfg.observability?.enabled) {
|
|
@@ -37997,12 +37928,12 @@ import {
|
|
|
37997
37928
|
copyFileSync as copyFileSync2,
|
|
37998
37929
|
existsSync as existsSync16,
|
|
37999
37930
|
mkdirSync as mkdirSync13,
|
|
38000
|
-
readFileSync as
|
|
37931
|
+
readFileSync as readFileSync14,
|
|
38001
37932
|
realpathSync as realpathSync2,
|
|
38002
37933
|
writeFileSync as writeFileSync14
|
|
38003
37934
|
} from "fs";
|
|
38004
37935
|
import { tmpdir as tmpdir3 } from "os";
|
|
38005
|
-
import { dirname as dirname10, join as
|
|
37936
|
+
import { dirname as dirname10, join as join19 } from "path";
|
|
38006
37937
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
38007
37938
|
|
|
38008
37939
|
// src/deploy/image-template.ts
|
|
@@ -38052,7 +37983,7 @@ function generateDockerfile(inputs) {
|
|
|
38052
37983
|
// src/deploy/image.ts
|
|
38053
37984
|
async function buildImage(ws, opts) {
|
|
38054
37985
|
await ensureDocker();
|
|
38055
|
-
const manifestPath =
|
|
37986
|
+
const manifestPath = join19(ws.arcDir, "manifest.json");
|
|
38056
37987
|
if (!existsSync16(manifestPath)) {
|
|
38057
37988
|
throw new Error(`No build manifest at ${manifestPath}. Run \`arc platform build\` first or omit --skip-build.`);
|
|
38058
37989
|
}
|
|
@@ -38063,9 +37994,9 @@ async function buildImage(ws, opts) {
|
|
|
38063
37994
|
const dockerfileInputs = collectDockerfileInputs(ws);
|
|
38064
37995
|
const dockerfile = generateDockerfile(dockerfileInputs);
|
|
38065
37996
|
const buildContextDir = ws.rootDir;
|
|
38066
|
-
const dockerfileDir =
|
|
37997
|
+
const dockerfileDir = join19(tmpdir3(), `arc-image-${Date.now()}`);
|
|
38067
37998
|
mkdirSync13(dockerfileDir, { recursive: true });
|
|
38068
|
-
const dockerfilePath =
|
|
37999
|
+
const dockerfilePath = join19(dockerfileDir, "Dockerfile");
|
|
38069
38000
|
writeFileSync14(dockerfilePath, dockerfile);
|
|
38070
38001
|
const buildArgs = [
|
|
38071
38002
|
"build",
|
|
@@ -38091,19 +38022,19 @@ async function buildImage(ws, opts) {
|
|
|
38091
38022
|
}
|
|
38092
38023
|
function embedCliBundle(ws) {
|
|
38093
38024
|
const source = locateCliBundle();
|
|
38094
|
-
const target =
|
|
38025
|
+
const target = join19(ws.arcDir, "host.js");
|
|
38095
38026
|
copyFileSync2(source, target);
|
|
38096
38027
|
}
|
|
38097
38028
|
function locateCliBundle() {
|
|
38098
38029
|
const here = fileURLToPath7(import.meta.url);
|
|
38099
38030
|
let cur = dirname10(here);
|
|
38100
38031
|
while (cur !== "/" && cur !== "") {
|
|
38101
|
-
const candidate =
|
|
38032
|
+
const candidate = join19(cur, "package.json");
|
|
38102
38033
|
if (existsSync16(candidate)) {
|
|
38103
38034
|
try {
|
|
38104
|
-
const pkg = JSON.parse(
|
|
38035
|
+
const pkg = JSON.parse(readFileSync14(candidate, "utf-8"));
|
|
38105
38036
|
if (pkg.name === "@arcote.tech/arc-cli") {
|
|
38106
|
-
const distIndex =
|
|
38037
|
+
const distIndex = join19(realpathSync2(cur), "dist", "index.js");
|
|
38107
38038
|
if (!existsSync16(distIndex)) {
|
|
38108
38039
|
throw new Error(`arc-cli bundle missing at ${distIndex}. Run \`bun run build\` in packages/cli/.`);
|
|
38109
38040
|
}
|
|
@@ -38136,17 +38067,17 @@ async function ensureDocker() {
|
|
|
38136
38067
|
}
|
|
38137
38068
|
}
|
|
38138
38069
|
function computeContentHash(manifestPath) {
|
|
38139
|
-
const raw = JSON.parse(
|
|
38070
|
+
const raw = JSON.parse(readFileSync14(manifestPath, "utf-8"));
|
|
38140
38071
|
delete raw.buildTime;
|
|
38141
38072
|
const canonical = JSON.stringify(raw);
|
|
38142
38073
|
return createHash3("sha256").update(canonical).digest("hex").slice(0, 12);
|
|
38143
38074
|
}
|
|
38144
38075
|
function collectDockerfileInputs(ws) {
|
|
38145
|
-
const hasPublicDir = existsSync16(
|
|
38146
|
-
const hasLocales = existsSync16(
|
|
38076
|
+
const hasPublicDir = existsSync16(join19(ws.rootDir, "public"));
|
|
38077
|
+
const hasLocales = existsSync16(join19(ws.rootDir, "locales"));
|
|
38147
38078
|
let manifestPath;
|
|
38148
38079
|
for (const name of ["manifest.webmanifest", "manifest.json"]) {
|
|
38149
|
-
if (existsSync16(
|
|
38080
|
+
if (existsSync16(join19(ws.rootDir, name))) {
|
|
38150
38081
|
manifestPath = name;
|
|
38151
38082
|
break;
|
|
38152
38083
|
}
|
|
@@ -38975,7 +38906,7 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
38975
38906
|
err(`Unknown env "${envArg}". Known: ${Object.keys(cfg.envs).join(", ")}`);
|
|
38976
38907
|
process.exit(1);
|
|
38977
38908
|
})() : Object.keys(cfg.envs);
|
|
38978
|
-
const manifestPath =
|
|
38909
|
+
const manifestPath = join20(ws.arcDir, "manifest.json");
|
|
38979
38910
|
if (!options.imageTag) {
|
|
38980
38911
|
const needBuild = options.rebuild || !existsSync17(manifestPath);
|
|
38981
38912
|
if (needBuild && !options.skipBuild) {
|
|
@@ -39048,9 +38979,9 @@ function readCliVersion2() {
|
|
|
39048
38979
|
let cur = dirname11(fileURLToPath8(import.meta.url));
|
|
39049
38980
|
const root = dirname11(cur).startsWith("/") ? "/" : ".";
|
|
39050
38981
|
while (cur !== root && cur !== "") {
|
|
39051
|
-
const candidate =
|
|
38982
|
+
const candidate = join20(cur, "package.json");
|
|
39052
38983
|
if (existsSync17(candidate)) {
|
|
39053
|
-
const pkg = JSON.parse(
|
|
38984
|
+
const pkg = JSON.parse(readFileSync15(candidate, "utf-8"));
|
|
39054
38985
|
if (pkg.name === "@arcote.tech/arc-cli") {
|
|
39055
38986
|
return pkg.version ?? "unknown";
|
|
39056
38987
|
}
|
|
@@ -39066,8 +38997,8 @@ function readCliVersion2() {
|
|
|
39066
38997
|
}
|
|
39067
38998
|
}
|
|
39068
38999
|
async function hashDeployConfig(rootDir) {
|
|
39069
|
-
const p2 =
|
|
39070
|
-
const content =
|
|
39000
|
+
const p2 = join20(rootDir, "deploy.arc.json");
|
|
39001
|
+
const content = readFileSync15(p2);
|
|
39071
39002
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
39072
39003
|
hasher.update(content);
|
|
39073
39004
|
hasher.update(readCliVersion2());
|
|
@@ -39075,8 +39006,8 @@ async function hashDeployConfig(rootDir) {
|
|
|
39075
39006
|
}
|
|
39076
39007
|
|
|
39077
39008
|
// src/platform/startup.ts
|
|
39078
|
-
import { existsSync as existsSync19, readFileSync as
|
|
39079
|
-
import { join as
|
|
39009
|
+
import { existsSync as existsSync19, readFileSync as readFileSync16, watch } from "fs";
|
|
39010
|
+
import { join as join22 } from "path";
|
|
39080
39011
|
|
|
39081
39012
|
// ../host/src/create-server.ts
|
|
39082
39013
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
@@ -40496,7 +40427,7 @@ async function createArcServer(config) {
|
|
|
40496
40427
|
// src/platform/server.ts
|
|
40497
40428
|
init_i18n();
|
|
40498
40429
|
import { existsSync as existsSync18, mkdirSync as mkdirSync14 } from "fs";
|
|
40499
|
-
import { join as
|
|
40430
|
+
import { join as join21 } from "path";
|
|
40500
40431
|
async function resolveDbAdapterFactory(dbPath) {
|
|
40501
40432
|
const databaseUrl = process.env.DATABASE_URL;
|
|
40502
40433
|
if (databaseUrl && databaseUrl.length > 0) {
|
|
@@ -40628,15 +40559,13 @@ function parseArcTokensHeader(header) {
|
|
|
40628
40559
|
return payloads;
|
|
40629
40560
|
}
|
|
40630
40561
|
async function filterManifestForTokens(manifest, moduleAccessMap, tokenPayloads) {
|
|
40631
|
-
const
|
|
40562
|
+
const tokensByName = new Map;
|
|
40632
40563
|
for (const t of tokenPayloads) {
|
|
40633
40564
|
if (t?.tokenType)
|
|
40634
|
-
|
|
40565
|
+
tokensByName.set(t.tokenType, t);
|
|
40635
40566
|
}
|
|
40636
40567
|
const filteredGroups = {};
|
|
40637
40568
|
for (const [name, group] of Object.entries(manifest.groups)) {
|
|
40638
|
-
if (!allowedGroups.has(name))
|
|
40639
|
-
continue;
|
|
40640
40569
|
let allGranted = true;
|
|
40641
40570
|
for (const moduleName of group.modules) {
|
|
40642
40571
|
const access = moduleAccessMap.get(moduleName);
|
|
@@ -40644,9 +40573,7 @@ async function filterManifestForTokens(manifest, moduleAccessMap, tokenPayloads)
|
|
|
40644
40573
|
continue;
|
|
40645
40574
|
let granted = false;
|
|
40646
40575
|
for (const rule of access.rules) {
|
|
40647
|
-
|
|
40648
|
-
continue;
|
|
40649
|
-
const matching = tokenPayloads.find((t) => t.tokenType === name);
|
|
40576
|
+
const matching = tokensByName.get(rule.token.name);
|
|
40650
40577
|
if (!matching)
|
|
40651
40578
|
continue;
|
|
40652
40579
|
granted = rule.check ? await rule.check(matching) : true;
|
|
@@ -40687,28 +40614,28 @@ function staticFilesHandler(ws, devMode, getManifest) {
|
|
|
40687
40614
|
return new Response("Forbidden", { status: 403, headers: ctx.corsHeaders });
|
|
40688
40615
|
}
|
|
40689
40616
|
}
|
|
40690
|
-
return serveFile(
|
|
40617
|
+
return serveFile(join21(ws.browserDir, file), {
|
|
40691
40618
|
...ctx.corsHeaders,
|
|
40692
40619
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
40693
40620
|
});
|
|
40694
40621
|
}
|
|
40695
40622
|
if (path4.startsWith("/locales/"))
|
|
40696
|
-
return serveFile(
|
|
40623
|
+
return serveFile(join21(ws.arcDir, path4.slice(1)), {
|
|
40697
40624
|
...ctx.corsHeaders,
|
|
40698
40625
|
"Cache-Control": devMode ? "no-cache" : "max-age=300,stale-while-revalidate=3600"
|
|
40699
40626
|
});
|
|
40700
40627
|
if (path4.startsWith("/assets/"))
|
|
40701
|
-
return serveFile(
|
|
40628
|
+
return serveFile(join21(ws.assetsDir, path4.slice(8)), {
|
|
40702
40629
|
...ctx.corsHeaders,
|
|
40703
40630
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
40704
40631
|
});
|
|
40705
40632
|
if (path4 === "/styles.css")
|
|
40706
|
-
return serveFile(
|
|
40633
|
+
return serveFile(join21(ws.arcDir, "styles.css"), {
|
|
40707
40634
|
...ctx.corsHeaders,
|
|
40708
40635
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
40709
40636
|
});
|
|
40710
40637
|
if (path4 === "/theme.css")
|
|
40711
|
-
return serveFile(
|
|
40638
|
+
return serveFile(join21(ws.arcDir, "theme.css"), {
|
|
40712
40639
|
...ctx.corsHeaders,
|
|
40713
40640
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
40714
40641
|
});
|
|
@@ -40716,7 +40643,7 @@ function staticFilesHandler(ws, devMode, getManifest) {
|
|
|
40716
40643
|
return serveFile(ws.manifest.path, ctx.corsHeaders);
|
|
40717
40644
|
}
|
|
40718
40645
|
if (path4.lastIndexOf(".") > path4.lastIndexOf("/")) {
|
|
40719
|
-
const publicFile =
|
|
40646
|
+
const publicFile = join21(ws.publicDir, path4.slice(1));
|
|
40720
40647
|
if (existsSync18(publicFile))
|
|
40721
40648
|
return serveFile(publicFile, ctx.corsHeaders);
|
|
40722
40649
|
}
|
|
@@ -40871,7 +40798,7 @@ async function startPlatformServer(opts) {
|
|
|
40871
40798
|
stop: () => server.stop()
|
|
40872
40799
|
};
|
|
40873
40800
|
}
|
|
40874
|
-
const dbPath = opts.dbPath ||
|
|
40801
|
+
const dbPath = opts.dbPath || join21(ws.arcDir, "data", "arc.db");
|
|
40875
40802
|
const baseDbFactory = await resolveDbAdapterFactory(dbPath);
|
|
40876
40803
|
let dbAdapterFactory = baseDbFactory;
|
|
40877
40804
|
if (telemetry) {
|
|
@@ -40912,17 +40839,17 @@ async function startPlatformServer(opts) {
|
|
|
40912
40839
|
async function startPlatform(opts) {
|
|
40913
40840
|
const { ws, devMode } = opts;
|
|
40914
40841
|
const port = opts.port ?? parseInt(process.env.PORT || "5005", 10);
|
|
40915
|
-
const dbPath = opts.dbPath ??
|
|
40842
|
+
const dbPath = opts.dbPath ?? join22(ws.rootDir, ".arc", "data", devMode ? "dev.db" : "prod.db");
|
|
40916
40843
|
let manifest;
|
|
40917
40844
|
if (devMode) {
|
|
40918
40845
|
manifest = await buildAll(ws);
|
|
40919
40846
|
} else {
|
|
40920
|
-
const manifestPath =
|
|
40847
|
+
const manifestPath = join22(ws.arcDir, "manifest.json");
|
|
40921
40848
|
if (!existsSync19(manifestPath)) {
|
|
40922
40849
|
err("No build found. Run `arc platform build` first.");
|
|
40923
40850
|
process.exit(1);
|
|
40924
40851
|
}
|
|
40925
|
-
manifest = JSON.parse(
|
|
40852
|
+
manifest = JSON.parse(readFileSync16(manifestPath, "utf-8"));
|
|
40926
40853
|
}
|
|
40927
40854
|
log2("Loading server context...");
|
|
40928
40855
|
const { context: context2, moduleAccess } = await loadServerContext(ws);
|
|
@@ -40998,7 +40925,7 @@ function attachDevWatcher(ws, platform3) {
|
|
|
40998
40925
|
}, 300);
|
|
40999
40926
|
};
|
|
41000
40927
|
for (const pkg of ws.packages) {
|
|
41001
|
-
const srcDir =
|
|
40928
|
+
const srcDir = join22(pkg.path, "src");
|
|
41002
40929
|
if (!existsSync19(srcDir))
|
|
41003
40930
|
continue;
|
|
41004
40931
|
watch(srcDir, { recursive: true }, (_event, filename) => {
|
|
@@ -41009,7 +40936,7 @@ function attachDevWatcher(ws, platform3) {
|
|
|
41009
40936
|
triggerRebuild();
|
|
41010
40937
|
});
|
|
41011
40938
|
}
|
|
41012
|
-
const localesDir =
|
|
40939
|
+
const localesDir = join22(ws.rootDir, "locales");
|
|
41013
40940
|
if (existsSync19(localesDir)) {
|
|
41014
40941
|
watch(localesDir, { recursive: false }, (_event, filename) => {
|
|
41015
40942
|
if (!filename?.endsWith(".po"))
|