Skip to content

Commit

Permalink
feat: add pack-up package (#18233)
Browse files Browse the repository at this point in the history
* feat(pack-up): add build command (#18058)

* chore: lint order of imports

* feat(pack-up): add watch command (#18121)

* feat: add watch command

feat: add ts watch task

* chore: pr amends

* fix: promptUser linter

* chore: remove \n with os.EOL

* feat(pack-up): add init command (#18133)

* feat(pack-up): add build command (#18058)

* feat(pack-up): add watch command (#18121)

* feat: add watch command

feat: add ts watch task

* chore: pr amends

* fix: promptUser linter

* chore: remove \n with os.EOL

* feat: add init command

fix: build

feat: add default template and tests

* chore: pr amends

* Update packages/utils/pack-up/tests/console.ts

Co-authored-by: Ben Irvin <ben@innerdvations.com>

* chore: re-add mock

* chore: fix tsconfig

* chore: fix inquirer types due to rxjs inclusion

* Update packages/utils/pack-up/src/node/templates/internal/files/typescript.ts

* chore: fix inquirer types

---------

Co-authored-by: Ben Irvin <ben@innerdvations.com>

* feat(pack-up): add check command (#18183)

* feat: add check command

* chore: reintroduce CLI tests

* fix: add build command to `prepublishOnly`

* docs(pack-up): add readme and contributor docs (#18237)

* chore: update README

* docs(pack-up): add contributor documentation

* chore: update overview doc to be clearer

* fix(pack-up): init command (#18245)

* fix: init command bugs

* fix: node tests

* fix: template exports ordering & file extensions

* test(upload): double timeout on UploadAssetDialog test

---------

Co-authored-by: Ben Irvin <ben@innerdvations.com>
  • Loading branch information
joshuaellis and innerdvations committed Oct 5, 2023
1 parent ce44a1c commit e5078d5
Show file tree
Hide file tree
Showing 87 changed files with 6,129 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ jobs:
uses: ./.github/actions/yarn-nm-install
- name: Run build:ts
run: yarn nx run-many --target=build:ts --nx-ignore-cycles --skip-nx-cache
- name: Run build
run: yarn build --projects=@strapi/pack-up --skip-nx-cache
- name: Run tests
run: yarn nx affected --target=test:unit --nx-ignore-cycles

Expand Down
6 changes: 6 additions & 0 deletions docs/docs/docs/05-utils/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"position": 5,
"label": "Utils",
"collapsible": true,
"collapsed": false
}
33 changes: 33 additions & 0 deletions docs/docs/docs/05-utils/pack-up/00-intro.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Introduction
tags:
- pack-up
- bundling
- packages
---

## What is pack-up?

Pack-Up is primarily a CLI interface to develop & build CJS/ESM interopable (meaning you can import your library in either environment with little effort)
packages. It's built on top of [vite](https://vitejs.dev/), but also utilises [esbuild](https://esbuild.github.io/) for certain parts. It also offers a
node API that can be used to build other tools on top of it.

It's designed to have as little dependencies as possible making it easier to react to changes in the ecosystem as and when we need too.
The configuration format at present is limited and is expected to grow with real-world requirements.

## Why do we need it?

Creating packages that work in both CJS and ESM environments is a pain. This tooling library aims to make it easier for _all_ developers,
if you're creating _any_ new project you should bundle your code and therefore use this tool to initialise / build & check the project.
We use internally to bundle all our libraries. Strapi also has it's own plugin system that realistically benefits from having the code bundled
for both the client and server packages of said plugins. Initially we wanted to keep this inside the `@strapi/strapi` package but realised
soon after that this package was required to be more low level than the former.

## Further reading

import DocCardList from '@theme/DocCardList';
import { useCurrentSidebarCategory } from '@docusaurus/theme-common';

<DocCardList
items={useCurrentSidebarCategory().items.filter((item) => item.label !== 'Introduction')}
/>
17 changes: 17 additions & 0 deletions docs/docs/docs/05-utils/pack-up/01-commands/00-overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: Overview
tags:
- pack-up
- CLI
---

Each command has a `node` api equivalent. This is useful if you want to use `pack-up` in your own scripts.

## Commands

import DocCardList from '@theme/DocCardList';
import { useCurrentSidebarCategory } from '@docusaurus/theme-common';

<DocCardList
items={useCurrentSidebarCategory().items.filter((item) => item.label !== 'Overview')}
/>
48 changes: 48 additions & 0 deletions docs/docs/docs/05-utils/pack-up/01-commands/01-init.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: Init
tags:
- pack-up
- CLI
---

## Usage

```bash
$ npx @strapi/pack-up init my-package
```

Creates a new package at the given path, by default uses the inbuilt template sensible options for your package to choose from.

### Options

- `--template [path]` – path to a custom template of type `TemplateOrTemplateResolver`.

## API

### Usage

```ts
import { init } from '@strapi/pack-up';

init({
path: 'my-package',
});
```

## Typescript

```ts
interface InitOptions {
cwd?: string;
debug?: boolean;
path: string;
silent?: boolean;
template?: TemplateOrTemplateResolver | string;
}

type Init = (options: InitOptions) => Promise<void>;

type TemplateOrTemplateResolver = Template | TemplateResolver;
```

You can see `Template` and `TemplateResolver` in on [Templates](/docs/utils/pack-up/templates#template)
43 changes: 43 additions & 0 deletions docs/docs/docs/05-utils/pack-up/01-commands/02-build.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Build
tags:
- pack-up
- CLI
---

## Usage

```bash
$ yarn pack-up build
```

Builds your current package based on the configuration in your `package.json` and `package.config.ts` (if applicable).

### Options

- `--minify` – minifies the output (default `false`).
- `--sourcemap` – generates sourcemaps for the output (default `true`).

## API

### Usage

```ts
import { build } from '@strapi/pack-up';

build();
```

## Typescript

```ts
interface BuildOptions {
cwd?: string;
debug?: boolean;
minify?: boolean;
silent?: boolean;
sourcemap?: boolean;
}

type Build = (options?: BuildOptions) => Promise<void>;
```
37 changes: 37 additions & 0 deletions docs/docs/docs/05-utils/pack-up/01-commands/03-check.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Check
tags:
- pack-up
- CLI
---

## Usage

```bash
$ yarn pack-up check
```

Checks your current package to ensure it's interoperable in the real world. In short, validates the files
in your dist have been produced as we expect & then `esbuild` can actually build, using your exported code.

## API

### Usage

```ts
import { check } from '@strapi/pack-up';

check();
```

## Typescript

```ts
interface CheckOptions {
cwd?: string;
debug?: boolean;
silent?: boolean;
}

type Check = (options?: CheckOptions) => Promise<void>;
```
36 changes: 36 additions & 0 deletions docs/docs/docs/05-utils/pack-up/01-commands/04-watch.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: Watch
tags:
- pack-up
- CLI
---

## Usage

```bash
$ yarn pack-up watch
```

Watches your current package for changes and rebuilds when necessary.

## API

### Usage

```ts
import { watch } from '@strapi/pack-up';

watch();
```

## Typescript

```ts
interface WatchOptions {
cwd?: string;
debug?: boolean;
silent?: boolean;
}

type Watch = (options?: WatchOptions) => Promise<void>;
```
6 changes: 6 additions & 0 deletions docs/docs/docs/05-utils/pack-up/01-commands/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"position": 1,
"label": "Commands",
"collapsible": true,
"collapsed": true
}
69 changes: 69 additions & 0 deletions docs/docs/docs/05-utils/pack-up/02-config.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: Configuration
tags:
- pack-up
- configuration
- configs
---

# Configuring pack-up

By default, `pack-up` is designed to use the `package.json` as a source of truth to bundle your package.
This creates a seemless alignment between the bundling & publishing process. However, if you require more
flexibility, `pack-up` also supports a configuration file – `packup.config.[mtj]s`.

## Usage

```ts
// package.config.ts
import { defineConfig } from '@strapi/pack-up';

export default defineConfig({
minify: true,
sourcemap: false,
externals: ['path', 'fs'],
});
```

## Interface

```ts
interface Config {
/**
* An array of entry points to bundle. This is useful if you want to bundle something that should not
* be exported by the package, e.g. CLI scripts or Node.js workers.
*/
bundles?: ConfigBundle[];
/**
* The directory to output the bundle to.
*/
dist?: string;
/**
* A list of external dependencies to exclude from the bundle.
* We already collect the dependencies & peerDeps from the package.json.
*/
externals?: string[];
/**
* Whether to minify the output or not.
*/
minify?: boolean;
/**
* Whether to generate sourcemaps for the output or not.
*/
sourcemap?: boolean;
/**
* The transpilation target of the bundle. This is useful if you're bundling many different CLIs or
* Node.js workers and you want them to be transpiled for the node environment.
*/
runtime?: Runtime;
}

interface ConfigBundle {
source: string;
import?: string;
require?: string;
runtime?: Runtime;
}

type Runtime = '*' | 'node' | 'web';
```
81 changes: 81 additions & 0 deletions docs/docs/docs/05-utils/pack-up/03-templates.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
title: Templates
tags:
- pack-up
- generating
- template
---

Templates are only used for the `init` api. You can either pass a path to the file containing your template (it's expected to be
a default export) if you're using the CLI. Or alternatively, if you're using the node functions then you can directly pass your template.

A template can either be an object (defined below) or a function returning said object. The function recieves an initiatialisation context
to be utilised at the discretion of the template author.

## Interfaces

### Template

```ts
interface Template {
/**
* If you're not using a template in a CLI environment,
* it's not recommended to use prompts. Instead, you should
* just return all the files your template needs in from the
* `getFiles` function.
*/
prompts?: Array<TemplateFeature | TemplateOption>;
/**
* A dictionary of the files that will be created in the
* new package. The key is the file name and the value is
* the file contents, we prettify the contents before writing
* using a default config if there's not one in the package.
*/
getFiles: (answers?: Array<{ name: string; answer: string }>) => Promise<Array<TemplateFile>>;
}

interface TemplateContext {
cwd: string;
logger: Logger;
packagePath: string;
}

type TemplateResolver = (ctx: TemplateContext) => Promise<Template>;
```

### Template Features & Options

Features & options are restricted just [prompts](https://github.com/terkelg/prompts). All features are boolean
answers using the `confirm` type. Options have a lot more flexibility and can be used to capture information.

```ts
interface TemplateFeature<T extends string = string>
extends Pick<prompts.PromptObject<T>, 'initial'> {
/**
* Name of the feature you want to add to your package.
* This must be identical to the name of the feature on npm.
*/
name: string;
/**
* @default true
*/
optional?: boolean;
}

interface TemplateOption<T extends string = string>
extends Omit<prompts.PromptObject<T>, 'onState' | 'onRender' | 'stdout' | 'stdin' | 'name'> {
name: string;
}
```

### Template file

Files are just objects with a name and contents. It's advised to use a library like `outdent` to handle indentation in
your file contents. Although the API will try to prettyify your files before writing them.

```ts
interface TemplateFile {
name: string;
contents: string;
}
```

0 comments on commit e5078d5

Please sign in to comment.