Skip to content

Commit

Permalink
Update @jakubmazanec/carson
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubmazanec committed Apr 16, 2024
1 parent 2a9871f commit 977bae1
Show file tree
Hide file tree
Showing 18 changed files with 107 additions and 56 deletions.
5 changes: 5 additions & 0 deletions .changeset/tough-carrots-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@jakubmazanec/carson": minor
---

Adds new Carson template config option `autoEject`. If set to `true`, Carson automatically ejects after using this template.
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
{
"disallowMultiProjectWorkspace": false,
"disallowSingleProjectWorkspace": false
}
{}
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
{
"disallowMultiProjectWorkspace": false,
"disallowSingleProjectWorkspace": false
}
{}
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
{
"disallowMultiProjectWorkspace": false,
"disallowSingleProjectWorkspace": false
}
{}
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
{
"disallowMultiProjectWorkspace": false,
"disallowSingleProjectWorkspace": false
}
{}
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
{
"disallowMultiProjectWorkspace": false,
"disallowSingleProjectWorkspace": false
}
{}
5 changes: 1 addition & 4 deletions packages/carson-templates/templates/workspace/config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
{
"disallowMultiProjectWorkspace": false,
"disallowSingleProjectWorkspace": false
}
{}
18 changes: 17 additions & 1 deletion packages/carson/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,20 @@ Creates new workspace.
| --path | Path where the workspace should be created. A relative path is appended to the current working directory. |
| --template | ID of the Carson template used to create the workspace. |

#### `eject [<options>]`

> ⚠️ Upcoming feature!
Ejects Carson from a workspace and all of its projects. That means all `.carson` directories (that
contain Carson config and snapshot files) will be deleted.

You can still add projects to the workspace that has had Carson ejected, but those projects also
won't contain `.carson` folder.

| Option | Description |
| ------ | -------------------------------------------------------------------------------------------------- |
| --path | Path where the workspace is located. A relative path is appended to the current working directory. |

### Carson templates

Carson template is just a directory containing `*.ejs` files and `config.json` file. The purpose of
Expand Down Expand Up @@ -355,7 +369,9 @@ Global variables available during the rendering:

#### Carson template config

Currently, the config isn't used for anything yet.
| Option | Type | Description |
| --------- | -------- | ------------------------------------------------------------------------ |
| autoEject | boolean? | If set to `true`, Carson automatically ejects after using this template. |

### Carson philosophy

Expand Down
19 changes: 19 additions & 0 deletions packages/carson/source/commands/create-project/CreateProject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ export function CreateProject({args, workspace}: CreateProjectProps) {
value: projectPath,
label: path.relative(workspace.path, projectPath).replace('\\', '/'),
}));

if (!possiblePaths.length) {
possiblePaths = workspace.projectGlobs
.filter((projectGlob) => !ONLY_ONE_STAR_REGEXP.test(projectGlob))
.map((projectGlob) => path.join(workspace.path, projectGlob))
.map((projectPath) => ({
value: projectPath,
label: path.relative(workspace.path, projectPath).replace('\\', '/'),
}));
}

