@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.
Files changed (35) hide show
  1. package/bundled-types/base/card-api.d.ts +2 -2
  2. package/bundled-types/base/card-serialization.d.ts +1 -1
  3. package/bundled-types/base/field-support.d.ts +6 -0
  4. package/bundled-types/boxel-ui/icons.gts +0 -3
  5. package/bundled-types/host-app/commands/create-submission-workflow.ts +2 -2
  6. package/bundled-types/host-app/commands/get-available-realm-identifiers.ts +1 -1
  7. package/bundled-types/host-app/commands/get-catalog-realm-identifiers.ts +1 -1
  8. package/bundled-types/host-app/commands/search-cards.ts +1 -1
  9. package/bundled-types/host-app/components/card-catalog/modal.gts +3 -3
  10. package/bundled-types/host-app/components/card-search/panel.gts +1 -1
  11. package/bundled-types/host-app/components/card-search/search-content.gts +2 -2
  12. package/bundled-types/host-app/components/operator-mode/code-submode/format-chooser.gts +12 -9
  13. package/bundled-types/host-app/components/operator-mode/code-submode/module-inspector.gts +1 -1
  14. package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-panel.gts +3 -3
  15. package/bundled-types/host-app/components/operator-mode/create-file-modal.gts +2 -2
  16. package/bundled-types/host-app/components/operator-mode/stack-item.gts +9 -1
  17. package/bundled-types/host-app/components/operator-mode/workspace-chooser/index.gts +32 -24
  18. package/bundled-types/host-app/components/operator-mode/workspace-chooser/workspace.gts +36 -23
  19. package/bundled-types/host-app/components/realm-picker/index.gts +2 -2
  20. package/bundled-types/host-app/components/search-sheet/index.gts +1 -1
  21. package/bundled-types/host-app/components/with-known-realms-loaded.gts +1 -1
  22. package/bundled-types/host-app/router.ts +1 -0
  23. package/bundled-types/host-app/services/host-mode-service.ts +21 -2
  24. package/bundled-types/host-app/services/matrix-service.ts +9 -8
  25. package/bundled-types/host-app/services/operator-mode-state-service.ts +8 -6
  26. package/bundled-types/host-app/services/realm-server.ts +18 -16
  27. package/bundled-types/host-app/services/store.ts +1 -1
  28. package/bundled-types/host-app/utils/card-search/url.ts +6 -2
  29. package/bundled-types/host-tests/helpers/index.gts +2 -2
  30. package/dist/index.js +69 -69
  31. package/package.json +2 -2
  32. package/src/commands/realm/publish.ts +10 -1
  33. package/src/commands/realm/sync.ts +28 -2
  34. package/src/commands/realm/unpublish.ts +2 -3
  35. package/src/lib/describe-fetch-error.ts +25 -0
@@ -7,7 +7,7 @@ import { ensureQueryFieldSearchResource } from './query-field-support';
7
7
  import { isSavedInstance } from './-private';
8
8
  import type { ComponentLike } from '@glint/template';
9
9
  import { deserialize, serialize, serializeCard, serializeFileDef, type DeserializeOpts, type JSONAPIResource, type JSONAPISingleResourceDocument, type SerializeOpts, getCardMeta } from './card-serialization';
10
- import { getDataBucket, getFieldDescription, getFields, isCard, peekAtField, realmContext, relationshipMeta } from './field-support';
10
+ import { beginComputePass, endComputePass, getDataBucket, getFieldDescription, getFields, isCard, peekAtField, realmContext, relationshipMeta, type ComputePassSnapshot } from './field-support';
11
11
  import { type GetMenuItemParams } from './menu-items';
12
12
  import { LinkableDocument, SingleFileMetaDocument } from '@cardstack/runtime-common/document-types';
13
13
  import type { FileMetaResource } from '@cardstack/runtime-common';
@@ -16,7 +16,7 @@ interface CardOrFieldTypeIconSignature {
16
16
  Element: SVGSVGElement;
17
17
  }
18
18
  export type CardOrFieldTypeIcon = ComponentLike<CardOrFieldTypeIconSignature>;
