diff --git a/.changeset/config.json b/.changeset/config.json index 7b3458c..f8048af 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,6 +1,6 @@ { "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", - "changelog": ["@changesets/changelog-github", { "repo": "/" }], + "changelog": ["@changesets/changelog-github", { "repo": "@oopsstudio/system" }], "commit": false, "fixed": [], "linked": [], diff --git a/README.md b/README.md index 8402c48..2dc82f8 100644 --- a/README.md +++ b/README.md @@ -1,250 +1,52 @@ -# Monorepo Template +# Ooops System — Monorepo -Opinionated TypeScript + pnpm workspace monorepo template. It ships with Vitest (V8 coverage), ESLint (flat config), tsup builds, Husky + Commitlint, Changesets, dependency-cruiser, publint, are-the-types-wrong, and size-limit. Batteries included; vendor lock-in not included. - -## Requirements - -- Node 20.x or 22.x -- pnpm 9.x - -## Quick start - -1. Use this repository as a **Template** on GitHub. -2. Clone your new repository and install: - - `pnpm install` -3. Validate everything: - - `pnpm -w validate` - (runs typecheck, lint, build, tests, size-limit, dep-cruise, publint, attw) - -## What’s inside - -- **TypeScript**: strict, ESM, project references ready -- **Vitest**: node environment, V8 coverage, per-package opt-in config -- **ESLint (flat)**: tabs, single quotes, no semicolons, max line length 100 -- **tsup**: ESM output, d.ts, sourcemaps, tree-shakeable -- **Husky + Commitlint**: Git hooks, Conventional Commits -- **Changesets**: versioning and publishing flow -- **dependency-cruiser**: no cycles, no unresolved, no importing other packages’ internals -- **publint & are-the-types-wrong**: package publishing sanity checks -- **size-limit**: per-entry bundle budgets - -## Workspace layout - -``` -. -├─ packages/ -│ └─ demo/ # example package (you can delete or replace) -├─ .github/workflows/ci.yml # CI pipeline (calls pnpm -w validate) -├─ .github/workflows/release.yml # Auto-release (Changesets) -├─ tsconfig.base.json # shared TS config -├─ eslint.config.js # flat ESLint config -├─ .dependency-cruiser.cjs # graph rules (no cycles, no cross-internals) -├─ package.json # workspace scripts -├─ README.md # README file -└─ vitest.config.ts # vitest config -``` - -## Common scripts (root) - -- `pnpm -w typecheck` — TypeScript type check for the workspace -- `pnpm -w lint` — ESLint across the workspace -- `pnpm -w build` — build all packages with tsup -- `pnpm -w test` — run Vitest across packages -- `pnpm -w size` — run size-limit across packages -- `pnpm -w depcruise` — dependency-cruiser checks -- `pnpm -w publint` — publint checks on built packages -- `pnpm -w attw` — are-the-types-wrong checks -- `pnpm -w validate` — runs the full validation pipeline above - -Filter by package: `pnpm -w -F @your-scope/ +``` + +## Usage (React) + +```tsx +import { useLogger } from '@ooopsstudio/frameworks/react' +import { useForm } from '@ooopsstudio/frameworks/react/forms' + +const Component = () => { + const logger = useLogger() + const form = useForm({ schema }) + + return
...
+} +``` + +--- + +## Structure + +| Framework | Features | +|------------|-----------| +| **Svelte** | actions, stores, components, and features | +| **React** | hooks and bindings for core + sdk utilities | + +--- + +## Requirements + +- Node 22.x or later +- TypeScript strict mode +- Svelte 5 or React 18+ + +--- + +## License + +[MIT](./LICENSE) © Ooops Studio \ No newline at end of file diff --git a/packages/demo/package.json b/packages/frameworks/package.json similarity index 75% rename from packages/demo/package.json rename to packages/frameworks/package.json index 10df599..6381cc4 100644 --- a/packages/demo/package.json +++ b/packages/frameworks/package.json @@ -1,6 +1,6 @@ { - "name": "@/", - "description": "", + "name": "@ooopstudio/frameworks", + "description": "Framework adapters for @ooopsstudio/core and @ooopsstudio/sdk, offering idiomatic Svelte and React bindings for deterministic, reactive runtime logic.", "version": "0.0.0", "type": "module", "publishConfig": {"access": "public"}, diff --git a/packages/frameworks/src/index.ts b/packages/frameworks/src/index.ts new file mode 100644 index 0000000..0d4397b --- /dev/null +++ b/packages/frameworks/src/index.ts @@ -0,0 +1,10 @@ +/** + * Returns a friendly greeting message + * @param name - The name to greet + * @returns A greeting string + * @example + * greet('World') // "Hello, World" + */ +export function greet(name: string): string { + return `Hello, ${name}` +} \ No newline at end of file diff --git a/packages/frameworks/test/index.test.ts b/packages/frameworks/test/index.test.ts new file mode 100644 index 0000000..38f5a81 --- /dev/null +++ b/packages/frameworks/test/index.test.ts @@ -0,0 +1,10 @@ +import {describe, it, expect} from 'vitest' + +import {greet} from '../src/index' + +describe('greet', () => { + it('should return a greeting message', () => { + expect(greet('World')).toBe('Hello, World') + expect(greet('Alice')).toBe('Hello, Alice') + }) +}) \ No newline at end of file diff --git a/packages/frameworks/tsconfig.json b/packages/frameworks/tsconfig.json new file mode 100644 index 0000000..fee0de8 --- /dev/null +++ b/packages/frameworks/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "sourceMap": true, + "rootDir": "src", + "outDir": "dist", + "types": ["node"], + "stripInternal": true + }, + "include": ["src"], + "exclude": ["dist", "coverage", "node_modules"] +} \ No newline at end of file diff --git a/packages/frameworks/tsup.config.ts b/packages/frameworks/tsup.config.ts new file mode 100644 index 0000000..cabf6b4 --- /dev/null +++ b/packages/frameworks/tsup.config.ts @@ -0,0 +1,15 @@ +// packages/root/tsup.config.ts +import {defineConfig} from 'tsup' + +export default defineConfig({ + entry: {'index': 'src/index.ts'}, + format: ['esm'], + platform: 'neutral', + target: 'node20', + dts: {resolve: true}, + sourcemap: true, + clean: true, + splitting: false, + treeshake: true, + minify: false +}) \ No newline at end of file diff --git a/packages/frameworks/vitest.config.ts b/packages/frameworks/vitest.config.ts new file mode 100644 index 0000000..c563d02 --- /dev/null +++ b/packages/frameworks/vitest.config.ts @@ -0,0 +1,24 @@ +import {defineConfig, mergeConfig} from 'vitest/config' + +import base from '../../vitest.config' + +export default mergeConfig(base, defineConfig({ + test: { + passWithNoTests: true, + coverage: { + exclude: [ + '**/*.d.ts', + '**/*.{test,spec}.{ts,tsx}', + '**/__tests__/**' + ], + + thresholds: { + perFile: true, + statements: 90, + branches: 90, + functions: 90, + lines: 90 + } + } + } +})) diff --git a/packages/sdk/.size-limit.json b/packages/sdk/.size-limit.json new file mode 100644 index 0000000..a11a7c6 --- /dev/null +++ b/packages/sdk/.size-limit.json @@ -0,0 +1,3 @@ +[ + { "name": "", "path": ["dist/index.js"], "limit": "6 KB" } +] \ No newline at end of file diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md new file mode 100644 index 0000000..7e81108 --- /dev/null +++ b/packages/sdk/CHANGELOG.md @@ -0,0 +1,3 @@ +# @ooopsstudio/sdk + +## 0.0.0 \ No newline at end of file diff --git a/packages/sdk/README.md b/packages/sdk/README.md new file mode 100644 index 0000000..402ccaf --- /dev/null +++ b/packages/sdk/README.md @@ -0,0 +1,57 @@ +# @ooopsstudio/sdk + +High-level developer utilities and integrations built on top of **@ooopsstudio/core**. +Includes framework-agnostic helpers for analytics, forms, configuration, cookies, and more — all deterministic, composable, and type-safe. + +--- + +## Installation + +```bash +pnpm add @ooopsstudio/sdk +# or +npm install @ooopsstudio/sdk +``` + +--- + +## Usage + +```ts +import { useAnalytics } from '@ooopsstudio/sdk/analytics' +import { loadConfig } from '@ooopsstudio/sdk/config' + +const analytics = useAnalytics({ provider: 'plausible' }) +const config = loadConfig({ schema }) + +analytics.track('page_view') +``` + +--- + +## Features + +- **Analytics** – unified provider-agnostic API (Plausible, Matomo, etc.) +- **Forms** – validation, state, and serialization with no framework lock-in +- **Config** – typed configuration loading and schema validation +- **Cookies** – consent and secure cookie handling +- **Utils** – lightweight helpers for i18n, URLs, and formatting + +--- + +## Relation to Core + +`@ooopsstudio/sdk` builds on top of [`@ooopsstudio/core`](https://www.npmjs.com/package/@ooopsstudio/core), extending its deterministic runtime into developer-facing tools. + +--- + +## Requirements + +- Node 22.x or later +- TypeScript strict mode + +--- + +## License + +[MIT](./LICENSE) © Ooops Studio \ No newline at end of file diff --git a/packages/sdk/package.json b/packages/sdk/package.json new file mode 100644 index 0000000..076bfd7 --- /dev/null +++ b/packages/sdk/package.json @@ -0,0 +1,24 @@ +{ + "name": "@ooopstudio/sdk", + "description": "Developer-friendly utilities and integrations built on top of @ooopsstudio/core — analytics, forms, config, cookies, and helpers for reproducible, framework-agnostic apps.", + "version": "0.0.0", + "type": "module", + "publishConfig": {"access": "public"}, + "sideEffects": false, + "license": "MIT", + "engines": {"node": ">=20"}, + "exports": { + ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } + }, + "files": ["dist"], + "scripts": { + "typecheck": "tsc -p tsconfig.json --noEmit", + "lint": "eslint .", + "test": "vitest run", + "build": "tsup", + "depcruise": "depcruise --no-config src", + "size": "size-limit", + "publint": "publint", + "attw": "pnpm -r --filter \"./packages/*\" exec attw --pack --ignore-rules no-resolution --ignore-rules cjs-resolves-to-esm" + } +} \ No newline at end of file diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts new file mode 100644 index 0000000..0d4397b --- /dev/null +++ b/packages/sdk/src/index.ts @@ -0,0 +1,10 @@ +/** + * Returns a friendly greeting message + * @param name - The name to greet + * @returns A greeting string + * @example + * greet('World') // "Hello, World" + */ +export function greet(name: string): string { + return `Hello, ${name}` +} \ No newline at end of file diff --git a/packages/sdk/test/index.test.ts b/packages/sdk/test/index.test.ts new file mode 100644 index 0000000..38f5a81 --- /dev/null +++ b/packages/sdk/test/index.test.ts @@ -0,0 +1,10 @@ +import {describe, it, expect} from 'vitest' + +import {greet} from '../src/index' + +describe('greet', () => { + it('should return a greeting message', () => { + expect(greet('World')).toBe('Hello, World') + expect(greet('Alice')).toBe('Hello, Alice') + }) +}) \ No newline at end of file diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json new file mode 100644 index 0000000..fee0de8 --- /dev/null +++ b/packages/sdk/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "sourceMap": true, + "rootDir": "src", + "outDir": "dist", + "types": ["node"], + "stripInternal": true + }, + "include": ["src"], + "exclude": ["dist", "coverage", "node_modules"] +} \ No newline at end of file diff --git a/packages/sdk/tsup.config.ts b/packages/sdk/tsup.config.ts new file mode 100644 index 0000000..cabf6b4 --- /dev/null +++ b/packages/sdk/tsup.config.ts @@ -0,0 +1,15 @@ +// packages/root/tsup.config.ts +import {defineConfig} from 'tsup' + +export default defineConfig({ + entry: {'index': 'src/index.ts'}, + format: ['esm'], + platform: 'neutral', + target: 'node20', + dts: {resolve: true}, + sourcemap: true, + clean: true, + splitting: false, + treeshake: true, + minify: false +}) \ No newline at end of file diff --git a/packages/sdk/vitest.config.ts b/packages/sdk/vitest.config.ts new file mode 100644 index 0000000..c563d02 --- /dev/null +++ b/packages/sdk/vitest.config.ts @@ -0,0 +1,24 @@ +import {defineConfig, mergeConfig} from 'vitest/config' + +import base from '../../vitest.config' + +export default mergeConfig(base, defineConfig({ + test: { + passWithNoTests: true, + coverage: { + exclude: [ + '**/*.d.ts', + '**/*.{test,spec}.{ts,tsx}', + '**/__tests__/**' + ], + + thresholds: { + perFile: true, + statements: 90, + branches: 90, + functions: 90, + lines: 90 + } + } + } +}))