if (!possiblePaths.length) {
possiblePaths = [
{
value: workspace.path,
label: workspace.path,
},
];
}
} else {
possiblePaths = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export function runCreateProject({

observer.next('Updating the new project');

// if the project doesn't have config with its template ID, it wasn't created on purpose, but is still needed for the next update, so we'll add it manually
project.config.template ??= templateId;

await project.update({args});
})()
.then(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export function runCreateWorkspace({workspacePath, templateId, args}: CreateWork

observer.next('Updating the new workspace');

// if the workspace doesn't have config with its template ID, it wasn't created on purpose, but is still needed for the next update, so we'll add it manually
workspace.config.template ??= templateId;

await workspace.update({args});
})()
.then(() => {
Expand Down
3 changes: 3 additions & 0 deletions packages/carson/source/template/CarsonTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {type templateDataSchema} from './TemplateData.js';
* Carson template.
*/
export type CarsonTemplate = {
/** Carson template ID. */
id: string;

/** Carson template name. */
name: string;

Expand Down
6 changes: 3 additions & 3 deletions packages/carson/source/template/CarsonTemplateConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {z} from 'zod';

export const carsonTemplateConfigSchema = z
.object({
disallowMultiProjectWorkspace: z.boolean().optional(),
disallowSingleProjectWorkspace: z.boolean().optional(),
// disallowMultiProjectWorkspace: z.boolean().optional(),
// disallowSingleProjectWorkspace: z.boolean().optional(),

// TODO: add extends property to allow reuisng template files from another carson template
autoEject: z.boolean().optional(),
})
.strict();

Expand Down
10 changes: 6 additions & 4 deletions packages/carson/source/template/applyTemplateRenders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {type TemplateRenders} from './TemplateRenders.js';
export type ApplyTemplateRendersOptions = {
templateRenders: TemplateRenders;
targetPath: string;
snapshotPath: string;
snapshotPath?: string | undefined;
ignoreStrategies: string[];
};

Expand All @@ -39,7 +39,7 @@ export async function applyTemplateRenders({
await prettier.clearConfigCache();

// first, we read the existing snapshots and use them to undo previous changes
if (await fs.pathExists(snapshotPath)) {
if (snapshotPath && (await fs.pathExists(snapshotPath))) {
let templateRenderSnapshots = await loadTemplateRenderSnapshots(snapshotPath);

for (let templateRenderSnapshot of templateRenderSnapshots) {
Expand Down Expand Up @@ -135,7 +135,9 @@ export async function applyTemplateRenders({
}
}

await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));
if (snapshotPath) {
await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));

await saveTemplateRenderSnapshots(templateRenders, snapshotPath);
await saveTemplateRenderSnapshots(templateRenders, snapshotPath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export async function readCarsonTemplate(templateId: string): Promise<CarsonTemp
dot: true,
});
let carsonTemplate: CarsonTemplate = {
id: templateId,
name: templateName,
config: templateConfig,
files: [],
Expand Down
17 changes: 6 additions & 11 deletions packages/carson/source/template/renderCarsonTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ import {pathToPosixPath} from '@jakubmazanec/fs-utils';
import _ from 'lodash';
import path from 'node:path';

import {
importCarsonTemplate,
parseCarsonTemplateId,
readCarsonTemplate,
resolveModule,
} from './internals.js';
import {type CarsonTemplate} from './CarsonTemplate.js';
import {importCarsonTemplate, parseCarsonTemplateId, resolveModule} from './internals.js';
import {type TemplateData} from './TemplateData.js';
import {type TemplateRenders} from './TemplateRenders.js';

export type RenderCarsonTemplateOptions = {
templateId: string;
template: CarsonTemplate;
templateData: TemplateData;
};

Expand All @@ -22,13 +18,12 @@ export type RenderCarsonTemplateOptions = {
export async function renderCarsonTemplate(
options: RenderCarsonTemplateOptions,
): Promise<TemplateRenders> {
let [moduleId] = parseCarsonTemplateId(options.templateId);
let [moduleId] = parseCarsonTemplateId(options.template.id);
let modulePath = await resolveModule(moduleId);
let template = await readCarsonTemplate(options.templateId);
let templateModule = await importCarsonTemplate(options.templateId);
let templateModule = await importCarsonTemplate(options.template.id);
let templateRenders: TemplateRenders = [];

for (let file of template.files) {
for (let file of options.template.files) {
templateRenders.push(
...(
await file.render(
Expand Down
21 changes: 16 additions & 5 deletions packages/carson/source/workspace/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {type ProjectOptions} from './ProjectOptions.js';
import {type ProjectUpdateOptions} from './ProjectUpdateOptions.js';
import {saveProjectConfig} from './saveProjectConfig.js';
import {type Workspace} from './Workspace.js';
import {readCarsonTemplate} from '../template/internals.js';

/**
* Project represent a self-contained piece of software (e.g. a package, or an app) that is part of a {@link Workspace}. Currently only Node.js projects are supported.
Expand Down Expand Up @@ -117,8 +118,9 @@ export class Project<M extends boolean = true> {
}
}

let template = await readCarsonTemplate(templateId);
let templateRenders = await renderCarsonTemplate({
templateId,
template,
templateData: {
workspace,
project,
Expand All @@ -129,11 +131,16 @@ export class Project<M extends boolean = true> {
await applyTemplateRenders({
templateRenders,
targetPath: project.path,
snapshotPath: path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
snapshotPath:
template.config.autoEject || !workspace.config.template ?
undefined
: path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
ignoreStrategies: ['check'],
});

await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});
if (!template.config.autoEject && workspace.config.template) {
await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});
}

await project.read();

Expand Down Expand Up @@ -242,8 +249,9 @@ export class Project<M extends boolean = true> {
});
}

let template = await readCarsonTemplate(this.config.template);
let templateRenders = await renderCarsonTemplate({
templateId: this.config.template,
template,
templateData: {
workspace: this.workspace,
project: this,
Expand All @@ -254,7 +262,10 @@ export class Project<M extends boolean = true> {
await applyTemplateRenders({
templateRenders,
targetPath: this.path,
snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
snapshotPath:
template.config.autoEject || !this.workspace.config.template ?
undefined
: path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
ignoreStrategies: ['create'],
});

Expand Down
27 changes: 19 additions & 8 deletions packages/carson/source/workspace/Workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
WORKSPACE_SNAPSHOT_FILENAME,
} from '../constants.js';
import {applyTemplateRenders} from '../template/applyTemplateRenders.js';
import {readCarsonTemplate} from '../template/internals.js';
import {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';
import {
compareProjectPath,
Expand Down Expand Up @@ -181,8 +182,9 @@ export class Workspace<M extends boolean = true> {
});
}

let template = await readCarsonTemplate(templateId);
let templateRenders = await renderCarsonTemplate({
templateId,
template,
templateData: {
workspace,
args,
Expand All @@ -192,14 +194,19 @@ export class Workspace<M extends boolean = true> {
await applyTemplateRenders({
templateRenders,
targetPath: workspace.path,
snapshotPath: path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
snapshotPath:
template.config.autoEject ?
undefined
: path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
ignoreStrategies: ['check'],
});

await saveWorkspaceConfig({
workspacePath: workspace.path,
workspaceConfig: {template: templateId},
});
if (!template.config.autoEject) {
await saveWorkspaceConfig({
workspacePath: workspace.path,
workspaceConfig: {template: templateId},
});
}

return Workspace.read(workspace.path);
}
Expand Down Expand Up @@ -490,8 +497,9 @@ export class Workspace<M extends boolean = true> {
});
}

let template = await readCarsonTemplate(this.config.template);
let templateRenders = await renderCarsonTemplate({
templateId: this.config.template,
template,
templateData: {
workspace: this,
args,
Expand All @@ -501,7 +509,10 @@ export class Workspace<M extends boolean = true> {
await applyTemplateRenders({
templateRenders,
targetPath: this.path,
snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
snapshotPath:
template.config.autoEject ?
undefined
: path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
ignoreStrategies: ['create'],
});

Expand Down

0 comments on commit 977bae1

Please sign in to comment.