Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- (Experimental) Added support for importing via `<script type="module">`, by [@compulim](https://github.com/compulim) in PR [#5592](https://github.com/microsoft/BotFramework-WebChat/pull/5592)
- Added support for `botframework-webchat-fluent-theme` package, by [@compulim](https://github.com/compulim) in PR [#5593](https://github.com/microsoft/BotFramework-WebChat/pull/5593)
- Bundling vendor chunks, by [@compulim](https://github.com/compulim) in PR [#5595](https://github.com/microsoft/BotFramework-WebChat/pull/5595)
- Added deprecation notes for legacy imports, by [@compulim](https://github.com/compulim) in PR [#5600](https://github.com/microsoft/BotFramework-WebChat/pull/5600)
- `import { hooks } from 'botframework-webchat'` should be replaced by `import * as hooks from 'botframework-webchat/hook'`

### Changed

Expand Down
51 changes: 51 additions & 0 deletions __tests__/html2/boot/deprecation/components.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<main id="webchat"></main>
<script type="importmap">
{
"imports": {
"botframework-webchat": "/__dist__/packages/bundle/static/botframework-webchat.js",
"jest-mock": "https://esm.sh/jest-mock",
"react": "/__dist__/packages/bundle/static/react.js",
"react-dom": "/__dist__/packages/bundle/static/react-dom.js"
}
}
</script>
<script type="module">
import { fn, spyOn } from 'jest-mock';

spyOn(console, 'warn');
</script>
<script type="module">
import '/test-harness.mjs';
import '/test-page-object.mjs';

import { Components, createDirectLine, createStoreWithOptions, renderWebChat } from 'botframework-webchat';
import { version } from 'react';

run(async function () {
expect(console.warn).toHaveBeenCalledTimes(0);

// WHEN: Touching "Components.BasicWebChat".
expect(Components.BasicWebChat).not.toBeUndefined();

// THEN: Should show deprecation note.
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenLastCalledWith(
"botframework-webchat: `import { Components } from 'botframework-webchat'` has been deprecated, use `import { %s } from 'botframework-webchat/component'` instead.",
'BasicWebChat'
);

// WHEN: Touching "Components.BasicTranscript".
expect(Components.BasicWebChat).not.toBeUndefined();

// THEN: Should not show deprecation note again.
expect(console.warn).toHaveBeenCalledTimes(1);
});
</script>
</body>
</html>
42 changes: 42 additions & 0 deletions __tests__/html2/boot/deprecation/components.new.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<main id="webchat"></main>
<script type="importmap">
{
"imports": {
"botframework-webchat": "/__dist__/packages/bundle/static/botframework-webchat.js",
"botframework-webchat/component": "/__dist__/packages/bundle/static/botframework-webchat/component.js",
"jest-mock": "https://esm.sh/jest-mock",
"react": "/__dist__/packages/bundle/static/react.js",
"react-dom": "/__dist__/packages/bundle/static/react-dom.js"
}
}
</script>
<script type="module">
import { fn, spyOn } from 'jest-mock';

spyOn(console, 'warn');
</script>
<script type="module">
import '/test-harness.mjs';
import '/test-page-object.mjs';

import { createDirectLine, createStoreWithOptions, renderWebChat } from 'botframework-webchat';
import * as Components from 'botframework-webchat/component';
import { version } from 'react';

run(async function () {
expect(console.warn).toHaveBeenCalledTimes(0);

// WHEN: Touching anything about "hooks".
expect(Components.BasicWebChat).not.toBeUndefined();

expect(console.warn).toHaveBeenCalledTimes(0);
});
</script>
</body>
</html>
51 changes: 51 additions & 0 deletions __tests__/html2/boot/deprecation/hooks.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<main id="webchat"></main>
<script type="importmap">
{
"imports": {
"botframework-webchat": "/__dist__/packages/bundle/static/botframework-webchat.js",
"jest-mock": "https://esm.sh/jest-mock",
"react": "/__dist__/packages/bundle/static/react.js",
"react-dom": "/__dist__/packages/bundle/static/react-dom.js"
}
}
</script>
<script type="module">
import { fn, spyOn } from 'jest-mock';

spyOn(console, 'warn');
</script>
<script type="module">
import '/test-harness.mjs';
import '/test-page-object.mjs';

import { createDirectLine, createStoreWithOptions, hooks, renderWebChat } from 'botframework-webchat';
import { version } from 'react';

run(async function () {
expect(console.warn).toHaveBeenCalledTimes(0);

// WHEN: Touching "hooks.useStyleOptions".
expect(hooks.useStyleOptions).not.toBeUndefined();

// THEN: Should show deprecation note.
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenLastCalledWith(
"botframework-webchat: `import { hooks } from 'botframework-webchat'` has been deprecated, use `import { %s } from 'botframework-webchat/hook'` instead.",
'useStyleOptions'
);

// WHEN: Touching "hooks.useStyleSet".
expect(hooks.useStyleSet).not.toBeUndefined();

// THEN: Should not show deprecation note again.
expect(console.warn).toHaveBeenCalledTimes(1);
});
</script>
</body>
</html>
42 changes: 42 additions & 0 deletions __tests__/html2/boot/deprecation/hooks.new.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<main id="webchat"></main>
<script type="importmap">
{
"imports": {
"botframework-webchat": "/__dist__/packages/bundle/static/botframework-webchat.js",
"botframework-webchat/hook": "/__dist__/packages/bundle/static/botframework-webchat/hook.js",
"jest-mock": "https://esm.sh/jest-mock",
"react": "/__dist__/packages/bundle/static/react.js",
"react-dom": "/__dist__/packages/bundle/static/react-dom.js"
}
}
</script>
<script type="module">
import { fn, spyOn } from 'jest-mock';

spyOn(console, 'warn');
</script>
<script type="module">
import '/test-harness.mjs';
import '/test-page-object.mjs';

import { createDirectLine, createStoreWithOptions, renderWebChat } from 'botframework-webchat';
import * as hooks from 'botframework-webchat/hook';
import { version } from 'react';

run(async function () {
expect(console.warn).toHaveBeenCalledTimes(0);

// WHEN: Touching anything about "hooks".
expect(hooks.useStyleOptions).not.toBeUndefined();

expect(console.warn).toHaveBeenCalledTimes(0);
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { warnOnce } from 'botframework-webchat-core';
import { warnOnce } from '@msinternal/botframework-webchat-base/utils';
import { type Enhancer } from 'handler-chain';
import React, { memo, type ReactNode } from 'react';
import {
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/hooks/useSendFiles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1024] }] */

import { warnOnce } from 'botframework-webchat-core';
import { warnOnce } from '@msinternal/botframework-webchat-base/utils';
import { useCallback } from 'react';

import useWebChatAPIContext from './internal/useWebChatAPIContext';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { warnOnce } from 'botframework-webchat-core';
import { warnOnce } from '@msinternal/botframework-webchat-base/utils';
import React, { memo, type ReactNode } from 'react';
import { createChainOfResponsibility, type ComponentMiddleware } from 'react-chain-of-responsibility';
import { array, function_, safeParse, type InferOutput } from 'valibot';
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/normalizeStyleOptions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { warnOnce } from 'botframework-webchat-core';
import { warnOnce } from '@msinternal/botframework-webchat-base/utils';

import defaultStyleOptions from './defaultStyleOptions';
import StyleOptions, { StrictStyleOptions } from './StyleOptions';
Expand Down
10 changes: 0 additions & 10 deletions packages/api/src/utils/warnOnce.ts

This file was deleted.

40 changes: 40 additions & 0 deletions packages/base/src/utils/deprecateObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import warnOnce from './warnOnce';

const PROPERTY_DENYLIST = new Set<string | symbol>([
'__defineGetter__',
'__defineSetter__',
'__lookupGetter__',
'__lookupSetter__',
'__proto__',
'constructor',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'prototype',
'toString',
'valueOf'
]);

export default function deprecateNamespace<T extends { [key: string | symbol]: any }>(
namespace: T,
message: string
): T {
const warnDeprecation = warnOnce(message);

return new Proxy<T>(namespace, {
get(target, p) {
if (
!PROPERTY_DENYLIST.has(p) &&
(typeof p === 'string'
? Object.getOwnPropertyNames(target).includes(p)
: Object.getOwnPropertySymbols(target).includes(p))
) {
warnDeprecation(p);

// Only can get own properties.
// eslint-disable-next-line security/detect-object-injection
return target[p];
}
}
});
}
2 changes: 2 additions & 0 deletions packages/base/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { default as createBuildInfo, type BuildInfo, type ReadonlyBuildInfo } from './createBuildInfo';
export { default as deprecateObject } from './deprecateObject';
export { default as warnOnce } from './warnOnce';
export { default as withResolvers, type PromiseWithResolvers } from './withResolvers';
10 changes: 10 additions & 0 deletions packages/base/src/utils/private/once.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default function once<P extends any[]>(fn: (...args: P) => void): (...args: P) => void {
let done = false;

return (...args) => {
if (!done) {
fn(...args);
done = true;
}
};
}
5 changes: 5 additions & 0 deletions packages/base/src/utils/warnOnce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import once from './private/once';

export default function warnOnce(message: string): (...args: any[]) => void {
return once((...args: any[]) => console.warn(`botframework-webchat: ${message}`, ...args));
}
5 changes: 3 additions & 2 deletions packages/bundle/src/AddFullBundle.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { warnOnce } from '@msinternal/botframework-webchat-base/utils';
import {
type AttachmentForScreenReaderMiddleware,
type AttachmentMiddleware,
type StyleOptions
} from 'botframework-webchat-api';
import { type HTMLContentTransformMiddleware } from 'botframework-webchat-component';
import { singleToArray, warnOnce, type OneOrMany } from 'botframework-webchat-core';
import { singleToArray, type OneOrMany } from 'botframework-webchat-core';
import React, { memo, type ReactNode } from 'react';

import AdaptiveCardsComposer from './adaptiveCards/AdaptiveCardsComposer';
Expand Down Expand Up @@ -76,4 +77,4 @@ function AddFullBundle({

export default memo(AddFullBundle);

export type { AddFullBundleProps, AddFullBundleChildren };
export type { AddFullBundleChildren, AddFullBundleProps };
22 changes: 19 additions & 3 deletions packages/bundle/src/boot/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,23 @@ export {
// #endregion

// #region Overrides for backward compatibility
// Web devs should move to named exports instead.
export * as Components from '../actual/component/full';
export * as hooks from '../actual/hook/full';
import { deprecateObject } from '@msinternal/botframework-webchat-base/utils';

import * as hooks from '../actual/hook/full';

const deprecatedHooks = deprecateObject(
hooks,
"`import { hooks } from 'botframework-webchat'` has been deprecated, use `import { %s } from 'botframework-webchat/hook'` instead."
);

export { deprecatedHooks as hooks };

import * as Components from '../actual/component/full';

const deprecatedComponents = deprecateObject(
Components,
"`import { Components } from 'botframework-webchat'` has been deprecated, use `import { %s } from 'botframework-webchat/component'` instead."
);

export { deprecatedComponents as Components };
// #endregion
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { warnOnce } from '@msinternal/botframework-webchat-base/utils';
import { hooks } from 'botframework-webchat-api';
import {
getOrgSchemaMessage,
OrgSchemaProject,
parseAction,
parseClaim,
warnOnce,
type WebChatActivity
} from 'botframework-webchat-core';
import classNames from 'classnames';
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import getOrgSchemaMessage from './utils/getOrgSchemaMessage';
import isForbiddenPropertyName from './utils/isForbiddenPropertyName';
import onErrorResumeNext from './utils/onErrorResumeNext';
import singleToArray from './utils/singleToArray';
import warnOnce from './utils/warnOnce';

export {
CLEAR_SUGGESTED_ACTIONS,
Expand Down Expand Up @@ -126,7 +125,6 @@ export {
stopDictate,
stopSpeakingActivity,
submitSendBox,
warnOnce,
withResolvers
};

Expand Down
5 changes: 0 additions & 5 deletions packages/core/src/utils/warnOnce.ts

This file was deleted.

Loading