@swell/cli
Version:
Swell's command line interface/utility
140 lines (139 loc) • 5.53 kB
JavaScript
import { checkbox } from '@inquirer/prompts';
import { Args, Flags } from '@oclif/core';
import { CreateCollectionCommand } from '../../create-collection-command.js';
import { ConfigType } from '../../lib/apps/index.js';
import { parseFields, parseViews, validateViews, } from '../../lib/create/content.js';
import { toCollectionLabel, toCollectionName, toFileName, } from '../../lib/create/index.js';
import { SCHEMAS } from '../../lib/create/schemas.js';
export default class CreateContent extends CreateCollectionCommand {
static args = {
collection: Args.string({
default: '',
description: 'Collection ID to create or extend (e.g., products)',
}),
};
static description = 'Interactive mode lets you choose to create a new collection or extend a standard one.\nTo discover standard collections: swell inspect models';
static examples = [
'$ swell create content',
'$ swell create content products -y',
'$ swell create content visitors -v list,edit,new -f name:short_text,verified:boolean -y',
];
static helpMeta = {
usageDirect: '<collection> [...] -y',
};
static flags = {
label: Flags.string({
char: 'l',
default: '',
description: 'Display label (default: capitalized collection)',
}),
description: Flags.string({
char: 'd',
default: '',
description: 'Description',
}),
fields: Flags.string({
char: 'f',
default: '',
description: 'Fields as id:type pairs (e.g., name:short_text,verified:boolean)',
}),
views: Flags.string({
char: 'v',
default: '',
description: 'Views to enable: list | edit | new',
}),
overwrite: Flags.boolean({
default: false,
description: 'Overwrite existing file',
}),
yes: Flags.boolean({
char: 'y',
description: 'Skip prompts, require all arguments',
}),
};
static summary = 'Create a content UI model configuration in the content folder.';
createType = ConfigType.CONTENT;
async run() {
const { args, flags } = await this.parse(CreateContent);
const confirmYes = Boolean(flags.yes);
// NON-INTERACTIVE PATH
if (confirmYes) {
// Validate required arguments
const argCollection = args.collection;
if (!argCollection) {
this.error('Missing required argument for non-interactive mode: COLLECTION\n\nExample: swell create content products -y\n\nTip: run `swell models` to list standard collections you can extend.', { exit: 1 });
}
// Process and normalize collection name
const collection = toCollectionName(argCollection);
// Apply defaults for optional values
const label = flags.label || toCollectionLabel(collection);
const description = flags.description || '';
// Validate and parse views
let viewsList;
if (flags.views) {
viewsList = flags.views
.split(',')
.map((v) => v.trim())
.filter(Boolean);
validateViews(viewsList, this.error.bind(this));
}
else {
// Default views when not specified
viewsList = ['list', 'edit', 'new'];
}
// Parse fields (no validation - trust user input)
const fieldsRaw = (flags.fields || '');
const fieldPairs = fieldsRaw
? fieldsRaw
.split(',')
.map((v) => v.trim())
.filter(Boolean)
: [];
// Build file body
const fileName = toFileName(collection);
const fileBody = {
$schema: SCHEMAS.CONTENT,
collection,
description,
fields: parseFields(fieldPairs),
label,
views: parseViews(viewsList),
};
// Create file with overwrite handling
await this.createFile({ fileBody, fileName }, flags.overwrite,
/* shouldConfirm */ false);
return;
}
// INTERACTIVE PATH (existing logic)
const { collection, description, label } = await this.promptCollection();
const fileName = toFileName(collection);
const fileBody = {
$schema: SCHEMAS.CONTENT,
collection,
};
const { fields, overwrite, views } = flags;
if (label) {
fileBody.label = label;
}
fileBody.description = description;
fileBody.fields = fields ? parseFields(fields.split(',')) : [];
if (views) {
fileBody.views = views ? parseViews(views.split(',')) : [];
}
else {
const viewsInput = await checkbox({
choices: [
{ name: 'List view', value: 'list' },
{ name: 'Edit view', value: 'edit' },
{ name: 'New view', value: 'new' },
],
message: 'Which views does your content have?',
});
fileBody.views = parseViews(viewsInput);
}
await this.createFile({
fileBody,
fileName,
}, overwrite);
}
}