create-soda 0.1.1 → 0.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-soda",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Create a Soda project: bun create soda my-app",
5
5
  "keywords": [
6
6
  "soda",
@@ -25,13 +25,15 @@
25
25
  },
26
26
  "files": [
27
27
  "dist",
28
- "template",
29
- "core-version.json"
28
+ "templates"
30
29
  ],
31
30
  "engines": {
32
31
  "node": ">=20"
33
32
  },
34
33
  "scripts": {
35
- "build": "rm -rf dist && tsc -p tsconfig.build.json && bun scripts/write-core-version.ts"
34
+ "build": "rm -rf dist && bun build src/index.ts --target node --outfile dist/index.js"
35
+ },
36
+ "devDependencies": {
37
+ "@clack/prompts": "^1.9.0"
36
38
  }
37
39
  }
@@ -4,9 +4,13 @@ Created with `create-soda`. Requires [Bun](https://bun.sh).
4
4
 
5
5
  ```bash
6
6
  bun install
7
- bun dev # bun --hot: reloads on change
8
- bun test
7
+ bun dev # bun --hot: reloads on change
8
+ bun debug # the same, with the inspector
9
+ bun test # test:watch, test:cov
9
10
  bun typecheck
11
+ bun lint # oxlint; lint:fix
12
+ bun run build # bundles src/main.ts into dist/
13
+ bun start:prod # runs the bundle
10
14
  ```
11
15
 
12
16
  - `src/main.ts`: creates the application, CORS, graceful shutdown.
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": [
4
+ "typescript",
5
+ "unicorn",
6
+ "oxc",
7
+ "import"
8
+ ],
9
+ "categories": {
10
+ "correctness": "error",
11
+ "suspicious": "warn"
12
+ },
13
+ "rules": {
14
+ "typescript/no-extraneous-class": [
15
+ "warn",
16
+ {
17
+ "allowWithDecorator": true
18
+ }
19
+ ]
20
+ },
21
+ "ignorePatterns": [
22
+ "dist"
23
+ ]
24
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "soda-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "bun --hot src/main.ts",
8
+ "debug": "bun --inspect --hot src/main.ts",
9
+ "start": "bun src/main.ts",
10
+ "build": "bun build src/main.ts --target bun --outdir dist --minify --sourcemap=linked",
11
+ "start:prod": "bun dist/main.js",
12
+ "test": "bun test",
13
+ "test:watch": "bun test --watch",
14
+ "test:cov": "bun test --coverage",
15
+ "typecheck": "bun check",
16
+ "lint": "oxlint",
17
+ "lint:fix": "oxlint --fix"
18
+ },
19
+ "dependencies": {
20
+ "@getsoda/core": "workspace",
21
+ "zod": "^4.6.7"
22
+ },
23
+ "devDependencies": {
24
+ "@types/bun": "latest",
25
+ "oxlint": "^1.93.0",
26
+ "typescript": "^7.0.2"
27
+ }
28
+ }
@@ -0,0 +1,18 @@
1
+ # Soda app
2
+
3
+ Created with `create-soda`. Requires [Bun](https://bun.sh).
4
+
5
+ ```bash
6
+ bun install
7
+ bun dev # bun --hot: reloads on change
8
+ bun debug # the same, with the inspector
9
+ bun test # test:watch, test:cov
10
+ bun typecheck
11
+ bun lint # oxlint; lint:fix
12
+ bun run build # bundles src/main.ts into dist/
13
+ bun start:prod # runs the bundle
14
+ ```
15
+
16
+ - `src/main.ts`: creates the application and starts listening.
17
+ - `src/app.module.ts`: the root module.
18
+ - `src/app.controller.ts`, `src/app.service.ts`: `GET /` answers `Hello Soda!`.
@@ -0,0 +1,11 @@
1
+ node_modules
2
+ dist
3
+ *.tgz
4
+ coverage
5
+
6
+ .env
7
+ .env.local
8
+ .env.*.local
9
+
10
+ .DS_Store
11
+ .idea
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": [
4
+ "typescript",
5
+ "unicorn",
6
+ "oxc",
7
+ "import"
8
+ ],
9
+ "categories": {
10
+ "correctness": "error",
11
+ "suspicious": "warn"
12
+ },
13
+ "rules": {
14
+ "typescript/no-extraneous-class": [
15
+ "warn",
16
+ {
17
+ "allowWithDecorator": true
18
+ }
19
+ ]
20
+ },
21
+ "ignorePatterns": [
22
+ "dist"
23
+ ]
24
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "soda-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "bun --hot src/main.ts",
8
+ "debug": "bun --inspect --hot src/main.ts",
9
+ "start": "bun src/main.ts",
10
+ "build": "bun build src/main.ts --target bun --outdir dist --minify --sourcemap=linked",
11
+ "start:prod": "bun dist/main.js",
12
+ "test": "bun test",
13
+ "test:watch": "bun test --watch",
14
+ "test:cov": "bun test --coverage",
15
+ "typecheck": "bun check",
16
+ "lint": "oxlint",
17
+ "lint:fix": "oxlint --fix"
18
+ },
19
+ "dependencies": {
20
+ "@getsoda/core": "workspace"
21
+ },
22
+ "devDependencies": {
23
+ "@types/bun": "latest",
24
+ "oxlint": "^1.93.0",
25
+ "typescript": "^7.0.2"
26
+ }
27
+ }
@@ -0,0 +1,12 @@
1
+ import { Controller, Get, inject } from '@getsoda/core'
2
+ import { AppService } from './app.service.ts'
3
+
4
+ @Controller()
5
+ export class AppController {
6
+ readonly #app = inject(AppService)
7
+
8
+ @Get()
9
+ getHello(): string {
10
+ return this.#app.getHello()
11
+ }
12
+ }
@@ -0,0 +1,6 @@
1
+ import { Module } from '@getsoda/core'
2
+ import { AppController } from './app.controller.ts'
3
+ import { AppService } from './app.service.ts'
4
+
5
+ @Module({ providers: [AppService], controllers: [AppController] })
6
+ export class AppModule {}
@@ -0,0 +1,5 @@
1
+ export class AppService {
2
+ getHello(): string {
3
+ return 'Hello Soda!'
4
+ }
5
+ }
@@ -0,0 +1,15 @@
1
+ import { afterAll, expect, test } from 'bun:test'
2
+ import { createApp } from '@getsoda/core'
3
+ import { AppModule } from './app.module.ts'
4
+
5
+ const app = await createApp(AppModule, { logger: false })
6
+ const server = await app.listen(0)
7
+
8
+ afterAll(() => app.close())
9
+
10
+ test('GET / says hello', async () => {
11
+ const response = await fetch(server.url)
12
+
13
+ expect(response.status).toBe(200)
14
+ expect(await response.text()).toBe('Hello Soda!')
15
+ })
@@ -0,0 +1,7 @@
1
+ import { createApp } from '@getsoda/core'
2
+ import { AppModule } from './app.module.ts'
3
+
4
+ const app = await createApp(AppModule)
5
+
6
+ app.enableShutdownSignals()
7
+ await app.listen(Number(process.env.PORT ?? 3000))
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["ESNext"],
4
+ "target": "ESNext",
5
+ "module": "Preserve",
6
+ "moduleDetection": "force",
7
+ "moduleResolution": "bundler",
8
+ "allowImportingTsExtensions": true,
9
+ "verbatimModuleSyntax": true,
10
+ "noEmit": true,
11
+ "types": ["bun"],
12
+
13
+ "strict": true,
14
+ "skipLibCheck": true,
15
+ "noFallthroughCasesInSwitch": true,
16
+ "noUncheckedIndexedAccess": true,
17
+ "noImplicitOverride": true
18
+ }
19
+ }
package/core-version.json DELETED
@@ -1 +0,0 @@
1
- {"version":"0.1.1"}
package/dist/project.js DELETED
@@ -1,68 +0,0 @@
1
- /**
2
- * @module
3
- * Creating a project from the template: names, target directory, files.
4
- *
5
- * Rules from `create-vite`: the target directory is cleaned of characters
6
- * file systems refuse, a directory holding only `.git` counts as empty, the
7
- * package name is made valid for npm, and `.gitignore` is stored as
8
- * `_gitignore` because npm drops `.gitignore` files from published packages.
9
- */
10
- import { existsSync } from 'node:fs';
11
- import { cp, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
12
- import { basename, join, resolve } from 'node:path';
13
- /** Template files renamed when copied. */
14
- const RENAMED = { _gitignore: '.gitignore' };
15
- /** `' my-app/ '` → `'my-app'`. */
16
- export const formatTargetDir = (dir) => dir
17
- .trim()
18
- .replace(/[<>:"\\|?*]/g, '')
19
- .replace(/\/+$/, '');
20
- export const isValidPackageName = (name) => /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(name);
21
- /** `'My App'` → `'my-app'`. */
22
- export const toValidPackageName = (name) => name
23
- .trim()
24
- .toLowerCase()
25
- .replace(/\s+/g, '-')
26
- .replace(/^[._]/, '')
27
- .replace(/[^a-z\d\-~]+/g, '-');
28
- /** `true` for a missing directory, an empty one, or one holding only `.git`. */
29
- export const isEmptyDir = async (dir) => {
30
- if (!existsSync(dir)) {
31
- return true;
32
- }
33
- const entries = await readdir(dir);
34
- return entries.length === 0 || (entries.length === 1 && entries[0] === '.git');
35
- };
36
- /** Removes everything in `dir` but `.git`. */
37
- export const emptyDir = async (dir) => {
38
- for (const entry of await readdir(dir)) {
39
- if (entry !== '.git') {
40
- await rm(join(dir, entry), { recursive: true, force: true });
41
- }
42
- }
43
- };
44
- /**
45
- * Copies the template into `dir`, renames `_gitignore`, sets the package name and the core version.
46
- */
47
- export const createProject = async (options) => {
48
- const root = resolve(options.dir);
49
- await cp(options.template, root, { recursive: true });
50
- for (const [from, to] of Object.entries(RENAMED)) {
51
- if (existsSync(join(root, from))) {
52
- await rename(join(root, from), join(root, to));
53
- }
54
- }
55
- const manifestPath = join(root, 'package.json');
56
- const manifest = JSON.parse(await readFile(manifestPath, 'utf8'));
57
- manifest.name = options.name ?? toValidPackageName(basename(root));
58
- manifest.dependencies['@getsoda/core'] = options.coreVersion;
59
- await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
60
- };
61
- /**
62
- * Package manager the command was run with, from `npm_config_user_agent`
63
- * (`bun/1.4.3 npm/? node/v24…` → `bun`). Defaults to `bun`.
64
- */
65
- export const detectPackageManager = (userAgent) => {
66
- const name = userAgent?.split(' ')[0]?.split('/')[0];
67
- return name === undefined || name === '' ? 'bun' : name;
68
- };
@@ -1,20 +0,0 @@
1
- {
2
- "name": "soda-app",
3
- "version": "0.1.0",
4
- "private": true,
5
- "type": "module",
6
- "scripts": {
7
- "dev": "bun --hot src/main.ts",
8
- "start": "bun src/main.ts",
9
- "test": "bun test",
10
- "typecheck": "bun check"
11
- },
12
- "dependencies": {
13
- "@getsoda/core": "workspace",
14
- "zod": "^4.6.7"
15
- },
16
- "devDependencies": {
17
- "@types/bun": "latest",
18
- "typescript": "^7.0.2"
19
- }
20
- }
File without changes
File without changes
File without changes
File without changes