create-foldkit-app 0.16.0 → 0.17.1

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.
@@ -60,10 +60,10 @@ const validateProject = (name, projectPath, packageManager) => Effect.gen(functi
60
60
  return yield* Effect.fail(`Package manager '${packageManager}' is not available. Please install it first.`);
61
61
  }
62
62
  });
63
- const setupProject = (name, projectPath, example) => Effect.gen(function* () {
63
+ const setupProject = (name, projectPath, example, packageManager) => Effect.gen(function* () {
64
64
  yield* Console.log(chalk.blue('🚀 Creating your Foldkit app...'));
65
65
  yield* Console.log('');
66
- yield* createProject(name, projectPath, example);
66
+ yield* createProject(name, projectPath, example, packageManager);
67
67
  yield* Console.log(chalk.green(`✅ Created project`));
68
68
  yield* Console.log('');
69
69
  });
@@ -118,7 +118,7 @@ export const create = (input) => Effect.gen(function* () {
118
118
  const path = yield* Path.Path;
119
119
  const projectPath = path.resolve(name);
120
120
  yield* validateProject(name, projectPath, packageManager);
121
- yield* setupProject(name, projectPath, example);
121
+ yield* setupProject(name, projectPath, example, packageManager);
122
122
  yield* installProjectDependencies(projectPath, packageManager, example);
123
123
  yield* displaySuccessMessage(name, packageManager);
124
124
  return name;
@@ -2,18 +2,21 @@ import { Array, Effect, FileSystem, Match, Option, Path, Record, Ref, Schema, St
2
2
  import { HttpClient, HttpClientRequest, } from 'effect/unstable/http';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  const GITHUB_API_BASE_URL = 'https://api.github.com/repos/foldkit/foldkit/contents/examples';
5
- const getBaseFiles = Effect.gen(function* () {
6
- const fs = yield* FileSystem.FileSystem;
5
+ const getTemplateRoot = Effect.gen(function* () {
7
6
  const path = yield* Path.Path;
8
7
  const currentDir = path.dirname(fileURLToPath(import.meta.url));
9
- const templatesDir = path.resolve(currentDir, '..', '..', 'templates', 'base');
8
+ return path.resolve(currentDir, '..', '..', 'templates');
9
+ });
10
+ const getTemplateFiles = (templateDir) => Effect.gen(function* () {
11
+ const fs = yield* FileSystem.FileSystem;
12
+ const path = yield* Path.Path;
10
13
  const fileContentByPath = yield* Ref.make({});
11
14
  const processEntry = (dir) => (entry) => Effect.gen(function* () {
12
15
  const fullPath = path.join(dir, entry);
13
16
  const stat = yield* fs.stat(fullPath);
14
17
  yield* Match.value(stat.type).pipe(Match.when('Directory', () => processDirectory(fullPath)), Match.when('File', () => Effect.gen(function* () {
15
18
  const content = yield* fs.readFileString(fullPath);
16
- const relativePath = path.relative(templatesDir, fullPath);
19
+ const relativePath = path.relative(templateDir, fullPath);
17
20
  yield* Ref.update(fileContentByPath, files => ({
18
21
  ...files,
19
22
  [relativePath]: content,
@@ -26,20 +29,31 @@ const getBaseFiles = Effect.gen(function* () {
26
29
  concurrency: 'unbounded',
27
30
  });
28
31
  });
29
- yield* processDirectory(templatesDir);
32
+ yield* processDirectory(templateDir);
30
33
  return yield* Ref.get(fileContentByPath);
31
34
  });
32
- export const createProject = (name, projectPath, example) => Effect.gen(function* () {
33
- yield* createBaseFiles(projectPath);
34
- yield* modifyBaseFiles(projectPath, name);
35
- yield* createExampleFiles(projectPath, example);
35
+ const getBaseFiles = Effect.gen(function* () {
36
+ const path = yield* Path.Path;
37
+ const templateRoot = yield* getTemplateRoot;
38
+ return yield* getTemplateFiles(path.join(templateRoot, 'base'));
36
39
  });
37
- const createBaseFiles = (projectPath) => Effect.gen(function* () {
40
+ const getPackageManagerFiles = (packageManager) => Effect.gen(function* () {
38
41
  const fs = yield* FileSystem.FileSystem;
39
42
  const path = yield* Path.Path;
40
- yield* fs.makeDirectory(projectPath, { recursive: true });
41
- const baseFiles = yield* getBaseFiles;
42
- yield* pipe(baseFiles, Record.toEntries, Effect.forEach(([filePath, content]) => Effect.gen(function* () {
43
+ const templateRoot = yield* getTemplateRoot;
44
+ const templateDir = path.join(templateRoot, 'package-managers', packageManager);
45
+ const isTemplateDirectoryPresent = yield* fs.exists(templateDir);
46
+ if (isTemplateDirectoryPresent) {
47
+ return yield* getTemplateFiles(templateDir);
48
+ }
49
+ else {
50
+ return {};
51
+ }
52
+ });
53
+ const createFiles = (projectPath, files) => Effect.gen(function* () {
54
+ const fs = yield* FileSystem.FileSystem;
55
+ const path = yield* Path.Path;
56
+ yield* pipe(files, Record.toEntries, Effect.forEach(([filePath, content]) => Effect.gen(function* () {
43
57
  const targetPath = Match.value(filePath).pipe(Match.when('gitignore', () => '.gitignore'), Match.when('ignore', () => '.ignore'), Match.orElse(() => filePath));
44
58
  const fullPath = path.join(projectPath, targetPath);
45
59
  const dirPath = path.dirname(fullPath);
@@ -47,11 +61,29 @@ const createBaseFiles = (projectPath) => Effect.gen(function* () {
47
61
  yield* fs.writeFileString(fullPath, content);
48
62
  }), { concurrency: 'unbounded' }));
49
63
  });
64
+ const createBaseFiles = (projectPath) => Effect.gen(function* () {
65
+ const fs = yield* FileSystem.FileSystem;
66
+ yield* fs.makeDirectory(projectPath, { recursive: true });
67
+ const baseFiles = yield* getBaseFiles;
68
+ yield* createFiles(projectPath, baseFiles);
69
+ });
70
+ const createPackageManagerFiles = (projectPath, packageManager) => Effect.gen(function* () {
71
+ const packageManagerFiles = yield* getPackageManagerFiles(packageManager);
72
+ yield* createFiles(projectPath, packageManagerFiles);
73
+ });
74
+ export const createProject = (name, projectPath, example, packageManager) => Effect.gen(function* () {
75
+ yield* createBaseFiles(projectPath);
76
+ yield* modifyBaseFiles(projectPath, name);
77
+ yield* createPackageManagerFiles(projectPath, packageManager);
78
+ yield* createExampleFiles(projectPath, example);
79
+ });
50
80
  const modifyBaseFiles = (projectPath, name) => Effect.gen(function* () {
51
81
  const fs = yield* FileSystem.FileSystem;
52
82
  const path = yield* Path.Path;
53
83
  const packageJsonPath = path.join(projectPath, 'package.json');
54
- return yield* fs.readFileString(packageJsonPath).pipe(Effect.map(String.replace('my-foldkit-app', name)), Effect.flatMap(updatedContent => fs.writeFileString(packageJsonPath, updatedContent)));
84
+ const content = yield* fs.readFileString(packageJsonPath);
85
+ const updatedContent = String.replace('my-foldkit-app', name)(content);
86
+ yield* fs.writeFileString(packageJsonPath, updatedContent);
55
87
  });
56
88
  const GitHubFileEntry = Schema.Struct({
57
89
  name: Schema.String,
@@ -16,6 +16,16 @@ const PASS_THROUGH_WORKSPACE_PACKAGES = new Set([
16
16
  '@foldkit/ui',
17
17
  '@foldkit/devtools',
18
18
  ]);
19
+ const TEMPLATE_DEV_DEPENDENCIES = [
20
+ '@foldkit/vite-plugin',
21
+ '@foldkit/devtools-mcp',
22
+ '@foldkit/oxlint-plugin',
23
+ '@trivago/prettier-plugin-sort-imports',
24
+ 'happy-dom',
25
+ 'oxlint',
26
+ 'prettier',
27
+ 'vitest',
28
+ ];
19
29
  const formatDeps = (deps) => pipe(deps, Record.toEntries, Array.filter(([name, version]) => !version.includes('workspace:') ||
20
30
  PASS_THROUGH_WORKSPACE_PACKAGES.has(name)), Array.map(([name, version]) => version.includes('workspace:') ? `${name}@latest` : `${name}@${version}`));
21
31
  const fetchExampleDeps = (example) => Effect.gen(function* () {
@@ -60,10 +70,7 @@ export const installDependencies = (projectPath, packageManager, example) => Eff
60
70
  const installDevArgs = getInstallArgs(packageManager, true);
61
71
  yield* runCommand(packageManager, [
62
72
  ...installDevArgs,
63
- '@foldkit/vite-plugin',
64
- '@foldkit/devtools-mcp',
65
- 'vitest',
66
- 'happy-dom',
73
+ ...TEMPLATE_DEV_DEPENDENCIES,
67
74
  ...exampleDeps.devDependencies,
68
75
  ], projectPath);
69
76
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-foldkit-app",
3
- "version": "0.16.0",
3
+ "version": "0.17.1",
4
4
  "description": "Create Foldkit applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,6 +19,9 @@
19
19
  "rimraf": "^6.1.3",
20
20
  "typescript": "^6.0.3"
21
21
  },
22
+ "devDependencies": {
23
+ "@types/node": "^25.9.3"
24
+ },
22
25
  "keywords": [
23
26
  "create-foldkit-app",
24
27
  "foldkit",
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": ["typescript"],
4
+ "jsPlugins": [
5
+ {
6
+ "name": "foldkit",
7
+ "specifier": "@foldkit/oxlint-plugin"
8
+ }
9
+ ],
10
+ "categories": {
11
+ "correctness": "off"
12
+ },
13
+ "rules": {
14
+ "no-unused-vars": [
15
+ "error",
16
+ {
17
+ "argsIgnorePattern": "^_",
18
+ "varsIgnorePattern": "^_",
19
+ "caughtErrorsIgnorePattern": "^_",
20
+ "destructuredArrayIgnorePattern": "^_"
21
+ }
22
+ ],
23
+ "typescript/no-explicit-any": "error",
24
+ "typescript/consistent-type-assertions": [
25
+ "error",
26
+ { "assertionStyle": "never" }
27
+ ],
28
+ "foldkit/no-noop-message": "error",
29
+ "foldkit/got-submodel-message-name": "error",
30
+ "foldkit/message-binding-matches-tag": "error",
31
+ "foldkit/got-prefix-requires-submodel-payload": "error",
32
+ "foldkit/no-empty-object-tagged-call": "error",
33
+ "foldkit/prefer-callable-message-constructor": "error",
34
+ "foldkit/command-binding-matches-name": "error"
35
+ },
36
+ "ignorePatterns": [
37
+ "dist/",
38
+ "node_modules/",
39
+ "repos/",
40
+ "**/*.d.ts",
41
+ "vite.config.ts",
42
+ "vitest.config.ts",
43
+ "**/*.config.js",
44
+ "**/*.config.mjs"
45
+ ]
46
+ }
@@ -9,6 +9,6 @@
9
9
  "typecheck": "tsc --noEmit",
10
10
  "format": "prettier -w .",
11
11
  "test": "vitest run",
12
- "lint": "eslint ."
12
+ "lint": "oxlint"
13
13
  }
14
14
  }
@@ -0,0 +1,2 @@
1
+ allowBuilds:
2
+ msgpackr-extract: false
@@ -1,52 +0,0 @@
1
- import js from '@eslint/js'
2
- import tsPlugin from '@typescript-eslint/eslint-plugin'
3
- import tsParser from '@typescript-eslint/parser'
4
-
5
- export default [
6
- {
7
- ...js.configs.recommended,
8
- files: ['**/*.ts', '**/*.js'],
9
- languageOptions: {
10
- parser: tsParser,
11
- parserOptions: {
12
- ecmaVersion: 'latest',
13
- sourceType: 'module',
14
- },
15
- },
16
- plugins: {
17
- '@typescript-eslint': tsPlugin,
18
- },
19
- rules: {
20
- 'no-redeclare': 'off',
21
- 'no-undef': 'off',
22
- 'no-unused-vars': 'off',
23
- '@typescript-eslint/consistent-type-assertions': [
24
- 'error',
25
- { assertionStyle: 'never' },
26
- ],
27
- '@typescript-eslint/no-explicit-any': 'error',
28
- '@typescript-eslint/no-unused-vars': [
29
- 'error',
30
- {
31
- argsIgnorePattern: '^_',
32
- varsIgnorePattern: '^_',
33
- caughtErrorsIgnorePattern: '^_',
34
- destructuredArrayIgnorePattern: '^_',
35
- },
36
- ],
37
- },
38
- },
39
-
40
- {
41
- ignores: [
42
- 'dist/',
43
- 'node_modules/',
44
- 'repos/',
45
- '**/*.d.ts',
46
- 'eslint.config.mjs',
47
- 'vite.config.ts',
48
- '**/*.config.js',
49
- '**/*.config.mjs',
50
- ],
51
- },
52
- ]