Skip to content
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

chore(shared): Apply deprecation warnings #1789

Merged
merged 6 commits into from
Sep 28, 2023
Merged
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
9 changes: 9 additions & 0 deletions .changeset/eighty-swans-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@clerk/shared': patch
---

Apply deprecation warnings:
- `OrganizationContext`
- `organizationList`
- `useOrganizations`
- `getRequestUrl`
6 changes: 5 additions & 1 deletion packages/shared/src/hooks/contexts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
import type { PropsWithChildren } from 'react';
import React from 'react';

import { deprecated } from '../utils';
import { disableSWRDevtools } from './clerk-swr';
disableSWRDevtools();
import { SWRConfig } from './clerk-swr';
Expand Down Expand Up @@ -65,7 +66,10 @@ const OrganizationProvider = ({
/**
* @deprecated use OrganizationProvider instead
*/
export const OrganizationContext = OrganizationProvider;
export const OrganizationContext = (...args: Parameters<typeof OrganizationProvider>) => {
deprecated('OrganizationContext', 'Use `OrganizationProvider` instead');
return OrganizationProvider(...args);
};

export {
ClientContext,
Expand Down
6 changes: 5 additions & 1 deletion packages/shared/src/hooks/useOrganizationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
UserOrganizationInvitationResource,
} from '@clerk/types';

import { deprecatedObjectProperty } from '../utils';
import { useClerkInstanceContext, useUserContext } from './contexts';
import type { PaginatedResources, PaginatedResourcesWithDefault } from './types';
import { usePagesOrInfinite, useWithSafeValues } from './usePagesOrInfinite';
Expand Down Expand Up @@ -210,7 +211,7 @@ export const useOrganizationList: UseOrganizationList = params => {
};
}

return {
const result = {
isLoaded: isClerkLoaded,
organizationList: createOrganizationList(user.organizationMemberships),
setActive: clerk.setActive,
Expand All @@ -219,6 +220,9 @@ export const useOrganizationList: UseOrganizationList = params => {
userInvitations: invitations,
userSuggestions: suggestions,
};
deprecatedObjectProperty(result, 'organizationList', 'Use `userMemberships` instead.');

return result;
};

function createOrganizationList(organizationMemberships: OrganizationMembershipResource[]) {
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/src/hooks/useOrganizations.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { CreateOrganizationParams, OrganizationMembershipResource, OrganizationResource } from '@clerk/types';

import { deprecated } from '../utils';
import { useClerkInstanceContext } from './contexts';

type UseOrganizationsReturn =
Expand Down Expand Up @@ -51,6 +52,7 @@ type UseOrganizations = () => UseOrganizationsReturn;
* @deprecated Use useOrganizationList, useOrganization, or useClerk instead
*/
export const useOrganizations: UseOrganizations = () => {
deprecated('useOrganizations', 'Use useOrganizationList, useOrganization, or useClerk instead.');
const clerk = useClerkInstanceContext();
if (!clerk.loaded) {
return {
Expand Down
73 changes: 72 additions & 1 deletion packages/shared/src/utils/deprecated.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jest.mock('./runtimeEnvironment', () => {
};
});

import { deprecated, deprecatedProperty } from './deprecated';
import { deprecated, deprecatedObjectProperty, deprecatedProperty } from './deprecated';
import { isProductionEnvironment, isTestEnvironment } from './runtimeEnvironment';

describe('deprecated(fnName, warning)', () => {
Expand Down Expand Up @@ -310,3 +310,74 @@ describe('deprecatedProperty(cls, propName, warning, isStatic = false)', () => {
});
});
});

describe('deprecatedObjectProperty(obj, propName, warning)', () => {
let consoleWarnSpy;

beforeEach(() => {
consoleWarnSpy = jest.spyOn(global.console, 'warn').mockImplementation();
});
afterEach(() => {
consoleWarnSpy.mockRestore();
});

test('deprecate object property shows warning', () => {
const example = { objectProperty: 'objectProperty-value' };

deprecatedObjectProperty(example, 'objectProperty', 'Use `objectPropertyElse` instead.');

expect(consoleWarnSpy).not.toBeCalled();
expect(example.objectProperty).toEqual('objectProperty-value');
expect(consoleWarnSpy).toBeCalledTimes(1);
expect(consoleWarnSpy).toBeCalledWith(
'DEPRECATION WARNING: "objectProperty" is deprecated and will be removed in the next major release.\nUse `objectPropertyElse` instead.',
);

expect(example.objectProperty).toEqual('objectProperty-value');
expect(consoleWarnSpy).toBeCalledTimes(1);
});

describe('for test environment', () => {
beforeEach(() => {
(isTestEnvironment as jest.Mock).mockReturnValue(true);
});
afterEach(() => {
(isTestEnvironment as jest.Mock).mockReturnValue(false);
});

test('deprecate object property does not show warning', () => {
const example = { objectPropertyInTest: 'objectPropertyInTest-value' };

deprecatedObjectProperty(example, 'objectPropertyInTest', 'Use `objectPropertyInTestElse` instead.');

expect(consoleWarnSpy).not.toBeCalled();
expect(example.objectPropertyInTest).toEqual('objectPropertyInTest-value');
// call it twice to verify that it's never called
expect(example.objectPropertyInTest).toEqual('objectPropertyInTest-value');
expect(example.objectPropertyInTest).toEqual('objectPropertyInTest-value');
expect(consoleWarnSpy).toBeCalledTimes(0);
});
});

describe('for production environment', () => {
beforeEach(() => {
(isProductionEnvironment as jest.Mock).mockReturnValue(true);
});
afterEach(() => {
(isProductionEnvironment as jest.Mock).mockReturnValue(false);
});

test('deprecate object property does not show warning', () => {
const example = { objectPropertyInProd: 'objectPropertyInProd-value' };

deprecatedObjectProperty(example, 'objectPropertyInProd', 'Use `objectPropertyInProdElse` instead.');

expect(consoleWarnSpy).not.toBeCalled();
expect(example.objectPropertyInProd).toEqual('objectPropertyInProd-value');
// call it twice to verify that it's never called
expect(example.objectPropertyInProd).toEqual('objectPropertyInProd-value');
expect(example.objectPropertyInProd).toEqual('objectPropertyInProd-value');
expect(consoleWarnSpy).toBeCalledTimes(0);
});
});
});
28 changes: 21 additions & 7 deletions packages/shared/src/utils/deprecated.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { isProductionEnvironment, isTestEnvironment } from './runtimeEnvironment';
/**
* Mark class methods or functions as deprecated.
* Mark class method / function as deprecated.
*
* A console WARNING will be displayed when class methods
* or functions are invoked.
* A console WARNING will be displayed when class method / function is invoked.
*
* Examples
* 1. Deprecate class method
Expand Down Expand Up @@ -34,9 +33,9 @@ export const deprecated = (fnName: string, warning: string, key?: string): void
);
};
/**
* Mark class properties as deprecated.
* Mark class property as deprecated.
*
* A console WARNING will be displayed when class properties are being accessed.
* A console WARNING will be displayed when class property is being accessed.
*
* 1. Deprecate class property
* class Example {
Expand All @@ -60,13 +59,28 @@ type AnyClass = new (...args: any[]) => any;
export const deprecatedProperty = (cls: AnyClass, propName: string, warning: string, isStatic = false): void => {
const target = isStatic ? cls : cls.prototype;

let value = target[propName];
Object.defineProperty(target, propName, {
get() {
deprecated(propName, warning, `${cls.name}:${propName}`);
return this['_' + propName];
return value;
},
set(v: unknown) {
this['_' + propName] = v;
value = v;
},
});
};

/**
* Mark object property as deprecated.
*
* A console WARNING will be displayed when object property is being accessed.
*
* 1. Deprecate object property
* const obj = { something: 'aloha' };
*
* deprecatedObjectProperty(obj, 'something', 'Use `somethingElse` instead.');
*/
export const deprecatedObjectProperty = (obj: Record<string, any>, propName: string, warning: string): void => {
deprecatedProperty(obj as any, propName, warning, true);
};
2 changes: 1 addition & 1 deletion packages/shared/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ export * from './isomorphicAtob';
export * from './globs';
export * from './loadScript';
export * from './runtimeEnvironment';
export { deprecated, deprecatedProperty } from './deprecated';
export { deprecated, deprecatedProperty, deprecatedObjectProperty } from './deprecated';
3 changes: 3 additions & 0 deletions packages/shared/src/utils/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { deprecated } from './deprecated';

export function isValidProxyUrl(key: string | undefined) {
if (!key) {
return true;
Expand Down Expand Up @@ -25,6 +27,7 @@ export function proxyUrlToAbsoluteURL(url: string | undefined): string {
* @deprecated Use `buildRequestUrl` from @clerk/backend
*/
export function getRequestUrl({ request, relativePath }: { request: Request; relativePath?: string }): URL {
deprecated('getRequestUrl', 'Use `buildRequestUrl` from @clerk/backend instead.');
const { headers, url: initialUrl } = request;
const url = new URL(initialUrl);
const host = headers.get('X-Forwarded-Host') ?? headers.get('host') ?? (headers as any)['host'] ?? url.host;
Expand Down