Skip to content

Commit

Permalink
chore: Refactor to bun workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 committed Aug 13, 2024
1 parent 262abf7 commit b9e5adf
Show file tree
Hide file tree
Showing 53 changed files with 280 additions and 7,083 deletions.
1 change: 0 additions & 1 deletion .github/workflows/publish-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ jobs:
if: ${{ steps.changelog.outputs.skipped == 'false' }}
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
pnpm build:dependencies
pnpm build
pnpm publish
working-directory: packages/${{ matrix.package }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ coverage
/docs/.vitepress/cache
.DS_Store
tsconfig.vitest-temp.json
/.cache
.output
.wxt
4 changes: 0 additions & 4 deletions .husky/pre-commit

This file was deleted.

Binary file added bun.lockb
Binary file not shown.
145 changes: 80 additions & 65 deletions docs/.vitepress/plugins/typescript-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ async function generateProjectDocs(
const publicSymbols = getPublicSymbols(project, entrypoints);
// Sort alphabetically
publicSymbols.sort((l, r) => l.getName().toLowerCase().localeCompare(r.getName().toLowerCase()));
const docs = renderDocs(projectDirname, project, publicSymbols);
const docs = await renderDocs(projectDirname, project, publicSymbols);
publicSymbols.forEach(s => {
(ctx.symbolMap[s.getName()] ??= []).push(projectDirname);
});
Expand Down Expand Up @@ -351,14 +351,24 @@ function collectReferencedSymbols(node: Node, symbols: Symbol[]): void {
warn(`Unknown kind, cannot extract symbols: ${node.getKindName()}`);
}

function renderDocs(projectDirname: string, project: Project, symbols: Symbol[]): string {
async function renderDocs(
projectDirname: string,
project: Project,
symbols: Symbol[],
): Promise<string> {
const renderedSymbols = await Promise.all(
symbols.map(async symbol => {
const rendered = await renderSymbol(project, symbol);
return rendered.trim();
}),
);
const sections = [
// Header
`<!-- GENERATED FILE, DO NOT EDIT -->`,
`# API Reference - \`${projectDirname}\``,
`> [\`@webext-core/${projectDirname}\`](/guide/${projectDirname}/)`,
// Symbols
...symbols.map(symbol => renderSymbol(project, symbol).trim()),
...renderedSymbols,
// Footer
'<br/><br/>',
'---',
Expand All @@ -367,9 +377,9 @@ function renderDocs(projectDirname: string, project: Project, symbols: Symbol[])
return sections.join('\n\n');
}

function renderSymbol(project: Project, symbol: Symbol): string {
async function renderSymbol(project: Project, symbol: Symbol): Promise<string> {
const { examples, description, parameters, returns, deprecated } = parseJsdoc(symbol);
const typeDefinition = getTypeDeclarations(project, symbol).join('\n\n');
const typeDefinition = (await getTypeDeclarations(project, symbol)).join('\n\n');
const properties: string[] = symbol
.getDeclarations()
.flatMap(dec => dec.asKind(ts.SyntaxKind.InterfaceDeclaration))
Expand Down Expand Up @@ -442,68 +452,73 @@ function cleanTypeText(text: string): string {
return text;
}

function getTypeDeclarations(project: Project, symbol: Symbol): string[] {
return symbol
.getDeclarations()
.flatMap(dec => {
// Remove body from function declarations.
if (dec.isKind(ts.SyntaxKind.FunctionDeclaration)) dec.setBodyText('// ...');

const text = cleanTypeText(dec.getText());
// console.log(text);

// text ~= "() => void"
if (dec.isKind(ts.SyntaxKind.FunctionType)) return text;
// text ~= "type Abc = Something"
if (dec.isKind(ts.SyntaxKind.TypeAliasDeclaration)) return text;
// text ~= "interface Abc { ... }"
if (dec.isKind(ts.SyntaxKind.InterfaceDeclaration)) return text;
// text ~= "function abc() { ... }"
if (dec.isKind(ts.SyntaxKind.FunctionDeclaration)) return text;
// text ~= "T"
if (dec.isKind(ts.SyntaxKind.TypeParameter)) return text;
// text ~= "varName = ...";
if (dec.isKind(ts.SyntaxKind.VariableDeclaration)) {
const name = dec.getName();
let declarationKeyword = dec.getVariableStatementOrThrow().getDeclarationKind();
const type = cleanTypeText(dec.getType().getText());
return `${declarationKeyword} ${name}: ${type}`;
}
// text ~= "class ... extends { ... }";
if (dec.isKind(ts.SyntaxKind.ClassDeclaration)) {
const w = new CodeBlockWriter();
const extend = dec.getExtends();
w.write(`class ${dec.getName()} `)
.conditionalWrite(!!extend, () => `extends ${extend?.getText()} `)
.inlineBlock(() => {
dec.getStaticMethods().forEach(method => {
if (method.hasModifier(ts.SyntaxKind.PrivateKeyword)) return;
w.writeLine(method.getText().replace(method.getBodyText() ?? '', '// ...'));
});
dec.getConstructors().forEach(con => {
if (con.hasModifier(ts.SyntaxKind.PrivateKeyword)) return;
w.writeLine(
con
.getText()
.replace(con.getBodyText() ?? '', '// ...')
.replace(/(private|readonly) /g, ''),
);
});
dec.getMethods().forEach(method => {
if (method.hasModifier(ts.SyntaxKind.PrivateKeyword)) return;
w.writeLine(method.getText().replace(method.getBodyText() ?? '', '// ...'));
async function getTypeDeclarations(project: Project, symbol: Symbol): Promise<string[]> {
return await Promise.all(
symbol
.getDeclarations()
.flatMap(dec => {
// Remove body from function declarations.
if (dec.isKind(ts.SyntaxKind.FunctionDeclaration)) dec.setBodyText('// ...');

const text = cleanTypeText(dec.getText());
// console.log(text);

// text ~= "() => void"
if (dec.isKind(ts.SyntaxKind.FunctionType)) return text;
// text ~= "type Abc = Something"
if (dec.isKind(ts.SyntaxKind.TypeAliasDeclaration)) return text;
// text ~= "interface Abc { ... }"
if (dec.isKind(ts.SyntaxKind.InterfaceDeclaration)) return text;
// text ~= "function abc() { ... }"
if (dec.isKind(ts.SyntaxKind.FunctionDeclaration)) return text;
// text ~= "T"
if (dec.isKind(ts.SyntaxKind.TypeParameter)) return text;
// text ~= "varName = ...";
if (dec.isKind(ts.SyntaxKind.VariableDeclaration)) {
const name = dec.getName();
let declarationKeyword = dec.getVariableStatementOrThrow().getDeclarationKind();
const type = cleanTypeText(dec.getType().getText());
return `${declarationKeyword} ${name}: ${type}`;
}
// text ~= "class ... extends { ... }";
if (dec.isKind(ts.SyntaxKind.ClassDeclaration)) {
const w = new CodeBlockWriter();
const extend = dec.getExtends();
w.write(`class ${dec.getName()} `)
.conditionalWrite(!!extend, () => `extends ${extend?.getText()} `)
.inlineBlock(() => {
dec.getStaticMethods().forEach(method => {
if (method.hasModifier(ts.SyntaxKind.PrivateKeyword)) return;
w.writeLine(method.getText().replace(method.getBodyText() ?? '', '// ...'));
});
dec.getConstructors().forEach(con => {
if (con.hasModifier(ts.SyntaxKind.PrivateKeyword)) return;
w.writeLine(
con
.getText()
.replace(con.getBodyText() ?? '', '// ...')
.replace(/(private|readonly) /g, ''),
);
});
dec.getMethods().forEach(method => {
if (method.hasModifier(ts.SyntaxKind.PrivateKeyword)) return;
w.writeLine(method.getText().replace(method.getBodyText() ?? '', '// ...'));
});
});
});
return w.toString();
}
return w.toString();
}

throw Error(
`ts.SyntaxKind.${dec.getKindName()} cannot convert to type declaration:\n${
dec.getText().split('\n')[0]
}`,
);
})
.map(text => prettier.format(text, { printWidth: 80, parser: 'typescript' }).trimEnd());
throw Error(
`ts.SyntaxKind.${dec.getKindName()} cannot convert to type declaration:\n${
dec.getText().split('\n')[0]
}`,
);
})
.map(async text => {
const res = await prettier.format(text, { printWidth: 80, parser: 'typescript' });
return res.trimEnd();
}),
);
}

function warn(message: string) {
Expand Down
11 changes: 9 additions & 2 deletions docs/api/isolated-element.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

```ts
async function createIsolatedElement(
options: CreateIsolatedElementOptions
options: CreateIsolatedElementOptions,
): Promise<{
parentElement: HTMLElement;
isolatedElement: HTMLElement;
Expand Down Expand Up @@ -36,6 +36,7 @@ Create an HTML element that has isolated styles from the rest of the page.
const { isolatedElement, parentElement } = createIsolatedElement({
name: 'example-ui',
css: { textContent: "p { color: red }" },
isolateEvents: true // or ['keydown', 'keyup', 'keypress']
});

// Create and mount your app inside the isolation
Expand All @@ -54,19 +55,25 @@ interface CreateIsolatedElementOptions {
name: string;
mode?: "open" | "closed";
css?: { url: string } | { textContent: string };
isolateEvents?: boolean | string[];
}
```

Options that can be passed into `createIsolatedElement`.

### Properties

- ***`name: string`***<br/>A unique tag name used when defining the web component used internally. Don't use the same name twice for different UIs.
- ***`name: string`***<br/>A unique HTML tag name (two words, kebab case - [see spec](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name)) used when defining the web component used internally. Don't use the same name twice for different UIs.

- ***`mode?: 'open' | 'closed'`*** (default: `'closed'`)<br/>See [`ShadowRoot.mode`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/mode).

- ***`css?: { url: string } | { textContent: string }`***<br/>Either the URL to a CSS file or the text contents of a CSS file. The styles will be mounted inside the shadow DOM so they don't effect the rest of the page.

- ***`isolateEvents?: boolean | string[]`***<br/>When enabled, `event.stopPropagation` will be called on events trying to bubble out of the shadow root.

- Set to `true` to stop the propagation of a default set of events, `["keyup", "keydown", "keypress"]`
- Set to an array of event names to stop the propagation of a custom list of events

<br/><br/>

---
Expand Down
4 changes: 2 additions & 2 deletions docs/api/job-scheduler.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ interface JobScheduler {
removeJob(jobId: string): Promise<void>;
on(
event: "success",
callback: (job: Job, result: any) => void
callback: (job: Job, result: any) => void,
): RemoveListenerFn;
on(
event: "error",
callback: (job: Job, error: unknown) => void
callback: (job: Job, error: unknown) => void,
): RemoveListenerFn;
}
```
Expand Down
22 changes: 11 additions & 11 deletions docs/api/messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Messenger returned by `defineCustomEventMessenger`.

```ts
function defineCustomEventMessaging<
TProtocolMap extends Record<string, any> = Record<string, any>
TProtocolMap extends Record<string, any> = Record<string, any>,
>(config: CustomEventMessagingConfig): CustomEventMessenger<TProtocolMap> {
// ...
}
Expand Down Expand Up @@ -89,7 +89,7 @@ websiteMessenger.onMessage("initInjectedScript", (...) => {

```ts
function defineExtensionMessaging<
TProtocolMap extends Record<string, any> = Record<string, any>
TProtocolMap extends Record<string, any> = Record<string, any>,
>(config?: ExtensionMessagingConfig): ExtensionMessenger<TProtocolMap> {
// ...
}
Expand All @@ -104,7 +104,7 @@ It can be used to send messages to and from the background page/service worker.

```ts
function defineWindowMessaging<
TProtocolMap extends Record<string, any> = Record<string, any>
TProtocolMap extends Record<string, any> = Record<string, any>,
>(config: WindowMessagingConfig): WindowMessenger<TProtocolMap> {
// ...
}
Expand Down Expand Up @@ -183,7 +183,7 @@ You cannot message between tabs directly. It must go through the background scri
interface GenericMessenger<
TProtocolMap extends Record<string, any>,
TMessageExtension,
TSendMessageArgs extends any[]
TSendMessageArgs extends any[],
> {
sendMessage<TType extends keyof TProtocolMap>(
type: TType,
Expand All @@ -193,8 +193,8 @@ interface GenericMessenger<
onMessage<TType extends keyof TProtocolMap>(
type: TType,
onReceived: (
message: Message<TProtocolMap, TType> & TMessageExtension
) => void | MaybePromise<GetReturnType<TProtocolMap[TType]>>
message: Message<TProtocolMap, TType> & TMessageExtension,
) => void | MaybePromise<GetReturnType<TProtocolMap[TType]>>,
): RemoveListenerCallback;
removeAllListeners(): void;
}
Expand All @@ -216,8 +216,8 @@ type GetDataType<T> = T extends (...args: infer Args) => any
? Args[0]
: never
: T extends ProtocolWithReturn<any, any>
? T["BtVgCTPYZu"]
: T;
? T["BtVgCTPYZu"]
: T;
```

Given a function declaration, `ProtocolWithReturn`, or a value, return the message's data type.
Expand All @@ -228,8 +228,8 @@ Given a function declaration, `ProtocolWithReturn`, or a value, return the messa
type GetReturnType<T> = T extends (...args: any[]) => infer R
? R
: T extends ProtocolWithReturn<any, any>
? T["RrhVseLgZW"]
: void;
? T["RrhVseLgZW"]
: void;
```

Given a function declaration, `ProtocolWithReturn`, or a value, return the message's return type.
Expand Down Expand Up @@ -261,7 +261,7 @@ async.
```ts
interface Message<
TProtocolMap extends Record<string, any>,
TType extends keyof TProtocolMap
TType extends keyof TProtocolMap,
> {
id: number;
data: GetDataType<TProtocolMap[TType]>;
Expand Down
17 changes: 8 additions & 9 deletions docs/api/proxy-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
type DeepAsync<TService> = TService extends (...args: any) => any
? ToAsyncFunction<TService>
: TService extends { [key: string]: any }
? {
[fn in keyof TService]: DeepAsync<TService[fn]>;
}
: never;
? {
[fn in keyof TService]: DeepAsync<TService[fn]>;
}
: never;
```

A recursive type that deeply converts all methods in `TService` to be async.
Expand All @@ -24,10 +24,10 @@ A recursive type that deeply converts all methods in `TService` to be async.
function defineProxyService<TService extends Service, TArgs extends any[]>(
name: string,
init: (...args: TArgs) => TService,
config?: ProxyServiceConfig
config?: ProxyServiceConfig,
): [
registerService: (...args: TArgs) => TService,
getService: () => ProxyService<TService>
getService: () => ProxyService<TService>,
] {
// ...
}
Expand Down Expand Up @@ -81,9 +81,8 @@ function createService(dependencyPromise: Promise<SomeDependency>) {
## `ProxyService`

```ts
type ProxyService<TService> = TService extends DeepAsync<TService>
? TService
: DeepAsync<TService>;
type ProxyService<TService> =
TService extends DeepAsync<TService> ? TService : DeepAsync<TService>;
```

A type that ensures a service has only async methods.
Expand Down
Loading

0 comments on commit b9e5adf

Please sign in to comment.