create-foldkit-app 0.3.0 → 0.3.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Devin Jameson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -19,9 +19,9 @@ const setupProject = (name, projectPath, example) => Effect.gen(function* () {
19
19
  yield* Console.log(chalk.green(`✅ Created project`));
20
20
  yield* Console.log('');
21
21
  });
22
- const installProjectDependencies = (projectPath, packageManager) => Effect.gen(function* () {
22
+ const installProjectDependencies = (projectPath, packageManager, example) => Effect.gen(function* () {
23
23
  yield* Console.log(chalk.blue(`📦 Installing dependencies with ${packageManager}...`));
24
- yield* installDependencies(projectPath, packageManager);
24
+ yield* installDependencies(projectPath, packageManager, example);
25
25
  yield* Console.log(chalk.green('✅ Dependencies installed'));
26
26
  yield* Console.log('');
27
27
  });
@@ -40,7 +40,7 @@ export const create = ({ name, example, packageManager }) => Effect.gen(function
40
40
  const projectPath = path.resolve(name);
41
41
  yield* validateProject(name, projectPath, packageManager);
42
42
  yield* setupProject(name, projectPath, example);
43
- yield* installProjectDependencies(projectPath, packageManager);
43
+ yield* installProjectDependencies(projectPath, packageManager, example);
44
44
  yield* displaySuccessMessage(name, packageManager);
45
45
  return name;
46
46
  });
package/dist/index.js CHANGED
@@ -7,7 +7,6 @@ import { create as create_ } from './commands/create.js';
7
7
  const nameSchema = Schema.String.pipe(Schema.filter((name) => Match.value(name).pipe(Match.whenOr(String.includes('/'), String.includes('\\'), () => 'Project name cannot contain path separators (/ or \\)'), Match.when(String.includes(' '), () => 'Project name cannot contain spaces'), Match.when(flow(String.match(/[<>:"|?*]/), Option.isSome), () => 'Project name cannot contain special characters: < > : " | ? *'), Match.whenOr(String.startsWith('.'), String.startsWith('-'), () => 'Project name cannot start with . or -'), Match.when(String.isEmpty, () => 'Project name cannot be empty'), Match.orElse(() => true))));
8
8
  const name = Options.text('name').pipe(Options.withAlias('n'), Options.withDescription('The name of the project to create'), Options.withSchema(nameSchema));
9
9
  const example = Options.choice('example', [
10
- 'auth',
11
10
  'counter',
12
11
  'stopwatch',
13
12
  'weather',
@@ -17,9 +16,9 @@ const example = Options.choice('example', [
17
16
  'routing',
18
17
  'shopping-cart',
19
18
  'websocket-chat',
19
+ 'auth',
20
20
  ]).pipe(Options.withAlias('e'), Options.withDescription("The example application to start from. Pick an example that's similar to the application you're building. Or create multiple projects and take pieces of each!\n\n" +
21
21
  'Available examples:\n' +
22
- ' auth - Authentication with Model-as-Union pattern and protected routes\n' +
23
22
  ' counter - Simple increment/decrement with reset\n' +
24
23
  ' stopwatch - Timer with start/stop/reset functionality\n' +
25
24
  ' weather - HTTP requests with async state handling\n' +
@@ -28,7 +27,8 @@ const example = Options.choice('example', [
28
27
  ' snake - Classic game built with command streams\n' +
29
28
  ' routing - URL routing with parser combinators and route parameters\n' +
30
29
  ' shopping-cart - Complex state management with nested models and routing\n' +
31
- ' websocket-chat - WebSocket integration'));
30
+ ' websocket-chat - WebSocket integration\n' +
31
+ ' auth - Authentication with Model-as-Union pattern and protected routes'));
32
32
  const packageManager = Options.choice('package-manager', [
33
33
  'pnpm',
34
34
  'npm',
@@ -41,7 +41,7 @@ const create = Command.make('create', {
41
41
  }, create_);
42
42
  const cli = Command.run(create, {
43
43
  name: 'Create Foldkit App',
44
- version: '0.3.0',
44
+ version: '0.3.1',
45
45
  summary: HelpDoc.getSpan(HelpDoc.p('Create a new Foldkit application')),
46
46
  });
47
47
  cli(process.argv).pipe(Effect.provide([FetchHttpClient.layer, NodeContext.layer]), NodeRuntime.runMain);
@@ -1,11 +1,30 @@
1
- import { Command } from '@effect/platform';
2
- import { Effect, Match, pipe } from 'effect';
1
+ import { Command, HttpClient, HttpClientRequest } from '@effect/platform';
2
+ import { Array, Effect, Match, Record, Schema, pipe } from 'effect';
3
+ const GITHUB_RAW_BASE_URL = 'https://raw.githubusercontent.com/devinjameson/foldkit/main/examples';
3
4
  const getInstallArgs = (packageManager, isDev = false) => pipe(Match.value(packageManager), Match.when('npm', () => ['install']), Match.when('yarn', () => ['add']), Match.when('pnpm', () => ['add']), Match.exhaustive, (args) => (isDev ? [...args, '-D'] : args));
4
- export const installDependencies = (projectPath, packageManager) => Effect.gen(function* () {
5
+ const StringRecord = Schema.Record({ key: Schema.String, value: Schema.String });
6
+ const PackageJson = Schema.Struct({
7
+ dependencies: Schema.optionalWith(StringRecord, { default: () => ({}) }),
8
+ devDependencies: Schema.optionalWith(StringRecord, { default: () => ({}) }),
9
+ });
10
+ const formatDeps = (deps) => pipe(deps, Record.toEntries, Array.filter(([_, version]) => !version.includes('workspace:')), Array.map(([name, version]) => `${name}@${version}`));
11
+ const fetchExampleDeps = (example) => Effect.gen(function* () {
12
+ const client = yield* HttpClient.HttpClient;
13
+ const url = `${GITHUB_RAW_BASE_URL}/${example}/package.json`;
14
+ const response = yield* client.execute(HttpClientRequest.get(url));
15
+ const json = yield* response.json;
16
+ const packageJson = yield* Schema.decodeUnknown(PackageJson)(json);
17
+ return {
18
+ dependencies: formatDeps(packageJson.dependencies),
19
+ devDependencies: formatDeps(packageJson.devDependencies),
20
+ };
21
+ });
22
+ export const installDependencies = (projectPath, packageManager, example) => Effect.gen(function* () {
23
+ const exampleDeps = yield* fetchExampleDeps(example);
5
24
  const installArgs = getInstallArgs(packageManager);
6
- const installDeps = Command.make(packageManager, ...installArgs, 'foldkit', 'effect@^3.18.2', '@tailwindcss/vite@^4.1.10', 'tailwindcss@^4.1.10').pipe(Command.workingDirectory(projectPath), Command.stdout('inherit'), Command.stderr('inherit'));
25
+ const installDeps = Command.make(packageManager, ...installArgs, 'foldkit', ...exampleDeps.dependencies).pipe(Command.workingDirectory(projectPath), Command.stdout('inherit'), Command.stderr('inherit'));
7
26
  yield* Command.exitCode(installDeps);
8
27
  const installDevArgs = getInstallArgs(packageManager, true);
9
- const installDevDeps = Command.make(packageManager, ...installDevArgs, '@foldkit/vite-plugin@0.2.0', 'vite@^7.1.9', 'typescript@^5.9.3', 'prettier@^3.6.2', '@trivago/prettier-plugin-sort-imports@^5.2.2', 'eslint@^9.37.0', '@eslint/js@^9.37.0', '@typescript-eslint/eslint-plugin@^8.45.0', '@typescript-eslint/parser@^8.45.0').pipe(Command.workingDirectory(projectPath), Command.stdout('inherit'), Command.stderr('inherit'));
28
+ const installDevDeps = Command.make(packageManager, ...installDevArgs, '@foldkit/vite-plugin', ...exampleDeps.devDependencies).pipe(Command.workingDirectory(projectPath), Command.stdout('inherit'), Command.stderr('inherit'));
10
29
  yield* Command.exitCode(installDevDeps);
11
30
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-foldkit-app",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Create Foldkit applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,12 +11,6 @@
11
11
  "dist",
12
12
  "templates"
13
13
  ],
14
- "scripts": {
15
- "clean": "rimraf dist *.tsbuildinfo",
16
- "build": "pnpm run clean && tsc -b",
17
- "format": "prettier -w .",
18
- "typecheck": "tsc -b --noEmit"
19
- },
20
14
  "dependencies": {
21
15
  "@effect/cli": "^0.73.0",
22
16
  "@effect/platform": "^0.94.1",
@@ -48,5 +42,11 @@
48
42
  },
49
43
  "engines": {
50
44
  "node": ">=18.0.0"
45
+ },
46
+ "scripts": {
47
+ "clean": "rimraf dist *.tsbuildinfo",
48
+ "build": "pnpm run clean && tsc -b",
49
+ "format": "prettier -w .",
50
+ "typecheck": "tsc -b --noEmit"
51
51
  }
52
- }
52
+ }
@@ -5,6 +5,7 @@
5
5
  "lib": ["ES2022", "DOM"],
6
6
  "moduleResolution": "bundler",
7
7
  "strict": true,
8
+ "noUncheckedIndexedAccess": true,
8
9
  "skipLibCheck": true,
9
10
  "esModuleInterop": true,
10
11
  "exactOptionalPropertyTypes": true,