Skip to content

Commit

Permalink
[identity] Migrate to ESM and tshy (#31647)
Browse files Browse the repository at this point in the history
### Packages impacted by this PR

@azure/identity-broker
@azure/identity 

### Issues associated with this PR

#31338 

### Describe the problem that is addressed by this PR

Migrates identity and identity-broker to ESM, tshy, and Vitest
  • Loading branch information
maorleger authored Nov 13, 2024
1 parent 6b16d57 commit 86ed16f
Show file tree
Hide file tree
Showing 173 changed files with 2,378 additions and 2,167 deletions.
918 changes: 507 additions & 411 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions common/tools/dev-tool/src/commands/admin/migrate-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ export default leafCommand(commandInfo, async ({ "package-name": packageName, br
await prepareFiles(projectFolder, { browser });
await applyCodemods(projectFolder);

log.info("Running `rush update`");
await run(["rush", "update"], { cwd: projectFolder });
log.info("Formatting files");
await run(["rushx", "format"], { cwd: projectFolder });
await commitChanges(projectFolder, "rushx format");

log.info(
"Done. Please run `rush update`, `rush build -t <project-name>`, and run tests to verify the changes.",
);

return true;
});

Expand Down
4 changes: 4 additions & 0 deletions sdk/identity/identity-broker/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

### Other Changes

- Native ESM support has been added, and this package will now emit both CommonJS and ESM. [#31647](https://github.com/Azure/azure-sdk-for-js/pull/31647)

## 1.1.0 (2024-10-15)

### Features Added
Expand All @@ -25,9 +27,11 @@
## 1.0.0 (2023-11-07)

### Features Added

- First GA release of the plugin package `@azure/identity-broker` to [support authentication through broker such as WAM](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-acquire-token-wam). This plugin works with the [`brokerOptions` on `InteractiveBrowserCredential` added in the `@azure/identity` package](https://github.com/Azure/azure-sdk-for-js/pull/26091/).

## 1.0.0-beta.1 (2023-10-23)

### Features Added

- Created a plugin package to [support authentication through broker such as WAM](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-acquire-token-wam). This plugin works with the [`brokerOptions` on `InteractiveBrowserCredential` added in the `@azure/identity` package](https://github.com/Azure/azure-sdk-for-js/pull/26091).
4 changes: 2 additions & 2 deletions sdk/identity/identity-broker/api-extractor.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "./types/identity-broker/src/index.d.ts",
"mainEntryPointFilePath": "dist/esm/index.d.ts",
"docModel": {
"enabled": true
},
Expand All @@ -11,7 +11,7 @@
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "",
"publicTrimmedFilePath": "./types/identity-broker.d.ts"
"publicTrimmedFilePath": "dist/identity-broker.d.ts"
},
"messages": {
"tsdocMessageReporting": {
Expand Down
67 changes: 48 additions & 19 deletions sdk/identity/identity-broker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
"version": "1.1.1",
"sdk-type": "client",
"description": "A native plugin for Azure Identity credentials to enable broker authentication such as WAM",
"main": "dist/index.js",
"module": "dist-esm/identity-broker/src/index.js",
"types": "./types/identity-broker.d.ts",
"main": "./dist/commonjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/commonjs/index.d.ts",
"scripts": {
"build": "npm run extract-api && tsc -p . && dev-tool run bundle",
"build": "npm run clean && dev-tool run build-package && dev-tool run extract-api",
"build:samples": "echo skipped",
"build:test": "tsc -p . && dev-tool run bundle",
"build:test": "dev-tool run build-package && dev-tool run bundle",
"check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
"clean": "dev-tool run vendored rimraf --glob dist dist-esm types \"*.tgz\" \"*.log\"",
"execute:samples": "echo skipped",
"extract-api": "tsc -p . && dev-tool run extract-api",
"extract-api": "dev-tool run build-package && dev-tool run extract-api",
"format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
"integration-test:browser": "echo skipped",
Expand All @@ -22,19 +22,16 @@
"lint:fix": "eslint package.json api-extractor.json README.md src test --fix --fix-type [problem,suggestion]",
"pack": "npm pack 2>&1",
"test": "npm run clean && npm run build:test && npm run unit-test && npm run integration-test",
"test:browser": "npm run clean && npm run build:test && npm run unit-test:browser && npm run integration-test:browser",
"test:browser": "echo skipped",
"test:node": "npm run clean && npm run build:test && npm run unit-test:node && npm run integration-test:node",
"unit-test": "npm run unit-test:node && npm run unit-test:browser",
"unit-test:browser": "echo skipped",
"unit-test:node": "dev-tool run test:node-ts-input -- --timeout 300000 --exclude 'test/**/browser/**/*.spec.ts' --exclude 'test/snippets.spec.ts' 'test/**/**/*.spec.ts'",
"unit-test:node": "dev-tool run test:vitest -- --test-timeout 300000",
"update-snippets": "dev-tool run update-snippets",
"unit-test:manual": "dev-tool run test:node-ts-input -- --timeout 300000 'test/manual/node/popTokenSupport.spec.ts'"
},
"files": [
"dist/",
"dist-esm/identity/src",
"dist-esm/identity-broker/src",
"types/identity-broker.d.ts",
"README.md",
"LICENSE"
],
Expand Down Expand Up @@ -65,23 +62,22 @@
"tslib": "^2.2.0"
},
"devDependencies": {
"@azure-tools/test-recorder": "^3.0.0",
"@azure-tools/test-utils": "^1.0.1",
"@azure-tools/test-recorder": "^4.1.0",
"@azure-tools/test-utils-vitest": "^1.0.0",
"@azure/abort-controller": "^1.1.0",
"@azure/core-client": "^1.7.0",
"@azure/core-rest-pipeline": "^1.17.0",
"@azure/core-util": "^1.6.0",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure/logger": "^1.0.4",
"@types/mocha": "^10.0.0",
"@types/node": "^18.0.0",
"@types/sinon": "^17.0.0",
"@vitest/browser": "^2.1.4",
"@vitest/coverage-istanbul": "^2.1.4",
"eslint": "^9.9.0",
"mocha": "^10.0.0",
"puppeteer": "^23.0.2",
"sinon": "^17.0.0",
"typescript": "~5.6.2"
"playwright": "^1.48.2",
"typescript": "~5.6.2",
"vitest": "^2.1.4"
},
"//sampleConfiguration": {
"productName": "Azure Identity Brokered Auth Plugin",
Expand All @@ -92,5 +88,38 @@
"requiredResources": {
"Microsoft Entra App Registration": "https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app"
}
},
"type": "module",
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
},
"dialects": [
"esm",
"commonjs"
],
"esmDialects": [
"browser"
],
"selfLink": false
},
"browser": "./dist/browser/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"browser": {
"types": "./dist/browser/index.d.ts",
"default": "./dist/browser/index.js"
},
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
}
}
16 changes: 14 additions & 2 deletions sdk/identity/identity-broker/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import type { AzurePluginContext } from "../../identity/src/plugins/provider";
import type { IdentityPlugin } from "@azure/identity";
import { NativeBrokerPlugin } from "@azure/msal-node-extensions";

