@arcote.tech/arc-cli 0.8.5 → 0.8.7
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 +245 -120
- package/package.json +10 -10
- package/src/builder/module-builder.ts +82 -20
- package/src/builder/seed-guard.ts +21 -4
package/dist/index.js
CHANGED
|
@@ -10191,8 +10191,72 @@ function apply(state, patches, applyOptions) {
|
|
|
10191
10191
|
}
|
|
10192
10192
|
return create(state, mutate, Object.assign(Object.assign({}, applyOptions), { enablePatches: false }));
|
|
10193
10193
|
}
|
|
10194
|
-
function
|
|
10195
|
-
return typeof
|
|
10194
|
+
function hasDocument() {
|
|
10195
|
+
return typeof document !== "undefined";
|
|
10196
|
+
}
|
|
10197
|
+
function signalCrossTabChange() {
|
|
10198
|
+
if (typeof localStorage === "undefined")
|
|
10199
|
+
return;
|
|
10200
|
+
try {
|
|
10201
|
+
localStorage.setItem(TOKEN_BUMP_KEY, String(Date.now()));
|
|
10202
|
+
} catch {}
|
|
10203
|
+
}
|
|
10204
|
+
function isSecureContext() {
|
|
10205
|
+
return typeof location !== "undefined" && location.protocol === "https:";
|
|
10206
|
+
}
|
|
10207
|
+
function tokenCookieName(scopeKey) {
|
|
10208
|
+
return scopeKey === "default" ? COOKIE_PREFIX : `${COOKIE_PREFIX}_${scopeKey.replace(/:/g, ".")}`;
|
|
10209
|
+
}
|
|
10210
|
+
function scopeKeyFromCookieName(name) {
|
|
10211
|
+
if (name === COOKIE_PREFIX)
|
|
10212
|
+
return "default";
|
|
10213
|
+
if (!name.startsWith(`${COOKIE_PREFIX}_`))
|
|
10214
|
+
return null;
|
|
10215
|
+
return name.slice(COOKIE_PREFIX.length + 1).replace(/\./g, ":");
|
|
10216
|
+
}
|
|
10217
|
+
function maxAgeFromExp(exp) {
|
|
10218
|
+
const THIRTY_DAYS = 30 * 24 * 60 * 60;
|
|
10219
|
+
if (typeof exp !== "number" || !Number.isFinite(exp))
|
|
10220
|
+
return THIRTY_DAYS;
|
|
10221
|
+
const expMs = exp > 1000000000000 ? exp : exp * 1000;
|
|
10222
|
+
const secs = Math.floor((expMs - Date.now()) / 1000);
|
|
10223
|
+
return secs > 0 ? secs : THIRTY_DAYS;
|
|
10224
|
+
}
|
|
10225
|
+
function writeTokenCookie(scopeKey, jwt, exp) {
|
|
10226
|
+
if (!hasDocument())
|
|
10227
|
+
return;
|
|
10228
|
+
const attrs = [
|
|
10229
|
+
"Path=/",
|
|
10230
|
+
"SameSite=Lax",
|
|
10231
|
+
`Max-Age=${maxAgeFromExp(exp)}`
|
|
10232
|
+
];
|
|
10233
|
+
if (isSecureContext())
|
|
10234
|
+
attrs.push("Secure");
|
|
10235
|
+
document.cookie = `${tokenCookieName(scopeKey)}=${encodeURIComponent(jwt)}; ${attrs.join("; ")}`;
|
|
10236
|
+
signalCrossTabChange();
|
|
10237
|
+
}
|
|
10238
|
+
function removeTokenCookie(scopeKey) {
|
|
10239
|
+
if (!hasDocument())
|
|
10240
|
+
return;
|
|
10241
|
+
document.cookie = `${tokenCookieName(scopeKey)}=; Path=/; SameSite=Lax; Max-Age=0`;
|
|
10242
|
+
signalCrossTabChange();
|
|
10243
|
+
}
|
|
10244
|
+
function readAllTokenCookies() {
|
|
10245
|
+
if (!hasDocument() || !document.cookie)
|
|
10246
|
+
return [];
|
|
10247
|
+
const out = [];
|
|
10248
|
+
for (const part of document.cookie.split(";")) {
|
|
10249
|
+
const eq = part.indexOf("=");
|
|
10250
|
+
if (eq < 0)
|
|
10251
|
+
continue;
|
|
10252
|
+
const scopeKey = scopeKeyFromCookieName(part.slice(0, eq).trim());
|
|
10253
|
+
if (scopeKey === null)
|
|
10254
|
+
continue;
|
|
10255
|
+
const jwt = decodeURIComponent(part.slice(eq + 1).trim());
|
|
10256
|
+
if (jwt)
|
|
10257
|
+
out.push({ scopeKey, jwt });
|
|
10258
|
+
}
|
|
10259
|
+
return out;
|
|
10196
10260
|
}
|
|
10197
10261
|
function notifyTokenChange(scope) {
|
|
10198
10262
|
if (typeof window !== "undefined") {
|
|
@@ -10208,24 +10272,21 @@ class AuthAdapter {
|
|
|
10208
10272
|
constructor(options) {
|
|
10209
10273
|
this.namespace = options?.storageNamespace || undefined;
|
|
10210
10274
|
}
|
|
10211
|
-
|
|
10212
|
-
return this.namespace ? `${
|
|
10275
|
+
scopeKey(scope) {
|
|
10276
|
+
return this.namespace ? `${this.namespace}:${scope}` : scope;
|
|
10213
10277
|
}
|
|
10214
10278
|
setToken(token, scope = "default") {
|
|
10215
10279
|
if (!token) {
|
|
10216
10280
|
this.scopes.delete(scope);
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
notifyTokenChange(scope);
|
|
10220
|
-
}
|
|
10281
|
+
removeTokenCookie(this.scopeKey(scope));
|
|
10282
|
+
notifyTokenChange(scope);
|
|
10221
10283
|
return;
|
|
10222
10284
|
}
|
|
10223
10285
|
try {
|
|
10224
10286
|
const parts = token.split(".");
|
|
10225
10287
|
if (parts.length !== 3) {
|
|
10226
10288
|
this.scopes.delete(scope);
|
|
10227
|
-
|
|
10228
|
-
localStorage.removeItem(this.storageKey(scope));
|
|
10289
|
+
removeTokenCookie(this.scopeKey(scope));
|
|
10229
10290
|
return;
|
|
10230
10291
|
}
|
|
10231
10292
|
const payload = JSON.parse(atob(parts[1]));
|
|
@@ -10238,49 +10299,45 @@ class AuthAdapter {
|
|
|
10238
10299
|
exp: payload.exp
|
|
10239
10300
|
}
|
|
10240
10301
|
});
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
notifyTokenChange(scope);
|
|
10244
|
-
}
|
|
10302
|
+
writeTokenCookie(this.scopeKey(scope), token, payload.exp);
|
|
10303
|
+
notifyTokenChange(scope);
|
|
10245
10304
|
} catch {
|
|
10246
10305
|
this.scopes.delete(scope);
|
|
10247
|
-
|
|
10248
|
-
localStorage.removeItem(this.storageKey(scope));
|
|
10306
|
+
removeTokenCookie(this.scopeKey(scope));
|
|
10249
10307
|
}
|
|
10250
10308
|
}
|
|
10251
10309
|
setDecoded(decoded, scope = "default") {
|
|
10252
10310
|
this.scopes.set(scope, { raw: "", decoded });
|
|
10253
10311
|
}
|
|
10254
10312
|
loadPersisted() {
|
|
10255
|
-
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
if (key?.startsWith(prefix)) {
|
|
10261
|
-
const scope = key.slice(prefix.length);
|
|
10262
|
-
if (!this.namespace && scope.includes(":"))
|
|
10313
|
+
const nsPrefix = this.namespace ? `${this.namespace}:` : "";
|
|
10314
|
+
for (const { scopeKey, jwt } of readAllTokenCookies()) {
|
|
10315
|
+
let scope;
|
|
10316
|
+
if (this.namespace) {
|
|
10317
|
+
if (!scopeKey.startsWith(nsPrefix))
|
|
10263
10318
|
continue;
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
}
|
|
10280
|
-
|
|
10281
|
-
|
|
10319
|
+
scope = scopeKey.slice(nsPrefix.length);
|
|
10320
|
+
} else {
|
|
10321
|
+
if (scopeKey.includes(":"))
|
|
10322
|
+
continue;
|
|
10323
|
+
scope = scopeKey;
|
|
10324
|
+
}
|
|
10325
|
+
try {
|
|
10326
|
+
const parts = jwt.split(".");
|
|
10327
|
+
if (parts.length !== 3)
|
|
10328
|
+
continue;
|
|
10329
|
+
const payload = JSON.parse(atob(parts[1]));
|
|
10330
|
+
this.scopes.set(scope, {
|
|
10331
|
+
raw: jwt,
|
|
10332
|
+
decoded: {
|
|
10333
|
+
tokenName: payload.tokenName,
|
|
10334
|
+
params: payload.params || {},
|
|
10335
|
+
iat: payload.iat,
|
|
10336
|
+
exp: payload.exp
|
|
10282
10337
|
}
|
|
10283
|
-
}
|
|
10338
|
+
});
|
|
10339
|
+
} catch {
|
|
10340
|
+
removeTokenCookie(scopeKey);
|
|
10284
10341
|
}
|
|
10285
10342
|
}
|
|
10286
10343
|
}
|
|
@@ -10312,10 +10369,8 @@ class AuthAdapter {
|
|
|
10312
10369
|
return Array.from(this.scopes.keys());
|
|
10313
10370
|
}
|
|
10314
10371
|
clear() {
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
localStorage.removeItem(this.storageKey(scope));
|
|
10318
|
-
}
|
|
10372
|
+
for (const scope of this.scopes.keys()) {
|
|
10373
|
+
removeTokenCookie(this.scopeKey(scope));
|
|
10319
10374
|
}
|
|
10320
10375
|
this.scopes.clear();
|
|
10321
10376
|
}
|
|
@@ -14595,7 +14650,7 @@ var Operation, PROXY_DRAFT, RAW_RETURN_SYMBOL, iteratorSymbol, dataTypes, intern
|
|
|
14595
14650
|
}
|
|
14596
14651
|
return returnValue(result);
|
|
14597
14652
|
};
|
|
14598
|
-
}, create, constructorString,
|
|
14653
|
+
}, create, constructorString, COOKIE_PREFIX = "arc_token", TOKEN_BUMP_KEY = "arc:token-bump", DEFAULT_TIMEOUT_MS = 8000, provider = null, latestSync = null, syncSeq = 0, eventWireInstanceCounter = 0, EVENT_TABLES, arrayValidator, ArcArray, objectValidator, ArcObject, ScopedDataStorage, ArcAuthenticationError, ArcAuthorizationError2, ArcValidationError2, ArcPrimitive, stringValidator, ArcString, ArcContextElement, ArcBoolean, ArcId, numberValidator, ArcNumber, ArcEvent, ArcCommand, ArcListener, ArcRoute, ForkedStoreState, ForkedDataStorage, MasterStoreState, MasterDataStorage2, dateValidator, _te, _td, originCache, originStackCache, originError, CLOSE, Query, PostgresError, Errors, types2, Identifier, Parameter, Builder, defaultHandlers, builders, serializers, parsers, mergeUserTypes = function(types22) {
|
|
14599
14654
|
const user = typeHandlers(types22 || {});
|
|
14600
14655
|
return {
|
|
14601
14656
|
serializers: Object.assign({}, serializers, user.serializers),
|
|
@@ -17838,8 +17893,72 @@ function apply2(state, patches, applyOptions) {
|
|
|
17838
17893
|
}
|
|
17839
17894
|
return create2(state, mutate, Object.assign(Object.assign({}, applyOptions), { enablePatches: false }));
|
|
17840
17895
|
}
|
|
17841
|
-
function
|
|
17842
|
-
return typeof
|
|
17896
|
+
function hasDocument2() {
|
|
17897
|
+
return typeof document !== "undefined";
|
|
17898
|
+
}
|
|
17899
|
+
function signalCrossTabChange2() {
|
|
17900
|
+
if (typeof localStorage === "undefined")
|
|
17901
|
+
return;
|
|
17902
|
+
try {
|
|
17903
|
+
localStorage.setItem(TOKEN_BUMP_KEY2, String(Date.now()));
|
|
17904
|
+
} catch {}
|
|
17905
|
+
}
|
|
17906
|
+
function isSecureContext2() {
|
|
17907
|
+
return typeof location !== "undefined" && location.protocol === "https:";
|
|
17908
|
+
}
|
|
17909
|
+
function tokenCookieName2(scopeKey) {
|
|
17910
|
+
return scopeKey === "default" ? COOKIE_PREFIX2 : `${COOKIE_PREFIX2}_${scopeKey.replace(/:/g, ".")}`;
|
|
17911
|
+
}
|
|
17912
|
+
function scopeKeyFromCookieName2(name) {
|
|
17913
|
+
if (name === COOKIE_PREFIX2)
|
|
17914
|
+
return "default";
|
|
17915
|
+
if (!name.startsWith(`${COOKIE_PREFIX2}_`))
|
|
17916
|
+
return null;
|
|
17917
|
+
return name.slice(COOKIE_PREFIX2.length + 1).replace(/\./g, ":");
|
|
17918
|
+
}
|
|
17919
|
+
function maxAgeFromExp2(exp) {
|
|
17920
|
+
const THIRTY_DAYS = 30 * 24 * 60 * 60;
|
|
17921
|
+
if (typeof exp !== "number" || !Number.isFinite(exp))
|
|
17922
|
+
return THIRTY_DAYS;
|
|
17923
|
+
const expMs = exp > 1000000000000 ? exp : exp * 1000;
|
|
17924
|
+
const secs = Math.floor((expMs - Date.now()) / 1000);
|
|
17925
|
+
return secs > 0 ? secs : THIRTY_DAYS;
|
|
17926
|
+
}
|
|
17927
|
+
function writeTokenCookie2(scopeKey, jwt, exp) {
|
|
17928
|
+
if (!hasDocument2())
|
|
17929
|
+
return;
|
|
17930
|
+
const attrs = [
|
|
17931
|
+
"Path=/",
|
|
17932
|
+
"SameSite=Lax",
|
|
17933
|
+
`Max-Age=${maxAgeFromExp2(exp)}`
|
|
17934
|
+
];
|
|
17935
|
+
if (isSecureContext2())
|
|
17936
|
+
attrs.push("Secure");
|
|
17937
|
+
document.cookie = `${tokenCookieName2(scopeKey)}=${encodeURIComponent(jwt)}; ${attrs.join("; ")}`;
|
|
17938
|
+
signalCrossTabChange2();
|
|
17939
|
+
}
|
|
17940
|
+
function removeTokenCookie2(scopeKey) {
|
|
17941
|
+
if (!hasDocument2())
|
|
17942
|
+
return;
|
|
17943
|
+
document.cookie = `${tokenCookieName2(scopeKey)}=; Path=/; SameSite=Lax; Max-Age=0`;
|
|
17944
|
+
signalCrossTabChange2();
|
|
17945
|
+
}
|
|
17946
|
+
function readAllTokenCookies2() {
|
|
17947
|
+
if (!hasDocument2() || !document.cookie)
|
|
17948
|
+
return [];
|
|
17949
|
+
const out = [];
|
|
17950
|
+
for (const part of document.cookie.split(";")) {
|
|
17951
|
+
const eq = part.indexOf("=");
|
|
17952
|
+
if (eq < 0)
|
|
17953
|
+
continue;
|
|
17954
|
+
const scopeKey = scopeKeyFromCookieName2(part.slice(0, eq).trim());
|
|
17955
|
+
if (scopeKey === null)
|
|
17956
|
+
continue;
|
|
17957
|
+
const jwt = decodeURIComponent(part.slice(eq + 1).trim());
|
|
17958
|
+
if (jwt)
|
|
17959
|
+
out.push({ scopeKey, jwt });
|
|
17960
|
+
}
|
|
17961
|
+
return out;
|
|
17843
17962
|
}
|
|
17844
17963
|
function notifyTokenChange2(scope) {
|
|
17845
17964
|
if (typeof window !== "undefined") {
|
|
@@ -17855,24 +17974,21 @@ class AuthAdapter2 {
|
|
|
17855
17974
|
constructor(options) {
|
|
17856
17975
|
this.namespace = options?.storageNamespace || undefined;
|
|
17857
17976
|
}
|
|
17858
|
-
|
|
17859
|
-
return this.namespace ? `${
|
|
17977
|
+
scopeKey(scope) {
|
|
17978
|
+
return this.namespace ? `${this.namespace}:${scope}` : scope;
|
|
17860
17979
|
}
|
|
17861
17980
|
setToken(token, scope = "default") {
|
|
17862
17981
|
if (!token) {
|
|
17863
17982
|
this.scopes.delete(scope);
|
|
17864
|
-
|
|
17865
|
-
|
|
17866
|
-
notifyTokenChange2(scope);
|
|
17867
|
-
}
|
|
17983
|
+
removeTokenCookie2(this.scopeKey(scope));
|
|
17984
|
+
notifyTokenChange2(scope);
|
|
17868
17985
|
return;
|
|
17869
17986
|
}
|
|
17870
17987
|
try {
|
|
17871
17988
|
const parts = token.split(".");
|
|
17872
17989
|
if (parts.length !== 3) {
|
|
17873
17990
|
this.scopes.delete(scope);
|
|
17874
|
-
|
|
17875
|
-
localStorage.removeItem(this.storageKey(scope));
|
|
17991
|
+
removeTokenCookie2(this.scopeKey(scope));
|
|
17876
17992
|
return;
|
|
17877
17993
|
}
|
|
17878
17994
|
const payload = JSON.parse(atob(parts[1]));
|
|
@@ -17885,49 +18001,45 @@ class AuthAdapter2 {
|
|
|
17885
18001
|
exp: payload.exp
|
|
17886
18002
|
}
|
|
17887
18003
|
});
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
notifyTokenChange2(scope);
|
|
17891
|
-
}
|
|
18004
|
+
writeTokenCookie2(this.scopeKey(scope), token, payload.exp);
|
|
18005
|
+
notifyTokenChange2(scope);
|
|
17892
18006
|
} catch {
|
|
17893
18007
|
this.scopes.delete(scope);
|
|
17894
|
-
|
|
17895
|
-
localStorage.removeItem(this.storageKey(scope));
|
|
18008
|
+
removeTokenCookie2(this.scopeKey(scope));
|
|
17896
18009
|
}
|
|
17897
18010
|
}
|
|
17898
18011
|
setDecoded(decoded, scope = "default") {
|
|
17899
18012
|
this.scopes.set(scope, { raw: "", decoded });
|
|
17900
18013
|
}
|
|
17901
18014
|
loadPersisted() {
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
17906
|
-
|
|
17907
|
-
if (key?.startsWith(prefix)) {
|
|
17908
|
-
const scope = key.slice(prefix.length);
|
|
17909
|
-
if (!this.namespace && scope.includes(":"))
|
|
18015
|
+
const nsPrefix = this.namespace ? `${this.namespace}:` : "";
|
|
18016
|
+
for (const { scopeKey, jwt } of readAllTokenCookies2()) {
|
|
18017
|
+
let scope;
|
|
18018
|
+
if (this.namespace) {
|
|
18019
|
+
if (!scopeKey.startsWith(nsPrefix))
|
|
17910
18020
|
continue;
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
|
|
17922
|
-
|
|
17923
|
-
|
|
17924
|
-
|
|
17925
|
-
|
|
17926
|
-
}
|
|
17927
|
-
|
|
17928
|
-
|
|
18021
|
+
scope = scopeKey.slice(nsPrefix.length);
|
|
18022
|
+
} else {
|
|
18023
|
+
if (scopeKey.includes(":"))
|
|
18024
|
+
continue;
|
|
18025
|
+
scope = scopeKey;
|
|
18026
|
+
}
|
|
18027
|
+
try {
|
|
18028
|
+
const parts = jwt.split(".");
|
|
18029
|
+
if (parts.length !== 3)
|
|
18030
|
+
continue;
|
|
18031
|
+
const payload = JSON.parse(atob(parts[1]));
|
|
18032
|
+
this.scopes.set(scope, {
|
|
18033
|
+
raw: jwt,
|
|
18034
|
+
decoded: {
|
|
18035
|
+
tokenName: payload.tokenName,
|
|
18036
|
+
params: payload.params || {},
|
|
18037
|
+
iat: payload.iat,
|
|
18038
|
+
exp: payload.exp
|
|
17929
18039
|
}
|
|
17930
|
-
}
|
|
18040
|
+
});
|
|
18041
|
+
} catch {
|
|
18042
|
+
removeTokenCookie2(scopeKey);
|
|
17931
18043
|
}
|
|
17932
18044
|
}
|
|
17933
18045
|
}
|
|
@@ -17959,10 +18071,8 @@ class AuthAdapter2 {
|
|
|
17959
18071
|
return Array.from(this.scopes.keys());
|
|
17960
18072
|
}
|
|
17961
18073
|
clear() {
|
|
17962
|
-
|
|
17963
|
-
|
|
17964
|
-
localStorage.removeItem(this.storageKey(scope));
|
|
17965
|
-
}
|
|
18074
|
+
for (const scope of this.scopes.keys()) {
|
|
18075
|
+
removeTokenCookie2(this.scopeKey(scope));
|
|
17966
18076
|
}
|
|
17967
18077
|
this.scopes.clear();
|
|
17968
18078
|
}
|
|
@@ -20673,7 +20783,7 @@ var Operation2, PROXY_DRAFT2, RAW_RETURN_SYMBOL2, iteratorSymbol2, dataTypes2, i
|
|
|
20673
20783
|
}
|
|
20674
20784
|
return returnValue(result);
|
|
20675
20785
|
};
|
|
20676
|
-
}, create2, constructorString2,
|
|
20786
|
+
}, create2, constructorString2, COOKIE_PREFIX2 = "arc_token", TOKEN_BUMP_KEY2 = "arc:token-bump", DEFAULT_TIMEOUT_MS2 = 8000, provider2 = null, latestSync2 = null, syncSeq2 = 0, eventWireInstanceCounter2 = 0, EVENT_TABLES2, arrayValidator2, ArcArray2, objectValidator2, ArcObject2, ScopedDataStorage2, ArcAuthenticationError2, ArcAuthorizationError3, ArcValidationError3, ArcPrimitive2, stringValidator2, ArcString2, ArcContextElement2, ArcBoolean2, ArcId2, numberValidator2, ArcNumber2, ArcEvent2, ArcCommand2, ArcListener2, ArcRoute2, ForkedStoreState2, ForkedDataStorage2, MasterStoreState2, MasterDataStorage3, dateValidator2, _te2, _td2, SQLiteReadWriteTransaction, createSQLiteAdapterFactory = (db) => {
|
|
20677
20787
|
return async (context) => {
|
|
20678
20788
|
const adapter = new SQLiteAdapter(db, context);
|
|
20679
20789
|
await adapter.initialize();
|
|
@@ -31692,7 +31802,7 @@ function workspaceSourcePlugin(srcByName) {
|
|
|
31692
31802
|
}
|
|
31693
31803
|
};
|
|
31694
31804
|
}
|
|
31695
|
-
var SERVER_ONLY_NODE_BUILTINS =
|
|
31805
|
+
var SERVER_ONLY_NODE_BUILTINS = [
|
|
31696
31806
|
"crypto",
|
|
31697
31807
|
"stream",
|
|
31698
31808
|
"zlib",
|
|
@@ -31720,15 +31830,13 @@ var SERVER_ONLY_NODE_BUILTINS = new Set([
|
|
|
31720
31830
|
"diagnostics_channel",
|
|
31721
31831
|
"module",
|
|
31722
31832
|
"constants"
|
|
31723
|
-
]
|
|
31833
|
+
];
|
|
31834
|
+
var NODE_STUB_FILTER = new RegExp(`^(node:)?(${SERVER_ONLY_NODE_BUILTINS.map((b) => b.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&")).join("|")})$`);
|
|
31724
31835
|
function nodeServerBuiltinStubPlugin() {
|
|
31725
31836
|
return {
|
|
31726
31837
|
name: "node-server-builtin-stub",
|
|
31727
31838
|
setup(build2) {
|
|
31728
|
-
build2.onResolve({ filter:
|
|
31729
|
-
const bare = args.path.replace(/^node:/, "");
|
|
31730
|
-
if (!SERVER_ONLY_NODE_BUILTINS.has(bare))
|
|
31731
|
-
return;
|
|
31839
|
+
build2.onResolve({ filter: NODE_STUB_FILTER }, (args) => {
|
|
31732
31840
|
return { path: args.path, namespace: "node-server-stub" };
|
|
31733
31841
|
});
|
|
31734
31842
|
build2.onLoad({ filter: /.*/, namespace: "node-server-stub" }, (args) => ({
|
|
@@ -31782,19 +31890,23 @@ function discoverPackages(rootDir) {
|
|
|
31782
31890
|
if (pkg.name?.startsWith("@arcote.tech/"))
|
|
31783
31891
|
continue;
|
|
31784
31892
|
const pkgDir = join9(baseDir, entry);
|
|
31785
|
-
const
|
|
31786
|
-
join9(pkgDir, "src",
|
|
31787
|
-
join9(pkgDir, "src",
|
|
31788
|
-
join9(pkgDir,
|
|
31789
|
-
join9(pkgDir,
|
|
31893
|
+
const entryCandidates = (variant) => [
|
|
31894
|
+
join9(pkgDir, "src", `index${variant}.ts`),
|
|
31895
|
+
join9(pkgDir, "src", `index${variant}.tsx`),
|
|
31896
|
+
join9(pkgDir, `index${variant}.ts`),
|
|
31897
|
+
join9(pkgDir, `index${variant}.tsx`)
|
|
31790
31898
|
];
|
|
31791
|
-
const entrypoint =
|
|
31899
|
+
const entrypoint = entryCandidates("").find((c) => existsSync8(c)) ?? null;
|
|
31792
31900
|
if (!entrypoint)
|
|
31793
31901
|
continue;
|
|
31902
|
+
const serverEntrypoint = entryCandidates(".server").find((c) => existsSync8(c)) ?? entrypoint;
|
|
31903
|
+
const clientEntrypoint = entryCandidates(".client").find((c) => existsSync8(c)) ?? entrypoint;
|
|
31794
31904
|
results.push({
|
|
31795
31905
|
name: pkg.name,
|
|
31796
31906
|
path: join9(baseDir, entry),
|
|
31797
31907
|
entrypoint,
|
|
31908
|
+
serverEntrypoint,
|
|
31909
|
+
clientEntrypoint,
|
|
31798
31910
|
packageJson: pkg
|
|
31799
31911
|
});
|
|
31800
31912
|
}
|
|
@@ -31836,13 +31948,15 @@ function depVersionsHash(rootDir, pkg) {
|
|
|
31836
31948
|
async function buildContextClient(pkg, rootDir, client, cache, noCache) {
|
|
31837
31949
|
const unitId = `context-pkg:${pkg.name}:${client.name}`;
|
|
31838
31950
|
const outDir = join9(pkg.path, "dist", client.name);
|
|
31951
|
+
const entry = client.target === "browser" ? pkg.clientEntrypoint : pkg.entrypoint;
|
|
31839
31952
|
const inputHash = sha256OfJson({
|
|
31840
31953
|
src: pkgSourceHash(pkg),
|
|
31841
31954
|
pkg: pkg.packageJson,
|
|
31842
31955
|
deps: depVersionsHash(rootDir, pkg),
|
|
31843
31956
|
client: client.name,
|
|
31844
31957
|
target: client.target,
|
|
31845
|
-
defines: client.defines
|
|
31958
|
+
defines: client.defines,
|
|
31959
|
+
entry: relative3(pkg.path, entry)
|
|
31846
31960
|
});
|
|
31847
31961
|
if (!noCache && isCacheHit(cache, unitId, inputHash, [join9(outDir, "main", "index.js")])) {
|
|
31848
31962
|
console.log(` \u2713 cached: ${pkg.name} (${client.name})`);
|
|
@@ -31853,7 +31967,7 @@ async function buildContextClient(pkg, rootDir, client, cache, noCache) {
|
|
|
31853
31967
|
const allDeps = pkg.packageJson.dependencies ?? {};
|
|
31854
31968
|
const externals = [...peerDeps, ...Object.keys(allDeps)];
|
|
31855
31969
|
const result = await Bun.build({
|
|
31856
|
-
entrypoints: [
|
|
31970
|
+
entrypoints: [entry],
|
|
31857
31971
|
outdir: join9(outDir, "main"),
|
|
31858
31972
|
target: client.target,
|
|
31859
31973
|
format: "esm",
|
|
@@ -31873,7 +31987,7 @@ async function buildContextClient(pkg, rootDir, client, cache, noCache) {
|
|
|
31873
31987
|
}
|
|
31874
31988
|
const globalsContent = Object.entries(client.defines).map(([k, v]) => `declare const ${k}: ${v};`).join(`
|
|
31875
31989
|
`);
|
|
31876
|
-
const declResult = await buildTypeDeclarations([
|
|
31990
|
+
const declResult = await buildTypeDeclarations([entry], outDir, dirname6(entry), globalsContent);
|
|
31877
31991
|
const declarationErrors = !declResult.success && declResult.errors.length > 0 ? declResult.errors.map((e) => `[${pkg.name}/${client.name}] ${e}`) : [];
|
|
31878
31992
|
const outputHash = sha256OfDir(outDir);
|
|
31879
31993
|
updateCache(cache, unitId, inputHash, { outputHash });
|
|
@@ -31928,7 +32042,7 @@ async function buildContextPackages(rootDir, packages, cache, noCache) {
|
|
|
31928
32042
|
async function buildServerApp(rootDir, serverDir, packages, cache, noCache) {
|
|
31929
32043
|
const contexts = packages.filter((p) => isContextPackage(p.packageJson));
|
|
31930
32044
|
mkdirSync7(serverDir, { recursive: true });
|
|
31931
|
-
const srcByName = new Map(packages.map((p) => [p.name, p.
|
|
32045
|
+
const srcByName = new Map(packages.map((p) => [p.name, p.serverEntrypoint]));
|
|
31932
32046
|
const externalSet = new Set(FRAMEWORK_PEERS);
|
|
31933
32047
|
for (const p of packages) {
|
|
31934
32048
|
for (const name of Object.keys(p.packageJson.peerDependencies ?? {})) {
|
|
@@ -31942,7 +32056,11 @@ async function buildServerApp(rootDir, serverDir, packages, cache, noCache) {
|
|
|
31942
32056
|
const external = [...externalSet];
|
|
31943
32057
|
const unitId = "server-app";
|
|
31944
32058
|
const inputHash = sha256OfJson({
|
|
31945
|
-
members: packages.map((p) => ({
|
|
32059
|
+
members: packages.map((p) => ({
|
|
32060
|
+
name: p.name,
|
|
32061
|
+
src: pkgSourceHash(p),
|
|
32062
|
+
serverEntry: relative3(p.path, p.serverEntrypoint)
|
|
32063
|
+
})).sort((a, b) => a.name.localeCompare(b.name)),
|
|
31946
32064
|
contexts: contexts.map((p) => p.name).sort(),
|
|
31947
32065
|
external: [...external].sort(),
|
|
31948
32066
|
defines: SERVER_DEFINES,
|
|
@@ -32184,11 +32302,11 @@ async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollec
|
|
|
32184
32302
|
const unitId = opts?.unitId ?? "browser-app";
|
|
32185
32303
|
const allMembers = [];
|
|
32186
32304
|
for (const m of publicMembers) {
|
|
32187
|
-
allMembers.push({ name: m.pkg.name, group: "public", srcHash: pkgSourceHash(m.pkg) });
|
|
32305
|
+
allMembers.push({ name: m.pkg.name, group: "public", srcHash: pkgSourceHash(m.pkg), clientEntry: relative3(m.pkg.path, m.pkg.clientEntrypoint) });
|
|
32188
32306
|
}
|
|
32189
32307
|
for (const g of protectedGroups) {
|
|
32190
32308
|
for (const m of g.members) {
|
|
32191
|
-
allMembers.push({ name: m.pkg.name, group: g.name, srcHash: pkgSourceHash(m.pkg) });
|
|
32309
|
+
allMembers.push({ name: m.pkg.name, group: g.name, srcHash: pkgSourceHash(m.pkg), clientEntry: relative3(m.pkg.path, m.pkg.clientEntrypoint) });
|
|
32192
32310
|
}
|
|
32193
32311
|
}
|
|
32194
32312
|
const inputHash = sha256OfJson({
|
|
@@ -32202,7 +32320,7 @@ async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollec
|
|
|
32202
32320
|
exposeRuntime,
|
|
32203
32321
|
minify,
|
|
32204
32322
|
externals: federated ? [...SHELL_EXTERNALS] : [],
|
|
32205
|
-
builderRev:
|
|
32323
|
+
builderRev: 4
|
|
32206
32324
|
});
|
|
32207
32325
|
if (!noCache && !buildStatsEnabled() && isCacheHit(cache, unitId, inputHash)) {
|
|
32208
32326
|
const cached = cache.units[unitId]?.outputHashes;
|
|
@@ -32255,6 +32373,12 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32255
32373
|
for (const g of protectedGroups)
|
|
32256
32374
|
for (const m of g.members)
|
|
32257
32375
|
allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
32376
|
+
const clientByName = new Map;
|
|
32377
|
+
for (const pkg of allMemberPkgs.values()) {
|
|
32378
|
+
if (pkg.clientEntrypoint !== pkg.entrypoint) {
|
|
32379
|
+
clientByName.set(pkg.name, pkg.clientEntrypoint);
|
|
32380
|
+
}
|
|
32381
|
+
}
|
|
32258
32382
|
const patchedPkgJsons = [];
|
|
32259
32383
|
for (const pkg of allMemberPkgs.values()) {
|
|
32260
32384
|
const pkgJsonPath = join9(pkg.path, "package.json");
|
|
@@ -32281,6 +32405,7 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32281
32405
|
target: "browser",
|
|
32282
32406
|
external: federated ? [...SHELL_EXTERNALS] : [],
|
|
32283
32407
|
plugins: [
|
|
32408
|
+
...clientByName.size > 0 ? [workspaceSourcePlugin(clientByName)] : [],
|
|
32284
32409
|
...federated ? [] : [singleReactPlugin(rootDir)],
|
|
32285
32410
|
jsxDevShimPlugin(),
|
|
32286
32411
|
nodeServerBuiltinStubPlugin(),
|
|
@@ -32672,7 +32797,7 @@ function walkTsFiles(dir, out) {
|
|
|
32672
32797
|
if (entry.name === "__tests__")
|
|
32673
32798
|
continue;
|
|
32674
32799
|
walkTsFiles(abs, out);
|
|
32675
|
-
} else if (entry.isFile() && /\.(ts|tsx)$/.test(entry.name) && !entry.name.endsWith(".d.ts")) {
|
|
32800
|
+
} else if (entry.isFile() && /\.(ts|tsx)$/.test(entry.name) && !entry.name.endsWith(".d.ts") && !/\.server\.tsx?$/.test(entry.name)) {
|
|
32676
32801
|
out.push(abs);
|
|
32677
32802
|
}
|
|
32678
32803
|
}
|
|
@@ -36917,11 +37042,11 @@ async function runSurvey(appName) {
|
|
|
36917
37042
|
});
|
|
36918
37043
|
if (BD(serverType))
|
|
36919
37044
|
cancel();
|
|
36920
|
-
const
|
|
37045
|
+
const location2 = await ue({
|
|
36921
37046
|
message: "Hetzner datacenter location",
|
|
36922
37047
|
initialValue: "nbg1"
|
|
36923
37048
|
});
|
|
36924
|
-
if (BD(
|
|
37049
|
+
if (BD(location2))
|
|
36925
37050
|
cancel();
|
|
36926
37051
|
const firstEnv = Object.keys(envs)[0] ?? "host";
|
|
36927
37052
|
const appSlug = sanitizeImageName(appName ?? "arc-app").replace(/[^a-z0-9-]+/g, "-");
|
|
@@ -36929,7 +37054,7 @@ async function runSurvey(appName) {
|
|
|
36929
37054
|
const terraform = {
|
|
36930
37055
|
provider: "hcloud",
|
|
36931
37056
|
serverType,
|
|
36932
|
-
location,
|
|
37057
|
+
location: location2,
|
|
36933
37058
|
image: "ubuntu-22.04",
|
|
36934
37059
|
tokenEnv,
|
|
36935
37060
|
serverName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"description": "CLI tool for Arc framework",
|
|
5
5
|
"module": "index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"build": "bun build --target=bun ./src/index.ts --outdir=dist --external @arcote.tech/arc --external @arcote.tech/arc-ds --external @arcote.tech/arc-react --external @arcote.tech/platform --external @arcote.tech/arc-map --external '@opentelemetry/*' && chmod +x dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@arcote.tech/arc": "^0.8.
|
|
16
|
-
"@arcote.tech/arc-ds": "^0.8.
|
|
17
|
-
"@arcote.tech/arc-react": "^0.8.
|
|
18
|
-
"@arcote.tech/arc-host": "^0.8.
|
|
19
|
-
"@arcote.tech/arc-adapter-db-sqlite": "^0.8.
|
|
20
|
-
"@arcote.tech/arc-adapter-db-postgres": "^0.8.
|
|
21
|
-
"@arcote.tech/arc-otel": "^0.8.
|
|
15
|
+
"@arcote.tech/arc": "^0.8.7",
|
|
16
|
+
"@arcote.tech/arc-ds": "^0.8.7",
|
|
17
|
+
"@arcote.tech/arc-react": "^0.8.7",
|
|
18
|
+
"@arcote.tech/arc-host": "^0.8.7",
|
|
19
|
+
"@arcote.tech/arc-adapter-db-sqlite": "^0.8.7",
|
|
20
|
+
"@arcote.tech/arc-adapter-db-postgres": "^0.8.7",
|
|
21
|
+
"@arcote.tech/arc-otel": "^0.8.7",
|
|
22
22
|
"@opentelemetry/api": "^1.9.0",
|
|
23
23
|
"@opentelemetry/api-logs": "^0.57.0",
|
|
24
24
|
"@opentelemetry/core": "^1.30.0",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"@opentelemetry/sdk-trace-base": "^1.30.0",
|
|
32
32
|
"@opentelemetry/sdk-trace-node": "^1.30.0",
|
|
33
33
|
"@opentelemetry/semantic-conventions": "^1.27.0",
|
|
34
|
-
"@arcote.tech/platform": "^0.8.
|
|
35
|
-
"@arcote.tech/arc-map": "^0.8.
|
|
34
|
+
"@arcote.tech/platform": "^0.8.7",
|
|
35
|
+
"@arcote.tech/arc-map": "^0.8.7",
|
|
36
36
|
"@clack/prompts": "^0.9.0",
|
|
37
37
|
"commander": "^11.1.0",
|
|
38
38
|
"chokidar": "^3.5.3",
|
|
@@ -248,12 +248,27 @@ function workspaceSourcePlugin(srcByName: Map<string, string>): import("bun").Bu
|
|
|
248
248
|
// CELOWO NIE stubujemy „przeglądarkowo-bezpiecznych" builtinów (buffer, util,
|
|
249
249
|
// events, path, url, string_decoder, querystring, assert, process) — te bywają
|
|
250
250
|
// realnie używane po stronie klienta i mają lekkie, działające polyfille.
|
|
251
|
-
const SERVER_ONLY_NODE_BUILTINS =
|
|
251
|
+
const SERVER_ONLY_NODE_BUILTINS = [
|
|
252
252
|
"crypto", "stream", "zlib", "fs", "fs/promises", "net", "tls", "http",
|
|
253
253
|
"https", "http2", "dns", "dgram", "child_process", "worker_threads",
|
|
254
254
|
"cluster", "os", "v8", "vm", "readline", "repl", "tty", "perf_hooks",
|
|
255
255
|
"inspector", "async_hooks", "diagnostics_channel", "module", "constants",
|
|
256
|
-
]
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Filtr onResolve dopasowujący DOKŁADNIE serwerowe builtiny (`node:crypto`,
|
|
260
|
+
* `crypto`, `fs/promises`, …) i NIC innego. KRYTYCZNE, że jest precyzyjny:
|
|
261
|
+
* szeroki filtr `/^(node:)?[a-z_/]+$/` łapał też gołe pakiety npm (np. `unified`,
|
|
262
|
+
* `vfile`, `micromark`), a samo przepuszczenie ich przez onResolve — nawet ze
|
|
263
|
+
* zwrotem `undefined` — korumpuje tree-shaking Buna pod minify: pakiet znika z
|
|
264
|
+
* bundla, ale zostaje wiszące wywołanie (`ReferenceError: X is not defined` w
|
|
265
|
+
* produkcji — react-markdown/`unified()` na stronach z markdownem).
|
|
266
|
+
*/
|
|
267
|
+
const NODE_STUB_FILTER = new RegExp(
|
|
268
|
+
`^(node:)?(${SERVER_ONLY_NODE_BUILTINS.map((b) =>
|
|
269
|
+
b.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&"),
|
|
270
|
+
).join("|")})$`,
|
|
271
|
+
);
|
|
257
272
|
|
|
258
273
|
/**
|
|
259
274
|
* Zastępuje serwerowe builtiny node (SERVER_ONLY_NODE_BUILTINS) rzucającym
|
|
@@ -266,9 +281,7 @@ function nodeServerBuiltinStubPlugin(): import("bun").BunPlugin {
|
|
|
266
281
|
return {
|
|
267
282
|
name: "node-server-builtin-stub",
|
|
268
283
|
setup(build) {
|
|
269
|
-
build.onResolve({ filter:
|
|
270
|
-
const bare = args.path.replace(/^node:/, "");
|
|
271
|
-
if (!SERVER_ONLY_NODE_BUILTINS.has(bare)) return undefined;
|
|
284
|
+
build.onResolve({ filter: NODE_STUB_FILTER }, (args) => {
|
|
272
285
|
return { path: args.path, namespace: "node-server-stub" };
|
|
273
286
|
});
|
|
274
287
|
build.onLoad({ filter: /.*/, namespace: "node-server-stub" }, (args) => ({
|
|
@@ -332,7 +345,12 @@ export const SERVER_EXTERNALS_FILE = "_externals.json";
|
|
|
332
345
|
export interface WorkspacePackage {
|
|
333
346
|
name: string;
|
|
334
347
|
path: string;
|
|
348
|
+
/** Base entry (src/index.ts). Fallback for both targets. */
|
|
335
349
|
entrypoint: string;
|
|
350
|
+
/** src/index.server.ts if present, else `entrypoint`. Used by the SERVER bundle. */
|
|
351
|
+
serverEntrypoint: string;
|
|
352
|
+
/** src/index.client.ts if present, else `entrypoint`. Used by the CLIENT (browser) bundle. */
|
|
353
|
+
clientEntrypoint: string;
|
|
336
354
|
packageJson: Record<string, any>;
|
|
337
355
|
}
|
|
338
356
|
|
|
@@ -374,19 +392,30 @@ export function discoverPackages(rootDir: string): WorkspacePackage[] {
|
|
|
374
392
|
if (pkg.name?.startsWith("@arcote.tech/")) continue;
|
|
375
393
|
|
|
376
394
|
const pkgDir = join(baseDir, entry);
|
|
377
|
-
const
|
|
378
|
-
join(pkgDir, "src",
|
|
379
|
-
join(pkgDir, "src",
|
|
380
|
-
join(pkgDir,
|
|
381
|
-
join(pkgDir,
|
|
395
|
+
const entryCandidates = (variant: "" | ".server" | ".client") => [
|
|
396
|
+
join(pkgDir, "src", `index${variant}.ts`),
|
|
397
|
+
join(pkgDir, "src", `index${variant}.tsx`),
|
|
398
|
+
join(pkgDir, `index${variant}.ts`),
|
|
399
|
+
join(pkgDir, `index${variant}.tsx`),
|
|
382
400
|
];
|
|
383
|
-
const entrypoint =
|
|
401
|
+
const entrypoint = entryCandidates("").find((c) => existsSync(c)) ?? null;
|
|
384
402
|
if (!entrypoint) continue;
|
|
385
403
|
|
|
404
|
+
// Per-target entry override by file convention: index.server.ts /
|
|
405
|
+
// index.client.ts. Absent → fall back to the base entry (zero change for
|
|
406
|
+
// packages that don't opt in). Lets seeds live in index.server.ts so they
|
|
407
|
+
// never enter the client graph (see seed-guard.ts).
|
|
408
|
+
const serverEntrypoint =
|
|
409
|
+
entryCandidates(".server").find((c) => existsSync(c)) ?? entrypoint;
|
|
410
|
+
const clientEntrypoint =
|
|
411
|
+
entryCandidates(".client").find((c) => existsSync(c)) ?? entrypoint;
|
|
412
|
+
|
|
386
413
|
results.push({
|
|
387
414
|
name: pkg.name,
|
|
388
415
|
path: join(baseDir, entry),
|
|
389
416
|
entrypoint,
|
|
417
|
+
serverEntrypoint,
|
|
418
|
+
clientEntrypoint,
|
|
390
419
|
packageJson: pkg,
|
|
391
420
|
});
|
|
392
421
|
}
|
|
@@ -467,6 +496,12 @@ async function buildContextClient(
|
|
|
467
496
|
const unitId = `context-pkg:${pkg.name}:${client.name}`;
|
|
468
497
|
const outDir = join(pkg.path, "dist", client.name);
|
|
469
498
|
|
|
499
|
+
// Per-target entry: the browser dist is built from the CLIENT entry
|
|
500
|
+
// (index.client.ts if present, else index.ts) so dist/browser reflects exactly
|
|
501
|
+
// what ships to the browser. Non-browser clients keep the base entry.
|
|
502
|
+
const entry =
|
|
503
|
+
client.target === "browser" ? pkg.clientEntrypoint : pkg.entrypoint;
|
|
504
|
+
|
|
470
505
|
const inputHash = sha256OfJson({
|
|
471
506
|
src: pkgSourceHash(pkg),
|
|
472
507
|
pkg: pkg.packageJson,
|
|
@@ -474,6 +509,7 @@ async function buildContextClient(
|
|
|
474
509
|
client: client.name,
|
|
475
510
|
target: client.target,
|
|
476
511
|
defines: client.defines,
|
|
512
|
+
entry: relative(pkg.path, entry),
|
|
477
513
|
});
|
|
478
514
|
|
|
479
515
|
if (!noCache && isCacheHit(cache, unitId, inputHash, [join(outDir, "main", "index.js")])) {
|
|
@@ -495,7 +531,7 @@ async function buildContextClient(
|
|
|
495
531
|
const externals = [...peerDeps, ...Object.keys(allDeps)];
|
|
496
532
|
|
|
497
533
|
const result = await Bun.build({
|
|
498
|
-
entrypoints: [
|
|
534
|
+
entrypoints: [entry],
|
|
499
535
|
outdir: join(outDir, "main"),
|
|
500
536
|
target: client.target,
|
|
501
537
|
format: "esm",
|
|
@@ -522,9 +558,9 @@ async function buildContextClient(
|
|
|
522
558
|
.join("\n");
|
|
523
559
|
|
|
524
560
|
const declResult = await buildTypeDeclarations(
|
|
525
|
-
[
|
|
561
|
+
[entry],
|
|
526
562
|
outDir,
|
|
527
|
-
dirname(
|
|
563
|
+
dirname(entry),
|
|
528
564
|
globalsContent,
|
|
529
565
|
);
|
|
530
566
|
|
|
@@ -658,7 +694,9 @@ export async function buildServerApp(
|
|
|
658
694
|
// Every workspace package name → its SOURCE entry. Spans ALL packages, not
|
|
659
695
|
// just context ones — a context package imports non-context workspace libs
|
|
660
696
|
// (e.g. content-core) that must inline from source too.
|
|
661
|
-
|
|
697
|
+
// SERVER bundle resolves every `@pkg` to its server entry (index.server.ts if
|
|
698
|
+
// present, else index.ts) via workspaceSourcePlugin — bypassing package.json.
|
|
699
|
+
const srcByName = new Map(packages.map((p) => [p.name, p.serverEntrypoint]));
|
|
662
700
|
|
|
663
701
|
// External = framework peers + every non-workspace npm dep any package
|
|
664
702
|
// declares. NOT bundled; resolved at runtime from /app/node_modules (the
|
|
@@ -680,7 +718,13 @@ export async function buildServerApp(
|
|
|
680
718
|
const unitId = "server-app";
|
|
681
719
|
const inputHash = sha256OfJson({
|
|
682
720
|
members: packages
|
|
683
|
-
.map((p) => ({
|
|
721
|
+
.map((p) => ({
|
|
722
|
+
name: p.name,
|
|
723
|
+
src: pkgSourceHash(p),
|
|
724
|
+
// Which file is the server entry — invalidate if the selection changes
|
|
725
|
+
// (e.g. an index.server.ts is added/removed) even without other src edits.
|
|
726
|
+
serverEntry: relative(p.path, p.serverEntrypoint),
|
|
727
|
+
}))
|
|
684
728
|
.sort((a, b) => a.name.localeCompare(b.name)),
|
|
685
729
|
contexts: contexts.map((p) => p.name).sort(),
|
|
686
730
|
external: [...external].sort(),
|
|
@@ -1118,13 +1162,13 @@ export async function buildBrowserApp(
|
|
|
1118
1162
|
|
|
1119
1163
|
// Cache key spans every package's source plus the build config that
|
|
1120
1164
|
// matters. If anything changes, full rebuild.
|
|
1121
|
-
const allMembers: { name: string; group: string; srcHash: string }[] = [];
|
|
1165
|
+
const allMembers: { name: string; group: string; srcHash: string; clientEntry: string }[] = [];
|
|
1122
1166
|
for (const m of publicMembers) {
|
|
1123
|
-
allMembers.push({ name: m.pkg.name, group: "public", srcHash: pkgSourceHash(m.pkg) });
|
|
1167
|
+
allMembers.push({ name: m.pkg.name, group: "public", srcHash: pkgSourceHash(m.pkg), clientEntry: relative(m.pkg.path, m.pkg.clientEntrypoint) });
|
|
1124
1168
|
}
|
|
1125
1169
|
for (const g of protectedGroups) {
|
|
1126
1170
|
for (const m of g.members) {
|
|
1127
|
-
allMembers.push({ name: m.pkg.name, group: g.name, srcHash: pkgSourceHash(m.pkg) });
|
|
1171
|
+
allMembers.push({ name: m.pkg.name, group: g.name, srcHash: pkgSourceHash(m.pkg), clientEntry: relative(m.pkg.path, m.pkg.clientEntrypoint) });
|
|
1128
1172
|
}
|
|
1129
1173
|
}
|
|
1130
1174
|
const inputHash = sha256OfJson({
|
|
@@ -1142,7 +1186,8 @@ export async function buildBrowserApp(
|
|
|
1142
1186
|
externals: federated ? [...SHELL_EXTERNALS] : [],
|
|
1143
1187
|
// Podbij przy zmianie SEMANTYKI builda (pluginy/flagi), której nie widać
|
|
1144
1188
|
// w źródłach — inaczej cache odda bundle zbudowany starą logiką.
|
|
1145
|
-
|
|
1189
|
+
// 4: client-entry (index.client.ts) + workspaceClientSourcePlugin.
|
|
1190
|
+
builderRev: 4,
|
|
1146
1191
|
});
|
|
1147
1192
|
|
|
1148
1193
|
// Tryb stats zawsze buduje od nowa — cache-hit pominąłby analizę i nie
|
|
@@ -1235,6 +1280,18 @@ export async function buildBrowserApp(
|
|
|
1235
1280
|
for (const g of protectedGroups)
|
|
1236
1281
|
for (const m of g.members) allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
1237
1282
|
|
|
1283
|
+
// Client-entry override: only packages that DECLARE `index.client.ts`
|
|
1284
|
+
// (clientEntrypoint !== entrypoint) are redirected to their client source.
|
|
1285
|
+
// Everything else — packages without a variant, framework peers, npm — misses
|
|
1286
|
+
// the map and resolves natively (package.json `exports.browser`, e.g. the
|
|
1287
|
+
// per-pkg dist/browser). Empty map ⇒ identical to today's behaviour.
|
|
1288
|
+
const clientByName = new Map<string, string>();
|
|
1289
|
+
for (const pkg of allMemberPkgs.values()) {
|
|
1290
|
+
if (pkg.clientEntrypoint !== pkg.entrypoint) {
|
|
1291
|
+
clientByName.set(pkg.name, pkg.clientEntrypoint);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1238
1295
|
const patchedPkgJsons: { path: string; original: string }[] = [];
|
|
1239
1296
|
for (const pkg of allMemberPkgs.values()) {
|
|
1240
1297
|
const pkgJsonPath = join(pkg.path, "package.json");
|
|
@@ -1275,6 +1332,11 @@ export async function buildBrowserApp(
|
|
|
1275
1332
|
// singletonów React/rejestru z hostem federacji.
|
|
1276
1333
|
external: federated ? [...SHELL_EXTERNALS] : [],
|
|
1277
1334
|
plugins: [
|
|
1335
|
+
// Client-entry: `@pkg` z wariantem index.client.ts → jego source. MUSI
|
|
1336
|
+
// być pierwszy (onResolve first-wins), ale mapa zawiera tylko pakiety
|
|
1337
|
+
// workspace z wariantem — react/@arcote.tech/*/npm i pakiety bez wariantu
|
|
1338
|
+
// miss → null → natywna rezolucja / external niżej. Zero regresji.
|
|
1339
|
+
...(clientByName.size > 0 ? [workspaceSourcePlugin(clientByName)] : []),
|
|
1278
1340
|
// Federated: singleReactPlugin MUSI zniknąć (jego onResolve wygrałby z
|
|
1279
1341
|
// `external` → React zbundlowany; singleton daje import mapa). Ale
|
|
1280
1342
|
// jsxDevShimPlugin ZOSTAJE (Bun i tak emituje jsxDEV) — jego shim jest
|
|
@@ -16,9 +16,17 @@ import type { WorkspacePackage } from "./module-builder";
|
|
|
16
16
|
// w PUBLICZNYM bundlu przeglądarki. Seedy czyta wyłącznie host (`runSeeds()`),
|
|
17
17
|
// po stronie klienta nie mają żadnego zastosowania — czysty wyciek.
|
|
18
18
|
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
19
|
+
// KANONICZNY WZORZEC (rekomendowany): trzymaj seedy w `index.server.ts` pakietu.
|
|
20
|
+
// Build serwera rozwiązuje `@pkg` do `index.server.ts`, a build przeglądarki go
|
|
21
|
+
// nigdy nie importuje — seedy są izolowane FIZYCZNIE (zero DCE, zero ternary,
|
|
22
|
+
// zero szansy na regresję z nieczystym top-level modułu seed). Guard POMIJA pliki
|
|
23
|
+
// `*.server.ts`, więc `.withSeeds(...)` nie wymaga tam gejtu. Patrz discoverPackages
|
|
24
|
+
// / buildServerApp (module-builder.ts).
|
|
25
|
+
//
|
|
26
|
+
// ŚCIEŻKA LEGACY (pliki współdzielone klient+serwer): gejt wywołania to WARUNEK
|
|
27
|
+
// KONIECZNY (ten guard go egzekwuje), ale to, gdzie fizycznie leży treść seeda,
|
|
28
|
+
// decyduje czy bajty realnie znikają. Zweryfikowane empirycznie (migracja ndt+bmf,
|
|
29
|
+
// grep bundla klienta):
|
|
22
30
|
//
|
|
23
31
|
// // mały seed — inline w gejtowanym literale (ZAWSZE działa: constant-fold):
|
|
24
32
|
// .seedWith(ONLY_SERVER ? [ { /* wiersze */ } ] : [])
|
|
@@ -63,7 +71,16 @@ function walkTsFiles(dir: string, out: string[]): void {
|
|
|
63
71
|
if (entry.isDirectory()) {
|
|
64
72
|
if (entry.name === "__tests__") continue;
|
|
65
73
|
walkTsFiles(abs, out);
|
|
66
|
-
} else if (
|
|
74
|
+
} else if (
|
|
75
|
+
entry.isFile() &&
|
|
76
|
+
/\.(ts|tsx)$/.test(entry.name) &&
|
|
77
|
+
!entry.name.endsWith(".d.ts") &&
|
|
78
|
+
// `*.server.ts(x)` (w tym index.server.ts) NIE trafiają do bundla klienta —
|
|
79
|
+
// build serwera rozwiązuje `@pkg` do index.server.ts, a build przeglądarki
|
|
80
|
+
// nigdy go nie importuje. Seedy w tych plikach są izolowane fizycznie, więc
|
|
81
|
+
// `.withSeeds(...)` nie wymaga tam gejtu `ONLY_SERVER`.
|
|
82
|
+
!/\.server\.tsx?$/.test(entry.name)
|
|
83
|
+
) {
|
|
67
84
|
out.push(abs);
|
|
68
85
|
}
|
|
69
86
|
}
|