diff --git a/packages/base/card-api.gts b/packages/base/card-api.gts index cc0992c1ea8..cd352701ea8 100644 --- a/packages/base/card-api.gts +++ b/packages/base/card-api.gts @@ -2356,7 +2356,7 @@ export type EditCardFn = ( opts?: { useBaseTemplate?: boolean }, ) => void; -export type SaveCardFn = (id: string) => void; +export type SaveCardFn = (id: RealmResourceIdentifier) => void; export type DeleteCardFn = (cardOrId: CardDef | URL | string) => Promise; @@ -2740,7 +2740,9 @@ export class FileDef extends BaseDef { } } - @field id = contains(ReadOnlyField); + @field id: RealmResourceIdentifier = contains( + ReadOnlyField, + ) as unknown as RealmResourceIdentifier; @field sourceUrl = contains(StringField); @field url = contains(StringField); @field name = contains(StringField); @@ -2900,7 +2902,9 @@ export class CardDef extends BaseDef { // notify glimmer to rerender this card notifyCardTracking(this); } - @field id = contains(ReadOnlyField); + @field id: RealmResourceIdentifier = contains( + ReadOnlyField, + ) as unknown as RealmResourceIdentifier; @field cardInfo = contains(CardInfoField); @field cardTitle = contains(StringField, { computeVia: function (this: CardDef) { @@ -3462,7 +3466,7 @@ function trackRuntimeRelationshipModuleDependencies( } } -export function setId(instance: CardDef, id: string) { +export function setId(instance: CardDef, id: RealmResourceIdentifier) { let field = getField(instance, 'id'); if (field) { setField(instance, field, id); diff --git a/packages/base/matrix-event.gts b/packages/base/matrix-event.gts index 319cc75afbf..d1e329b6a8c 100644 --- a/packages/base/matrix-event.gts +++ b/packages/base/matrix-event.gts @@ -27,6 +27,7 @@ import { CodeRef, APP_BOXEL_LLM_MODE, type LLMMode, + type RealmResourceIdentifier, } from '@cardstack/runtime-common'; import { type SerializedFile } from './file-api'; @@ -191,7 +192,7 @@ export interface BoxelErrorForContext { export interface BoxelContext { agentId?: string; - openCardIds?: string[]; + openCardIds?: RealmResourceIdentifier[]; realmUrl?: string; realmPermissions?: { canRead: boolean; @@ -210,7 +211,7 @@ export interface BoxelContext { currentFile?: string; moduleInspectorPanel?: string; previewPanelSelection?: { - cardId: string; + cardId: RealmResourceIdentifier; format: string; }; selectedCodeRef?: CodeRef; diff --git a/packages/catalog-realm/commands/collect-submission-files.ts b/packages/catalog-realm/commands/collect-submission-files.ts index c366e29b0fe..ff44b5c64ce 100644 --- a/packages/catalog-realm/commands/collect-submission-files.ts +++ b/packages/catalog-realm/commands/collect-submission-files.ts @@ -9,6 +9,7 @@ import { planModuleInstall, type ListingPathResolver, type LooseSingleCardDocument, + type RealmResourceIdentifier, type Relationship, } from '@cardstack/runtime-common'; import type { CopyInstanceMeta } from '@cardstack/runtime-common/catalog'; @@ -310,11 +311,11 @@ export default class CollectSubmissionFilesCommand extends Command< let getCardCommand = new GetCardCommand(this.commandContext); let serializeCardCommand = new SerializeCardCommand(this.commandContext); - const instancesById = new Map(); - const visited = new Set(); - const queue: string[] = instances + const instancesById = new Map(); + const visited = new Set(); + const queue: RealmResourceIdentifier[] = instances .map((instance) => instance.id) - .filter((id): id is string => typeof id === 'string'); + .filter((id): id is RealmResourceIdentifier => typeof id === 'string'); while (queue.length > 0) { const id = queue.shift(); diff --git a/packages/catalog-realm/crm-app/components/base-task-planner.gts b/packages/catalog-realm/crm-app/components/base-task-planner.gts index d4934adb440..624d2f5f9cb 100644 --- a/packages/catalog-realm/crm-app/components/base-task-planner.gts +++ b/packages/catalog-realm/crm-app/components/base-task-planner.gts @@ -85,7 +85,6 @@ export type FilterType = 'status' | 'assignee'; // Type definitions for the card structure export interface TaskCard extends CardDef { - id: string; status?: { label: string; index: number; diff --git a/packages/catalog-realm/sprint-planner/components/base-task-planner.gts b/packages/catalog-realm/sprint-planner/components/base-task-planner.gts index 05ddb3bf69a..3e8e367ccd6 100644 --- a/packages/catalog-realm/sprint-planner/components/base-task-planner.gts +++ b/packages/catalog-realm/sprint-planner/components/base-task-planner.gts @@ -85,7 +85,6 @@ export type FilterType = 'status' | 'assignee'; // Type definitions for the card structure export interface TaskCard extends CardDef { - id: string; status?: { label: string; index: number; diff --git a/packages/experiments-realm/components/base-task-planner.gts b/packages/experiments-realm/components/base-task-planner.gts index d4934adb440..624d2f5f9cb 100644 --- a/packages/experiments-realm/components/base-task-planner.gts +++ b/packages/experiments-realm/components/base-task-planner.gts @@ -85,7 +85,6 @@ export type FilterType = 'status' | 'assignee'; // Type definitions for the card structure export interface TaskCard extends CardDef { - id: string; status?: { label: string; index: number; diff --git a/packages/host/app/commands/listing-install.ts b/packages/host/app/commands/listing-install.ts index 01570600edc..e51c77048b4 100644 --- a/packages/host/app/commands/listing-install.ts +++ b/packages/host/app/commands/listing-install.ts @@ -11,6 +11,7 @@ import { PlanBuilder, extractRelationshipIds, type Relationship, + type RealmResourceIdentifier, } from '@cardstack/runtime-common'; import { logger } from '@cardstack/runtime-common'; import type { CopyInstanceMeta } from '@cardstack/runtime-common/catalog'; @@ -162,11 +163,11 @@ export default class ListingInstallCommand extends HostBaseCommand< // Walk relationships by fetching linked cards and enqueueing their ids. private async expandInstances(instances: CardDef[]): Promise { - let instancesById = new Map(); - let visited = new Set(); - let queue: string[] = instances + let instancesById = new Map(); + let visited = new Set(); + let queue: RealmResourceIdentifier[] = instances .map((instance) => instance.id) - .filter((id): id is string => typeof id === 'string'); + .filter((id): id is RealmResourceIdentifier => typeof id === 'string'); // - Queue of ids to traverse; visited prevents duplicate relationship ids. // - Each loop extracts relationship ids and enqueues them, so we descend diff --git a/packages/host/app/commands/open-create-listing-modal.ts b/packages/host/app/commands/open-create-listing-modal.ts index d3d26009fd4..1db180e7db4 100644 --- a/packages/host/app/commands/open-create-listing-modal.ts +++ b/packages/host/app/commands/open-create-listing-modal.ts @@ -1,6 +1,9 @@ import { service } from '@ember/service'; -import { isFieldDef } from '@cardstack/runtime-common'; +import { + isFieldDef, + type RealmResourceIdentifier, +} from '@cardstack/runtime-common'; import { loadCardDef } from '@cardstack/runtime-common/code-ref'; import type * as BaseCommandModule from 'https://cardstack.com/base/command'; @@ -42,7 +45,7 @@ export default class OpenCreateListingModalCommand extends HostBaseCommand< this.operatorModeStateService.showCreateListingModal({ codeRef: input.codeRef, targetRealm: input.targetRealm, - openCardIds: input.openCardIds, + openCardIds: input.openCardIds as RealmResourceIdentifier[] | undefined, declarationKind, }); } diff --git a/packages/host/app/commands/show-card.ts b/packages/host/app/commands/show-card.ts index 8c938446046..e9f917ff895 100644 --- a/packages/host/app/commands/show-card.ts +++ b/packages/host/app/commands/show-card.ts @@ -78,7 +78,7 @@ export default class ShowCardCommand extends HostBaseCommand< } this.playgroundPanelService.persistSelections( internalKeyFor(cardDefRef, undefined), - input.cardId, + rri(input.cardId), (input.format as Format) || 'isolated', undefined, ); diff --git a/packages/host/app/commands/update-playground-selection.ts b/packages/host/app/commands/update-playground-selection.ts index d2149aa8006..f86f0b0202d 100644 --- a/packages/host/app/commands/update-playground-selection.ts +++ b/packages/host/app/commands/update-playground-selection.ts @@ -1,5 +1,7 @@ import { service } from '@ember/service'; +import { rri } from '@cardstack/runtime-common'; + import type { Format } from 'https://cardstack.com/base/card-api'; import type * as BaseCommandModule from 'https://cardstack.com/base/command'; @@ -27,7 +29,7 @@ export default class UpdatePlaygroundSelectionCommand extends HostBaseCommand< ): Promise { this.playgroundPanelService.persistSelections( input.moduleId, - input.cardId, + rri(input.cardId), input.format as Format, input.fieldIndex, ); diff --git a/packages/host/app/components/matrix/room.gts b/packages/host/app/components/matrix/room.gts index 2c807509491..1ebb2ad5972 100644 --- a/packages/host/app/components/matrix/room.gts +++ b/packages/host/app/components/matrix/room.gts @@ -36,7 +36,10 @@ import { } from '@cardstack/boxel-ui/components'; import { and, eq, not } from '@cardstack/boxel-ui/helpers'; -import type { ResolvedCodeRef } from '@cardstack/runtime-common'; +import type { + RealmResourceIdentifier, + ResolvedCodeRef, +} from '@cardstack/runtime-common'; import { baseFileRef, formattedError, @@ -1608,7 +1611,7 @@ export default class Room extends Component { let openCardIds = new Set([ ...(this.operatorModeStateService.getOpenCardIds() || []), ...this.autoAttachedCardIds, - ]); + ]) as Set; let context = await this.operatorModeStateService.getSummaryForAIBot(openCardIds); try { diff --git a/packages/host/app/components/operator-mode/code-submode/module-inspector.gts b/packages/host/app/components/operator-mode/code-submode/module-inspector.gts index 8855055a06b..7404b722557 100644 --- a/packages/host/app/components/operator-mode/code-submode/module-inspector.gts +++ b/packages/host/app/components/operator-mode/code-submode/module-inspector.gts @@ -411,7 +411,7 @@ export default class ModuleInspector extends Component this.selectedDeclarationAsCodeRef, undefined, ); - const cardId = id.replace(/\.json$/, ''); + const cardId = rri(id.replace(/\.json$/, '')); const selections = window.localStorage.getItem(PlaygroundSelections); let existingFormat: Format = isField ? 'embedded' : 'isolated'; diff --git a/packages/host/app/components/operator-mode/code-submode/playground/playground-panel.gts b/packages/host/app/components/operator-mode/code-submode/playground/playground-panel.gts index 9ac656576da..e2e784fd9aa 100644 --- a/packages/host/app/components/operator-mode/code-submode/playground/playground-panel.gts +++ b/packages/host/app/components/operator-mode/code-submode/playground/playground-panel.gts @@ -703,7 +703,7 @@ export default class PlaygroundPanel extends Component { this.playgroundPanelService.persistSelections( this.moduleId, - trimJsonExtension(selectedCardId), + rri(trimJsonExtension(selectedCardId)), selectedFormat, index, // `undefined` means we are previewing a card instances. fields MUST have a corresponding index // based on their position on their spec's containedExamples field. otherwise, it means that we are previewing diff --git a/packages/host/app/components/operator-mode/workspace-chooser/workspace.gts b/packages/host/app/components/operator-mode/workspace-chooser/workspace.gts index e5b7c9e5ea4..ac12ed06f9d 100644 --- a/packages/host/app/components/operator-mode/workspace-chooser/workspace.gts +++ b/packages/host/app/components/operator-mode/workspace-chooser/workspace.gts @@ -34,7 +34,6 @@ import { hasExecutableExtension, RealmPaths, ri, - rri, SupportedMimeType, } from '@cardstack/runtime-common'; @@ -995,7 +994,7 @@ export default class Workspace extends Component { this.operatorModeStateService.realmURL === this.args.realmURL || this.operatorModeStateService .getOpenCardIds() - .some((cardId) => realmPath.inRealm(rri(cardId))) || + .some((cardId) => realmPath.inRealm(cardId)) || this.operatorModeStateService.codePathString?.startsWith( this.args.realmURL, ); diff --git a/packages/host/app/lib/gc-card-store.ts b/packages/host/app/lib/gc-card-store.ts index 750c97bff9a..5176202afb1 100644 --- a/packages/host/app/lib/gc-card-store.ts +++ b/packages/host/app/lib/gc-card-store.ts @@ -11,6 +11,7 @@ import { localId as localIdSymbol, loadCardDocument, loadFileMetaDocument, + rri, trackRuntimeFileDependency, trackRuntimeInstanceDependency, logger, @@ -794,7 +795,7 @@ export default class CardStoreWithGarbageCollection implements CardStore { localId = remoteId.split('/').pop()!; item = bucket.get(localId) ?? silentBucket.get(localId); if (item && type === 'instance' && isCardOrFileInstance(item)) { - item.id = remoteId; + item.id = rri(remoteId); } } } diff --git a/packages/host/app/resources/search.ts b/packages/host/app/resources/search.ts index 42990168d01..3329a51b028 100644 --- a/packages/host/app/resources/search.ts +++ b/packages/host/app/resources/search.ts @@ -25,7 +25,6 @@ import { buildQueryParamValue, parseSearchURL, ri, - rri, RealmPaths, runtimeDependencyContextWithSource, } from '@cardstack/runtime-common'; @@ -304,7 +303,7 @@ export class SearchResource< .map((realm) => { let realmPath = new RealmPaths(ri(realm)); let cards = this.instances.filter((card) => - realmPath.inRealm(rri(card.id)), + realmPath.inRealm(card.id), ); return { realm, cards }; }) diff --git a/packages/host/app/services/operator-mode-state-service.ts b/packages/host/app/services/operator-mode-state-service.ts index b8834ce2266..43aa909248f 100644 --- a/packages/host/app/services/operator-mode-state-service.ts +++ b/packages/host/app/services/operator-mode-state-service.ts @@ -80,7 +80,7 @@ import type IndexController from '../controllers'; export interface CreateListingModalPayload { codeRef: CodeRef; targetRealm: string; - openCardIds?: string[]; + openCardIds?: RealmResourceIdentifier[]; declarationKind: 'card' | 'field'; } @@ -687,15 +687,15 @@ export default class OperatorModeStateService extends Service { return undefined; } - getOpenCardIds(): string[] { + getOpenCardIds(): RealmResourceIdentifier[] { if (this._state.submode === Submodes.Code) { - let openCardsInCodeMode = []; + let openCardsInCodeMode: RealmResourceIdentifier[] = []; if (this.playgroundPanelSelection) { openCardsInCodeMode.push(this.playgroundPanelSelection.cardId); } // Alternatively we may simply be looking at a card in code mode if (this.isViewingCardInCodeMode) { - let cardId = this.codePathString!.replace(/\.json$/, ''); + let cardId = rri(this.codePathString!.replace(/\.json$/, '')); if (!openCardsInCodeMode.includes(cardId)) { openCardsInCodeMode.push(cardId); } @@ -706,7 +706,7 @@ export default class OperatorModeStateService extends Service { return this.topMostStackItems() .filter((stackItem: StackItem) => stackItem) .map((stackItem: StackItem) => stackItem.id) - .filter(Boolean) as string[]; + .filter(Boolean) as RealmResourceIdentifier[]; } } @@ -820,8 +820,10 @@ export default class OperatorModeStateService extends Service { return undefined; } - get codePathString() { - return this._state.codePath?.toString(); + get codePathString(): RealmResourceIdentifier | undefined { + return this._state.codePath?.toString() as + | RealmResourceIdentifier + | undefined; } onFileSelected = async (entryPath: LocalPath) => { @@ -1460,7 +1462,9 @@ export default class OperatorModeStateService extends Service { } async getSummaryForAIBot( - openCardIdsSet: Set = new Set([...this.getOpenCardIds()]), + openCardIdsSet: Set = new Set([ + ...this.getOpenCardIds(), + ]), ): Promise { let codeMode: BoxelContext['codeMode'] = undefined; if (this._state.workspaceChooserOpened) { @@ -1506,7 +1510,7 @@ export default class OperatorModeStateService extends Service { if (this.isViewingCardInCodeMode) { codeMode.moduleInspectorPanel = 'preview'; codeMode.previewPanelSelection = { - cardId: this.codePathString!.replace(/\.json$/, ''), + cardId: rri(this.codePathString!.replace(/\.json$/, '')), format: this.currentViewingFormat ?? 'isolated', }; } else { @@ -1554,7 +1558,9 @@ export default class OperatorModeStateService extends Service { return result; } - private makeRemoteIdsList(ids: (string | undefined)[]) { + private makeRemoteIdsList( + ids: (RealmResourceIdentifier | undefined)[], + ): RealmResourceIdentifier[] { return ids .map((id) => { if (!id) { @@ -1574,7 +1580,7 @@ export default class OperatorModeStateService extends Service { } return id; }) - .filter(Boolean) as string[]; + .filter(Boolean) as RealmResourceIdentifier[]; } } diff --git a/packages/host/app/services/playground-panel-service.ts b/packages/host/app/services/playground-panel-service.ts index 822e910accc..f9608ffe978 100644 --- a/packages/host/app/services/playground-panel-service.ts +++ b/packages/host/app/services/playground-panel-service.ts @@ -8,7 +8,12 @@ import { task } from 'ember-concurrency'; import window from 'ember-window-mock'; import { TrackedObject } from 'tracked-built-ins'; -import { isCardInstance, localId, isLocalId } from '@cardstack/runtime-common'; +import { + isCardInstance, + localId, + isLocalId, + type RealmResourceIdentifier, +} from '@cardstack/runtime-common'; import { PlaygroundSelections } from '@cardstack/host/utils/local-storage-keys'; @@ -26,7 +31,7 @@ import type ResetService from './reset'; import type StoreService from './store'; export interface PlaygroundSelection { - cardId: string; // for fields, this is their corresponding spec card's id, since fields do not have a card id + cardId: RealmResourceIdentifier; // for fields, this is their corresponding spec card's id, since fields do not have a card id format: Format; // default is 'isolated' for cards, 'embedded' for fields fieldIndex?: number; /* fieldIndex `undefined` means we are previewing a card instances. fields MUST have a corresponding index @@ -73,7 +78,7 @@ export default class PlaygroundPanelService extends Service { persistSelections = ( moduleId: string, - cardId: string, + cardId: RealmResourceIdentifier, format: Format, fieldIndex: number | undefined, ) => { diff --git a/packages/host/tests/acceptance/code-submode-test.ts b/packages/host/tests/acceptance/code-submode-test.ts index c4e2532b416..7c0f1013159 100644 --- a/packages/host/tests/acceptance/code-submode-test.ts +++ b/packages/host/tests/acceptance/code-submode-test.ts @@ -1983,7 +1983,7 @@ module('Acceptance | code submode tests', function (_hooks) { setPlaygroundSelections({ [`${testRealmURL}person/Person`]: { - cardId: `${testRealmURL}Person/with-friends`, + cardId: rri(`${testRealmURL}Person/with-friends`), format: 'isolated', }, }); diff --git a/packages/host/tests/acceptance/code-submode/card-playground-test.gts b/packages/host/tests/acceptance/code-submode/card-playground-test.gts index bc040823b4a..9a4e83b3cc9 100644 --- a/packages/host/tests/acceptance/code-submode/card-playground-test.gts +++ b/packages/host/tests/acceptance/code-submode/card-playground-test.gts @@ -14,6 +14,7 @@ import { module, test } from 'qunit'; import { baseRealm, hasExecutableExtension, + rri, trimJsonExtension, type Realm, cardDefFormats, @@ -664,7 +665,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { removePlaygroundSelections(); setPlaygroundSelections({ [`${testRealmURL}head-preview/HeadPreview`]: { - cardId: `${testRealmURL}HeadPreview/example`, + cardId: rri(`${testRealmURL}HeadPreview/example`), format: 'head', }, }); @@ -1357,11 +1358,11 @@ module('Acceptance | code-submode | card playground', function (_hooks) { const authorModuleId = `${testRealmURL}author/Author`; const categoryModuleId = `${testRealmURL}blog-post/Category`; const blogPostModuleId = `${testRealmURL}blog-post/BlogPost`; - const authorId = `${testRealmURL}Author/jane-doe`; - const categoryId1 = `${testRealmURL}Category/city-design`; - const categoryId2 = `${testRealmURL}Category/future-tech`; - const blogPostId1 = `${testRealmURL}BlogPost/mad-hatter`; - const blogPostId2 = `${testRealmURL}BlogPost/remote-work`; + const authorId = rri(`${testRealmURL}Author/jane-doe`); + const categoryId1 = rri(`${testRealmURL}Category/city-design`); + const categoryId2 = rri(`${testRealmURL}Category/future-tech`); + const blogPostId1 = rri(`${testRealmURL}BlogPost/mad-hatter`); + const blogPostId2 = rri(`${testRealmURL}BlogPost/remote-work`); setPlaygroundSelections({ [`${authorModuleId}`]: { @@ -1989,7 +1990,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { ); setPlaygroundSelections({ [`${testRealmURL}boom-pet/BoomPet`]: { - cardId: `${testRealmURL}BoomPet/cassidy`, + cardId: rri(`${testRealmURL}BoomPet/cassidy`), format: 'isolated', }, }); @@ -2180,7 +2181,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { }); test('it can render stale card in edit format when the server is in an error state for the card', async function (assert) { - const cardId = `${testRealmURL}Person/delilah`; + const cardId = rri(`${testRealmURL}Person/delilah`); setRecentFiles([[testRealmURL, 'Person/delilah.json']]); setPlaygroundSelections({ [`${testRealmURL}person/Person`]: { @@ -2260,7 +2261,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { }), ); - const cardId = `${testRealmURL}Person/delilah`; + const cardId = rri(`${testRealmURL}Person/delilah`); setRecentFiles([[testRealmURL, 'Person/delilah.json']]); setPlaygroundSelections({ [`${testRealmURL}person/Person`]: { @@ -2318,7 +2319,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { test('it renders error message for missing file', async function (assert) { setPlaygroundSelections({ [`${testRealmURL}person/Person`]: { - cardId: `${testRealmURL}Person/chef-mike`, + cardId: rri(`${testRealmURL}Person/chef-mike`), format: 'isolated', }, }); @@ -2360,7 +2361,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { ); setPlaygroundSelections({ [`${testRealmURL}person/Person`]: { - cardId: `${testRealmURL}Person/chef-mike`, + cardId: rri(`${testRealmURL}Person/chef-mike`), format: 'isolated', }, }); diff --git a/packages/host/tests/acceptance/code-submode/field-playground-test.gts b/packages/host/tests/acceptance/code-submode/field-playground-test.gts index ffae1d34db6..3584d21b982 100644 --- a/packages/host/tests/acceptance/code-submode/field-playground-test.gts +++ b/packages/host/tests/acceptance/code-submode/field-playground-test.gts @@ -4,6 +4,7 @@ import { module, test } from 'qunit'; import { fieldDefFormats, + rri, specRef, type Realm, } from '@cardstack/runtime-common'; @@ -661,7 +662,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { let selection = getPlaygroundSelections()?.[`${testRealmURL}blog-post/Comment`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/comment-main`, + cardId: rri(`${testRealmURL}Spec/comment-main`), format: 'embedded', fieldIndex: 0, url: `${testRealmURL}blog-post.gts`, @@ -700,7 +701,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { selection = getPlaygroundSelections()?.[`${testRealmURL}blog-post/Comment`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/comment-alt`, + cardId: rri(`${testRealmURL}Spec/comment-alt`), format: 'embedded', fieldIndex: 0, url: `${testRealmURL}blog-post.gts`, @@ -720,7 +721,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { let selection = getPlaygroundSelections()?.[`${testRealmURL}blog-post/Comment`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/comment-main`, + cardId: rri(`${testRealmURL}Spec/comment-main`), format: 'embedded', fieldIndex: 0, url: `${testRealmURL}blog-post.gts`, @@ -744,7 +745,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { selection = getPlaygroundSelections()?.[`${testRealmURL}blog-post/Comment`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/comment-main`, + cardId: rri(`${testRealmURL}Spec/comment-main`), format: 'embedded', fieldIndex: 1, url: `${testRealmURL}blog-post.gts`, @@ -754,7 +755,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { test('preview the next available example if the previously selected one has been deleted', async function (assert) { setPlaygroundSelections({ [`${testRealmURL}blog-post/Comment`]: { - cardId: `${testRealmURL}Spec/comment-main`, + cardId: rri(`${testRealmURL}Spec/comment-main`), format: 'embedded', fieldIndex: 1, }, @@ -855,7 +856,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { let selection = getPlaygroundSelections()?.[`${testRealmURL}blog-post/Comment`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/comment-main`, + cardId: rri(`${testRealmURL}Spec/comment-main`), format: 'embedded', fieldIndex: 0, url: `${testRealmURL}blog-post.gts`, @@ -870,7 +871,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { selection = getPlaygroundSelections()?.[`${testRealmURL}blog-post/Comment`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/comment-main`, + cardId: rri(`${testRealmURL}Spec/comment-main`), format: 'edit', fieldIndex: 2, url: `${testRealmURL}blog-post.gts`, @@ -937,7 +938,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { selection = getPlaygroundSelections()?.[`${testRealmURL}author/FullNameField`]; assert.deepEqual(selection, { - cardId: `${testRealmURL}Spec/full-name`, + cardId: rri(`${testRealmURL}Spec/full-name`), format: 'edit', fieldIndex: 0, url: `${testRealmURL}author.gts`, @@ -967,8 +968,8 @@ module('Acceptance | code-submode | field playground', function (_hooks) { }); test('does not persist the wrong card for field', async function (assert) { - const cardId = `${testRealmURL}Pet/mango`; - const specId = `${testRealmURL}Spec/toy`; + const cardId = rri(`${testRealmURL}Pet/mango`); + const specId = rri(`${testRealmURL}Spec/toy`); let selections: Record = { [`${testRealmURL}pet/PetCard`]: { cardId, @@ -1284,7 +1285,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { let selection = getPlaygroundSelections()?.[`${additionalRealmURL}pet/ToyField`]; assert.deepEqual(selection, { - cardId: `${additionalRealmURL}Spec/toy`, + cardId: rri(`${additionalRealmURL}Spec/toy`), format: 'atom', fieldIndex: 0, url: `${additionalRealmURL}pet.gts`, @@ -1299,7 +1300,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { selection = getPlaygroundSelections()?.[`${additionalRealmURL}pet/ToyField`]; assert.deepEqual(selection, { - cardId: `${additionalRealmURL}Spec/toy`, + cardId: rri(`${additionalRealmURL}Spec/toy`), format: 'edit', fieldIndex: 1, url: `${additionalRealmURL}pet.gts`, @@ -1370,7 +1371,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { `${additionalRealmURL}author/FullNameField` ]; assert.deepEqual(selection, { - cardId: `${additionalRealmURL}Spec/full-name`, + cardId: rri(`${additionalRealmURL}Spec/full-name`), format: 'edit', fieldIndex: 0, url: `${additionalRealmURL}author.gts`, diff --git a/packages/host/tests/acceptance/code-submode/spec-test.gts b/packages/host/tests/acceptance/code-submode/spec-test.gts index c52f450862d..d1e8f0ae9db 100644 --- a/packages/host/tests/acceptance/code-submode/spec-test.gts +++ b/packages/host/tests/acceptance/code-submode/spec-test.gts @@ -10,7 +10,7 @@ import { import { getService } from '@universal-ember/test-support'; import { module, skip, test } from 'qunit'; -import { baseRealm, Deferred } from '@cardstack/runtime-common'; +import { baseRealm, Deferred, rri } from '@cardstack/runtime-common'; import { setupLocalIndexing, @@ -1143,7 +1143,7 @@ module('Acceptance | Spec preview', function (hooks) { await click(`[data-test-option-id="${testRealmURL}pet-entry-2"]`); // Wait for linked examples to appear - const petId = `${testRealmURL}Pet/mango`; + const petId = rri(`${testRealmURL}Pet/mango`); assert.dom(`[data-test-card="${petId}"]`).exists(); // Click on the first linked example @@ -1205,8 +1205,8 @@ module('Acceptance | Spec preview', function (hooks) { }); test('updatePlaygroundSelections preserves existing format when selecting different examples card', async function (assert) { - const firstPetId = `${testRealmURL}Pet/mango`; - const secondPetId = `${testRealmURL}Pet/pudding`; + const firstPetId = rri(`${testRealmURL}Pet/mango`); + const secondPetId = rri(`${testRealmURL}Pet/pudding`); await visitOperatorMode({ submode: 'code', codePath: `${testRealmURL}pet.gts`, diff --git a/packages/host/tests/acceptance/operator-mode-acceptance-test.gts b/packages/host/tests/acceptance/operator-mode-acceptance-test.gts index 05f852690f7..fcf5e3a7249 100644 --- a/packages/host/tests/acceptance/operator-mode-acceptance-test.gts +++ b/packages/host/tests/acceptance/operator-mode-acceptance-test.gts @@ -1510,7 +1510,7 @@ module('Acceptance | operator mode tests', function (hooks) { ]); setPlaygroundSelections({ [`${testRealmURL}Pet/mango.json`]: { - cardId: `${testRealmURL}Pet/mango.json`, + cardId: rri(`${testRealmURL}Pet/mango.json`), format: 'edit', }, }); diff --git a/packages/host/tests/integration/commands/open-create-listing-modal-test.gts b/packages/host/tests/integration/commands/open-create-listing-modal-test.gts index a8f5a525118..5e3feadb8fa 100644 --- a/packages/host/tests/integration/commands/open-create-listing-modal-test.gts +++ b/packages/host/tests/integration/commands/open-create-listing-modal-test.gts @@ -1,6 +1,8 @@ import { getService } from '@universal-ember/test-support'; import { module, test } from 'qunit'; +import { rri } from '@cardstack/runtime-common'; + import OpenCreateListingModalCommand from '@cardstack/host/commands/open-create-listing-modal'; import { @@ -76,7 +78,7 @@ module('Integration | commands | open-create-listing-modal', function (hooks) { name: 'Pet', }, targetRealm: testRealmURL, - openCardIds: [`${testRealmURL}Pet/mango`], + openCardIds: [rri(`${testRealmURL}Pet/mango`)], } as never); assert.deepEqual(operatorModeStateService.createListingModalPayload, { @@ -85,7 +87,7 @@ module('Integration | commands | open-create-listing-modal', function (hooks) { name: 'Pet', }, targetRealm: testRealmURL, - openCardIds: [`${testRealmURL}Pet/mango`], + openCardIds: [rri(`${testRealmURL}Pet/mango`)], declarationKind: 'card', }); }); @@ -161,7 +163,7 @@ module('Integration | commands | open-create-listing-modal', function (hooks) { name: 'Pet', }, targetRealm: testRealmURL, - openCardIds: [`${testRealmURL}Pet/mango`], + openCardIds: [rri(`${testRealmURL}Pet/mango`)], } as never); assert.ok( diff --git a/packages/host/tests/integration/components/ai-assistant-panel/skills-test.gts b/packages/host/tests/integration/components/ai-assistant-panel/skills-test.gts index 03560b1d1d7..fd8a527675a 100644 --- a/packages/host/tests/integration/components/ai-assistant-panel/skills-test.gts +++ b/packages/host/tests/integration/components/ai-assistant-panel/skills-test.gts @@ -11,6 +11,7 @@ import { SEARCH_MARKER, SEPARATOR_MARKER, baseRealm, + rri, skillCardRef, } from '@cardstack/runtime-common'; import type { Loader } from '@cardstack/runtime-common/loader'; @@ -430,7 +431,7 @@ module('Integration | ai-assistant-panel | skills', function (hooks) { test('skill pill menu opens the skill card', async function (assert) { await renderAiAssistantPanel(); - let skillId = `${testRealmURL}Skill/example`; + let skillId = rri(`${testRealmURL}Skill/example`); await addSkillToAiAssistant(skillId); assert.false( operatorModeStateService.getOpenCardIds().includes(skillId), diff --git a/packages/host/tests/integration/components/card-basics-test.gts b/packages/host/tests/integration/components/card-basics-test.gts index 77b2e3156ed..128855122a9 100644 --- a/packages/host/tests/integration/components/card-basics-test.gts +++ b/packages/host/tests/integration/components/card-basics-test.gts @@ -32,6 +32,7 @@ import { PermissionsContextName, fields, cardTypeDisplayName, + rri, type CodeRef, } from '@cardstack/runtime-common'; @@ -1313,10 +1314,10 @@ module('Integration | card-basics', function (hooks) { } let mango = new Person(); - mango.id = `${testRealmURL}Person/mango`; + mango.id = rri(`${testRealmURL}Person/mango`); assert.strictEqual(mango.id, `${testRealmURL}Person/mango`); - let vanGogh = new Person({ id: `${testRealmURL}Person/vanGogh` }); + let vanGogh = new Person({ id: rri(`${testRealmURL}Person/vanGogh`) }); assert.strictEqual(vanGogh.id, `${testRealmURL}Person/vanGogh`); }); @@ -1344,7 +1345,7 @@ module('Integration | card-basics', function (hooks) { await saveCard(card, `${testRealmURL}Person/mango`, loader); try { - card.id = 'boom'; + card.id = rri('boom'); throw new Error(`expected exception not thrown`); } catch (err: any) { assert.ok( diff --git a/packages/host/tests/integration/components/create-listing-modal-test.gts b/packages/host/tests/integration/components/create-listing-modal-test.gts index b6458783b69..d7234e07161 100644 --- a/packages/host/tests/integration/components/create-listing-modal-test.gts +++ b/packages/host/tests/integration/components/create-listing-modal-test.gts @@ -3,6 +3,8 @@ import GlimmerComponent from '@glimmer/component'; import { module, test } from 'qunit'; +import { rri } from '@cardstack/runtime-common'; + import OperatorMode from '@cardstack/host/components/operator-mode/container'; import { testRealmURL, testRRI } from '../../helpers'; @@ -119,7 +121,7 @@ module('Integration | components | create-listing-modal', function (hooks) { name: 'Pet', }, targetRealm: testRealmURL, - openCardIds: [`${testRealmURL}Pet/mango`], + openCardIds: [rri(`${testRealmURL}Pet/mango`)], declarationKind: 'card', }); @@ -155,7 +157,7 @@ module('Integration | components | create-listing-modal', function (hooks) { name: 'Pet', }, targetRealm: testRealmURL, - openCardIds: [`${testRealmURL}Pet/mango`], + openCardIds: [rri(`${testRealmURL}Pet/mango`)], declarationKind: 'card', }); diff --git a/packages/host/tests/integration/resources/search-test.ts b/packages/host/tests/integration/resources/search-test.ts index 10030c12712..e38a3a780b4 100644 --- a/packages/host/tests/integration/resources/search-test.ts +++ b/packages/host/tests/integration/resources/search-test.ts @@ -11,6 +11,7 @@ import { baseRRI, Deferred, isFileDefInstance, + rri, type Realm, type LooseSingleCardDocument, } from '@cardstack/runtime-common'; @@ -626,11 +627,11 @@ module(`Integration | search resource`, function (hooks) { assert.ok(search.instances.length >= 2, 'returns file-meta instances'); let ids = search.instances.map((i) => i.id); assert.ok( - ids.includes(`${testRealmURL}files/hello.txt`), + ids.includes(rri(`${testRealmURL}files/hello.txt`)), 'hello.txt is in results', ); assert.ok( - ids.includes(`${testRealmURL}files/notes.txt`), + ids.includes(rri(`${testRealmURL}files/notes.txt`)), 'notes.txt is in results', ); for (let instance of search.instances) { @@ -672,7 +673,7 @@ module(`Integration | search resource`, function (hooks) { let ids = search.instances.map((i) => i.id); assert.ok( - ids.includes(`${testRealmURL}files/new-file.txt`), + ids.includes(rri(`${testRealmURL}files/new-file.txt`)), 'new file appears in live search results', ); assert.ok( diff --git a/packages/host/tests/unit/index-query-engine-test.ts b/packages/host/tests/unit/index-query-engine-test.ts index 60f5300ce23..5937d02d9d5 100644 --- a/packages/host/tests/unit/index-query-engine-test.ts +++ b/packages/host/tests/unit/index-query-engine-test.ts @@ -12,6 +12,7 @@ import { internalKeyFor, identifyCard, getFieldDefinitions, + rri, type RealmResourceIdentifier, type ResolvedCodeRef, type Definition, @@ -194,7 +195,7 @@ module('Unit | query', function (hooks) { numberFieldEntry, }; for (let [name, card] of Object.entries(testCards)) { - card.id = `${testRealmURL}${name}`; + card.id = rri(`${testRealmURL}${name}`); setCardAsSavedForTest(card); } diff --git a/packages/runtime-common/resource-types.ts b/packages/runtime-common/resource-types.ts index 1073daa63fa..feec9ae443e 100644 --- a/packages/runtime-common/resource-types.ts +++ b/packages/runtime-common/resource-types.ts @@ -164,17 +164,17 @@ export { export function extractRelationshipIds( relationship: Relationship, baseUrl: string | URL, -): string[] { - let ids: string[] = []; +): RealmResourceIdentifier[] { + let ids: RealmResourceIdentifier[] = []; let data = relationship.data; if (!data || typeof data !== 'object') { return ids; } - let resolveId = (id: string) => { + let resolveId = (id: string): RealmResourceIdentifier => { try { - return resolveCardReference(id, baseUrl); + return resolveCardReference(id, baseUrl) as RealmResourceIdentifier; } catch { - return id; + return id as RealmResourceIdentifier; } }; if (Array.isArray(data)) {