/**
* A subset of the AzurePluginContext provided by \@azure/identity
*
* @internal
*/
interface AzurePluginContext {
nativeBrokerPluginControl: NativeBrokerPluginControl;
}

interface NativeBrokerPluginControl {
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
setNativeBroker(nativeBroker: import("@azure/msal-node").INativeBrokerPlugin): void;
}

/**
* A plugin that provides WAM Integration for `@azure/identity`
* credentials. The plugin API is compatible with `@azure/identity` versions
Expand All @@ -26,7 +39,6 @@ import { NativeBrokerPlugin } from "@azure/msal-node-extensions";
* });
* ```
*/

export const nativeBrokerPlugin: IdentityPlugin = (context: unknown) => {
const { nativeBrokerPluginControl } = context as AzurePluginContext;
const brokerPlugin = new NativeBrokerPlugin();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,42 @@
// Licensed under the MIT License.
import type { InteractiveBrowserCredentialNodeOptions } from "@azure/identity";
import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity";
import type { MsalTestCleanup } from "../../../../identity/test/node/msalNodeTestSetup";
import { msalNodeTestSetup } from "../../../../identity/test/node/msalNodeTestSetup";
import { PublicClientApplication } from "@azure/msal-node";
import type Sinon from "sinon";
import type { Recorder } from "@azure-tools/test-recorder";
import { isLiveMode, env, isPlaybackMode } from "@azure-tools/test-recorder";
import { nativeBrokerPlugin } from "../../../src";
import { nativeBrokerPlugin } from "../../../src/index.js";
import { isNodeLike } from "@azure/core-util";
import { assert } from "@azure-tools/test-utils";
import type http from "http";
import type http from "node:http";
import type { MockInstance } from "vitest";
import { describe, it, assert, expect, vi, beforeEach, afterEach } from "vitest";

describe("InteractiveBrowserCredential (internal)", function (this: Mocha.Suite) {
let cleanup: MsalTestCleanup;
describe("InteractiveBrowserCredential (internal)", function () {
let listen: http.Server | undefined;
let doGetTokenSpy: Sinon.SinonSpy;
let doGetTokenSpy: MockInstance;
let recorder: Recorder;

beforeEach(async function (this: Mocha.Context) {
const setup = await msalNodeTestSetup(this.currentTest);
cleanup = setup.cleanup;
recorder = setup.recorder;

// getTokenSilentSpy = setup.sandbox.spy(MsalNode.prototype, "getTokenSilent");

doGetTokenSpy = setup.sandbox.spy(PublicClientApplication.prototype, "acquireTokenInteractive");
beforeEach(async function (ctx) {
doGetTokenSpy = vi.spyOn(PublicClientApplication.prototype, "acquireTokenInteractive");
});

afterEach(async function () {
if (listen) {
listen.close();
}

await cleanup();
vi.restoreAllMocks();
});
it("Throws error when no plugin is imported", async function (this: Mocha.Context) {

it("Throws error when no plugin is imported", async function (ctx) {
if (isNodeLike) {
// OSX asks for passwords on CI, so we need to skip these tests from our automation
if (process.platform !== "win32") {
this.skip();
ctx.skip();
}
// These tests should not run live because this credential requires user interaction.
// currently test with broker is hanging, so skipping in playback mode for the ci
if (isLiveMode() || isPlaybackMode()) {
this.skip();
ctx.skip();
}
const winHandle = Buffer.from("srefleqr93285329lskadjffa");
const interactiveBrowserCredentialOptions: InteractiveBrowserCredentialNodeOptions = {
Expand All @@ -61,19 +54,19 @@ describe("InteractiveBrowserCredential (internal)", function (this: Mocha.Suite)
);
}, "Broker for WAM was requested to be enabled, but no native broker was configured.");
} else {
this.skip();
ctx.skip();
}
});
it("Accepts interactiveBrowserCredentialOptions", async function (this: Mocha.Context) {
it("Accepts interactiveBrowserCredentialOptions", async function (ctx) {
if (isNodeLike) {
// OSX asks for passwords on CI, so we need to skip these tests from our automation
if (process.platform !== "win32") {
this.skip();
ctx.skip();
}
// These tests should not run live because this credential requires user interaction.
// currently test with broker is hanging, so skipping in playback mode for the ci
if (isLiveMode() || isPlaybackMode()) {
this.skip();
ctx.skip();
}
useIdentityPlugin(nativeBrokerPlugin);
const winHandle = Buffer.from("srefleqr93285329lskadjffa");
Expand All @@ -94,15 +87,16 @@ describe("InteractiveBrowserCredential (internal)", function (this: Mocha.Suite)
try {
const accessToken = await credential.getToken(scope);
assert.exists(accessToken.token);
assert.equal(doGetTokenSpy.callCount, 1);
const result = await doGetTokenSpy.lastCall.returnValue;
assert.equal(result.fromNativeBroker, true);
expect(doGetTokenSpy).toHaveBeenCalledOnce();
expect(doGetTokenSpy.mock.results[0].value).toEqual(
expect.objectContaining({ fromNativeBroker: true }),
);
} catch (e) {
console.log(e);
assert.equal(doGetTokenSpy.callCount, 1);
expect(doGetTokenSpy).toHaveBeenCalledOnce();
}
} else {
this.skip();
ctx.skip();
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
SendRequest,
PipelinePolicy,
} from "@azure/core-rest-pipeline";
import { createTokenCycler } from "./popTokenCycler";
import { createTokenCycler } from "./popTokenCycler.js";

/**
* The programmatic identifier of the popTokenAuthenticationPolicy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import {
createPipelineRequest,
createDefaultHttpClient,
} from "@azure/core-rest-pipeline";
import { popTokenAuthenticationPolicy } from "./popTokenAuthenticationPolicy";
import { popTokenAuthenticationPolicy } from "./popTokenAuthenticationPolicy.js";
import type { TokenCredential } from "@azure/core-auth";
import { authorizeRequestOnPopTokenChallenge } from "./authRequestPopTokenChallenge";
import { authorizeRequestOnPopTokenChallenge } from "./authRequestPopTokenChallenge.js";

export async function sendGraphRequest(credential: TokenCredential): Promise<PipelineResponse> {
const pipeline = createEmptyPipeline();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import type { InteractiveBrowserCredentialNodeOptions } from "@azure/identity";
import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity";

import { env, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder";
import { nativeBrokerPlugin } from "../../../src";
import { nativeBrokerPlugin } from "../../../src/index.js";
import { isNodeLike } from "@azure/core-util";
import { sendGraphRequest } from "./popTokenClient";
import { assert } from "@azure-tools/test-utils";
import { sendGraphRequest } from "./popTokenClient.js";
import { describe, it, assert } from "vitest";

describe("InteractiveBrowserCredential", function (this: Mocha.Suite) {
it("supports pop token authentication", async function (this: Mocha.Context) {
describe("InteractiveBrowserCredential", function () {
it("supports pop token authentication", async function (ctx) {
if (isNodeLike) {
// OSX asks for passwords on CI, so we need to skip these tests from our automation
if (process.platform !== "win32") {
this.skip();
ctx.skip();
}
if (isLiveMode() || isPlaybackMode()) {
this.skip();
ctx.skip();
}
useIdentityPlugin(nativeBrokerPlugin);
const winHandle = Buffer.from("srefleqr93285329lskadjffa");
Expand All @@ -35,7 +35,7 @@ describe("InteractiveBrowserCredential", function (this: Mocha.Suite) {
assert.equal(response.status, 200);
assert.exists(response.bodyAsText);
} else {
this.skip();
ctx.skip();
}
});
});
1 change: 1 addition & 0 deletions sdk/identity/identity-broker/test/snippets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { InteractiveBrowserCredential, useIdentityPlugin } from "@azure/identity";
import { nativeBrokerPlugin } from "@azure/identity-broker";
import { setLogLevel } from "@azure/logger";
import { describe, it } from "vitest";

describe("snippets", function () {
it("getting_started", function () {
Expand Down
10 changes: 10 additions & 0 deletions sdk/identity/identity-broker/tsconfig.browser.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./.tshy/build.json",
"include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts", "./test/**/*.mts"],
"exclude": ["./test/**/node/**/*.ts"],
"compilerOptions": {
"outDir": "./dist-test/browser",
"rootDir": ".",
"skipLibCheck": true
}
}
Loading

0 comments on commit 86ed16f

Please sign in to comment.