Skip to content

feat: Using the AtlasUserData class to demo save user data project COMPASS-9565 #7152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: extend-user-data
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions packages/atlas-service/src/atlas-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ export class AtlasService {
// https://github.com/10gen/mms/blob/9f858bb987aac6aa80acfb86492dd74c89cbb862/client/packages/project/common/ajaxPrefilter.ts#L34-L49
return this.cloudEndpoint(path);
}
tempEndpoint(path?: string): string {
return `https://cluster-connection.cloud-dev.mongodb.com${normalizePath(
path
)}`;
}
driverProxyEndpoint(path?: string): string {
return `${this.config.ccsBaseUrl}${normalizePath(path)}`;
}
Expand All @@ -88,13 +93,14 @@ export class AtlasService {
{ url }
);
try {
const headers = {
...this.options?.defaultHeaders,
...(shouldAddCSRFHeaders(init?.method) && getCSRFHeaders()),
...init?.headers,
};
const res = await fetch(url, {
...init,
headers: {
...this.options?.defaultHeaders,
...(shouldAddCSRFHeaders(init?.method) && getCSRFHeaders()),
...init?.headers,
},
headers,
});
this.logger.log.info(
this.logger.mongoLogId(1_001_000_309),
Expand Down
2 changes: 1 addition & 1 deletion packages/atlas-service/src/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const AtlasServiceProvider: React.FC<{
);
});

function useAtlasServiceContext(): AtlasService {
export function useAtlasServiceContext(): AtlasService {
const service = useContext(AtlasServiceContext);
if (!service) {
throw new Error('No AtlasService available in this context');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,7 @@ export const saveRecentAsFavorite = (
};

// add it in the favorite
await favoriteQueryStorage?.updateAttributes(
favoriteQuery._id,
favoriteQuery
);
await favoriteQueryStorage?.saveQuery(favoriteQuery, favoriteQuery._id);

// update favorites
void dispatch(fetchFavorites());
Expand Down
58 changes: 34 additions & 24 deletions packages/compass-user-data/src/user-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { log, mongoLogId } = createLogger('COMPASS-USER-STORAGE');

type SerializeContent<I> = (content: I) => string;
type DeserializeContent = (content: string) => unknown;
type GetResourceUrl = (path?: string) => Promise<string>;
type GetResourceUrl = (path?: string) => string;
type AuthenticatedFetch = (
url: RequestInfo | URL,
options?: RequestInit
Expand Down Expand Up @@ -61,6 +61,10 @@ export abstract class IUserData<T extends z.Schema> {
abstract write(id: string, content: z.input<T>): Promise<boolean>;
abstract delete(id: string): Promise<boolean>;
abstract readAll(options?: ReadOptions): Promise<ReadAllResult<T>>;
abstract readOne(
id: string,
options?: ReadOptions
): Promise<z.output<T> | undefined>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When does this return undefined? I kinda would've expected this to return a version of ReadAllResult that either has a single item in the arrays or the properties are one item instead of an array

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identified that readOne in AtlasUserData should not be returning null when an error is found. readOne in FileUserData originally had a return type of Promise<z.output<T> | undefined>, so the abstract method should also have type undefined.

abstract updateAttributes(
id: string,
data: Partial<z.input<T>>
Expand Down Expand Up @@ -292,20 +296,19 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
this.validator.parse(content);

const response = await this.authenticatedFetch(
await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}`
this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: id,
data: this.serialize(content),
createdAt: new Date(),
projectId: this.projectId,
}),
credentials: 'include',
}
);

Expand All @@ -322,8 +325,8 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
'Atlas Backend',
'Error writing data',
{
url: await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}`
url: this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}`
),
error: (error as Error).message,
}
Expand All @@ -335,11 +338,12 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
async delete(id: string): Promise<boolean> {
try {
const response = await this.authenticatedFetch(
await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}/${id}`
this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
{
method: 'DELETE',
credentials: 'include',
}
);
if (!response.ok) {
Expand All @@ -354,8 +358,8 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
'Atlas Backend',
'Error deleting data',
{
url: await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}/${id}`
url: this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
error: (error as Error).message,
}
Expand All @@ -369,13 +373,15 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
data: [],
errors: [],
};
// debugger;
try {
const response = await this.authenticatedFetch(
await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}`
this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}`
),
{
method: 'GET',
credentials: 'include',
}
);
if (!response.ok) {
Expand Down Expand Up @@ -411,15 +417,19 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
};

const response = await this.authenticatedFetch(
await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}/${id}`
this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: this.serialize(newData),
body: JSON.stringify({
data: this.serialize(newData),
createdAt: new Date(),
}),
credentials: 'include',
}
);
if (!response.ok) {
Expand All @@ -434,8 +444,8 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
'Atlas Backend',
'Error updating data',
{
url: await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}/${id}`
url: this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
error: (error as Error).message,
}
Expand All @@ -445,14 +455,15 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
}

// TODO: change this depending on whether or not updateAttributes can provide all current data
async readOne(id: string): Promise<z.output<T>> {
async readOne(id: string): Promise<z.output<T> | undefined> {
try {
const getResponse = await this.authenticatedFetch(
await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}/${id}`
this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
{
method: 'GET',
credentials: 'include',
}
);
if (!getResponse.ok) {
Expand All @@ -469,13 +480,12 @@ export class AtlasUserData<T extends z.Schema> extends IUserData<T> {
'Atlas Backend',
'Error reading data',
{
url: await this.getResourceUrl(
`${this.dataType}/${this.orgId}/${this.projectId}/${id}`
url: this.getResourceUrl(
`userData/${this.dataType}/${this.orgId}/${this.projectId}/${id}`
),
error: (error as Error).message,
}
);
return null;
}
}
}
Loading
Loading