@8ux-co/eelzap-cli
v0.10.0
Published
The Eel Zap command line: `eelzap codegen` generates TypeScript types for your collections and documents. Install it as a devDependency.
Maintainers
Readme
@8ux-co/eelzap-cli
The Eel Zap command line. eelzap codegen reads your live collections and
documents and generates TypeScript types for them, which you use with the
client from @8ux-co/eelzap.
It is a development tool: install it as a devDependency, so its prompt and
.env dependencies never ship with your site.
Install
npm install --save-dev @8ux-co/eelzap-cli
npm install @8ux-co/eelzapThe generated files import their helper types from @8ux-co/eelzap, so the
site needs the client installed as a regular dependency.
Quick usage
# Reads EELZAP_API_KEY from .env.local, .env and the other env files
npx eelzap codegen
# Explicit command form
npx eelzap codegen generate --api-key secret_abc123 --output-dir src/generated/cms
# Preview only
npx eelzap codegen --dry-runeelzap gen is an alias of eelzap codegen, and eelzap generate … is short
for eelzap codegen generate ….
Generated output defaults to types/eel-zap/:
types/eel-zap/
├── index.ts
├── collections/
│ ├── index.ts
│ └── blog-posts.ts
└── documents/
├── index.ts
└── homepage.tsConfig file
The CLI looks for one of:
eelzap.config.tseelzap.config.jseelzap.config.mjseelzap.config.json.eelzaprc.json
// eelzap.config.ts
import type { EelZapCodegenConfig } from '@8ux-co/eelzap-cli/codegen'
export default {
apiKey: process.env.EELZAP_API_KEY,
baseUrl: process.env.EELZAP_BASE_URL,
outputDir: 'types/eel-zap',
collections: true,
documents: true,
includeCollections: ['blog-posts'],
excludeDocuments: ['internal-notes'],
fileNameCasing: 'kebab',
folderNameCasing: 'kebab',
typeNameCasing: 'pascal',
addFieldComments: true,
generateIndex: true,
includeSeo: true,
includeMeta: true,
header: '/* Auto-generated by @8ux-co/eelzap-cli codegen - DO NOT EDIT */',
} satisfies EelZapCodegenConfigWhen you run eelzap codegen without flags and without a config file, it
enters interactive mode, prompts for the missing values, and writes
eelzap.config.json for subsequent runs. The API key is kept in .env.
Flags
--api-key <key> API key (overrides config/env)
--base-url <url> Base URL (overrides config/env)
--output-dir <path> Output directory (default: types/eel-zap)
--collections-only Only generate collection types
--documents-only Only generate document types
--include <keys...> Only include these collection/document keys
--exclude <keys...> Exclude these collection/document keys
--no-comments Skip JSDoc comments
--no-seo Skip SEO helper fields
--no-meta Skip meta helper fields
--no-index Skip barrel index.ts files
--dry-run Print generated files without writing them
--verbose Print detailed progress
--config <path> Path to config fileEnvironment files
The CLI reads the env files of the directory you run it in, with the names and precedence Next.js uses. Highest first:
- Variables already set in the environment: they always win.
.env.$NODE_ENV.local.env.local(skipped whenNODE_ENVistest).env.$NODE_ENV.env
NODE_ENV is development when it is not set, so a plain npx eelzap codegen
reads .env.development.local, .env.local, .env.development and .env;
NODE_ENV=production reads the production files instead. A missing file is
skipped. Values are not expanded ($OTHER stays as written). --verbose
prints which files were read, never their values.
Base URL and the path prefix
Of the env files, the CLI only understands EELZAP_API_KEY and
EELZAP_BASE_URL. There is no
--path-prefix flag, no EELZAP_PATH_PREFIX read, and no pathPrefix config
key: the CLI always uses the client's default /v1.
The prefix composes, so put everything before /v1 in the base URL and let
the default supply the rest:
# Target a local Zap at http://localhost:5047/api/public/v1/...
EELZAP_BASE_URL=http://localhost:5047/api/public npx eelzap codegen
# or: npx eelzap codegen --base-url http://localhost:5047/api/publicDo not put the full /api/public/v1 in the base URL: the default /v1 is
appended to it and you get /api/public/v1/v1/....
What the generated types say
Codegen reads each collection's and document's schema (its fields and sections) and writes:
- The builder's order. Fields come in the order Zap's field builder shows them: fields outside a section and sections in their place, each section's fields in its own order.
- Required fields as non-null. Zap refuses a save that leaves a required
field empty, for entries and documents alike, so delivered content has it:
title: string. Any other field may be empty and isT | null, except a gallery, which is delivered as[]when empty and so is always an array. - ENUM values narrowed to the field's options:
EnumValue & { value: 'a' | 'b' }.
Required-ness is checked when content is saved, so two cases can still read
as null: content saved before the field was made required, until it is
saved again, and a draft or preview of a document that was never saved.
Use a secret key. The schema routes refuse a public_ key; codegen then
falls back to the delivery schema and warns: collections keep their
required-ness but follow the delivery order, and every document field is
typed T | null with ENUMs not narrowed.
Generated type usage
import { createClient } from '@8ux-co/eelzap'
import type { BlogPostsContent, HomepageDocument } from '@/types/eel-zap'
const cms = createClient({
apiKey: process.env.EELZAP_API_KEY!,
})
const { data: posts } = await cms.items.list<BlogPostsContent>('blog-posts', {
pageSize: 10,
})
const homepage = await cms.documents.get<HomepageDocument['content']>('homepage')
posts[0]?.content.title
homepage.content.hero_titleNext.js workflow
{
"scripts": {
"codegen": "eelzap codegen generate",
"dev": "npm run codegen && next dev",
"build": "npm run codegen && next build"
}
}Programmatic API
import { generateTypes } from '@8ux-co/eelzap-cli/codegen'
const result = await generateTypes({
apiKey: process.env.EELZAP_API_KEY,
outputDir: 'types/eel-zap',
writeFiles: true,
})
console.log(result.filesWritten)
for (const warning of result.warnings) console.warn(warning)warnings lists what the types could not reflect, such as a key that cannot
read the schema. generateTypes reads process.env but no env file: load
those yourself.
@8ux-co/eelzap-cli/codegen also exports resolveCodegenConfig,
DEFAULT_CODEGEN_CONFIG and the EelZapCodegenConfig and
ResolvedCodegenConfig types.
Moving from @8ux-co/eelzap-api-sdk-ts
Up to 0.9.x the CLI shipped inside the SDK package as the eelzap-codegen
bin. From 0.10.0:
| Before | Now |
| -------------------------------------------------- | ----------------------------------------- |
| npx eelzap-codegen [generate] [options] | npx eelzap codegen [generate] [options] |
| @8ux-co/eelzap-api-sdk-ts/codegen | @8ux-co/eelzap-cli/codegen |
| generated files import @8ux-co/eelzap-api-sdk-ts | generated files import @8ux-co/eelzap |
Regenerate your types after upgrading so the generated imports point at the new client package.
License
MIT
