Skip to content

Commit

Permalink
Merge changes from topic "api-extractor"
Browse files Browse the repository at this point in the history
* changes:
  Use API Extractor in build.mjs
  Remove print-module-api and API txt files

GitOrigin-RevId: 51e8d78ef38bbbc5046dffdf31d27247a9b0db85
  • Loading branch information
jaslong authored and Copybara committed Nov 8, 2023
1 parent 60e1945 commit 5c7f191
Show file tree
Hide file tree
Showing 56 changed files with 2,003 additions and 209 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# Local .terraform directories
**/.terraform/*
**/.vscode/
**/api/temp
**/api/tsc
*.pyc
# .tfstate files
*.tfstate
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ repos:
hooks:
- id: prettier
name: Run prettier on code written by humans
files: ^.*\.(js|jsx|ts|tsx|json|css|scss|md|toml|xml)$
exclude: (^.*/(plasmic|deps|static|\.yalc)/.*$|.md$)|(^loader-tests/data/.*\.json$)|examples/hydrogen-.*
files: ^.*\.(js|jsx|cjs|mjs|ts|tsx|cts|mts|json|css|scss|md|toml|xml)$
exclude: (^.*/(plasmic|deps|static|\.yalc)/.*$)|(^loader-tests/data/.*\.json$)|(examples/hydrogen-.*)|(api/.*\.md$)
env:
NODE_OPTIONS: "--max-old-space-size=4096"
additional_dependencies:
Expand Down
149 changes: 110 additions & 39 deletions build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,62 @@
* Validates package.json and builds bundles in a consistently across our packages.
*/

import fs from 'fs/promises';
import console from 'console';
import path from 'path';
import process from 'process';
import esbuild from 'esbuild';
import { Extractor, ExtractorConfig } from "@microsoft/api-extractor";
import console from "console";
import esbuild from "esbuild";
import fs from "fs/promises";
import path from "path";
import process from "process";

async function main() {
if (process.argv.length < 3) {
throw new Error('missing entry point');
throw new Error("missing entry point");
}

const entryPoint = process.argv[2];
const options = process.argv.slice(3);

const useClient = findAndRemoveOption(options, '--use-client');
const useClient = findAndRemoveOption(options, "--use-client");
// TODO: default ESM extension should be "mjs" once we figure out how to use .mjs properly
const defaultEsmExtension = "esm.js";
// Some packages may not work with a .mjs extension due to the stricter Node ES module rules.
// loader-react uses it for "react/jsx-runtime" imports.
// See https://app.shortcut.com/plasmic/story/33688/es-module-support for more details.
const esmExtension = findAndRemoveOption(options, '--no-esm') ? null : findAndRemoveOption(options, '--no-mjs') ? "esm.js" : defaultEsmExtension;
const watch = findAndRemoveOption(options, '--watch');
const esmExtension = findAndRemoveOption(options, "--no-esm")
? null
: findAndRemoveOption(options, "--no-mjs")
? "esm.js"
: defaultEsmExtension;
const watch = findAndRemoveOption(options, "--watch");
if (options.length > 0) {
throw new Error(`unknown or duplicate options: ${options.join(' ')}`);
throw new Error(`unknown or duplicate options: ${options.join(" ")}`);
}

const name = path.parse(entryPoint).name;
const subpath = name === "index" ? "." : `./${name}`;

const expectedPackageJson = generateExpectedPackageJson(name, esmExtension);
const expectedPackageJson = generateExpectedPackageJson(
name,
subpath,
esmExtension
);
const actualPackageJson = JSON.parse(
await fs.readFile(path.resolve('package.json'))
await fs.readFile(path.resolve("package.json"))
);
validatePackageJson(actualPackageJson, expectedPackageJson);
validatePackageJsonReactServerConditional(actualPackageJson);

const ctx = {
await buildBundle({
entryPoint,
name,
esmExtension,
useClient,
watch,
};

await buildBundle(ctx);
});
await extractApi({
name,
dtsRollupPath: expectedPackageJson.exports[subpath].types,
});
}

