npx apply <your-username/your-preset>
It was made to automate the repetitive task of doing the same modifications each time a project is created.
Learn more
·
Built with ❤︎ by Enzo Innocenzi
Elegant, ecosystem-agnostic preset mechanism
Home Page: https://preset.dev
npx apply <your-username/your-preset>
·
Built with ❤︎ by Enzo Innocenzi
Add support for Git tags in order to handle versioning. Not sure about the syntax though. I'm thinking either a flag (--tag v0.1.4
), or directly in the URL/shorthand:
# handle syntax
npx use-preset user/repo@tag:subdirectory
# url syntax
npx use-preset https://github.com/user/repo@tag:subdirectory
https://github.com/innocenzi/laravel-vite/issues/78
Should handle file paths instead of only directories
Does the package.json file get replaced when installing a preset ?
We should be able to add dependencies directly in the package.json file when adding a preset.
For very big presets it would be nice if actions could be grouped together, on one hand this would allow naming of multiple commands together so the cli output can be less cluttered and on the other and would allow multiples of the same if statement to be condensed into one.
In use it could look something like this:
// Before:
.command('git', ['init', '--quiet'])
.if(({ prompts }) => Boolean(prompts.git))
.chain()
.command('git', ['add', 'README.md'])
.if(({ prompts }) => Boolean(prompts.git))
.chain()
.command('git', ['commit', '-m', '"Add README.md"', '--quiet'])
.if(({ prompts }) => Boolean(prompts.git))
.chain()
.command('git', ['checkout', '-b', 'develop', '--quiet'])
.if(({ prompts }) => Boolean(prompts.git))
.chain()
// After:
.command()
.title('Initialising local git repo')
.if(({ prompts }) => Boolean(prompts.git)
.run('git', ['init', '--quiet'])
.run('git', ['add', 'README.md'])
.run('git', ['commit', '-m', '"Add README.md"', '--quiet'])
.run('git', ['checkout', '-b', 'develop', '--quiet'])
Currently this isn't possible, only the last run action in the command will actually be executed.
I'm just reading about Preset and I really appreciate the philosophy. I've used Yeoman in the past and this makes much more sense to me.
I'd like to understand how you're thinking about indentation. If I'm understanding the documentation correctly, the options are either to double the previous line's indentation or to use a fixed indentation that isn't based on the previous line. I'd like to be able to add or subtract a single tab or number of spaces from the previous line. (Ideally, the library would detect tabs vs spaces if it's consistent in the file.)
I make GitHub Workflow to check my preset
https://github.com/oanhnn/preset-laravel/runs/1189176191
npx: installed 102 in 5.03s
[STARTED] Resolve
[SUCCESS] Resolve
[STARTED] Parse
[SUCCESS] Parse
[STARTED] Task without title.
[TITLE] Apply laravel
[STARTED] Copy some default config files
[STARTED] Validate
[SUCCESS] Validate
[STARTED] Execute
[DATA] ? .editorconfig already exists. Do you want to replace it? ‣ /
[DATA] ? .editorconfig already exists. Do you want to replace it? ‣ no / yes
But it has a problem: in non-interaction mode (CI), Copy conflict strategy "ask" still show question and exit.
How it doesn't ask and get the initial value?
Hello @innocenzi
To install node dependencies without confirmation i had to write my preset like this:
.installDependencies()
.for('node')
.withoutAsking(false)
.title('Install npm dependencies')
.chain();
is the correct behavior? i was expecting to say withoutAsking = true
Instead of building presets with the object syntax, allow for an alternative fluent one.
Preset.make('preset-name')
.applyPreset('external/preset')
.copyTemplates()
.execute(() => {
// custom action
})
// etc etc
Not sure about the exact API yet. Ideally, it would support everything the object syntax does, hooks included.
Inspired from cliui, a post-install instruction would be nice to have for preset makers to give additional information about their installation.
It wouldn't be of the form of an action, but a preset property, just like the preset name.
// Object-based
module.exports = {
name: 'some preset',
instructions: [
'Run "npm run dev" to start development'
]
}
// Fluent
module.exports = Preset.make('some preset')
.instruct([
'Run "npm run dev" to start development'
])
The idea is to implement a resolver, similar to the community resolver, which reads a ~/.preset
file to find custom repositories.
Not sure of the format of that configuration file, but it should be able to map a keyword:repository
to a custom Git repository.
I was trying to use Tailwind with SvelteKit when came across this project svelte-add/tailwindcss.
But when I tried running npx apply svelte-add/postcss
, it does nothing except echoing:
After a few minutes trying, I realised that this could possibly mean that npx apply
was actually running a built in command (instead of running preset/cli). So I tried man apply
. And lo!
I don't remember installing it. I also have checked with brew ls
in case it was installed as a package dependency of other clis that I actually use, and the result is negative.
I'm running:
Oh by the way, in npx introductory blog post:
Calling
npx <command>
when<command>
isn’t already in your$PATH
will automatically install a package with that name from the npm registry for you, and invoke it.
In other words, if <command>
(in this case apply
) is already in my $PATH
, then by default npx
will run that.
So this is the expected behaviour on npx part.
An action that would look for specific files and edit their content. Ideally, support for this feature should be added:
If I create the repository call user/preset-a
, I hope will use apply user/a
or apply user/preset-a
both can to run the preset..
I think this feature will allow me to create repo with preset-
without having to type the prefix preset-
.
Is this feature possible?
An action that would apply another preset on the same directory. This would be useful for combining presets, in order for users to apply modifications on top of existing presets.
Call apply user
, automatic search the user/preset
repository.
Is this feature possible?
New actions for ecosystem-specific dependency management. Currently, edit-json
works fine for editing package.json
and composer.json
files, but it could help some syntactic sugar, and maybe new features (eg. sorting, see #45).
Allow for custom aliases to avoid having to type the whole organization/repository
resolvable for presets that are used often.
Also allows for default package manager for installPackages
.
Hi, is possible update esbuild
to min version 0.9.7 because this version adds Android support.
When extract from template file to target file, it don't existed yet, preset make incorrect target path.
Make preset with preset.ts
Preset.extract()
.from('abc/.eslintignore')
.to('.eslintignore')
.withDots(true)
.whenConflict(Preset.isInteractive() ? 'ask' : 'override')
Make template file templates/abc/.eslintignore
Run
mkdir ci-test
apply /path/to/preset ci-test
The preset copy templates/abc/.eslintignore
to ci-test/.eslintignore
The preset copy templates/abc/.eslintignore
to ci-test/.eslintignore/abc/.eslintignore
Why not set .to('')
? Because it will make ci-test/abc/.eslintignore
Right now, the fluent API is made with a Preset
object and multiple pending objects, but none are commented. They should be properly commented to reduce the round-trips to the actual documentation for users that do not know the API that well yet.
Everyone’s code style is different. I'm using space indent in package.json
.
Can add a new Method to set editJson
indent to set tab
/ 2 space
/ 4 space
?
An action that would copy files, the same way as the copy
action, but with additional support for replacing its content.
It can be useful for template files which contents should be determined by user input or with data fetched from the target directory (eg. classes with namespaces, custom names, etc).
Currently, the presets are evaluated with eval
so there is no need to install their dependencies, since most of the time they don't have any. This is a design choice that was made because application speed was in mind.
That said, there are times where dependencies may be useful, and as such, support for installing them should be added.
It means that the new importer should look for pnpm
or yarn
and fallback to npm
, install dependencies after a clone, and then require
the preset.
This can be done with the recently added installDependencies
utility method.
require()
the preset fileA preset maker would chose the installation mode with a mode
property on the preset object.
module.exports = {
name: 'Some preset',
mode: 'install'
}
Since yesterday, presets can't be cloned anymore. Not sure if simple-git changed something or if it's related to yesterday's update. Checking tonight.
Preset.delete(path)
does not work, Preset.delete([path])
does.
It would be nice to use a preset located in a monorepo with the GitHub URL syntax
npx use-preset username/repository/tree/branch/package
Alternatives:
# Omit "tree"
npx use-preset username/repository/branch/package
# Branchname will default to master | main
npx use-preset username/repository/package
Just like the previous rewrite, I didn't focus on the console output. I previously used taskr2 but the console logging was way too tied to the logic, so I eventually removed it.
Now that the logging is event-based, I'm considering improving it while keeping it simple, with something like ora. But this one appears to not work properly, so not sure when I'll dive into that.
An action that makes it easier to install dependencies, in order to avoid using the after
hook and installDependencies
context function.
This should install dependencies for the selected ecosystem. For node
, it would look for yarn
first, then npm
.
module.exports = {
actions: () => [{
type: 'install-dependencies',
mode: 'install', // and 'update'
for: 'node' // and 'php', and maybe other ecosystems
}]
}
- lodash.merge(data, original)
+ lodash.merge(original, data)
Le'ts say I want to edit the package.json and and want to configure jest. Then I have the following code:
Preset.editJson('package.json').merge({
jest: {
roots: ['<rootDir>/src'],
setupFilesAfterEnv: ['<rootDir>/jest/jest.setup.js'],
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
testMatch: ['<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}', '<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}'],
testEnvironment: 'jsdom',
transform: {
'^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': '<rootDir>/node_modules/babel-jest',
'.+\\.(svg|css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
},
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', '^.+\\.module\\.(css|sass|scss)$'],
moduleNameMapper: {
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
},
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
resetMocks: true,
},
});
I run my preset once: everything as expected.
I run it several times. Then there are two cases:
"testEnvironment": "jsdom",
or the "resetMocks": true
: this will not be added again to the package json roots: ['<rootDir>/src'],
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
This will be added several times to the package json
Conclusion:
It looks like that his happens with array values only.
I would expect that that also checked and not added again when they are already existing.
A simple action that would allow to run shell commands.
Should be used with care because cross-platform is important. Because of that, an os
property should be added to the context
object.
I'm not sure how catching errors is supposed to work. editJson
errors on JSONC (JSON with comments), which is common in files like tsconfig
, or settings.json
.
Is there a recommended way to handle errors and provide error messages?
I'd like to improve the console feedback when doing resource-heavy manipulations, such as installing dependency. Right now, it can be done from the context without any feedback (the console will hang).
An option would be to include Listr and integrate it. If this is done, it can be used throughout the whole CLI for better overall feedback.
Additionally, some of the logger icons takes too much space on windows, which renders pretty bad. The Logger
and Prompt
classes should be rewritten properly in the future.
The CLI should be used with npx use-preset
, but this is sometimes frustrating because it's a bit slower. Because of that, chances are that use-preset
is installed globally.
For this reason, when running a preset, the tool should asynchronously check for a new version. If one is found, use should be alerted.
A directory starting with a .
can't be extracted without a workaround because of the glob matcher.
Either an option to match dotfiles should be added, or a workaround like .dotfile
should be used. Not sure yet.
Currently, global execution hooks are available, but per-action hooks should be added to the base action contract.
I want add an environment variable base existed environment variable in .env
file.
I was try with replace().with()
, but it don't work. (See below comments)
module.exports = Preset.make('Update ENV')
.edit('.env')
.replace(/^APP_URL=http:\/\/(.*)$/)
.with((str, domain) => {
return ['APP_URL=http://' + domain, 'APP_DOMAIN=' + domain].join('\n')
})
.chain()
I think addAfter
/addBefore
method should support functional like replace().with()
.
module.exports = Preset.make('Update ENV')
.edit('.env')
.search(/^APP_URL=http:\/\/(.*)$/)
.addAfter((str, domain) => 'APP_DOMAIN=' + domain)
.end()
.chain()
I would like to have an option to create an preset without git. This would make it possible to use the code generator for local code generation. This I could use for example when I want to generate a new menu entry and a page. This I don't want to have in a separate repository. It should just live in my project.
I would suggest to have an optional argument to the init command
npx apply <preset-name> --init --local
or even have the git as an optional command:
npx apply <preset-name> --init --add-git
The git
and gist
resolvers clone repositories into temporary folders. However, they are not automatically deleted. They should be.
I managed to get apply
, but little did I know this was an existing command name on macOS. For this reason, instead of requiring users to use --ignore-existing
, I'm thinking about maintaining both apply
and use-preset
. That would require a change in the importer as well.
An action that would provide support for easily working with JSON files. Merging objects or removing paths should be easily done.
For instance, its API could look like this:
{
merge: {
dependencies: {
vue: '^2'
}
},
remove: [
'dependencies.axios'
]
}
I wish the order of dependencies
is correct. But still respect your ideas, can you implement this feature?
Lodash code of sort object with key (Refrence: lodash/lodash#1459 (comment)):
_(obj).toPairs().sortBy(0).fromPairs().value()
{
type: 'install-dependencies',
for: 'node',
prompt: true
}
This would ask the user if they won't their dependencies installed.
I've been struggling to figure out how to implement the MultiSelect Prompt.
import { Preset } from 'apply';
Preset.setName('Config');
Preset.prompt()
.add('configs', {
type: 'ArrayPrompt',
name: 'configs',
message: 'What configs would you like?',
choices: ['stylelint', 'settings.json']
});
I've read through the docs multiple times, but can't seem to understand how it's meant to work.
Any advice would be greatly appreciated!
A function in the Context
object that ensures a condition passes. If not, it would cleanly stop the preset.
Hello, I'm trying to make a preset for Laravel that will publish the vendor.
After installing the desired package, I try execute:
Preset.execute('php')
.withArguments([
'artisan',
'vendor:publish',
'--provider="NunoMaduro\\PhpInsights\\Application\\Adapters\\Laravel\\InsightsServiceProvider"',
])
However, the vendor is not published, and there are no errors.
Apparently a lot of people don't have SSH set up so instead of requiring them to use --no-ssh
, I'll just update the resolvers to use https
by default unless --ssh
(or an URL) is passed.
Downside: private presets will require --ssh
.
Alternative: detect if SSH is configured before cloning.
Alternative: keep stuff as-is but improve error message and provide steps to solve it (links to the docs for setting up SSH w/ GitHub, and hint about the --no-ssh
flag)
Hello !
Does it also work with Yarn?
Allow this:
{
type: 'preset',
preset: 'innocenzi/dotfiles',
argv: '--force'
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.