19
- export { deserialize, getCardMeta, getDataBucket, getFieldDescription, getFields, peekAtField, isCard, isField, isFileDef, localId, meta, primitive, realmURL, relativeTo, relationshipMeta, serialize, serializeCard, serializeFileDef, ensureQueryFieldSearchResource, getStore, type BoxComponent, type DeserializeOpts, type GetMenuItemParams, type JSONAPISingleResourceDocument, type ResourceID, type SerializeOpts };
19
+ export { beginComputePass, endComputePass, deserialize, getCardMeta, getDataBucket, getFieldDescription, getFields, peekAtField, isCard, isField, isFileDef, localId, meta, primitive, realmURL, relativeTo, relationshipMeta, serialize, serializeCard, serializeFileDef, ensureQueryFieldSearchResource, getStore, type BoxComponent, type ComputePassSnapshot, type DeserializeOpts, type GetMenuItemParams, type JSONAPISingleResourceDocument, type ResourceID, type SerializeOpts };
20
20
  export declare const useIndexBasedKey: unique symbol;
21
21
  export declare const fieldDecorator: unique symbol;
22
22
  export declare const queryableValue: unique symbol;
@@ -27,7 +27,7 @@ export interface SerializeOpts {
27
27
  useAbsoluteURL?: boolean;
28
28
  omitFields?: [typeof BaseDef];
29
29
  omitQueryFields?: boolean;
30
- maybeRelativeURL?: (possibleURL: string) => string;
30
+ maybeRelativeReference?: (possibleReference: string) => string;
31
31
  overrides?: Map<string, typeof BaseDef>;
32
32
  }
33
33
  export interface DeserializeOpts {
@@ -6,6 +6,12 @@ export interface NotLoadedValue {
6
6
  reference: string;
7
7
  }
8
8
  export declare const realmContext: unique symbol;
9
+ export interface ComputePassSnapshot {
10
+ calls: number;
11
+ cacheHits: number;
12
+ }
13
+ export declare function beginComputePass(): void;
14
+ export declare function endComputePass(): ComputePassSnapshot;
9
15
  export declare function getter<CardT extends BaseDefConstructor>(instance: BaseDef, field: Field<CardT>): BaseInstanceType<CardT>;
10
16
  export declare function entangleWithCardTracking(instance: BaseDef): void;
11
17
  export declare function notifyCardTracking(instance: BaseDef): void;
@@ -66,7 +66,6 @@ import ImagePlaceholder from './icons/image-placeholder.gts';
66
66
  import Isolated from './icons/isolated.gts';
67
67
  import LoadingIndicator from './icons/loading-indicator.gts';
68
68
  import Lock from './icons/lock.gts';
69
- import Markdown from './icons/markdown.gts';
70
69
  import Profile from './icons/profile.gts';
71
70
  import PublishSiteIcon from './icons/publish-site-icon.gts';
72
71
  import Rows4 from './icons/rows-4.gts';
@@ -147,7 +146,6 @@ export const ALL_ICON_COMPONENTS = [
147
146
  Isolated,
148
147
  LoadingIndicator,
149
148
  Lock,
150
- Markdown,
151
149
  Profile,
152
150
  PublishSiteIcon,
153
151
  Rows4,
@@ -230,7 +228,6 @@ export {
230
228
  Isolated,
231
229
  LoadingIndicator,
232
230
  Lock,
233
- Markdown,
234
231
  Profile,
235
232
  PublishSiteIcon,
236
233
  Rows4,
@@ -37,7 +37,7 @@ export default class CreateSubmissionWorkflowCommand extends HostBaseCommand<
37
37
  requireInputFields = ['realm', 'listingId'];
38
38
 
39
39
  get submissionsRealm(): string | undefined {
40
- return this.realmServer.catalogRealmURLs.find((realm) =>
40
+ return this.realmServer.catalogRealmIdentifiers.find((realm) =>
41
41
  realm.endsWith('/submissions/'),
42
42
  );
43
43
  }
@@ -165,7 +165,7 @@ export default class CreateSubmissionWorkflowCommand extends HostBaseCommand<
165
165
  }
166
166
 
167
167
  private get catalogRealm(): string | undefined {
168
- return this.realmServer.catalogRealmURLs.find((realm) =>
168
+ return this.realmServer.catalogRealmIdentifiers.find((realm) =>
169
169
  realm.endsWith('/catalog/'),
170
170
  );
171
171
  }
@@ -23,7 +23,7 @@ export default class GetAvailableRealmIdentifiersCommand extends HostBaseCommand
23
23
  let commandModule = await this.loadCommandModule();
24
24
  const { GetAvailableRealmIdentifiersResult } = commandModule;
25
25
  return new GetAvailableRealmIdentifiersResult({
26
- realmIdentifiers: this.realmServer.availableRealmURLs,
26
+ realmIdentifiers: this.realmServer.availableRealmIdentifiers,
27
27
  });
28
28
  }
29
29
  }
@@ -23,7 +23,7 @@ export default class GetCatalogRealmIdentifiersCommand extends HostBaseCommand<
23
23
  let commandModule = await this.loadCommandModule();
24
24
  const { GetCatalogRealmIdentifiersResult } = commandModule;
25
25
  return new GetCatalogRealmIdentifiersResult({
26
- realmIdentifiers: this.realmServer.catalogRealmURLs,
26
+ realmIdentifiers: this.realmServer.catalogRealmIdentifiers,
27
27
  });
28
28
  }
29
29
  }
