diff --git a/docs/API.md b/docs/API.md index 8dca2d4..bd6429f 100644 --- a/docs/API.md +++ b/docs/API.md @@ -177,37 +177,37 @@ function IsArchiveDeviceExample() { | Function | Type | | ---------- | ---------- | -| `getManyDocumentsQueryKey` | `({ projectId, docType, opts, }: { projectId: string; docType: D; opts?: Parameters[D]["getMany"]>[0] or undefined; }) => readonly [...]` | +| `getManyDocumentsQueryKey` | `({ projectId, docType, includeDeleted, lang, }: { projectId: string; docType: D; includeDeleted?: boolean or undefined; lang?: string or undefined; }) => readonly ["@comapeo/core-react", "projects", string, D, { ...; }]` | ### getDocumentByDocIdQueryKey | Function | Type | | ---------- | ---------- | -| `getDocumentByDocIdQueryKey` | `({ projectId, docType, docId, opts, }: { projectId: string; docType: D; docId: Parameters[D]["getByDocId"]>[0]; opts?: Parameters[D]["getByDocId"]>[1] or undefined; }) => readonly [...]` | +| `getDocumentByDocIdQueryKey` | `({ projectId, docType, docId, lang, }: { projectId: string; docType: D; docId: string; lang?: string or undefined; }) => readonly ["@comapeo/core-react", "projects", string, D, string, { readonly lang: string or undefined; }]` | ### getDocumentByVersionIdQueryKey | Function | Type | | ---------- | ---------- | -| `getDocumentByVersionIdQueryKey` | `({ projectId, docType, versionId, opts, }: { projectId: string; docType: D; versionId: Parameters[D]["getByVersionId"]>[0]; opts?: Parameters[D]["getByVersionId"]>[1] or undefined; }) => readonly [...]` | +| `getDocumentByVersionIdQueryKey` | `({ projectId, docType, versionId, lang, }: { projectId: string; docType: D; versionId: string; lang?: string or undefined; }) => readonly ["@comapeo/core-react", "projects", string, D, string, { readonly lang: string or undefined; }]` | ### documentsQueryOptions | Function | Type | | ---------- | ---------- | -| `documentsQueryOptions` | `({ projectApi, projectId, docType, opts, }: { projectApi: ClientApi; projectId: string; docType: D; opts?: Parameters[D]["getMany"]>[0] or undefined; }) => OmitKeyof<...> and ... 1 more ... and { ...; }` | +| `documentsQueryOptions` | `({ projectApi, projectId, docType, includeDeleted, lang, }: { projectApi: ClientApi; projectId: string; docType: D; includeDeleted?: boolean or undefined; lang?: string or undefined; }) => OmitKeyof<...> and ... 1 more ... and { ...; }` | ### documentByDocumentIdQueryOptions | Function | Type | | ---------- | ---------- | -| `documentByDocumentIdQueryOptions` | `({ projectApi, projectId, docType, docId, opts, }: { projectApi: ClientApi; projectId: string; docType: D; docId: Parameters[D]["getByDocId"]>[0]; opts?: Omit<...> or undefined; }) => OmitKeyof<...> and ... 1 more ... and { ...; }` | +| `documentByDocumentIdQueryOptions` | `({ projectApi, projectId, docType, docId, lang, }: { projectApi: ClientApi; projectId: string; docType: D; docId: string; lang?: string or undefined; }) => OmitKeyof({ projectApi, projectId, docType, versionId, opts, }: { projectApi: ClientApi; projectId: string; docType: D; versionId: Parameters[D]["getByVersionId"]>[0]; opts?: Parameters<...>[1] or undefined; }) => OmitKeyof<...> and ... 1 more ... and { ...; }` | +| `documentByVersionIdQueryOptions` | `({ projectApi, projectId, docType, versionId, lang, }: { projectApi: ClientApi; projectId: string; docType: D; versionId: string; lang?: string or undefined; }) => OmitKeyof readonly ["@comapeo/core-react", "projects", string, "icons", string, BitmapOpts or SvgOpts]` | +| `getIconUrlQueryKey` | `({ projectId, iconId, ...mimeBasedOpts }: { projectId: string; iconId: string; } and (BitmapOpts or SvgOpts)) => readonly ["@comapeo/core-react", "projects", string, "icons", string, { mimeType: "image/png"; pixelDensity: 2 or ... 1 more ... or 1; size: ValidSizes; } or { ...; }]` | ### getDocumentCreatedByQueryKey @@ -303,7 +303,7 @@ function IsArchiveDeviceExample() { | Function | Type | | ---------- | ---------- | -| `iconUrlQueryOptions` | `({ projectApi, projectId, iconId, opts, }: { projectApi: ClientApi; projectId: string; iconId: string; opts: BitmapOpts or SvgOpts; }) => OmitKeyof, "queryFn"> and { ...; } and { ...; }` | +| `iconUrlQueryOptions` | `({ projectApi, projectId, iconId, ...mimeBasedOpts }: { projectApi: ClientApi; projectId: string; iconId: string; } and (BitmapOpts or SvgOpts)) => OmitKeyof, "queryFn"> and { ...; } and { ...; }` | ### documentCreatedByQueryOptions @@ -441,13 +441,15 @@ _TODO: Explain bitmap opts vs svg opts_ | Function | Type | | ---------- | ---------- | -| `useIconUrl` | `({ projectId, iconId, opts, }: { projectId: string; iconId: string; opts: BitmapOpts or SvgOpts; }) => { data: string; error: Error or null; isRefetching: boolean; }` | +| `useIconUrl` | `({ projectId, iconId, ...mimeBasedOpts }: { projectId: string; iconId: string; } and (BitmapOpts or SvgOpts)) => { data: string; error: Error or null; isRefetching: boolean; }` | Parameters: * `opts.projectId`: Project public ID * `opts.iconId`: Icon ID of interest -* `opts.opts`: Parameters related to the mime type of the icon of interest +* `opts.mimeType`: MIME type of desired resource +* `opts.pixelDensity`: Pixel density resource (only applicable when `mimeType` is `'image/png'`) +* `opts.size`: Size of desired resource Examples: @@ -457,11 +459,9 @@ function PngExample() { const { data } = useIconUrl({ projectId: '...', iconId: '...', - opts: { - mimeType: 'image/png', - pixelDensity: 1, - size: 'medium' - } + mimeType: 'image/png', + pixelDensity: 1, + size: 'medium' }) } ``` @@ -471,10 +471,8 @@ function SvgExample() { const { data } = useIconUrl({ projectId: '...', iconId: '...', - opts: { - mimeType: 'image/svg', - size: 'medium' - } + mimeType: 'image/svg', + size: 'medium' }) } ``` @@ -575,14 +573,14 @@ Triggers the closest error boundary if the document cannot be found | Function | Type | | ---------- | ---------- | -| `useSingleDocByDocId` | `({ projectId, docType, docId, opts, }: { projectId: string; docType: D; docId: string; opts?: Omit<{ mustBeFound?: boolean or undefined; lang?: string or undefined; } or undefined, "mustBeFound"> or undefined; }) => { ...; }` | +| `useSingleDocByDocId` | `({ projectId, docType, docId, lang, }: { projectId: string; docType: D; docId: string; lang?: string or undefined; }) => { data: ({ schemaName: "track"; locations: Position[]; observationRefs: { docId: string; versionId: string; }[]; ... 7 more ...; deleted: boolean; } and { ...; }) or ({ ...; } ...` | Parameters: * `opts.projectId`: Project public ID * `opts.docType`: Document type of interest * `opts.docId`: Document ID -* `opts.opts.lang`: Language to translate the document into +* `opts.lang`: Language to translate the document into Examples: @@ -608,14 +606,14 @@ Triggers the closest error boundary if the document cannot be found. | Function | Type | | ---------- | ---------- | -| `useSingleDocByVersionId` | `({ projectId, docType, versionId, opts, }: { projectId: string; docType: D; versionId: string; opts?: { lang?: string or undefined; } or undefined; }) => { data: { schemaName: "track"; locations: Position[]; ... 8 more ...; deleted: boolean; } or { ...; } or { ...; } or { ...; } or { ...; }; error:...` | +| `useSingleDocByVersionId` | `({ projectId, docType, versionId, lang, }: { projectId: string; docType: D; versionId: string; lang?: string or undefined; }) => { data: { schemaName: "track"; locations: Position[]; observationRefs: { ...; }[]; ... 7 more ...; deleted: boolean; } or { ...; } or { ...; } or { ...; } or { ...; }; e...` | Parameters: * `opts.projectId`: Project public ID * `opts.docType`: Document type of interest * `opts.versionId`: Document's version ID -* `opts.opts.lang`: Language to translate the document into +* `opts.lang`: Language to translate the document into * @@ -641,14 +639,14 @@ Retrieve all documents of a specific `docType`. | Function | Type | | ---------- | ---------- | -| `useManyDocs` | `({ projectId, docType, opts, }: { projectId: string; docType: D; opts?: { includeDeleted?: boolean or undefined; lang?: string or undefined; } or undefined; }) => { data: ({ schemaName: "track"; locations: Position[]; ... 8 more ...; deleted: boolean; } and { ...; })[] or ({ ...; } and { ...; })[] or ...` | +| `useManyDocs` | `({ projectId, docType, includeDeleted, lang, }: { projectId: string; docType: D; includeDeleted?: boolean or undefined; lang?: string or undefined; }) => { data: ({ schemaName: "track"; locations: Position[]; ... 8 more ...; deleted: boolean; } and { ...; })[] or ({ ...; } and { ...; })[] or ({ ...; ...` | Parameters: * `opts.projectId`: Project public ID * `opts.docType`: Document type of interest -* `opts.opts.includeDeleted`: Include documents that have been marked as deleted -* `opts.opts.lang`: Language to translate the documents into +* `opts.includeDeleted`: Include documents that have been marked as deleted +* `opts.lang`: Language to translate the documents into Examples: diff --git a/src/contexts/ClientApi.ts b/src/contexts/ClientApi.ts index e864254..77736aa 100644 --- a/src/contexts/ClientApi.ts +++ b/src/contexts/ClientApi.ts @@ -6,7 +6,7 @@ export const ClientApiContext = createContext(null) /** * Create a context provider that holds a CoMapeo API client instance. * - * @param {Object} opts + * @param opts * @param {ReactNode} opts.children React children node * @param {MapeoClientApi} opts.clientApi Client API instance */ diff --git a/src/hooks/client.ts b/src/hooks/client.ts index 2ea5994..b0a193e 100644 --- a/src/hooks/client.ts +++ b/src/hooks/client.ts @@ -11,7 +11,7 @@ import { * Access a client API instance. If a ClientApiContext provider is not * set up, it will throw an error. * - * @returns {import('@comapeo/ipc').MapeoClientApi} Client API instance + * @returns Client API instance * * @example * ```tsx diff --git a/src/hooks/documents.ts b/src/hooks/documents.ts index 9bf4445..86e917c 100644 --- a/src/hooks/documents.ts +++ b/src/hooks/documents.ts @@ -14,12 +14,10 @@ import { useSingleProject } from './projects' * * Triggers the closest error boundary if the document cannot be found * - * @param {Object} opts - * @param {string} opts.projectId Project public ID - * @param {DocumentType} opts.docType Document type of interest - * @param {string} opts.docId Document ID - * @param {Object} [opts.opts] - * @param {string} [opts.opts.lang] Language to translate the document into + * @param opts.projectId Project public ID + * @param opts.docType Document type of interest + * @param opts.docId Document ID + * @param opts.lang Language to translate the document into * * @example * ```tsx @@ -38,12 +36,12 @@ export function useSingleDocByDocId({ projectId, docType, docId, - opts, + lang, }: { projectId: string docType: D docId: string - opts?: Parameters[0]['opts'] + lang?: string }) { const { data: projectApi } = useSingleProject({ projectId }) @@ -53,7 +51,7 @@ export function useSingleDocByDocId({ projectId, docType, docId, - opts, + lang, }), ) @@ -66,12 +64,10 @@ export function useSingleDocByDocId({ * * Triggers the closest error boundary if the document cannot be found. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID - * @param {DocumentType} opts.docType Document type of interest - * @param {string} opts.versionId Document's version ID - * @param {Object} [opts.opts] - * @param {string} [opts.opts.lang] Language to translate the document into + * @param opts.projectId Project public ID + * @param opts.docType Document type of interest + * @param opts.versionId Document's version ID + * @param opts.lang Language to translate the document into * * * @example * ```tsx @@ -90,12 +86,12 @@ export function useSingleDocByVersionId({ projectId, docType, versionId, - opts, + lang, }: { projectId: string docType: D versionId: string - opts?: Parameters[0]['opts'] + lang?: string }) { const { data: projectApi } = useSingleProject({ projectId }) @@ -105,7 +101,7 @@ export function useSingleDocByVersionId({ projectId, docType, versionId, - opts, + lang, }), ) @@ -116,12 +112,10 @@ export function useSingleDocByVersionId({ /** * Retrieve all documents of a specific `docType`. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID - * @param {DocumentType} opts.docType Document type of interest - * @param {Object} [opts.opts] - * @param {boolean} [opts.opts.includeDeleted] Include documents that have been marked as deleted - * @param {string} [opts.opts.lang] Language to translate the documents into + * @param opts.projectId Project public ID + * @param opts.docType Document type of interest + * @param opts.includeDeleted Include documents that have been marked as deleted + * @param opts.lang Language to translate the documents into * * @example * ```tsx @@ -152,11 +146,13 @@ export function useSingleDocByVersionId({ export function useManyDocs({ projectId, docType, - opts, + includeDeleted, + lang, }: { projectId: string docType: D - opts?: Parameters[0]['opts'] + includeDeleted?: boolean + lang?: string }) { const { data: projectApi } = useSingleProject({ projectId }) @@ -165,7 +161,8 @@ export function useManyDocs({ projectApi, projectId, docType, - opts, + includeDeleted, + lang, }), ) diff --git a/src/hooks/maps.ts b/src/hooks/maps.ts index 82f0f75..65f5c22 100644 --- a/src/hooks/maps.ts +++ b/src/hooks/maps.ts @@ -9,8 +9,7 @@ import { useClientApi } from './client' * If `opts.refreshToken` is specified, it will be appended to the returned URL as a search param. This is useful for forcing cache busting * due to hidden internal details by consuming components (e.g. map component from MapLibre). * - * @param {Object} opts - * @param {string} opts.refreshToken String to append to the returned value as a search param + * @param opts.refreshToken String to append to the returned value as a search param * * @example * ```tsx diff --git a/src/hooks/projects.ts b/src/hooks/projects.ts index c66dff9..5df0f27 100644 --- a/src/hooks/projects.ts +++ b/src/hooks/projects.ts @@ -1,3 +1,4 @@ +import type { BitmapOpts, SvgOpts } from '@comapeo/core/dist/icon-api' import type { BlobId } from '@comapeo/core/dist/types' import { useSuspenseQuery } from '@tanstack/react-query' @@ -16,8 +17,7 @@ import { useClientApi } from './client' /** * Retrieve the project settings for a project. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID + * @param opts.projectId Project public ID * * @example * ```tsx @@ -53,8 +53,7 @@ export function useProjectSettings({ projectId }: { projectId: string }) { * * This is mostly used internally by the other hooks and should only be used if certain project APIs are not exposed via the hooks. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID + * @param opts.projectId Project public ID * * @example * ```tsx @@ -109,9 +108,8 @@ export function useManyProjects() { /** * Retrieve a single member of a project. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID - * @param {deviceId} opts.projectId Device ID of interest + * @param opts.projectId Project public ID + * @param opts.projectId Device ID of interest * * @example * ```tsx @@ -145,8 +143,7 @@ export function useSingleMember({ /** * Retrieve all members of a project. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID + * @param opts.projectId Project public ID * * @example * ```tsx @@ -172,10 +169,11 @@ export function useManyMembers({ projectId }: { projectId: string }) { * * _TODO: Explain bitmap opts vs svg opts_ * - * @param {Object} opts - * @param {string} opts.projectId Project public ID - * @param {string} opts.iconId Icon ID of interest - * @param {BitmapOpts | SvgOpts} opts.opts Parameters related to the mime type of the icon of interest + * @param opts.projectId Project public ID + * @param opts.iconId Icon ID of interest + * @param opts.mimeType MIME type of desired resource + * @param opts.pixelDensity Pixel density resource (only applicable when `mimeType` is `'image/png'`) + * @param opts.size Size of desired resource * * @example * ```tsx @@ -183,11 +181,9 @@ export function useManyMembers({ projectId }: { projectId: string }) { * const { data } = useIconUrl({ * projectId: '...', * iconId: '...', - * opts: { - * mimeType: 'image/png', - * pixelDensity: 1, - * size: 'medium' - * } + * mimeType: 'image/png', + * pixelDensity: 1, + * size: 'medium' * }) * } * ``` @@ -197,10 +193,8 @@ export function useManyMembers({ projectId }: { projectId: string }) { * const { data } = useIconUrl({ * projectId: '...', * iconId: '...', - * opts: { - * mimeType: 'image/svg', - * size: 'medium' - * } + * mimeType: 'image/svg', + * size: 'medium' * }) * } * ``` @@ -208,20 +202,19 @@ export function useManyMembers({ projectId }: { projectId: string }) { export function useIconUrl({ projectId, iconId, - opts, + ...mimeBasedOpts }: { projectId: string iconId: string - opts: Parameters[0]['opts'] -}) { +} & (BitmapOpts | SvgOpts)) { const { data: projectApi } = useSingleProject({ projectId }) const { data, error, isRefetching } = useSuspenseQuery( iconUrlQueryOptions({ + ...mimeBasedOpts, projectApi, projectId, iconId, - opts, }), ) @@ -233,9 +226,8 @@ export function useIconUrl({ * * _TODO: Explain BlobId in more depth_ * - * @param {Object} opts - * @param {string} opts.projectId Project public Id - * @param {BlobId} opts.blobId Blob ID of the desired resource + * @param opts.projectId Project public Id + * @param opts.blobId Blob ID of the desired resource * * @example * ```tsx @@ -304,9 +296,8 @@ export function useAttachmentUrl({ /** * Retrieve the device ID that created a document. * - * @param {Object} opts - * @param {string} opts.projectId Project public ID - * @param {string} opts.originalVersionId Version ID of document + * @param opts.projectId Project public ID + * @param opts.originalVersionId Version ID of document * * @example * ```tsx diff --git a/src/lib/react-query/documents.ts b/src/lib/react-query/documents.ts index d835b41..5f2b9bd 100644 --- a/src/lib/react-query/documents.ts +++ b/src/lib/react-query/documents.ts @@ -22,39 +22,54 @@ export function getDocumentsQueryKey({ export function getManyDocumentsQueryKey({ projectId, docType, - opts, + includeDeleted, + lang, }: { projectId: string docType: D - opts?: Parameters[0] + includeDeleted?: boolean + lang?: string }) { - return [ROOT_QUERY_KEY, 'projects', projectId, docType, opts] as const + return [ + ROOT_QUERY_KEY, + 'projects', + projectId, + docType, + { includeDeleted, lang }, + ] as const } export function getDocumentByDocIdQueryKey({ projectId, docType, docId, - opts, + lang, }: { projectId: string docType: D - docId: Parameters[0] - opts?: Parameters[1] + docId: string + lang?: string }) { - return [ROOT_QUERY_KEY, 'projects', projectId, docType, docId, opts] as const + return [ + ROOT_QUERY_KEY, + 'projects', + projectId, + docType, + docId, + { lang }, + ] as const } export function getDocumentByVersionIdQueryKey({ projectId, docType, versionId, - opts, + lang, }: { projectId: string docType: D - versionId: Parameters[0] - opts?: Parameters[1] + versionId: string + lang?: string }) { return [ ROOT_QUERY_KEY, @@ -62,7 +77,7 @@ export function getDocumentByVersionIdQueryKey({ projectId, docType, versionId, - opts, + { lang }, ] as const } @@ -70,18 +85,28 @@ export function documentsQueryOptions({ projectApi, projectId, docType, - opts, + includeDeleted, + lang, }: { projectApi: MapeoProjectApi projectId: string docType: D - opts?: Parameters[0] + includeDeleted?: boolean + lang?: string }) { return queryOptions({ ...baseQueryOptions(), - queryKey: getManyDocumentsQueryKey({ projectId, docType, opts }), + queryKey: getManyDocumentsQueryKey({ + projectId, + docType, + includeDeleted, + lang, + }), queryFn: async () => { - return projectApi[docType].getMany(opts) + return projectApi[docType].getMany({ + includeDeleted, + lang, + }) }, }) } @@ -91,13 +116,13 @@ export function documentByDocumentIdQueryOptions({ projectId, docType, docId, - opts, + lang, }: { projectApi: MapeoProjectApi projectId: string docType: D - docId: Parameters[0] - opts?: Omit[1], 'mustBeFound'> + docId: string + lang?: string }) { return queryOptions({ ...baseQueryOptions(), @@ -105,11 +130,11 @@ export function documentByDocumentIdQueryOptions({ projectId, docType, docId, - opts, + lang, }), queryFn: async () => { return projectApi[docType].getByDocId(docId, { - ...opts, + lang, // We want to make sure that this throws in the case that no match is found mustBeFound: true, }) @@ -122,13 +147,13 @@ export function documentByVersionIdQueryOptions({ projectId, docType, versionId, - opts, + lang, }: { projectApi: MapeoProjectApi projectId: string docType: D - versionId: Parameters[0] - opts?: Parameters[1] + versionId: string + lang?: string }) { return queryOptions({ ...baseQueryOptions(), @@ -136,10 +161,10 @@ export function documentByVersionIdQueryOptions({ projectId, docType, versionId, - opts, + lang, }), queryFn: async () => { - return projectApi[docType].getByVersionId(versionId, opts) + return projectApi[docType].getByVersionId(versionId, { lang }) }, }) } diff --git a/src/lib/react-query/projects.ts b/src/lib/react-query/projects.ts index 87c7bfa..b3615da 100644 --- a/src/lib/react-query/projects.ts +++ b/src/lib/react-query/projects.ts @@ -1,3 +1,4 @@ +import type { BitmapOpts, SvgOpts } from '@comapeo/core/dist/icon-api' import type { BlobId } from '@comapeo/core/dist/types.js' import type { MapeoClientApi, MapeoProjectApi } from '@comapeo/ipc' import { queryOptions } from '@tanstack/react-query' @@ -41,13 +42,19 @@ export function getMemberByIdQueryKey({ export function getIconUrlQueryKey({ projectId, iconId, - opts, + ...mimeBasedOpts }: { projectId: string - iconId: Parameters[0] - opts: Parameters[1] -}) { - return [ROOT_QUERY_KEY, 'projects', projectId, 'icons', iconId, opts] as const + iconId: string +} & (BitmapOpts | SvgOpts)) { + return [ + ROOT_QUERY_KEY, + 'projects', + projectId, + 'icons', + iconId, + mimeBasedOpts, + ] as const } export function getDocumentCreatedByQueryKey({ @@ -176,18 +183,17 @@ export function iconUrlQueryOptions({ projectApi, projectId, iconId, - opts, + ...mimeBasedOpts }: { projectApi: MapeoProjectApi projectId: string iconId: Parameters[0] - opts: Parameters[1] -}) { +} & (BitmapOpts | SvgOpts)) { return queryOptions({ ...baseQueryOptions(), - queryKey: getIconUrlQueryKey({ projectId, iconId, opts }), + queryKey: getIconUrlQueryKey({ ...mimeBasedOpts, projectId, iconId }), queryFn: async () => { - return projectApi.$icons.getIconUrl(iconId, opts) + return projectApi.$icons.getIconUrl(iconId, mimeBasedOpts) }, }) }