Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions .changeset/stale-showers-write.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@wbce/projen-directus-extension": patch
"@wbce/projen-directus": patch
---

add readmes
86 changes: 85 additions & 1 deletion packages/directus-extension/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,85 @@
# replace this
# @wbce/projen-directus-extension

Projen constructs for authoring [d9](https://github.com/LaWebcapsule/d9) (Directus 9) extensions. Provides:

- `ExtensionFolder` — a pnpm workspace that holds extension packages
- `DirectusExtensionProject` — a TypeScript project for a single extension or a bundle of related extensions
- `DirectusExtensionType` — enum of supported extension kinds

This package is typically consumed via [`@wbce/projen-directus`](../directus), which wires up an `ExtensionFolder` automatically and exposes `project.addExtension(...)`.

## Usage

In a `DirectusProject`:

```js
import { DirectusProject } from '@wbce/projen-directus';
import { DirectusExtensionType } from '@wbce/projen-directus-extension';

const project = new DirectusProject({
name: 'my-d9',
defaultReleaseBranch: 'main',
});

// Single-type extension
project.addExtension('my-hook', [DirectusExtensionType.HOOK]);

// Bundle: multiple types in one package
project.addExtension('my-bundle', [
DirectusExtensionType.INTERFACE,
DirectusExtensionType.DISPLAY,
]);

// Shared library (no extension type) — can be depended on by other extensions
project.addExtension('shared', []);

// Cross-extension dependency
const myHook = project.addExtension('feature', [DirectusExtensionType.HOOK]);
myHook.addDeps('shared@workspace:');

project.synth();
```

## Extension types

`DirectusExtensionType` values:

| Type | Kind |
| --- | --- |
| `INTERFACE` | UI |
| `DISPLAY` | UI |
| `LAYOUT` | UI |
| `MODULE` | UI |
| `PANEL` | UI |
| `ENDPOINT` | API |
| `HOOK` | API |
| `OPERATION` | API |

Passing `[]` produces a plain TypeScript library that emits `lib/` with type declarations — useful for sharing code between extensions.

## What gets generated

Per extension:

- A TypeScript project under `<extensions-folder>/<name>/`
- Sample `src/index.ts` from a template matching the chosen type(s)
- `directus:extension` field in `package.json` (single type) or a `bundle` config (multiple types)
- Build step that runs `directus-extension build` and copies `dist/` into the parent project's `extensions/` tree at the right subfolder (`hooks/<name>`, `endpoints/<name>`, …)
- Vue is added as a devDep automatically when a UI type is included

The `ExtensionFolder` itself is a pnpm workspace; running `pnpm install` + `pnpm run --recursive build` inside it builds every extension. This is what the parent `DirectusProject`'s `build-extensions` task does.

## Direct usage

The constructs can be used outside `DirectusProject` if needed:

```js
import { ExtensionFolder, DirectusExtensionType } from '@wbce/projen-directus-extension';

const folder = new ExtensionFolder({ parent: someProject, name: 'plugins' });
folder.add('my-endpoint', [DirectusExtensionType.ENDPOINT]);
```

## License

GPL-3.0-or-later
25 changes: 25 additions & 0 deletions packages/directus-extension/src/directus-extension-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,31 @@ export class DirectusExtensionProject extends typescript.TypeScriptProject {
projenrcTs: false,
projenrcJs: false,
projenrcJson: false,
readme: options.readme ?? {
contents: isEmpty
? [
`# ${options.name}`,
'',
`Shared library used by sibling [d9](https://github.com/LaWebcapsule/d9) extensions in this workspace.`,
'',
'Built via `tsc`; consumers depend on it with `<name>@workspace:`.',
].join('\n')
: [
`# ${options.name}`,
'',
`[d9](https://github.com/LaWebcapsule/d9) extension (${extensionTypes.join(', ')}).`,
'',
'## Develop',
'',
'Edit files under `src/`. The build step runs `directus-extension build` and copies the output into the parent project\'s `extensions/` folder so d9 picks it up (with `EXTENSIONS_AUTO_RELOAD=true`, no restart needed).',
'',
'```sh',
'pnpm build # build this extension only',
'```',
'',
'Or from the parent project root: `npx projen build-extensions` to build every extension.',
].join('\n'),
},
devDeps: [
'@wbce/projen-directus-extension',
'@wbce-d9/extensions-sdk',
Expand Down
82 changes: 81 additions & 1 deletion packages/directus/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,81 @@
# replace this
# @wbce/projen-directus

Projen template for [d9](https://github.com/LaWebcapsule/d9) projects (fork of Directus v9). Scaffolds a local development setup with Docker Compose (Postgres + Redis), extension management, and GitHub workflows — then produces a Docker image you can deploy to any environment.

Companion package: [`@wbce/projen-directus-extension`](../directus-extension) for authoring extensions.

## Bootstrap a new project

```sh
npx projen new --from @wbce/projen-directus
```

This creates a `.projenrc.js` and synthesizes the project.

## Usage

`.projenrc.js`:

```js
import { DirectusProject } from '@wbce/projen-directus';
import { DirectusExtensionType } from '@wbce/projen-directus-extension';

const project = new DirectusProject({
name: 'my-d9',
defaultReleaseBranch: 'main',
eslintOptions: {
dirs: ['src', 'test'],
prettier: true,
},
});

// A shared package other extensions can depend on
project.addExtension('shared', []);

// A hook extension that depends on the shared package
const myHook = project.addExtension('my-hook', [DirectusExtensionType.HOOK]);
myHook.addDeps('shared@workspace:');

project.synth();
```

Then synth and start it:

```sh
npx projen
npx projen first-run # boot stack + create admin user
npx projen run # start d9 (port 8055)
```

The default admin user is `admin@example.com` / `totototo`.

### Extension types

`DirectusExtensionType` values: `INTERFACE`, `DISPLAY`, `LAYOUT`, `MODULE`, `PANEL`, `ENDPOINT`, `HOOK`, `OPERATION`. Pass an empty array for a shared (non-extension) package.

Extensions live under `./plugins/` (configurable via `extensionsFolderName`) and are built by the `build-extensions` task.

## Generated tasks

| Task | Description |
| --- | --- |
| `first-run` | Boot the stack, create admin, start d9 |
| `run` | Start d9 (`docker compose up directus`) |
| `build-extensions` | Install and build all extensions |
| `create-an-admin` | Create the default admin user |

## What gets generated

- `docker-compose.yml` — d9, Postgres (PostGIS), Redis with healthchecks
- `Dockerfile` — Node 22 + pnpm, builds extensions
- `.env.local` — sample for local environment overrides
- GitHub workflows via [`@wbce/projen-shared`](../shared) (set `githubConfig: false` to disable)

## Options

See [API.md](./API.md) for the full `DirectusProjectOptions` reference. Highlights:

- `extensionsFolderName` — folder for extension packages (default: `plugins`)
- `packageVersions.d9` — version of `@wbce-d9/directus9` (default: `12.0.1`)
- `packageVersions.atlas` — version of `@ariga/atlas` (default: `0.32.0`)
- `githubConfig` — `GitHubConfigOptions` or `false` to disable
53 changes: 53 additions & 0 deletions packages/directus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,59 @@ export class DirectusProject extends javascript.NodeProject {
},
},
licensed: false,
readme: options.readme ?? {
contents: [
`# ${options.name}`,
'',
'A [d9](https://github.com/LaWebcapsule/d9) (Directus 9 fork) project scaffolded with [`@wbce/projen-directus`](https://www.npmjs.com/package/@wbce/projen-directus). Develop locally against Docker Compose, then build a Docker image to deploy anywhere.',
'',
'## Local development',
'',
'```sh',
'npx projen install # install dependencies',
'npx projen first-run # boot stack, create admin, start d9',
'```',
'',
'Open http://localhost:8055 and sign in as `admin@example.com` / `totototo`. Extensions auto-reload (`EXTENSIONS_AUTO_RELOAD=true`).',
'',
'## Deploy',
'',
'A `Dockerfile` is included. Build and push the image for your target environment:',
'',
'```sh',
'docker build -t <registry>/<image>:<tag> .',
'docker push <registry>/<image>:<tag>',
'```',
'',
'Configure the deployed instance with environment variables (database, cache, secrets) — see the d9 docs.',
'',
'## Common tasks',
'',
'| Task | Description |',
'| --- | --- |',
'| `npx projen run` | Start d9 (`docker compose up directus`) |',
'| `npx projen build-extensions` | Install and build all extensions |',
'| `npx projen create-an-admin` | Create the default admin user |',
'',
'See `.projen/tasks.json` for the full list.',
'',
'## Configuration',
'',
'Edit `.projenrc.js` and run `npx projen` to regenerate project files. Local environment overrides go in `.env.local`.',
'',
'## Extensions',
'',
'Extensions live under `./plugins/`. Add new ones in `.projenrc.js`:',
'',
'```js',
"import { DirectusExtensionType } from '@wbce/projen-directus-extension';",
'',
"project.addExtension('my-hook', [DirectusExtensionType.HOOK]);",
'```',
'',
'Then `npx projen && npx projen build-extensions`.',
].join('\n'),
},
devDeps: [
'@wbce/projen-directus',
'@wbce/projen-directus-extension',
Expand Down
Loading