@@ -75,7 +75,7 @@ export class SearchCardsByQueryCommand extends HostBaseCommand<
75
75
  input: BaseCommandModule.SearchCardsByQueryInput,
76
76
  ): Promise<BaseCommandModule.SearchCardsResult> {
77
77
  assertQuery(input.query);
78
- let realmUrls = this.realmServer.availableRealmURLs;
78
+ let realmUrls = this.realmServer.availableRealmIdentifiers;
79
79
  let instances: CardDef[] = [];
80
80
  try {
81
81
  instances = await this.store.search(input.query, realmUrls);
@@ -344,7 +344,7 @@ export default class CardCatalogModal extends Component<Signature> {
344
344
  await this.realmServer.ready;
345
345
  // Preload realm info without blocking the modal from opening.
346
346
  let prefetchRealmInfo = Promise.all(
347
- this.realmServer.availableRealmURLs.map(async (realmURL) => {
347
+ this.realmServer.availableRealmIdentifiers.map(async (realmURL) => {
348
348
  let resource = this.realm.getOrCreateRealmResource(realmURL);
349
349
  try {
350
350
  await resource.fetchInfo();
@@ -378,7 +378,7 @@ export default class CardCatalogModal extends Component<Signature> {
378
378
  if (opts?.preselectedCardTypeQuery) {
379
379
  let instances: CardDef[] = await this.store.search(
380
380
  opts.preselectedCardTypeQuery!,
381
- this.realmServer.availableRealmURLs,
381
+ this.realmServer.availableRealmIdentifiers,
382
382
  );
383
383
  if (instances?.[0]?.id) {
384
384
  preselectedCardUrl = `${instances[0].id}.json`;
@@ -399,7 +399,7 @@ export default class CardCatalogModal extends Component<Signature> {
399
399
  searchKey: '',
400
400
  dismissModal: false,
401
401
  baseFilter: query.filter,
402
- availableRealmUrls: this.realmServer.availableRealmURLs,
402
+ availableRealmUrls: this.realmServer.availableRealmIdentifiers,
403
403
  selectedCards: preselectedCardUrls,
404
404
  multiSelect: opts?.multiSelect ?? false,
405
405
  hasPreselectedCard: preselectedCardUrls.length > 0,
@@ -66,7 +66,7 @@ export default class SearchPanel extends Component<Signature> {
66
66
 
67
67
  private get selectedRealmURLs(): string[] {
68
68
  if (this.selectedRealms.length === 0) {
69
- return this.realmServer.availableRealmURLs;
69
+ return this.realmServer.availableRealmIdentifiers;
70
70
  }
71
71
  return this.selectedRealms.map((url) => url.href);
72
72
  }
@@ -167,7 +167,7 @@ export default class SearchContent extends Component<Signature> {
167
167
  private get searchKeyAsURL() {
168
168
  return resolveSearchKeyAsURL(
169
169
  this.args.searchKey,
170
- this.realmServer.availableRealmURLs,
170
+ this.realmServer.availableRealmIdentifiers,
171
171
  );
172
172
  }
173
173
 
@@ -328,7 +328,7 @@ export default class SearchContent extends Component<Signature> {
328
328
  const urls =
329
329
  this.args.realmFilter.selectedURLs.length > 0
330
330
  ? this.args.realmFilter.selectedURLs
331
- : this.realmServer.availableRealmURLs;
331
+ : this.realmServer.availableRealmIdentifiers;
332
332
  return urls ?? [];
333
333
  }
334
334
 
@@ -7,6 +7,7 @@ import Component from '@glimmer/component';
7
7
  import { tracked } from '@glimmer/tracking';
8
8
 
9
9
  import MetadataIcon from '@cardstack/boxel-icons/clipboard-data';
10
+ import MarkdownIcon from '@cardstack/boxel-icons/markdown';
10
11
  import EditIcon from '@cardstack/boxel-icons/pencil';
11
12
  import { modifier } from 'ember-modifier';
12
13
  import window from 'ember-window-mock';
@@ -19,7 +20,6 @@ import {
19
20
  Fitted as FittedIcon,
20
21
  Atom as AtomIcon,
21
22
  Head as HeadIcon,
22
- Markdown as MarkdownIcon,
23
23
  Form as FormIcon,
24
24
  type Icon,
25
25
  } from '@cardstack/boxel-ui/icons';
@@ -86,7 +86,12 @@ const FormatButton: TemplateOnlyComponent<FormatButtonSignature> = <template>
86
86
  {{on 'click' @onClick}}
87
87
  >
88
88
  {{#if @icon}}
89
- <@icon class='pf-icon' width={{ICON_W}} height={{ICON_W}} />
89
+ {{! md icon is larger because tabler icons have extra padding which shrinks them }}
90
+ <@icon
91
+ class='pf-icon'
92
+ width={{if (eq @format 'markdown') '24' ICON_W}}
93
+ height={{if (eq @format 'markdown') '24' ICON_W}}
94
+ />
90
95
  {{/if}}
91
96
  </Button>
92
97
  <style scoped>
@@ -124,16 +129,10 @@ const FormatButton: TemplateOnlyComponent<FormatButtonSignature> = <template>
124
129
  }
125
130
  .pf-icon {
126
131
  flex: 0 0 auto;
127
- height: var(--pf-icon-w);
128
132
  display: inline-flex;
129
133
  align-items: center;
130
134
  justify-content: center;
131
135
  }
132
- .pf-icon :deep(svg) {
133
- height: var(--pf-icon-w);
134
- width: auto;
135
- display: block;
136
- }
137
136
  </style>
138
137
  </template>;
139
138
 
@@ -430,7 +429,11 @@ export default class PillFormatChooser extends Component<Signature> {
430
429
  </svg>
431
430
  <div class='pill-content'>
432
431
  {{#if this.pillTargetIcon}}
433
- <this.pillTargetIcon class='pf-icon' width='16' height='16' />
432
+ <this.pillTargetIcon
433
+ class='pf-icon'
434
+ width={{ICON_W}}
435
+ height={{ICON_W}}
436
+ />
434
437
  {{/if}}
435
438
  <span
436
439
  class='pf-label'
@@ -465,7 +465,7 @@ export default class ModuleInspector extends Component<ModuleInspectorSignature>
465
465
  this.specSearch = this.getCards(
466
466
  this,
467
467
  () => this.queryForSpecsForSelectedDefinition,
468
- () => this.realmServer.availableRealmURLs,
468
+ () => this.realmServer.availableRealmIdentifiers,
469
469
  { isLive: true, doWhileRefreshing: this.doWhileRefreshing },
470
470
  ) as ReturnType<getCards<Spec>>;
471
471
  };
@@ -360,7 +360,7 @@ export default class PlaygroundPanel extends Component<Signature> {
360
360
  this.fileSearchResults = this.getCards(
361
361
  this,
362
362
  () => this.fileMetaQuery,
363
- () => this.realmServer.availableRealmURLs,
363
+ () => this.realmServer.availableRealmIdentifiers,
364
364
  { isLive: true },
365
365
  );
366
366
  };
@@ -997,7 +997,7 @@ export default class PlaygroundPanel extends Component<Signature> {
997
997
  <PrerenderedCardSearch
998
998
  @query={{this.expandedQuery}}
999
999
  @format='fitted'
1000
- @realms={{this.realmServer.availableRealmURLs}}
1000
+ @realms={{this.realmServer.availableRealmIdentifiers}}
1001
1001
  >
1002
1002
  <:response as |maybeCards|>
1003
1003
  {{! TODO: remove side-effects for instance chooser in CS-8746 }}
@@ -1139,7 +1139,7 @@ export default class PlaygroundPanel extends Component<Signature> {
1139
1139
  {{else if this.maybeGenerateFieldSpec}}
1140
1140
  <SpecSearch
1141
1141
  @query={{this.specQuery}}
1142
- @realms={{this.realmServer.availableRealmURLs}}
1142
+ @realms={{this.realmServer.availableRealmIdentifiers}}
1143
1143
  @createNewCard={{this.createNew}}
1144
1144
  />
1145
1145
  {{else if @isFileDef}}
@@ -39,7 +39,7 @@ import {
39
39
  RealmPaths,
40
40
  Deferred,
41
41
  SupportedMimeType,
42
- maybeRelativeURL,
42
+ maybeRelativeReference,
43
43
  GetCardContextName,
44
44
  isCardInstance,
45
45
  type getCard,
@@ -844,7 +844,7 @@ export default class CreateFileModal extends Component<Signature> {
844
844
  ) as ResolvedCodeRef
845
845
  ).module;
846
846
  const absoluteModule = new URL(absoluteModuleHref);
847
- let moduleURL = maybeRelativeURL(
847
+ let moduleURL = maybeRelativeReference(
848
848
  absoluteModule,
849
849
  url,
850
850
  new URL(this.selectedRealmURL),
@@ -32,12 +32,13 @@ import {
32
32
  import {
33
33
  MenuDivider,
34
34
  MenuItem,
35
+ copyCardURLToClipboard,
35
36
  getContrastColor,
36
37
  toMenuItems,
37
38
  } from '@cardstack/boxel-ui/helpers';
38
39
  import { cn, cssVar, optional, not } from '@cardstack/boxel-ui/helpers';
39
40
 
40
- import { IconTrash } from '@cardstack/boxel-ui/icons';
41
+ import { IconLink, IconTrash } from '@cardstack/boxel-ui/icons';
41
42
 
42
43
  import type { CommandContext } from '@cardstack/runtime-common';
43
44
  import {
@@ -619,6 +620,13 @@ export default class OperatorModeStackItem extends Component<Signature> {
619
620
  return undefined;
620
621
  }
621
622
  return [
623
+ new MenuItem({
624
+ label: 'Copy Card URL',
625
+ action: () =>
626
+ this.cardIdentifier && copyCardURLToClipboard(this.cardIdentifier),
627
+ icon: IconLink,
628
+ disabled: !this.cardIdentifier,
629
+ }),
622
630
  new MenuItem({
623
631
  label: 'Delete Card',
624
632
  action: () =>
@@ -10,6 +10,8 @@ import { BoxelSelect } from '@cardstack/boxel-ui/components';
10
10
  import { IconGlobe, Lock, StarFilled } from '@cardstack/boxel-ui/icons';
11
11
  import type { Icon } from '@cardstack/boxel-ui/icons';
12
12
 
13
+ import { ri } from '@cardstack/runtime-common';
14
+
13
15
  import config from '@cardstack/host/config/environment';
14
16
  import type MatrixService from '@cardstack/host/services/matrix-service';
15
17
  import type RealmService from '@cardstack/host/services/realm';
@@ -54,13 +56,13 @@ export default class WorkspaceChooser extends Component<Signature> {
54
56
 
55
57
  private get displayCatalogWorkspaces() {
56
58
  return (
57
- this.realmServer.displayedCatalogRealmURLs &&
58
- this.realmServer.displayedCatalogRealmURLs.length > 0
59
+ this.realmServer.displayedCatalogRealmIdentifiers &&
60
+ this.realmServer.displayedCatalogRealmIdentifiers.length > 0
59
61
  );
60
62
  }
61
63
 
62
- private get communityRealmURLs() {
63
- let realmURLs = this.realmServer.displayedCatalogRealmURLs ?? [];
64
+ private get communityRealmIdentifiers() {
65
+ let realmURLs = this.realmServer.displayedCatalogRealmIdentifiers ?? [];
64
66
  if (config.environment !== 'production') {
65
67
  return realmURLs;
66
68
  }
@@ -78,35 +80,35 @@ export default class WorkspaceChooser extends Component<Signature> {
78
80
  );
79
81
  };
80
82
 
81
- private filterByHosted(urls: string[]): string[] {
83
+ private filterByHosted<T extends string>(urls: T[]): T[] {
82
84
  if (this.sortOrder === 'hosted-only') {
83
85
  return urls.filter(this.isHosted);
84
86
  }
85
87
  return urls;
86
88
  }
87
89
 
88
- private get filteredUserRealmURLs() {
89
- return this.filterByHosted(this.realmServer.userRealmURLs);
90
+ private get filteredUserRealmIdentifiers() {
91
+ return this.filterByHosted(this.realmServer.userRealmIdentifiers);
90
92
  }
91
93
 
92
- private get filteredCatalogRealmURLs() {
93
- return this.filterByHosted(this.communityRealmURLs);
94
+ private get filteredCatalogRealmIdentifiers() {
95
+ return this.filterByHosted(this.communityRealmIdentifiers);
94
96
  }
95
97
 
96
- private get favoriteRealmURLs() {
98
+ private get favoriteRealmIdentifiers() {
97
99
  let favorites = this.matrixService.workspaceFavorites;
98
- let allURLs = [
99
- ...this.realmServer.userRealmURLs,
100
- ...(this.realmServer.displayedCatalogRealmURLs ?? []),
101
- ];
102
- let filtered = favorites.filter((url) => allURLs.includes(url));
100
+ let allURLs = new Set<string>([
101
+ ...this.realmServer.userRealmIdentifiers,
102
+ ...(this.realmServer.displayedCatalogRealmIdentifiers ?? []),
103
+ ]);
104
+ let filtered = favorites.filter((url) => allURLs.has(url)).map(ri);
103
105
  return this.filterByHosted(filtered);
104
106
  }
105
107
 
106
108
  private get userWorkspacesEmptyMessage(): string | null {
107
109
  if (
108
110
  this.sortOrder === 'hosted-only' &&
109
- this.filteredUserRealmURLs.length === 0
111
+ this.filteredUserRealmIdentifiers.length === 0
110
112
  ) {
111
113
  return 'No matching results';
112
114
  }
@@ -116,7 +118,7 @@ export default class WorkspaceChooser extends Component<Signature> {
116
118
  private get catalogEmptyMessage(): string | null {
117
119
  if (
118
120
  this.sortOrder === 'hosted-only' &&
119
- this.filteredCatalogRealmURLs.length === 0
121
+ this.filteredCatalogRealmIdentifiers.length === 0
120
122
  ) {
121
123
  return 'No matching results';
122
124
  }
@@ -127,7 +129,7 @@ export default class WorkspaceChooser extends Component<Signature> {
127
129
  if (this.matrixService.workspaceFavorites.length === 0) {
128
130
  return 'You have no favorites yet';
129
131
  }
130
- if (this.favoriteRealmURLs.length === 0) {
132
+ if (this.favoriteRealmIdentifiers.length === 0) {
131
133
  return 'No matching results';
132
134
  }
133
135
  return null;
@@ -168,8 +170,8 @@ export default class WorkspaceChooser extends Component<Signature> {
168
170
  >{{this.favoritesEmptyMessage}}</span>
169
171
  {{else}}
170
172
  <div class='workspace-list' data-test-favorites-list>
171
- {{#each this.favoriteRealmURLs as |realmURL|}}
172
- <Workspace @realmURL={{realmURL}} />
173
+ {{#each this.favoriteRealmIdentifiers as |realmIdentifier|}}
174
+ <Workspace @realmIdentifier={{realmIdentifier}} />
173
175
  {{/each}}
174
176
  </div>
175
177
  {{/if}}
@@ -186,8 +188,11 @@ export default class WorkspaceChooser extends Component<Signature> {
186
188
  >{{this.userWorkspacesEmptyMessage}}</span>
187
189
  {{else}}
188
190
  <div class='workspace-list' data-test-workspace-list>
189
- {{#each this.filteredUserRealmURLs as |realmURL|}}
190
- <Workspace @realmURL={{realmURL}} @showMenu={{true}} />
191
+ {{#each this.filteredUserRealmIdentifiers as |realmIdentifier|}}
192
+ <Workspace
193
+ @realmIdentifier={{realmIdentifier}}
194
+ @showMenu={{true}}
195
+ />
191
196
  {{/each}}
192
197
  {{#if this.matrixService.isInitializingNewUser}}
193
198
  <WorkspaceLoadingIndicator />
@@ -209,8 +214,11 @@ export default class WorkspaceChooser extends Component<Signature> {
209
214
  >{{this.catalogEmptyMessage}}</span>
210
215
  {{else}}
211
216
  <div class='workspace-list' data-test-catalog-list>
212
- {{#each this.filteredCatalogRealmURLs as |realmURL|}}
213
- <Workspace @realmURL={{realmURL}} />
217
+ {{#each
218
+ this.filteredCatalogRealmIdentifiers
219
+ as |realmIdentifier|
220
+ }}
221
+ <Workspace @realmIdentifier={{realmIdentifier}} />
214
222
  {{/each}}
215
223
  </div>
216
224
  {{/if}}
@@ -33,8 +33,8 @@ import {
33
33
  import {
34
34
  hasExecutableExtension,
35
35
  RealmPaths,
36
- ri,
37
36
  SupportedMimeType,
37
+ type RealmIdentifier,
38
38
  } from '@cardstack/runtime-common';
39
39
 
40
40
  import ModalContainer from '@cardstack/host/components/modal-container';
@@ -51,7 +51,7 @@ import WorkspaceLoadingIndicator from './workspace-loading-indicator';
51
51
  interface Signature {
52
52
  Element: HTMLDivElement;
53
53
  Args: {
54
- realmURL: string;
54
+ realmIdentifier: RealmIdentifier;
55
55
  showMenu?: boolean;
56
56
  };
57
57
  }
@@ -93,7 +93,7 @@ export default class Workspace extends Component<Signature> {
93
93
  @width='16'
94
94
  @height='16'
95
95
  {{on 'click' this.toggleFavorite}}
96
- data-test-workspace-favorite-btn={{@realmURL}}
96
+ data-test-workspace-favorite-btn={{@realmIdentifier}}
97
97
  />
98
98
  <div class='tile-menu-btn'>
99
99
  <BoxelDropdown>
@@ -103,7 +103,7 @@ export default class Workspace extends Component<Signature> {
103
103
  @variant='ghost'
104
104
  @width='16'
105
105
  @height='16'
106
- data-test-workspace-menu-trigger={{@realmURL}}
106
+ data-test-workspace-menu-trigger={{@realmIdentifier}}
107
107
  {{bindings}}
108
108
  />
109
109
  </:trigger>
@@ -116,7 +116,7 @@ export default class Workspace extends Component<Signature> {
116
116
  <button
117
117
  class='host-trigger'
118
118
  type='button'
119
- data-test-host-trigger={{@realmURL}}
119
+ data-test-host-trigger={{@realmIdentifier}}
120
120
  {{on 'click' this.toggleHostDropdown}}
121
121
  >
122
122
  <span class='trigger-house'><Home width='13' height='13' /></span>
@@ -127,7 +127,10 @@ export default class Workspace extends Component<Signature> {
127
127
  </button>
128
128
 
129
129
  {{#if this.isHostDropdownOpen}}
130
- <div class='host-dropdown' data-test-host-dropdown={{@realmURL}}>
130
+ <div
131
+ class='host-dropdown'
132
+ data-test-host-dropdown={{@realmIdentifier}}
133
+ >
131
134
  <span class='dropdown-header'>Launch in new window</span>
132
135
  <ul class='dropdown-list'>
133
136
  {{#each this.publishedRealmURLs as |url|}}
@@ -179,7 +182,7 @@ export default class Workspace extends Component<Signature> {
179
182
  @size='medium'
180
183
  @cardContainerClass='workspace-chooser-delete-modal'
181
184
  class='workspace-chooser-delete-modal-container'
182
- data-test-delete-modal={{@realmURL}}
185
+ data-test-delete-modal={{@realmIdentifier}}
183
186
  >
184
187
  <:content>
185
188
  <div class='delete-modal__header'>
@@ -773,7 +776,9 @@ export default class Workspace extends Component<Signature> {
773
776
  </template>
774
777
 
775
778
  get isFavorited() {
776
- return this.matrixService.workspaceFavorites.includes(this.args.realmURL);
779
+ return this.matrixService.workspaceFavorites.includes(
780
+ this.args.realmIdentifier,
781
+ );
777
782
  }
778
783
 
779
784
  @service declare private operatorModeStateService: OperatorModeStateService;
@@ -794,13 +799,13 @@ export default class Workspace extends Component<Signature> {
794
799
  }
795
800
 
796
801
  private loadRealmTask = task(async () => {
797
- await this.realm.login(this.args.realmURL);
798
- await this.realm.ensureRealmMeta(this.args.realmURL);
802
+ await this.realm.login(this.args.realmIdentifier);
803
+ await this.realm.ensureRealmMeta(this.args.realmIdentifier);
799
804
  });
800
805
 
801
806
  @cached
802
807
  private get realmInfo() {
803
- return this.realm.info(this.args.realmURL);
808
+ return this.realm.info(this.args.realmIdentifier);
804
809
  }
805
810
 
806
811
  private get name() {
@@ -826,9 +831,11 @@ export default class Workspace extends Component<Signature> {
826
831
 
827
832
  @action async toggleFavorite() {
828
833
  if (this.isFavorited) {
829
- await this.matrixService.removeWorkspaceFavorite(this.args.realmURL);
834
+ await this.matrixService.removeWorkspaceFavorite(
835
+ this.args.realmIdentifier,
836
+ );
830
837
  } else {
831
- await this.matrixService.addWorkspaceFavorite(this.args.realmURL);
838
+ await this.matrixService.addWorkspaceFavorite(this.args.realmIdentifier);
832
839
  }
833
840
  }
834
841
 
@@ -900,7 +907,7 @@ export default class Workspace extends Component<Signature> {
900
907
  }
901
908
 
902
909
  private get canDeleteWorkspace() {
903
- return this.realm.isRealmOwner(this.args.realmURL);
910
+ return this.realm.isRealmOwner(this.args.realmIdentifier);
904
911
  }
905
912
 
906
913
  private get deleteSummaryText() {
@@ -933,7 +940,9 @@ export default class Workspace extends Component<Signature> {
933
940
  }
934
941
 
935
942
  @action async openWorkspace() {
936
- await this.operatorModeStateService.openWorkspace(this.args.realmURL);
943
+ await this.operatorModeStateService.openWorkspace(
944
+ this.args.realmIdentifier,
945
+ );
937
946
  }
938
947
 
939
948
  @action openDeleteModal() {
@@ -957,7 +966,7 @@ export default class Workspace extends Component<Signature> {
957
966
  private loadDeleteSummaryTask = dropTask(async () => {
958
967
  try {
959
968
  let response = await this.network.authedFetch(
960
- `${this.args.realmURL}_mtimes`,
969
+ `${this.args.realmIdentifier}_mtimes`,
961
970
  {
962
971
  headers: {
963
972
  Accept: SupportedMimeType.Mtimes,
@@ -989,23 +998,27 @@ export default class Workspace extends Component<Signature> {
989
998
  this.deleteError = undefined;
990
999
 
991
1000
  try {
992
- let realmPath = new RealmPaths(ri(this.args.realmURL));
1001
+ let realmPath = new RealmPaths(this.args.realmIdentifier);
993
1002
  let isActiveWorkspace =
994
- this.operatorModeStateService.realmURL === this.args.realmURL ||
1003
+ this.operatorModeStateService.realmURL === this.args.realmIdentifier ||
995
1004
  this.operatorModeStateService
996
1005
  .getOpenCardIds()
997
1006
  .some((cardId) => realmPath.inRealm(cardId)) ||
998
1007
  this.operatorModeStateService.codePathString?.startsWith(
999
- this.args.realmURL,
1008
+ this.args.realmIdentifier,
1000
1009
  );
1001
1010
 
1002
- await this.realmServer.deleteRealm(this.args.realmURL);
1003
- await this.matrixService.removeRealmFromAccountData(this.args.realmURL);
1004
- this.recentFilesService.removeRecentFilesForRealmURL(this.args.realmURL);
1011
+ await this.realmServer.deleteRealm(this.args.realmIdentifier);
1012
+ await this.matrixService.removeRealmFromAccountData(
1013
+ this.args.realmIdentifier,
1014
+ );
1015
+ this.recentFilesService.removeRecentFilesForRealmURL(
1016
+ this.args.realmIdentifier,
1017
+ );
1005
1018
  for (let publishedRealmURL of this.publishedRealmURLs) {
1006
1019
  this.recentFilesService.removeRecentFilesForRealmURL(publishedRealmURL);
1007
1020
  }
1008
- this.realm.removeRealm(this.args.realmURL);
1021
+ this.realm.removeRealm(this.args.realmIdentifier);
1009
1022
 
1010
1023
  if (isActiveWorkspace) {
1011
1024
  this.operatorModeStateService.clearStacks();
@@ -36,7 +36,7 @@ export default class RealmPicker extends Component<Signature> {
36
36
  // interprets as a user-initiated filter change (expanding the search sheet).
37
37
  @cached
38
38
  get selectAllOption(): PickerOption {
39
- const urls = this.realmServer.availableRealmURLs;
39
+ const urls = this.realmServer.availableRealmIdentifiers;
40
40
  return {
41
41
  id: 'select-all',
42
42
  label: `Select All (${urls.length})`,
@@ -60,7 +60,7 @@ export default class RealmPicker extends Component<Signature> {
60
60
  }
61
61
 
62
62
  get realmOptions(): PickerOption[] {
63
- const urls = this.realmServer.availableRealmURLs;
63
+ const urls = this.realmServer.availableRealmIdentifiers;
64
64
  const options: PickerOption[] = [this.selectAllOption];
65
65
  for (const realmURL of urls) {
66
66
  const info = this.realm.info(realmURL);
@@ -197,7 +197,7 @@ export default class SearchSheet extends Component<Signature> {
197
197
  private get searchKeyAsURL() {
198
198
  return resolveSearchKeyAsURL(
199
199
  this.searchKey,
200
- this.realmServer.availableRealmURLs,
200
+ this.realmServer.availableRealmIdentifiers,
201
201
  );
202
202
  }
203
203
 
@@ -23,7 +23,7 @@ export default class WithKnownRealmsLoaded extends Component<Signature> {
23
23
  }
24
24
 
25
25
  private loadRealmsTask = task(async () => {
26
- let realmURLs = this.realmServer.availableRealmURLs;
26
+ let realmURLs = this.realmServer.availableRealmIdentifiers;
27
27
  await Promise.all(
28
28
  realmURLs.map(
29
29
  async (realmURL) => await this.realm.ensureRealmMeta(realmURL),