fix(ScafTemplate): Use interactive shell for post-scaffold scripts; update CI workflows and package metadata

This commit is contained in:
2025-08-17 15:56:11 +00:00
parent b2ba770b78
commit abc7cbc5ea
21 changed files with 187 additions and 77 deletions

View File

@@ -6,8 +6,8 @@ on:
- '**'
env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
@@ -26,7 +26,7 @@ jobs:
- name: Install pnpm and npmci
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
pnpm install -g @ship.zone/npmci
- name: Run npm prepare
run: npmci npm prepare

View File

@@ -6,8 +6,8 @@ on:
- '*'
env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
@@ -26,7 +26,7 @@ jobs:
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Audit production dependencies
@@ -54,7 +54,7 @@ jobs:
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Test stable
@@ -82,7 +82,7 @@ jobs:
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Release
@@ -104,7 +104,7 @@ jobs:
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Code quality

7
.gitignore vendored
View File

@@ -3,7 +3,6 @@
# artifacts
coverage/
public/
pages/
# installs
node_modules/
@@ -17,4 +16,8 @@ node_modules/
dist/
dist_*/
# custom
# AI
.claude/
.serena/
#------# custom

View File

@@ -1,6 +1,19 @@
# Changelog
## 2025-08-17 - 4.0.18 - fix(ScafTemplate)
Use interactive shell for post-scaffold scripts; update CI workflows and package metadata
- Switched ScafTemplate.runScripts to use smartshell.execInteractive so post-scaffold 'runafter' commands can run interactively
- Updated Gitea workflow environment: replaced CI image with code.foss.global/host.today/ht-docker-node:npmci and adjusted NPMCI_COMPUTED_REPOURL
- Changed CI install target from @shipzone/npmci to @ship.zone/npmci
- Updated package.json metadata (bugs URL and homepage now point to code.foss.global) and added a pnpm.overrides entry
- Minor TypeScript code cleanups and formatting (consistent trailing commas, safer string handling when parsing templates/frontmatter, improved concatenation when merging template files)
- tsconfig adjustments: enabled emitDecoratorMetadata and added baseUrl/paths entries
- Normalized README and template/test output files; updated .gitignore to ignore AI agent directories
- Updated changelog and commitinfo metadata
## 2025-08-17 - 4.0.17 - fix(ScafTemplate)
Use interactive shell for post-scaffold scripts; update test/build config and dependency versions
- Switched from smartshell.exec to smartshell.execInteractive when running smartscaf 'runafter' commands to allow interactive commands during post-scaffold execution (ScafTemplate.runScripts).
@@ -10,6 +23,7 @@ Use interactive shell for post-scaffold scripts; update test/build config and de
- Added pnpm-workspace.yaml with onlyBuiltDependencies configuration (esbuild, mongodb-memory-server, puppeteer).
## 2025-04-15 - 4.0.16 - fix(dependencies)
Update dependency references and bump version numbers; adjust workflow and template commands
- Bump versions for devDependencies (@git.zone/tsbuild, @git.zone/tsrun, @git.zone/tstest, @push.rocks/tapbundle, and @types/node) and dependencies (@push.rocks/lik, @push.rocks/smartfile, @push.rocks/smartfm, @push.rocks/smarthbs, @push.rocks/smartinteract, @push.rocks/smartobject, @push.rocks/smartpromise, @push.rocks/smartshell, and @push.rocks/smartyaml)
@@ -18,6 +32,7 @@ Update dependency references and bump version numbers; adjust workflow and templ
- Update template runafter command from 'npm install' to 'echo "runafter"'
## 2024-05-29 - 4.0.15 - configuration updates
Updates to the projects configuration files, description and build settings.
- Updated description.
@@ -25,219 +40,262 @@ Updates to the projects configuration files, description and build settings.
- Updated npmextra.json (githost).
## 2023-08-18 - 4.0.14 - core
Improved core functionality.
- Fixed core update.
## 2023-07-25 - 4.0.13 - core & organization
Enhancements in core behavior and organizational structure.
- Fixed core update.
- Switched to new organization scheme.
## 2023-06-25 - 4.0.12 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.11 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.10 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.9 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.8 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.7 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.6 - core
Core improvements.
- Fixed core update.
## 2023-06-25 - 4.0.5 - core
Core improvements.
- Fixed core update.
## 2023-06-24 - 4.0.4 - core
Core improvements.
- Fixed core update.
## 2023-06-24 - 4.0.3 - core
Core improvements.
- Fixed core update.
## 2022-06-25 - 4.0.2 - core
Core improvements.
- Fixed core update.
## 2022-06-25 - 4.0.1 - core
Core improvements.
- Fixed core update.
## 2022-06-25 - 4.0.0 - core
Core improvements.
- Fixed core update.
## 2022-06-25 - 3.0.10 - core (breaking)
A breaking change was introduced affecting the module format.
- BREAKING CHANGE (core): switched to ESM.
## 2020-01-31 - 3.0.9 - core
Routine core update.
- Fixed core update.
## 2019-10-11 - 3.0.8 - core
Routine core update.
- Fixed core update.
## 2019-10-02 - 3.0.7 - core
Routine core update.
- Fixed core update.
## 2019-09-10 - 3.0.6 - core
Routine core update.
- Fixed core update.
## 2019-09-10 - 3.0.5 - core
Routine core update.
- Fixed core update.
## 2019-09-10 - 3.0.4 - core
Routine core update.
- Fixed core update.
## 2019-09-10 - 3.0.3 - general updates
Updates to project dependencies and general code improvements.
- Performed update.
- Updated dependencies.
## 2019-02-17 - 3.0.2 - core
Routine core update.
- Fixed core update.
## 2019-01-27 - 3.0.1 - core
Routine core update.
- Fixed core update.
## 2018-10-04 - 3.0.0 - core
Changes from merging and core improvements.
- Fixed core update.
- Merged master branch changes and performed additional updates.
## 2018-08-30 - 2.0.2 - structure (breaking)
A breaking change in the projects structure.
- BREAKING CHANGE (structure): templates now take their path within the constructor.
## 2018-08-27 - 2.0.1 - minor
Versions in this range involved only version bump commits with no significant changes.
- No significant changes.
## 2017-08-09 - 1.0.14 - scope (breaking)
A breaking change in the package scope was applied.
- BREAKING CHANGE (scope): switched to new @pushrocks scope.
## 2017-08-09 - 1.0.13 - core
Improvements to variable handling.
- Fixed variable distribution.
## 2017-07-28 - 1.0.12 - dependencies
Dependency updates.
- Updated dependencies.
## 2017-06-01 - 1.0.11 - dependencies
Dependency updates.
- Updated dependencies.
## 2017-06-01 - 1.0.10 - CLI improvements
Enhanced CLI error prevention.
- Prevented error due to empty defaults.yml.
## 2017-05-27 - 1.0.9 - dependencies
Dependency updates.
- Updated dependencies.
## 2017-05-27 - 1.0.8 - templating
Improved file templating support.
- Added support for frontmatter for advanced file templating.
## 2017-05-27 - 1.0.7 - documentation
Documentation improvements.
- Added docs.
## 2017-05-27 - 1.0.6 - fixes
Minor fixes.
- Fixed deep add.
## 2017-05-26 - 1.0.5 - smartfile updates
Smartfile updates.
- Updated smartfile.
## 2017-05-26 - 1.0.4 - tests
Test fixes.
- Fixed tests.
## 2017-05-26 - 1.0.3 - smartfile updates
Smartfile updates.
- Updated smartfile.
## 2017-05-25 - 1.0.2 - functionality
Minor functionality improvements.
- Ensured proper functionality.
## 2017-05-25 - 1.0.1 - core
Core fixes.
- Fixed working issues.
## 2017-05-06 - 1.0.0 - initial release and CLI integration
The initial release introducing CLI support and project setup.
- Added CLI to prompt for missing variables.

