Page MenuHomeSealhub

add-verbose-crud.ts
No OneTemporary

add-verbose-crud.ts

import _locreq from "locreq";
import { escape_url_params } from "./utils/escape-url-params.js";
import prompts from "prompts";
import { toKebabCase, toPascalCase } from "js-convert-case";
import { listCollections } from "./utils/list-collections.js";
import { collectionListTemplate } from "./templates/shared/collection-list.js";
import { writeFile } from "./utils/write-file.js";
import { importPath } from "./utils/import-path.js";
import { sharedCrudFormFields } from "./templates/shared/shared-crud-form-fields.js";
import { generateRoutes } from "./generate-routes.js";
import { createItemFormTemplate } from "./templates/shared/collection-create-form.js";
import { editItemFormTemplate } from "./templates/shared/collection-edit-form.js";
import { askItemDeleteTemplate } from "./templates/shared/confirm-item-delete.js";
import { itemDeleteTemplate } from "./templates/shared/item-delete.js";
export async function addVerboseCRUD(
params: Partial<{ [key in "collection" | "url"]: string }>,
app_directory: string = process.cwd()
) {
const target_locreq = _locreq(app_directory);
prompts.override(params);
const response = await prompts([
{
type: "autocomplete",
name: "collection",
message:
"Which sealious collection do you like to add CRUD forms for?",
choices: (
await listCollections()
).map((collection) => ({
title: collection,
value: collection,
})),
},
{
type: "text",
name: "url",
message:
"Enter a full absolute path for the new route (for example: /admin/users/:id/edit): ",
validate: (s: string) =>
s.trim()[0] == "/" ? true : "Should start with a '/'",
initial: function (_, { collection }: { collection: string }) {
return "/" + toKebabCase(collection);
},
},
]);
const collection_name = response.collection as string;
const url = response.url as string;
const list_action_name = toPascalCase(collection_name) + "CRUDList";
const create_action_name = toPascalCase(collection_name) + "CRUDCreate";
const edit_action_name = toPascalCase(collection_name) + "CRUDEdit";
const delete_ask_action_name =
toPascalCase(collection_name) + "CRUDDeleteAsk";
const delete_action_name = toPascalCase(collection_name) + "CRUDDelete";
/* create the list endpoint */
const list_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/index.list.tsx`
);
const list_content = await collectionListTemplate(
collection_name,
list_action_name,
list_path,
{
post_import_js: `import { ${create_action_name}URL, ${edit_action_name}URL, ${delete_ask_action_name}URL } from "${importPath(
list_path,
"src/back/routes/urls.ts"
)}";`,
post_header_html: `<a href={${create_action_name}URL}> Create </a>`,
render_item: (
collection_name: string
) => ` async renderItem(ctx: Context, item: CollectionItem<typeof ${toPascalCase(
collection_name
)}>) {
return <tr>
{displayFields.map(({ field, format }) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
const value = item.get(field as any);
return <td>{format ? format(value, item) : value}</td>;
})}
<td><div class="sealious-list__actions">
<a href={${edit_action_name}URL(item.id)}>Edit</a>
<a href={${delete_ask_action_name}URL(item.id)}>Delete</a>
</div>
</td>
</tr>;
}`,
}
);
await writeFile(list_path, list_content);
/* create the shared fields file */
const fields_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/shared.ts`
);
const fields_content = await sharedCrudFormFields(
collection_name,
fields_path
);
await writeFile(fields_path, fields_content);
/* create the create endpoint */
const create_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/create.form.ts`
);
const create_content = await createItemFormTemplate(
create_action_name,
create_path,
collection_name,
list_action_name
);
await writeFile(create_path, create_content);
/* create the edit endpoint */
const edit_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/[id]/edit.form.ts`
);
const edit_content = await editItemFormTemplate(
edit_action_name,
edit_path,
collection_name,
list_action_name
);
await writeFile(edit_path, edit_content);
/* create the confirm delete endpoint */
const delete_ask_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/[id]/delete-ask.page.tsx`
);
const delete_ask_content = await askItemDeleteTemplate(
delete_ask_action_name,
collection_name,
delete_ask_path,
list_action_name,
delete_action_name
);
await writeFile(delete_ask_path, delete_ask_content);
/* create the actual delete endpoint */
const delete_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/[id]/delete.page.tsx`
);
const delete_content = await itemDeleteTemplate(
delete_action_name,
collection_name,
delete_ask_path,
list_action_name
);
await writeFile(delete_path, delete_content);
await generateRoutes();
}

File Metadata

Mime Type
text/html
Expires
Wed, May 7, 19:37 (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
629486
Default Alt Text
add-verbose-crud.ts (5 KB)

Event Timeline