create-absolutejs 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/.prettierignore +0 -4
- package/.prettierrc.json +0 -9
- package/eslint.config.mjs +0 -189
- package/index.ts +0 -232
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-absolutejs",
|
|
3
3
|
"description": "A CLI tool to create a new AbsoluteJS project",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"license": "CC BY-NC 4.0",
|
|
6
6
|
"author": "Alex Kahn",
|
|
7
7
|
"type": "module",
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
"bin": {
|
|
10
10
|
"create-absolutejs": "dist/index.js"
|
|
11
11
|
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
12
15
|
"scripts": {
|
|
13
16
|
"build": "rm -rf dist && bun build index.ts --outdir dist --target=bun --external elysia && tsc --emitDeclarationOnly --project tsconfig.json",
|
|
14
17
|
"test": "echo \"Error: no test specified\" && exit 1",
|
package/.prettierignore
DELETED
package/.prettierrc.json
DELETED
package/eslint.config.mjs
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
// eslint.config.mjs
|
|
2
|
-
import { dirname } from 'path'
|
|
3
|
-
import { fileURLToPath } from 'url'
|
|
4
|
-
import pluginJs from '@eslint/js'
|
|
5
|
-
import stylisticTs from '@stylistic/eslint-plugin-ts'
|
|
6
|
-
import tsParser from '@typescript-eslint/parser'
|
|
7
|
-
import { defineConfig } from "eslint/config";
|
|
8
|
-
import absolutePlugin from 'eslint-plugin-absolute'
|
|
9
|
-
import importPlugin from 'eslint-plugin-import'
|
|
10
|
-
import promisePlugin from 'eslint-plugin-promise'
|
|
11
|
-
import securityPlugin from 'eslint-plugin-security'
|
|
12
|
-
import globals from 'globals'
|
|
13
|
-
import tseslint from 'typescript-eslint'
|
|
14
|
-
|
|
15
|
-
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
16
|
-
|
|
17
|
-
export default defineConfig([
|
|
18
|
-
{
|
|
19
|
-
ignores: ['dist/**']
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
pluginJs.configs.recommended,
|
|
23
|
-
|
|
24
|
-
...tseslint.configs.recommended,
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
files: ['**/*.{ts,tsx}'],
|
|
28
|
-
languageOptions: {
|
|
29
|
-
globals: globals.browser,
|
|
30
|
-
parser: tsParser,
|
|
31
|
-
parserOptions: {
|
|
32
|
-
createDefaultProgram: true,
|
|
33
|
-
project: './tsconfig.json',
|
|
34
|
-
tsconfigRootDir: __dirname
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
files: ['**/*.{ts,tsx}'],
|
|
41
|
-
plugins: { '@stylistic/ts': stylisticTs },
|
|
42
|
-
rules: {
|
|
43
|
-
'@stylistic/ts/padding-line-between-statements': [
|
|
44
|
-
'error',
|
|
45
|
-
{ blankLine: 'always', next: 'return', prev: '*' }
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
{
|
|
51
|
-
files: ['**/*.{js,mjs,cjs,ts,tsx,jsx}'],
|
|
52
|
-
ignores: ['example/build/**'],
|
|
53
|
-
plugins: {
|
|
54
|
-
absolute: absolutePlugin,
|
|
55
|
-
import: importPlugin,
|
|
56
|
-
promise: promisePlugin,
|
|
57
|
-
security: securityPlugin
|
|
58
|
-
},
|
|
59
|
-
rules: {
|
|
60
|
-
'absolute/explicit-object-types': 'error',
|
|
61
|
-
'absolute/localize-react-props': 'error',
|
|
62
|
-
'absolute/max-depth-extended': ['error', 1],
|
|
63
|
-
'absolute/max-jsxnesting': ['error', 5],
|
|
64
|
-
'absolute/min-var-length': [
|
|
65
|
-
'error',
|
|
66
|
-
{ allowedVars: ['_', 'id', 'db', 'OK'], minLength: 3 }
|
|
67
|
-
],
|
|
68
|
-
'absolute/no-explicit-return-type': 'error',
|
|
69
|
-
'absolute/no-type-cast': 'error',
|
|
70
|
-
'absolute/no-useless-function': 'error',
|
|
71
|
-
'absolute/sort-exports': [
|
|
72
|
-
'error',
|
|
73
|
-
{
|
|
74
|
-
caseSensitive: true,
|
|
75
|
-
natural: true,
|
|
76
|
-
order: 'asc',
|
|
77
|
-
variablesBeforeFunctions: true
|
|
78
|
-
}
|
|
79
|
-
],
|
|
80
|
-
'absolute/sort-keys-fixable': [
|
|
81
|
-
'error',
|
|
82
|
-
{
|
|
83
|
-
caseSensitive: true,
|
|
84
|
-
natural: true,
|
|
85
|
-
order: 'asc',
|
|
86
|
-
variablesBeforeFunctions: true
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
'arrow-body-style': ['error', 'as-needed'],
|
|
90
|
-
'consistent-return': 'error',
|
|
91
|
-
eqeqeq: 'error',
|
|
92
|
-
'func-style': ['error', 'expression', { allowArrowFunctions: true }],
|
|
93
|
-
'import/no-cycle': 'error',
|
|
94
|
-
'import/no-default-export': 'error',
|
|
95
|
-
'import/no-relative-packages': 'error',
|
|
96
|
-
'import/no-unused-modules': ['error', { missingExports: true }],
|
|
97
|
-
'import/order': ['error', { alphabetize: { order: 'asc' } }],
|
|
98
|
-
'no-await-in-loop': 'error',
|
|
99
|
-
'no-console': ['error', { allow: ['warn', 'error'] }],
|
|
100
|
-
'no-debugger': 'error',
|
|
101
|
-
'no-duplicate-case': 'error',
|
|
102
|
-
'no-duplicate-imports': 'error',
|
|
103
|
-
'no-else-return': 'error',
|
|
104
|
-
'no-empty-function': 'error',
|
|
105
|
-
'no-empty-pattern': 'error',
|
|
106
|
-
'no-empty-static-block': 'error',
|
|
107
|
-
'no-fallthrough': 'error',
|
|
108
|
-
'no-floating-decimal': 'error',
|
|
109
|
-
'no-global-assign': 'error',
|
|
110
|
-
'no-implicit-coercion': 'error',
|
|
111
|
-
'no-implicit-globals': 'error',
|
|
112
|
-
'no-loop-func': 'error',
|
|
113
|
-
'no-magic-numbers': [
|
|
114
|
-
'warn',
|
|
115
|
-
{ detectObjects: false, enforceConst: true, ignore: [0, 1] }
|
|
116
|
-
],
|
|
117
|
-
'no-misleading-character-class': 'error',
|
|
118
|
-
'no-nested-ternary': 'error',
|
|
119
|
-
'no-new-native-nonconstructor': 'error',
|
|
120
|
-
'no-new-wrappers': 'error',
|
|
121
|
-
'no-param-reassign': 'error',
|
|
122
|
-
'no-restricted-imports': [
|
|
123
|
-
'error',
|
|
124
|
-
{
|
|
125
|
-
paths: [
|
|
126
|
-
{
|
|
127
|
-
importNames: ['default'],
|
|
128
|
-
message: 'Import only named React exports for tree-shaking.',
|
|
129
|
-
name: 'react'
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
importNames: ['default'],
|
|
133
|
-
message: 'Import only the required Bun exports.',
|
|
134
|
-
name: 'bun'
|
|
135
|
-
}
|
|
136
|
-
]
|
|
137
|
-
}
|
|
138
|
-
],
|
|
139
|
-
'no-return-await': 'error',
|
|
140
|
-
'no-shadow': 'error',
|
|
141
|
-
'no-undef': 'error',
|
|
142
|
-
'no-unneeded-ternary': 'error',
|
|
143
|
-
'no-unreachable': 'error',
|
|
144
|
-
'no-useless-assignment': 'error',
|
|
145
|
-
'no-useless-concat': 'error',
|
|
146
|
-
'no-useless-return': 'error',
|
|
147
|
-
'no-var': 'error',
|
|
148
|
-
'prefer-arrow-callback': 'error',
|
|
149
|
-
'prefer-const': 'error',
|
|
150
|
-
'prefer-destructuring': [
|
|
151
|
-
'error',
|
|
152
|
-
{ array: true, object: true },
|
|
153
|
-
{ enforceForRenamedProperties: false }
|
|
154
|
-
],
|
|
155
|
-
'prefer-template': 'error',
|
|
156
|
-
'promise/always-return': 'warn',
|
|
157
|
-
'promise/avoid-new': 'warn',
|
|
158
|
-
'promise/catch-or-return': 'error',
|
|
159
|
-
'promise/no-callback-in-promise': 'warn',
|
|
160
|
-
'promise/no-nesting': 'warn',
|
|
161
|
-
'promise/no-promise-in-callback': 'warn',
|
|
162
|
-
'promise/no-return-wrap': 'error',
|
|
163
|
-
'promise/param-names': 'error'
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
{
|
|
168
|
-
files: [
|
|
169
|
-
'index.ts'
|
|
170
|
-
],
|
|
171
|
-
rules: {
|
|
172
|
-
'import/no-unused-modules': 'off',
|
|
173
|
-
'no-console': 'off'
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
files: ['eslint.config.mjs'],
|
|
178
|
-
rules: {
|
|
179
|
-
'no-magic-numbers': 'off'
|
|
180
|
-
}
|
|
181
|
-
},
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
files: ['eslint.config.mjs'],
|
|
185
|
-
rules: {
|
|
186
|
-
'import/no-default-export': 'off'
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
])
|
package/index.ts
DELETED
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { argv, exit } from 'node:process';
|
|
3
|
-
import { parseArgs } from 'node:util';
|
|
4
|
-
import {
|
|
5
|
-
cancel,
|
|
6
|
-
isCancel,
|
|
7
|
-
multiselect,
|
|
8
|
-
outro,
|
|
9
|
-
select,
|
|
10
|
-
text
|
|
11
|
-
} from '@clack/prompts';
|
|
12
|
-
import colors from 'picocolors';
|
|
13
|
-
|
|
14
|
-
const { blueBright, yellow, cyan, green, magenta, red, reset, white } = colors;
|
|
15
|
-
|
|
16
|
-
const frameworkNames: Record<string, string> = {
|
|
17
|
-
angular: 'Angular',
|
|
18
|
-
html: 'HTML',
|
|
19
|
-
htmx: 'HTMX',
|
|
20
|
-
react: 'React',
|
|
21
|
-
solid: 'Solid',
|
|
22
|
-
svelte: 'Svelte',
|
|
23
|
-
vue: 'Vue'
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/* eslint-disable */
|
|
27
|
-
function abort(): never {
|
|
28
|
-
cancel('Operation cancelled');
|
|
29
|
-
exit(0);
|
|
30
|
-
}
|
|
31
|
-
/* eslint-enable */
|
|
32
|
-
|
|
33
|
-
const DEFAULT_ARG_LENGTH = 2;
|
|
34
|
-
const { values } = parseArgs({
|
|
35
|
-
args: argv.slice(DEFAULT_ARG_LENGTH),
|
|
36
|
-
options: {
|
|
37
|
-
help: { default: false, short: 'h', type: 'boolean' }
|
|
38
|
-
},
|
|
39
|
-
strict: false
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
if (values.help) {
|
|
43
|
-
// prettier-ignore
|
|
44
|
-
console.log(`
|
|
45
|
-
Usage: create-absolute [OPTION]...
|
|
46
|
-
|
|
47
|
-
Options:
|
|
48
|
-
-h, --help Show this help message and exit
|
|
49
|
-
`);
|
|
50
|
-
exit(0);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 1. Project name
|
|
54
|
-
const projectName = await text({
|
|
55
|
-
message: 'Project name:',
|
|
56
|
-
placeholder: 'absolutejs-project'
|
|
57
|
-
});
|
|
58
|
-
if (isCancel(projectName)) abort();
|
|
59
|
-
|
|
60
|
-
// 2. Language
|
|
61
|
-
const language = await select({
|
|
62
|
-
message: 'Language:',
|
|
63
|
-
options: [
|
|
64
|
-
{ label: blueBright('TypeScript'), value: 'ts' },
|
|
65
|
-
{ label: yellow('JavaScript'), value: 'js' }
|
|
66
|
-
]
|
|
67
|
-
});
|
|
68
|
-
if (isCancel(language)) abort();
|
|
69
|
-
|
|
70
|
-
// 3. Tailwind support?
|
|
71
|
-
const useTailwind = await select({
|
|
72
|
-
message: 'Add Tailwind support?',
|
|
73
|
-
options: [
|
|
74
|
-
{ label: green('Yes'), value: true },
|
|
75
|
-
{ label: red('No'), value: false }
|
|
76
|
-
]
|
|
77
|
-
});
|
|
78
|
-
if (isCancel(useTailwind)) abort();
|
|
79
|
-
|
|
80
|
-
let tailwind: { input: string; output: string } | undefined;
|
|
81
|
-
if (useTailwind) {
|
|
82
|
-
const input = await text({
|
|
83
|
-
message: 'Tailwind input CSS file:',
|
|
84
|
-
placeholder: './example/styles/tailwind.css'
|
|
85
|
-
});
|
|
86
|
-
if (isCancel(input)) abort();
|
|
87
|
-
const output = await text({
|
|
88
|
-
message: 'Tailwind output CSS file:',
|
|
89
|
-
placeholder: '/assets/css/tailwind.generated.css'
|
|
90
|
-
});
|
|
91
|
-
if (isCancel(output)) abort();
|
|
92
|
-
tailwind = { input, output };
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// 4. Framework(s)
|
|
96
|
-
const frameworks = await multiselect({
|
|
97
|
-
message: 'Framework(s) (space to select, enter to finish):',
|
|
98
|
-
options: [
|
|
99
|
-
{ label: cyan('React'), value: 'react' },
|
|
100
|
-
{ label: green('Vue'), value: 'vue' },
|
|
101
|
-
{ label: magenta('Svelte'), value: 'svelte' },
|
|
102
|
-
{ label: red('Angular'), value: 'angular' },
|
|
103
|
-
{ label: blueBright('Solid'), value: 'solid' },
|
|
104
|
-
{ label: white('HTML'), value: 'html' },
|
|
105
|
-
{ label: white('HTMX'), value: 'htmx' }
|
|
106
|
-
]
|
|
107
|
-
});
|
|
108
|
-
if (isCancel(frameworks)) abort();
|
|
109
|
-
|
|
110
|
-
// 5. Build directory
|
|
111
|
-
const buildDir = await text({
|
|
112
|
-
message: 'Build directory:',
|
|
113
|
-
placeholder: 'build'
|
|
114
|
-
});
|
|
115
|
-
if (isCancel(buildDir)) abort();
|
|
116
|
-
|
|
117
|
-
// 6. Assets directory
|
|
118
|
-
const assetsDir = await text({
|
|
119
|
-
message: 'Assets directory:',
|
|
120
|
-
placeholder: 'src/backend/assets'
|
|
121
|
-
});
|
|
122
|
-
if (isCancel(assetsDir)) abort();
|
|
123
|
-
|
|
124
|
-
// 7. Framework-specific directories
|
|
125
|
-
type Config = { framework: string; pages: string; index: string };
|
|
126
|
-
|
|
127
|
-
const single = frameworks.length === 1;
|
|
128
|
-
|
|
129
|
-
const configs = await frameworks.reduce<Promise<Config[]>>(
|
|
130
|
-
async (previousConfigsPromise, framework) => {
|
|
131
|
-
const previousConfigs = await previousConfigsPromise;
|
|
132
|
-
|
|
133
|
-
const prettyName = frameworkNames[framework] ?? framework;
|
|
134
|
-
const baseDirectory = single
|
|
135
|
-
? 'src/frontend'
|
|
136
|
-
: `src/frontend/${framework}`;
|
|
137
|
-
|
|
138
|
-
const defaultPagesDirectory = `${baseDirectory}/pages`;
|
|
139
|
-
const defaultIndexDirectory = `${baseDirectory}/indexes`;
|
|
140
|
-
|
|
141
|
-
const pagesDirectory = await text({
|
|
142
|
-
message: `${prettyName} pages directory:`,
|
|
143
|
-
placeholder: defaultPagesDirectory
|
|
144
|
-
});
|
|
145
|
-
if (isCancel(pagesDirectory)) abort();
|
|
146
|
-
|
|
147
|
-
const indexDirectory = await text({
|
|
148
|
-
message: `${prettyName} index directory:`,
|
|
149
|
-
placeholder: defaultIndexDirectory
|
|
150
|
-
});
|
|
151
|
-
if (isCancel(indexDirectory)) abort();
|
|
152
|
-
|
|
153
|
-
return [
|
|
154
|
-
...previousConfigs,
|
|
155
|
-
{ framework, index: indexDirectory, pages: pagesDirectory }
|
|
156
|
-
];
|
|
157
|
-
},
|
|
158
|
-
Promise.resolve([])
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
// 8. Database provider
|
|
162
|
-
const dbProvider = await select({
|
|
163
|
-
message: 'Database provider:',
|
|
164
|
-
options: [
|
|
165
|
-
{ label: cyan('PostgreSQL'), value: 'postgres' },
|
|
166
|
-
{ label: green('MySQL'), value: 'mysql' },
|
|
167
|
-
{ label: reset('None'), value: 'none' }
|
|
168
|
-
]
|
|
169
|
-
});
|
|
170
|
-
if (isCancel(dbProvider)) abort();
|
|
171
|
-
|
|
172
|
-
// 9. ORM choice (optional)
|
|
173
|
-
let orm: 'drizzle' | 'prisma' | undefined;
|
|
174
|
-
if (dbProvider !== 'none') {
|
|
175
|
-
const ormChoice = await select({
|
|
176
|
-
message: 'Choose an ORM (optional):',
|
|
177
|
-
options: [
|
|
178
|
-
{ label: cyan('Drizzle'), value: 'drizzle' },
|
|
179
|
-
{ label: magenta('Prisma'), value: 'prisma' },
|
|
180
|
-
{ label: reset('None'), value: 'none' }
|
|
181
|
-
]
|
|
182
|
-
});
|
|
183
|
-
if (isCancel(ormChoice)) abort();
|
|
184
|
-
orm = ormChoice === 'none' ? undefined : ormChoice;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// 10. Auth provider
|
|
188
|
-
const authProvider = await select({
|
|
189
|
-
message: 'Auth provider:',
|
|
190
|
-
options: [
|
|
191
|
-
{ label: cyan('Absolute Auth'), value: 'absoluteAuth' },
|
|
192
|
-
{ label: yellow('JWT'), value: 'jwt' },
|
|
193
|
-
{ label: reset('None'), value: 'none' }
|
|
194
|
-
]
|
|
195
|
-
});
|
|
196
|
-
if (isCancel(authProvider)) abort();
|
|
197
|
-
|
|
198
|
-
// 11. Additional plugins (optional)
|
|
199
|
-
const plugins = await multiselect({
|
|
200
|
-
message:
|
|
201
|
-
'Select additional Elysia plugins (space to select, enter to submit):',
|
|
202
|
-
options: [
|
|
203
|
-
{ label: cyan('⚙️ @elysia/cors'), value: 'cors' },
|
|
204
|
-
{ label: cyan('📦 @elysia/static'), value: 'static' },
|
|
205
|
-
{ label: green('🛠️ elysia-rate-limit'), value: 'rateLimit' },
|
|
206
|
-
{ label: green('📑 elysia-swagger'), value: 'swagger' }
|
|
207
|
-
],
|
|
208
|
-
required: false
|
|
209
|
-
});
|
|
210
|
-
if (isCancel(plugins)) abort();
|
|
211
|
-
|
|
212
|
-
// Summary
|
|
213
|
-
outro(`
|
|
214
|
-
Project Name: ${projectName}
|
|
215
|
-
Language: ${language === 'ts' ? 'TypeScript' : 'JavaScript'}
|
|
216
|
-
Tailwind: ${tailwind ? `input: ${tailwind.input}, output: ${tailwind.output}` : 'None'}
|
|
217
|
-
Framework(s): ${frameworks.join(', ')}
|
|
218
|
-
Build Directory: ${buildDir}
|
|
219
|
-
Assets Directory: ${assetsDir}
|
|
220
|
-
Database: ${dbProvider === 'none' ? 'None' : dbProvider}
|
|
221
|
-
ORM: ${orm ?? 'None'}
|
|
222
|
-
Auth: ${authProvider === 'none' ? 'None' : authProvider}
|
|
223
|
-
Plugins: ${plugins.length ? plugins.join(', ') : 'None'}
|
|
224
|
-
|
|
225
|
-
Framework Config:
|
|
226
|
-
${configs
|
|
227
|
-
.map(
|
|
228
|
-
({ framework, pages, index }) =>
|
|
229
|
-
`${frameworkNames[framework] ?? framework} ⇒ pages: ${pages}, index: ${index}`
|
|
230
|
-
)
|
|
231
|
-
.join('\n ')}
|
|
232
|
-
`);
|