function findAndRemoveOption(options, option) {
Expand All @@ -57,23 +69,22 @@ function findAndRemoveOption(options, option) {
return found;
}

function generateExpectedPackageJson(name, esmExtension) {
const subpath = name === 'index' ? '.' : `./${name}`;
function generateExpectedPackageJson(name, subpath, esmExtension) {
const packageJson = {
exports: {
[subpath]: generateExpectedPackageJsonSubpath(name, esmExtension),
},
};

if (name === 'index') {
packageJson.types = './dist/index.d.ts';
packageJson.main = './dist/index.js';
if (name === "index") {
packageJson.types = "./dist/index.d.ts";
packageJson.main = "./dist/index.js";
if (esmExtension) {
// "index.esm.js" should be set as the "module" field for webpack 4 and other tools,
// since they don't support the "exports" field.
// We change the extension from ".mjs" to ".js" because ".mjs" doesn't work properly in webpack 4.
// https://github.com/adobe/react-spectrum/pull/4038
packageJson.module = './dist/index.esm.js';
packageJson.module = "./dist/index.esm.js";
}
}

Expand All @@ -96,14 +107,14 @@ function generateExpectedPackageJsonSubpath(name, esmExtension) {
}

/** Validates that `expected` is a subset of `actual`. Throws if not. */
function validatePackageJson(actual, expected, path = '') {
function validatePackageJson(actual, expected, path = "") {
for (const [key, expectedValue] of Object.entries(expected)) {
const nestedPath = path ? `${path} > "${key}"` : `"${key}"`;
const nestedPath = path ? `${path} > "${key}"` : `"${key}"`;
if (!(key in actual)) {
throw new Error(`package.json ${nestedPath} field missing`);
}

if (typeof expectedValue === 'string') {
if (typeof expectedValue === "string") {
if (expectedValue !== actual[key]) {
throw new Error(
`package.json ${nestedPath} field should be "${expectedValue}"`
Expand All @@ -116,29 +127,40 @@ function validatePackageJson(actual, expected, path = '') {
}

function validatePackageJsonReactServerConditional(packageJson) {
const indexSubpath = packageJson.exports['.']
const reactServerSubpath = packageJson.exports['./react-server']
const reactServerConditionalSubpath = packageJson.exports['./react-server-conditional']
const indexSubpath = packageJson.exports["."];
const reactServerSubpath = packageJson.exports["./react-server"];
const reactServerConditionalSubpath =
packageJson.exports["./react-server-conditional"];
if (indexSubpath && reactServerSubpath && reactServerConditionalSubpath) {
validatePackageJson(reactServerConditionalSubpath, {
'react-server': reactServerSubpath,
'default': indexSubpath
}, '"exports" > "./react-server-conditional"')
validatePackageJson(
reactServerConditionalSubpath,
{
"react-server": reactServerSubpath,
default: indexSubpath,
},
'"exports" > "./react-server-conditional"'
);
}
}

async function buildBundle({ entryPoint, name, esmExtension, useClient, watch }) {
const formats = esmExtension ? ['cjs', 'esm'] : ['cjs']
async function buildBundle({
entryPoint,
name,
esmExtension,
useClient,
watch,
}) {
const formats = esmExtension ? ["cjs", "esm"] : ["cjs"];
return Promise.all(
formats.map(async (format) => {
const outfile = `dist/${name}.${format === 'cjs' ? 'js' : esmExtension}`;
const outfile = `dist/${name}.${format === "cjs" ? "js" : esmExtension}`;
const esbuildOptions = {
bundle: true,
packages: 'external', // don't bundle node_modules
packages: "external", // don't bundle node_modules

entryPoints: [entryPoint],
format,
target: 'es6',
target: "es6",
outfile,

// This means we are not targeting node or browser specifically, which is
Expand Down Expand Up @@ -167,8 +189,8 @@ async function buildBundle({ entryPoint, name, esmExtension, useClient, watch })
// since they don't support the "exports" field.
// We change the extension from ".mjs" to ".js" because ".mjs" doesn't work properly in webpack 4.
// https://github.com/adobe/react-spectrum/pull/4038
if (outfile === 'dist/index.mjs') {
await fs.copyFile('dist/index.mjs', 'dist/index.esm.js');
if (outfile === "dist/index.mjs") {
await fs.copyFile("dist/index.mjs", "dist/index.esm.js");
console.info(
`built ${format.toUpperCase()} bundle at "dist/index.esm.js"`
);
Expand All @@ -178,6 +200,55 @@ async function buildBundle({ entryPoint, name, esmExtension, useClient, watch })
);
}

/**
* Runs API Extractor, which outputs the following:
* - `./api/${name}.api.md` - API report for diffing API changes.
* This file should be checked into version control.
* - `./dist/${name}.d.ts` - Rollup of TypeScript declaration files (.d.ts).
*
* Currently, this process depends on `tsc` being run externally with the
* TS config at `../../tsconfig.types.json` with output to `./api/tsc`.
* The reason `tsc` is not run in this script yet is because some packages run
* this script multiple times for multiple entry points, which would result in
* duplicative `tsc` runs.
*/
function extractApi({ name, dtsRollupPath }) {
const extractorConfig = ExtractorConfig.prepare({
configObject: {
apiReport: {
enabled: true,
reportFolder: path.resolve("./api"),
reportTempFolder: path.resolve("./api/temp"),
reportFileName: `${name}.api.md`,
},
compiler: {
tsconfigFilePath: path.resolve("./tsconfig.json"),
},
dtsRollup: {
enabled: true,
untrimmedFilePath: path.resolve(dtsRollupPath),
},
mainEntryPointFilePath: path.resolve(`./api/tsc/${name}.d.ts`),
newlineKind: "lf",
projectFolder: path.resolve("."),
},
packageJsonFullPath: path.resolve("./package.json"),
});
const extractorResult = Extractor.invoke(extractorConfig, {
showVerboseMessages: true,
// On local builds, API reports will automatically be updated.
// On CI builds, API report changes will result in a failed build.
localBuild: !process.env.CI,
});

if (!extractorResult.succeeded) {
throw new Error(
`API Extractor completed with ${extractorResult.errorCount} errors` +
` and ${extractorResult.warningCount} warnings`
);
}
}

try {
await main();
} catch (error) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"upgrade-internal": "bash scripts/upgrade-internal.bash"
},
"devDependencies": {
"@microsoft/api-extractor": "7.38.2",
"@size-limit/preset-small-lib": "8.2.4",
"@typescript-eslint/eslint-plugin": "5.59.0",
"@typescript-eslint/parser": "5.59.0",
Expand Down
60 changes: 60 additions & 0 deletions packages/auth-api/api/index.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## API Report File for "@plasmicapp/auth-api"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts

// @public (undocumented)
export const createPlasmicAppUser: typeof ensurePlasmicAppUser;

// @public (undocumented)
export function ensurePlasmicAppUser(opts: {
host?: string;
appSecret: string;
roleId?: string;
} & UserIdentifier): Promise<PlasmicUserResult>;

// @public (undocumented)
export function getPlasmicAppUser(opts: {
host?: string;
appId: string;
codeVerifier: string;
code: string;
}): Promise<PlasmicUserResult>;

// @public (undocumented)
export function getPlasmicAppUserFromToken(opts: {
host?: string;
token: string;
}): Promise<PlasmicUserResult>;

// @public (undocumented)
export interface PlasmicUser {
// (undocumented)
email: string;
// (undocumented)
properties: Record<string, unknown> | null;
// (undocumented)
roleId: string;
// (undocumented)
roleIds: string[];
// (undocumented)
roleName: string;
// (undocumented)
roleNames: string[];
}

// @public (undocumented)
export type PlasmicUserResult = {
user: null;
token: null;
error: Error;
} | {
user: PlasmicUser;
token: string;
error?: never;
};

// (No @packageDocumentation comment for this package)

```
2 changes: 1 addition & 1 deletion packages/auth-api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"extends": "../../tsconfig.types.json",
"include": ["./src"],
"compilerOptions": {
"outDir": "./dist"
"outDir": "./api/tsc"
}
}
24 changes: 24 additions & 0 deletions packages/auth-react/api/index.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## API Report File for "@plasmicapp/auth-react"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts

import { PlasmicUser } from '@plasmicapp/auth-api';

// @public
export function usePlasmicAuth(opts: {
host?: string;
appId?: string;
}): {
user: PlasmicUser | null | undefined;
token: string | null | undefined;
isUserLoading: boolean | undefined;
};


export * from "@plasmicapp/auth-api";

// (No @packageDocumentation comment for this package)

```
2 changes: 1 addition & 1 deletion packages/auth-react/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"extends": "../../tsconfig.types.json",
"include": ["./src"],
"compilerOptions": {
"outDir": "./dist"
"outDir": "./api/tsc"
}
}
Loading

0 comments on commit 5c7f191

Please sign in to comment.