@cardstack/boxel-cli 0.3.0-unstable.13 → 0.3.0-unstable.87
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/bundled-types/base/card-api.d.ts +2 -2
- package/bundled-types/base/card-serialization.d.ts +1 -1
- package/bundled-types/base/field-support.d.ts +6 -0
- package/bundled-types/boxel-ui/icons.gts +0 -3
- package/bundled-types/host-app/commands/create-submission-workflow.ts +2 -2
- package/bundled-types/host-app/commands/get-available-realm-identifiers.ts +1 -1
- package/bundled-types/host-app/commands/get-catalog-realm-identifiers.ts +1 -1
- package/bundled-types/host-app/commands/search-cards.ts +1 -1
- package/bundled-types/host-app/components/card-catalog/modal.gts +3 -3
- package/bundled-types/host-app/components/card-search/panel.gts +1 -1
- package/bundled-types/host-app/components/card-search/search-content.gts +2 -2
- package/bundled-types/host-app/components/operator-mode/code-submode/format-chooser.gts +12 -9
- package/bundled-types/host-app/components/operator-mode/code-submode/module-inspector.gts +1 -1
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-panel.gts +3 -3
- package/bundled-types/host-app/components/operator-mode/create-file-modal.gts +2 -2
- package/bundled-types/host-app/components/operator-mode/stack-item.gts +9 -1
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/index.gts +32 -24
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/workspace.gts +36 -23
- package/bundled-types/host-app/components/realm-picker/index.gts +2 -2
- package/bundled-types/host-app/components/search-sheet/index.gts +1 -1
- package/bundled-types/host-app/components/with-known-realms-loaded.gts +1 -1
- package/bundled-types/host-app/router.ts +1 -0
- package/bundled-types/host-app/services/host-mode-service.ts +21 -2
- package/bundled-types/host-app/services/matrix-service.ts +9 -8
- package/bundled-types/host-app/services/operator-mode-state-service.ts +8 -6
- package/bundled-types/host-app/services/realm-server.ts +18 -16
- package/bundled-types/host-app/services/store.ts +1 -1
- package/bundled-types/host-app/utils/card-search/url.ts +6 -2
- package/bundled-types/host-tests/helpers/index.gts +2 -2
- package/dist/index.js +69 -69
- package/package.json +2 -2
- package/src/commands/realm/publish.ts +10 -1
- package/src/commands/realm/sync.ts +28 -2
- package/src/commands/realm/unpublish.ts +2 -3
- package/src/lib/describe-fetch-error.ts +25 -0
|
@@ -19,6 +19,16 @@ function ensureSingleTitle(headHTML: string): string {
|
|
|
19
19
|
? headHTML
|
|
20
20
|
: `${DEFAULT_HEAD_HTML}\n${headHTML}`;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
// Normalize trailing-slash variance for routing-map matching. `/realm/`
|
|
24
|
+
// and `/realm` are the same destination from the user's perspective,
|
|
25
|
+
// but the injected map keys and Ember's `params.path` disagree on
|
|
26
|
+
// the trailing slash. Stripping it on both sides makes the comparator
|
|
27
|
+
// robust. Preserve the root `/` since stripping it would empty the path.
|
|
28
|
+
function canonicalizeRoutingPath(path: string): string {
|
|
29
|
+
if (path === '/') return '/';
|
|
30
|
+
return path.replace(/\/+$/, '');
|
|
31
|
+
}
|
|
22
32
|
import type HostModeStateService from '@cardstack/host/services/host-mode-state-service';
|
|
23
33
|
import type OperatorModeStateService from '@cardstack/host/services/operator-mode-state-service';
|
|
24
34
|
import type RealmService from '@cardstack/host/services/realm';
|
|
@@ -130,10 +140,19 @@ export default class HostModeService extends Service {
|
|
|
130
140
|
// `https://host/<user>/<realm>/whitepaper`); a leading slash is added if
|
|
131
141
|
// absent so the index path is matchable as either '' or '/'. The
|
|
132
142
|
// server prefixes each rule's `path` with the realm's mount pathname
|
|
133
|
-
// before injecting the map, so the two sides line up as direct equality
|
|
143
|
+
// before injecting the map, so the two sides line up as direct equality
|
|
144
|
+
// — except for the trailing-slash variance at the realm root. A `/`
|
|
145
|
+
// rule's injected key is the realm's mount pathname WITH trailing
|
|
146
|
+
// slash (e.g. `/progressive-cheetah/`), but Ember's catch-all strips
|
|
147
|
+
// it (`params.path === 'progressive-cheetah'` for either visit form).
|
|
148
|
+
// Canonicalize both sides by stripping trailing slashes (except the
|
|
149
|
+
// root `/` itself) before comparing so `/realm` ↔ `/realm/` resolve.
|
|
134
150
|
resolveRoutedPath(path: string): string | null {
|
|
135
151
|
let normalized = path.startsWith('/') ? path : `/${path}`;
|
|
136
|
-
let
|
|
152
|
+
let canonical = canonicalizeRoutingPath(normalized);
|
|
153
|
+
let rule = this.hostRoutingMap.find(
|
|
154
|
+
(r) => canonicalizeRoutingPath(r.path) === canonical,
|
|
155
|
+
);
|
|
137
156
|
return rule ? rule.id : null;
|
|
138
157
|
}
|
|
139
158
|
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
logger,
|
|
34
34
|
isCardInstance,
|
|
35
35
|
Deferred,
|
|
36
|
+
ri,
|
|
36
37
|
SEARCH_MARKER,
|
|
37
38
|
REPLACE_MARKER,
|
|
38
39
|
SEPARATOR_MARKER,
|
|
@@ -371,8 +372,8 @@ export default class MatrixService extends Service {
|
|
|
371
372
|
async (e) => {
|
|
372
373
|
switch (e.event.type) {
|
|
373
374
|
case APP_BOXEL_REALMS_EVENT_TYPE:
|
|
374
|
-
await this.realmServer.
|
|
375
|
-
e.event.content.realms,
|
|
375
|
+
await this.realmServer.setAvailableRealmIdentifiers(
|
|
376
|
+
(e.event.content.realms as string[]).map(ri),
|
|
376
377
|
);
|
|
377
378
|
// Only do this after we've completed our overall login
|
|
378
379
|
if (this.postLoginCompleted) {
|
|
@@ -654,7 +655,7 @@ export default class MatrixService extends Service {
|
|
|
654
655
|
await this.client.setAccountData(APP_BOXEL_REALMS_EVENT_TYPE, {
|
|
655
656
|
realms: newRealms,
|
|
656
657
|
});
|
|
657
|
-
await this.realmServer.
|
|
658
|
+
await this.realmServer.setAvailableRealmIdentifiers(newRealms.map(ri));
|
|
658
659
|
}
|
|
659
660
|
|
|
660
661
|
public async removeRealmFromAccountData(realmURLString: string) {
|
|
@@ -667,7 +668,7 @@ export default class MatrixService extends Service {
|
|
|
667
668
|
await this.client.setAccountData(APP_BOXEL_REALMS_EVENT_TYPE, {
|
|
668
669
|
realms: newRealms,
|
|
669
670
|
});
|
|
670
|
-
await this.realmServer.
|
|
671
|
+
await this.realmServer.setAvailableRealmIdentifiers(newRealms.map(ri));
|
|
671
672
|
}
|
|
672
673
|
|
|
673
674
|
public async getWorkspaceFavorites(): Promise<string[]> {
|
|
@@ -767,13 +768,13 @@ export default class MatrixService extends Service {
|
|
|
767
768
|
|
|
768
769
|
await Promise.all([
|
|
769
770
|
this.realmServer.fetchCatalogRealms(),
|
|
770
|
-
this.realmServer.
|
|
771
|
-
accountDataContent?.realms ?? [],
|
|
771
|
+
this.realmServer.setAvailableRealmIdentifiers(
|
|
772
|
+
(accountDataContent?.realms ?? []).map(ri),
|
|
772
773
|
),
|
|
773
774
|
]);
|
|
774
775
|
|
|
775
776
|
await this.realm.prefetchRealmInfos(
|
|
776
|
-
this.realmServer.
|
|
777
|
+
this.realmServer.availableRealmIdentifiers,
|
|
777
778
|
);
|
|
778
779
|
|
|
779
780
|
await this.initSlidingSync(accountDataContent);
|
|
@@ -882,7 +883,7 @@ export default class MatrixService extends Service {
|
|
|
882
883
|
async loginToRealms() {
|
|
883
884
|
// This is where we would actually load user-specific choices out of the
|
|
884
885
|
// user's profile based on this.client.getUserId();
|
|
885
|
-
let activeRealms = this.realmServer.
|
|
886
|
+
let activeRealms = this.realmServer.availableRealmIdentifiers;
|
|
886
887
|
|
|
887
888
|
await Promise.all(
|
|
888
889
|
activeRealms.map(async (realmURL: string) => {
|
|
@@ -1468,16 +1468,18 @@ export default class OperatorModeStateService extends Service {
|
|
|
1468
1468
|
): Promise<BoxelContext> {
|
|
1469
1469
|
let codeMode: BoxelContext['codeMode'] = undefined;
|
|
1470
1470
|
if (this._state.workspaceChooserOpened) {
|
|
1471
|
-
let userWorkspaces = this.realmServer.
|
|
1471
|
+
let userWorkspaces = this.realmServer.userRealmIdentifiers.map((url) => ({
|
|
1472
1472
|
url,
|
|
1473
1473
|
name: this.realm.info(url).name,
|
|
1474
1474
|
type: 'user-workspace' as const,
|
|
1475
1475
|
}));
|
|
1476
|
-
let catalogWorkspaces = this.realmServer.
|
|
1477
|
-
url
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1476
|
+
let catalogWorkspaces = this.realmServer.catalogRealmIdentifiers.map(
|
|
1477
|
+
(url) => ({
|
|
1478
|
+
url,
|
|
1479
|
+
name: this.realm.info(url).name,
|
|
1480
|
+
type: 'catalog-workspace' as const,
|
|
1481
|
+
}),
|
|
1482
|
+
);
|
|
1481
1483
|
let result: BoxelContext = {
|
|
1482
1484
|
agentId: this.matrixService.agentId,
|
|
1483
1485
|
submode: 'workspace-chooser',
|
|
@@ -17,7 +17,9 @@ import {
|
|
|
17
17
|
ensureTrailingSlash,
|
|
18
18
|
SupportedMimeType,
|
|
19
19
|
Deferred,
|
|
20
|
+
ri,
|
|
20
21
|
testRealmURL,
|
|
22
|
+
type RealmIdentifier,
|
|
21
23
|
type RealmInfo,
|
|
22
24
|
type JWTPayload,
|
|
23
25
|
} from '@cardstack/runtime-common';
|
|
@@ -253,8 +255,8 @@ export default class RealmServerService extends Service {
|
|
|
253
255
|
}
|
|
254
256
|
|
|
255
257
|
@cached
|
|
256
|
-
get
|
|
257
|
-
return this.availableRealms.map((r) => r.url);
|
|
258
|
+
get availableRealmIdentifiers(): RealmIdentifier[] {
|
|
259
|
+
return this.availableRealms.map((r) => ri(r.url));
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
assertOwnRealmServer(realmServerURLs: string[]): void {
|
|
@@ -338,27 +340,27 @@ export default class RealmServerService extends Service {
|
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
@cached
|
|
341
|
-
get
|
|
343
|
+
get userRealmIdentifiers(): RealmIdentifier[] {
|
|
342
344
|
return this.availableRealms
|
|
343
345
|
.filter((r) => r.type === 'user')
|
|
344
|
-
.map((r) => r.url);
|
|
346
|
+
.map((r) => ri(r.url));
|
|
345
347
|
}
|
|
346
348
|
|
|
347
349
|
@cached
|
|
348
|
-
get
|
|
350
|
+
get catalogRealmIdentifiers(): RealmIdentifier[] {
|
|
349
351
|
return this.availableRealms
|
|
350
352
|
.filter((r) => r.type === 'catalog')
|
|
351
|
-
.map((r) => r.url);
|
|
353
|
+
.map((r) => ri(r.url));
|
|
352
354
|
}
|
|
353
355
|
|
|
354
356
|
@cached
|
|
355
|
-
get
|
|
356
|
-
return this.
|
|
357
|
+
get displayedCatalogRealmIdentifiers(): RealmIdentifier[] {
|
|
358
|
+
return this.catalogRealmIdentifiers;
|
|
357
359
|
}
|
|
358
360
|
|
|
359
361
|
@cached
|
|
360
362
|
get availableRealmIndexCardIds() {
|
|
361
|
-
return this.
|
|
363
|
+
return this.availableRealmIdentifiers.map((url) => `${url}index`);
|
|
362
364
|
}
|
|
363
365
|
|
|
364
366
|
async authenticateToAllAccessibleRealms() {
|
|
@@ -389,22 +391,22 @@ export default class RealmServerService extends Service {
|
|
|
389
391
|
}
|
|
390
392
|
}
|
|
391
393
|
|
|
392
|
-
async
|
|
394
|
+
async setAvailableRealmIdentifiers(userRealmIdentifiers: RealmIdentifier[]) {
|
|
393
395
|
await this._ready.promise;
|
|
394
|
-
|
|
395
|
-
if (!this.availableRealms.find((r) => r.url ===
|
|
396
|
+
userRealmIdentifiers.forEach((userRealmIdentifier) => {
|
|
397
|
+
if (!this.availableRealms.find((r) => r.url === userRealmIdentifier)) {
|
|
396
398
|
this.availableRealms.push({
|
|
397
399
|
type: 'user',
|
|
398
|
-
url:
|
|
400
|
+
url: userRealmIdentifier,
|
|
399
401
|
});
|
|
400
402
|
}
|
|
401
403
|
});
|
|
402
404
|
|
|
403
|
-
// pluck out any user realms that aren't a part of
|
|
405
|
+
// pluck out any user realms that aren't a part of userRealmIdentifiers
|
|
404
406
|
this.availableRealms
|
|
405
407
|
.filter((r) => r.type === 'user')
|
|
406
408
|
.forEach((realm) => {
|
|
407
|
-
if (!
|
|
409
|
+
if (!userRealmIdentifiers.includes(ri(realm.url))) {
|
|
408
410
|
this.availableRealms.splice(
|
|
409
411
|
this.availableRealms.findIndex((r) => r.url === realm.url),
|
|
410
412
|
1,
|
|
@@ -414,7 +416,7 @@ export default class RealmServerService extends Service {
|
|
|
414
416
|
}
|
|
415
417
|
|
|
416
418
|
async fetchCatalogRealms() {
|
|
417
|
-
if (this.
|
|
419
|
+
if (this.catalogRealmIdentifiers.length > 0) {
|
|
418
420
|
return;
|
|
419
421
|
}
|
|
420
422
|
let response = await this.network.fetch(
|
|
@@ -943,7 +943,7 @@ export default class StoreService extends Service implements StoreInterface {
|
|
|
943
943
|
let searchRealms =
|
|
944
944
|
normalizedRealms.length > 0
|
|
945
945
|
? normalizedRealms
|
|
946
|
-
: this.realmServer.
|
|
946
|
+
: this.realmServer.availableRealmIdentifiers;
|
|
947
947
|
if (searchRealms.length === 0) {
|
|
948
948
|
if (query.asData) {
|
|
949
949
|
return opts?.includeMeta
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RealmIdentifier } from '@cardstack/runtime-common';
|
|
2
|
+
|
|
1
3
|
export function isURLSearchKey(searchKey: string): boolean {
|
|
2
4
|
try {
|
|
3
5
|
new URL(searchKey);
|
|
@@ -13,11 +15,13 @@ export function isSearchKeyEmpty(searchKey: string): boolean {
|
|
|
13
15
|
|
|
14
16
|
export function resolveSearchKeyAsURL(
|
|
15
17
|
searchKey: string,
|
|
16
|
-
|
|
18
|
+
availableRealmIdentifiers: readonly RealmIdentifier[],
|
|
17
19
|
): string | undefined {
|
|
18
20
|
if (!isURLSearchKey(searchKey)) {
|
|
19
21
|
return undefined;
|
|
20
22
|
}
|
|
21
|
-
let maybeIndexCardURL =
|
|
23
|
+
let maybeIndexCardURL = availableRealmIdentifiers.find(
|
|
24
|
+
(u) => u === searchKey + '/',
|
|
25
|
+
);
|
|
22
26
|
return maybeIndexCardURL ?? searchKey;
|
|
23
27
|
}
|
|
@@ -1367,8 +1367,8 @@ async function setupTestRealm({
|
|
|
1367
1367
|
}
|
|
1368
1368
|
|
|
1369
1369
|
let realmServer = getService('realm-server');
|
|
1370
|
-
if (!realmServer.
|
|
1371
|
-
await realmServer.
|
|
1370
|
+
if (!realmServer.availableRealmIdentifiers.includes(ri(realmURL))) {
|
|
1371
|
+
await realmServer.setAvailableRealmIdentifiers([ri(realmURL)]);
|
|
1372
1372
|
}
|
|
1373
1373
|
|
|
1374
1374
|
return { realm, adapter };
|