View File

@@ -17,9 +17,9 @@
"author": "Lossless GmbH",
"license": "MIT",
"bugs": {
"url": "https://gitlab.com/pushrocks/smartscaf/issues"
"url": "https://code.foss.global/push.rocks/smartscaf/issues"
},
"homepage": "https://code.foss.global/push.rocks/smartscaf",
"homepage": "https://code.foss.global/push.rocks/smartscaf#readme",
"keywords": [
"typescript",
"scaffolding",
@@ -64,5 +64,8 @@
"browserslist": [
"last 1 chrome versions"
],
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6"
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6",
"pnpm": {
"overrides": {}
}
}

View File

@@ -1,7 +1,9 @@
# @push.rocks/smartscaf
scaffold projects quickly
## Install
To install `@push.rocks/smartscaf`, run the following command in your project directory:
```bash
@@ -20,14 +22,14 @@ A Smartscaf template is essentially a directory with a set of files that you wan
2. **Define Template Variables in `.smartscaf.yml`**: This YAML file contains metadata about your template, such as default values for variables, dependency templates to merge, and scripts to run after scaffolding. Here's a basic example:
```yml
defaults:
projectName: "My Awesome Project"
dependencies:
merge: []
runafter:
- "npm install"
```
```yml
defaults:
projectName: 'My Awesome Project'
dependencies:
merge: []
runafter:
- 'npm install'
```
3. **Utilize Handlebars Syntax for Dynamic Content**: Files in your template can use the Handlebars syntax (`{{variableName}}`) for dynamic content that will be replaced during the scaffolding process.
@@ -37,30 +39,33 @@ Once you have a template ready, you can scaffold a new project by programmatical
1. **Import Smartscaf and Create a New Instance**:
```typescript
import { ScafTemplate } from '@push.rocks/smartscaf';
```typescript
import { ScafTemplate } from '@push.rocks/smartscaf';
async function scaffoldProject() {
const myTemplate = await ScafTemplate.createTemplateFromDir('<path-to-your-template>');
await myTemplate.readTemplateFromDir(); // Load the template
// Supply any additional variables or override defaults
await myTemplate.supplyVariables({
projectName: 'My New Project'
});
// Optionally, interactively ask for missing variables
// await myTemplate.askCliForMissingVariables();
await myTemplate.writeToDisk('<destination-path>'); // Scaffold!
}
async function scaffoldProject() {
const myTemplate = await ScafTemplate.createTemplateFromDir(
'<path-to-your-template>',
);
await myTemplate.readTemplateFromDir(); // Load the template
// Supply any additional variables or override defaults
await myTemplate.supplyVariables({
projectName: 'My New Project',
});
// Optionally, interactively ask for missing variables
// await myTemplate.askCliForMissingVariables();
await myTemplate.writeToDisk('<destination-path>'); // Scaffold!
}
scaffoldProject().then(() => console.log('Project scaffolded successfully!'));
```
scaffoldProject().then(() =>
console.log('Project scaffolded successfully!'),
);
```
2. **Customizing the Scaffolding Process**: You can customize the scaffolding process by defining additional logic to manipulate files, directories, or template variables before writing to disk.
### Advanced Features
- **Merging Templates**: Smartscaf allows you to compose complex templates by specifying dependencies in the `.smartscaf.yml` file. This enables you to merge multiple templates into one scaffolded project.
- **Running Scripts After Scaffolding**: Specify an array of shell commands in the `runafter` section of your `.smartscaf.yml` to be executed after the project is scaffolded. This is useful for running installations or initial builds.
- **Programmatic API**: Smartscaf's flexible API allows for programmatically controlling every aspect of the scaffolding process, making it suitable for integrating into build tools, command line utilities, or CI/CD pipelines.

View File

@@ -1,3 +1,6 @@
# this is a wow
# this is a here
# this is a undefined variable

View File

@@ -1 +1,2 @@
# some undefined variable

View File

@@ -1,3 +1,5 @@
# this is a from default yaml
# this is a this is another value from yml
# this is a undefined variable

View File

@@ -1,6 +1,9 @@
---
fileName: anothername.yml
---
# this is a {{templateObject.value1}}
# this is a {{templateObject.value2}}
# this is a {{templateVar3}}

View File

@@ -1,3 +1,5 @@
# this is a {{templateVar1}}
# this is a {{templateVar2}}
# this is a {{templateVar3}}

View File

@@ -1,4 +1,5 @@
---
fileName: changedname.md
---
# some {{wow}}

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartscaf',
version: '4.0.17',
version: '4.0.18',
description: 'A project aimed at quickly scaffolding projects with support for TypeScript, smart file handling, and template rendering.'
}

View File

@@ -50,7 +50,10 @@ export class ScafTemplate {
* read a template from a directory
*/
public async readTemplateFromDir() {
this.templateSmartfileArray = await plugins.smartfile.fs.fileTreeToObject(this.dirPath, '**/*');
this.templateSmartfileArray = await plugins.smartfile.fs.fileTreeToObject(
this.dirPath,
'**/*',
);
// read .smartscaf.yml file
let smartscafFile: interfaces.ISmartscafFile = {
@@ -61,15 +64,17 @@ export class ScafTemplate {
runafter: [],
};
const smartscafSmartfile = this.templateSmartfileArray.find((smartfileArg) => {
return smartfileArg.parsedPath.base === '.smartscaf.yml';
});
const smartscafSmartfile = this.templateSmartfileArray.find(
(smartfileArg) => {
return smartfileArg.parsedPath.base === '.smartscaf.yml';
},
);
if (smartscafSmartfile) {
smartscafFile = {
...smartscafFile,
...(await plugins.smartyaml.yamlStringToObject(
smartscafSmartfile.contentBuffer.toString()
smartscafSmartfile.contentBuffer.toString(),
)),
};
}
@@ -105,7 +110,10 @@ export class ScafTemplate {
name: missingVariable,
type: 'input',
default: (() => {
if (this.defaultVariables && this.defaultVariables[missingVariable]) {
if (
this.defaultVariables &&
this.defaultVariables[missingVariable]
) {
return this.defaultVariables[missingVariable];
} else {
return 'undefined variable';
@@ -118,7 +126,11 @@ export class ScafTemplate {
const answerBucket = await localSmartInteract.runQueue();
const answers = answerBucket.getAllAnswers();
for (const answer of answers) {
await plugins.smartobject.smartAdd(this.suppliedVariables, answer.name, answer.value);
await plugins.smartobject.smartAdd(
this.suppliedVariables,
answer.name,
answer.value,
);
}
}
@@ -136,23 +148,32 @@ export class ScafTemplate {
}
// render the template
const template = await plugins.smarthbs.getTemplateForString(smartfile.contents.toString());
const template = await plugins.smarthbs.getTemplateForString(
smartfile.contents.toString(),
);
const renderedTemplateString = template(this.suppliedVariables);
// handle frontmatter
const smartfmInstance = new plugins.smartfm.Smartfm({
fmType: 'yaml',
});
const parsedTemplate = smartfmInstance.parse(renderedTemplateString) as any;
const parsedTemplate = smartfmInstance.parse(
renderedTemplateString,
) as any;
if (parsedTemplate.data.fileName) {
smartfile.updateFileName(parsedTemplate.data.fileName);
}
smartfile.contents = Buffer.from(await plugins.smarthbs.postprocess(parsedTemplate.content));
smartfile.contents = Buffer.from(
await plugins.smarthbs.postprocess(parsedTemplate.content),
);
smartfileArrayToWrite.push(smartfile);
}
await plugins.smartfile.memory.smartfileArrayToFs(smartfileArrayToWrite, destinationDirArg);
await plugins.smartfile.memory.smartfileArrayToFs(
smartfileArrayToWrite,
destinationDirArg,
);
await this.runScripts();
}
@@ -164,7 +185,7 @@ export class ScafTemplate {
let templateVariables: string[] = [];
for (const templateSmartfile of this.templateSmartfileArray) {
const localTemplateVariables = await plugins.smarthbs.findVarsInHbsString(
templateSmartfile.contents.toString()
templateSmartfile.contents.toString(),
);
templateVariables = [...templateVariables, ...localTemplateVariables];
}
@@ -181,7 +202,7 @@ export class ScafTemplate {
for (const templateSmartfile of this.templateSmartfileArray) {
const localMissingVars = await plugins.smarthbs.checkVarsSatisfaction(
templateSmartfile.contents.toString(),
this.suppliedVariables
this.suppliedVariables,
);
// combine with other missingVars
@@ -208,13 +229,15 @@ export class ScafTemplate {
* >> - yourDeeperKey: yourValue
*/
private async _checkDefaultVariables() {
const smartscafSmartfile = this.templateSmartfileArray.find((smartfileArg) => {
return smartfileArg.parsedPath.base === '.smartscaf.yml';
});
const smartscafSmartfile = this.templateSmartfileArray.find(
(smartfileArg) => {
return smartfileArg.parsedPath.base === '.smartscaf.yml';
},
);
if (smartscafSmartfile) {
const smartscafObject = await plugins.smartyaml.yamlStringToObject(
smartscafSmartfile.contents.toString()
smartscafSmartfile.contents.toString(),
);
const defaultObject = smartscafObject.defaults;
this.defaultVariables = defaultObject;
@@ -237,15 +260,18 @@ export class ScafTemplate {
const templatePathToMerge = plugins.path.join(this.dirPath, dependency);
if (!plugins.smartfile.fs.isDirectory(templatePathToMerge)) {
console.log(
`dependency ${dependency} resolves to ${templatePathToMerge} which ist NOT a directory`
`dependency ${dependency} resolves to ${templatePathToMerge} which ist NOT a directory`,
);
continue;
}
const templateSmartfileArray = await plugins.smartfile.fs.fileTreeToObject(
templatePathToMerge,
'**/*'
const templateSmartfileArray =
await plugins.smartfile.fs.fileTreeToObject(
templatePathToMerge,
'**/*',
);
this.templateSmartfileArray = this.templateSmartfileArray.concat(
templateSmartfileArray,
);
this.templateSmartfileArray = this.templateSmartfileArray.concat(templateSmartfileArray);
}
}
@@ -257,7 +283,9 @@ export class ScafTemplate {
executor: 'bash',
});
for (const command of this.smartscafFile.runafter) {
await smartshellInstance.execInteractive(`cd ${this.destinationPath} && ${command}`);
await smartshellInstance.execInteractive(
`cd ${this.destinationPath} && ${command}`,
);
}
}
}

View File

@@ -1,14 +1,15 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"verbatimModuleSyntax": true
"verbatimModuleSyntax": true,
"baseUrl": ".",
"paths": {}
},
"exclude": [
"dist_*/**/*.d.ts"
]
"exclude": ["dist_*/**/*.d.ts"]
}