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 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.3",
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
@@ -1,4 +0,0 @@
1
- node_modules
2
- dist
3
- build
4
- *.min.js
package/.prettierrc.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "semi": true,
3
- "trailingComma": "none",
4
- "singleQuote": true,
5
- "printWidth": 80,
6
- "tabWidth": 4,
7
- "endOfLine": "auto",
8
- "useTabs": true
9
- }
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
- `);