@livestore/cli 0.4.0-dev.9 → 0.5.0-dev.0
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/dist/.tsbuildinfo +1 -0
- package/dist/__tests__/fixtures/mock-config.d.ts +63 -0
- package/dist/__tests__/fixtures/mock-config.d.ts.map +1 -0
- package/dist/__tests__/fixtures/mock-config.js +94 -0
- package/dist/__tests__/fixtures/mock-config.js.map +1 -0
- package/dist/__tests__/sync-operations.test.d.ts +2 -0
- package/dist/__tests__/sync-operations.test.d.ts.map +1 -0
- package/dist/__tests__/sync-operations.test.js +167 -0
- package/dist/__tests__/sync-operations.test.js.map +1 -0
- package/dist/bin.js +6 -5
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts +2 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/__fixtures__/mcp-protocol-server.d.ts +2 -0
- package/dist/commands/__fixtures__/mcp-protocol-server.d.ts.map +1 -0
- package/dist/commands/__fixtures__/mcp-protocol-server.js +10 -0
- package/dist/commands/__fixtures__/mcp-protocol-server.js.map +1 -0
- package/dist/commands/import-export.d.ts +20 -0
- package/dist/commands/import-export.d.ts.map +1 -0
- package/dist/commands/import-export.js +135 -0
- package/dist/commands/import-export.js.map +1 -0
- package/dist/commands/mcp-coach.d.ts +21 -12
- package/dist/commands/mcp-coach.d.ts.map +1 -1
- package/dist/commands/mcp-coach.js +49 -53
- package/dist/commands/mcp-coach.js.map +1 -1
- package/dist/commands/mcp-protocols.d.ts +7 -0
- package/dist/commands/mcp-protocols.d.ts.map +1 -0
- package/dist/commands/mcp-protocols.js +12 -0
- package/dist/commands/mcp-protocols.js.map +1 -0
- package/dist/commands/mcp-protocols.test.d.ts +2 -0
- package/dist/commands/mcp-protocols.test.d.ts.map +1 -0
- package/dist/commands/mcp-protocols.test.js +60 -0
- package/dist/commands/mcp-protocols.test.js.map +1 -0
- package/dist/commands/mcp-stdio.test.d.ts +2 -0
- package/dist/commands/mcp-stdio.test.d.ts.map +1 -0
- package/dist/commands/mcp-stdio.test.js +79 -0
- package/dist/commands/mcp-stdio.test.js.map +1 -0
- package/dist/commands/mcp-tool-handlers.d.ts +6 -0
- package/dist/commands/mcp-tool-handlers.d.ts.map +1 -0
- package/dist/commands/{mcp-tools.js → mcp-tool-handlers.js} +80 -45
- package/dist/commands/mcp-tool-handlers.js.map +1 -0
- package/dist/commands/mcp-tools-defs.d.ts +134 -0
- package/dist/commands/mcp-tools-defs.d.ts.map +1 -0
- package/dist/commands/mcp-tools-defs.js +285 -0
- package/dist/commands/mcp-tools-defs.js.map +1 -0
- package/dist/commands/mcp-tools-defs.test.d.ts +2 -0
- package/dist/commands/mcp-tools-defs.test.d.ts.map +1 -0
- package/dist/commands/mcp-tools-defs.test.js +11 -0
- package/dist/commands/mcp-tools-defs.test.js.map +1 -0
- package/dist/commands/mcp.d.ts +1 -3
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +7 -5
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/new-project.d.ts +22 -23
- package/dist/commands/new-project.d.ts.map +1 -1
- package/dist/commands/new-project.js +85 -44
- package/dist/commands/new-project.js.map +1 -1
- package/dist/mcp-content/architecture.d.ts +1 -1
- package/dist/mcp-content/architecture.d.ts.map +1 -1
- package/dist/mcp-content/architecture.js +3 -3
- package/dist/mcp-content/features.d.ts +1 -1
- package/dist/mcp-content/features.d.ts.map +1 -1
- package/dist/mcp-content/features.js +1 -1
- package/dist/mcp-content/getting-started.d.ts +1 -1
- package/dist/mcp-content/getting-started.d.ts.map +1 -1
- package/dist/mcp-content/getting-started.js +37 -37
- package/dist/mcp-content/overview.d.ts +1 -1
- package/dist/mcp-content/overview.d.ts.map +1 -1
- package/dist/mcp-content/overview.js +6 -6
- package/dist/mcp-content/schemas/blog.d.ts +1 -1
- package/dist/mcp-content/schemas/blog.d.ts.map +1 -1
- package/dist/mcp-content/schemas/blog.js +25 -25
- package/dist/mcp-content/schemas/ecommerce.d.ts +1 -1
- package/dist/mcp-content/schemas/ecommerce.d.ts.map +1 -1
- package/dist/mcp-content/schemas/ecommerce.js +67 -67
- package/dist/mcp-content/schemas/social.d.ts +1 -1
- package/dist/mcp-content/schemas/social.d.ts.map +1 -1
- package/dist/mcp-content/schemas/social.js +48 -48
- package/dist/mcp-content/schemas/todo.d.ts +1 -1
- package/dist/mcp-content/schemas/todo.d.ts.map +1 -1
- package/dist/mcp-content/schemas/todo.js +35 -35
- package/dist/mcp-runtime/runtime.d.ts +48 -0
- package/dist/mcp-runtime/runtime.d.ts.map +1 -0
- package/dist/mcp-runtime/runtime.js +107 -0
- package/dist/mcp-runtime/runtime.js.map +1 -0
- package/dist/module-loader.d.ts +22 -0
- package/dist/module-loader.d.ts.map +1 -0
- package/dist/module-loader.js +75 -0
- package/dist/module-loader.js.map +1 -0
- package/dist/package-manager.d.ts +38 -0
- package/dist/package-manager.d.ts.map +1 -0
- package/dist/package-manager.js +33 -0
- package/dist/package-manager.js.map +1 -0
- package/dist/package-manager.test.d.ts +2 -0
- package/dist/package-manager.test.d.ts.map +1 -0
- package/dist/package-manager.test.js +57 -0
- package/dist/package-manager.test.js.map +1 -0
- package/dist/sync-operations.d.ts +115 -0
- package/dist/sync-operations.d.ts.map +1 -0
- package/dist/sync-operations.js +178 -0
- package/dist/sync-operations.js.map +1 -0
- package/package.json +57 -15
- package/src/__tests__/fixtures/mock-config.ts +112 -0
- package/src/__tests__/sync-operations.test.ts +218 -0
- package/src/bin.ts +8 -6
- package/src/cli.ts +5 -6
- package/src/commands/__fixtures__/mcp-protocol-server.ts +12 -0
- package/src/commands/import-export.ts +283 -0
- package/src/commands/mcp-coach.ts +76 -75
- package/src/commands/mcp-protocols.test.ts +76 -0
- package/src/commands/mcp-protocols.ts +12 -0
- package/src/commands/mcp-stdio.test.ts +93 -0
- package/src/commands/{mcp-tools.ts → mcp-tool-handlers.ts} +100 -61
- package/src/commands/mcp-tools-defs.test.ts +13 -0
- package/src/commands/mcp-tools-defs.ts +320 -0
- package/src/commands/mcp.ts +10 -6
- package/src/commands/new-project.ts +124 -57
- package/src/mcp-content/architecture.ts +3 -3
- package/src/mcp-content/features.ts +1 -1
- package/src/mcp-content/getting-started.ts +37 -37
- package/src/mcp-content/overview.ts +6 -6
- package/src/mcp-content/schemas/blog.ts +25 -25
- package/src/mcp-content/schemas/ecommerce.ts +67 -67
- package/src/mcp-content/schemas/social.ts +48 -48
- package/src/mcp-content/schemas/todo.ts +35 -35
- package/src/mcp-runtime/runtime.ts +147 -0
- package/src/module-loader.ts +94 -0
- package/src/package-manager.test.ts +66 -0
- package/src/package-manager.ts +44 -0
- package/src/sync-operations.ts +360 -0
- package/dist/commands/mcp-tools.d.ts +0 -58
- package/dist/commands/mcp-tools.d.ts.map +0 -1
- package/dist/commands/mcp-tools.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1,57 +1,72 @@
|
|
|
1
1
|
import * as os from 'node:os';
|
|
2
2
|
import * as nodePath from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { sluggify } from '@livestore/utils';
|
|
4
|
+
import { ChildProcess, ChildProcessSpawner, Console, Effect, FileSystem, HttpClient, HttpClientRequest, Option, Schema, } from '@livestore/utils/effect';
|
|
4
5
|
import { Cli } from '@livestore/utils/node';
|
|
6
|
+
import { detectPackageManager, pmCommands } from "../package-manager.js";
|
|
5
7
|
// Schema for GitHub API response
|
|
6
8
|
const GitHubContentSchema = Schema.Struct({
|
|
7
9
|
name: Schema.String,
|
|
8
|
-
type: Schema.
|
|
10
|
+
type: Schema.Literals(['dir', 'file']),
|
|
9
11
|
path: Schema.String,
|
|
10
12
|
download_url: Schema.NullOr(Schema.String),
|
|
11
13
|
});
|
|
12
14
|
const GitHubContentsResponseSchema = Schema.Array(GitHubContentSchema);
|
|
15
|
+
const githubRequest = (url) => {
|
|
16
|
+
const request = HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader('accept', 'application/vnd.github+json'));
|
|
17
|
+
const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
|
|
18
|
+
return token === undefined ? request : request.pipe(HttpClientRequest.setHeader('authorization', `Bearer ${token}`));
|
|
19
|
+
};
|
|
20
|
+
/** Schema for parsing package.json scripts (dev or start) */
|
|
21
|
+
const PackageJsonScriptsSchema = Schema.Struct({
|
|
22
|
+
scripts: Schema.Union([Schema.Struct({ dev: Schema.String }), Schema.Struct({ start: Schema.String })]),
|
|
23
|
+
});
|
|
13
24
|
// Error types
|
|
14
|
-
export class ExampleNotFoundError extends Schema.TaggedError()('ExampleNotFoundError', {
|
|
25
|
+
export class ExampleNotFoundError extends Schema.TaggedError('~@livestore/cli/ExampleNotFoundError')('ExampleNotFoundError', {
|
|
15
26
|
exampleName: Schema.String,
|
|
16
27
|
availableExamples: Schema.Array(Schema.String),
|
|
17
28
|
message: Schema.String,
|
|
18
29
|
}) {
|
|
19
30
|
}
|
|
20
|
-
export class NetworkError extends Schema.TaggedError()('NetworkError', {
|
|
31
|
+
export class NetworkError extends Schema.TaggedError('~@livestore/cli/NetworkError')('NetworkError', {
|
|
21
32
|
cause: Schema.Unknown,
|
|
22
33
|
message: Schema.String,
|
|
23
34
|
}) {
|
|
24
35
|
}
|
|
25
|
-
export class DirectoryExistsError extends Schema.TaggedError()('DirectoryExistsError', {
|
|
36
|
+
export class DirectoryExistsError extends Schema.TaggedError('~@livestore/cli/DirectoryExistsError')('DirectoryExistsError', {
|
|
26
37
|
path: Schema.String,
|
|
27
38
|
message: Schema.String,
|
|
28
39
|
}) {
|
|
29
40
|
}
|
|
41
|
+
export class NoExamplesError extends Schema.TaggedError('~@livestore/cli/NoExamplesError')('NoExamplesError', {
|
|
42
|
+
message: Schema.String,
|
|
43
|
+
}) {
|
|
44
|
+
}
|
|
30
45
|
// Fetch available examples from GitHub
|
|
31
|
-
const fetchExamples = (
|
|
32
|
-
const url = `https://api.github.com/repos/livestorejs/livestore/contents/examples?ref=${
|
|
33
|
-
yield* Effect.log(`Fetching examples from
|
|
34
|
-
const request =
|
|
35
|
-
const response = yield* HttpClient.execute(request).pipe(Effect.scoped, Effect.
|
|
46
|
+
const fetchExamples = (ref) => Effect.gen(function* () {
|
|
47
|
+
const url = `https://api.github.com/repos/livestorejs/livestore/contents/examples?ref=${ref}`;
|
|
48
|
+
yield* Effect.log(`Fetching examples from ref: ${ref}`);
|
|
49
|
+
const request = githubRequest(url);
|
|
50
|
+
const response = yield* HttpClient.execute(request).pipe(Effect.scoped, Effect.catch((error) => new NetworkError({
|
|
36
51
|
cause: error,
|
|
37
|
-
message: `Failed to fetch examples from GitHub: ${error}`,
|
|
52
|
+
message: `Failed to fetch examples from GitHub: ${String(error)}`,
|
|
38
53
|
})));
|
|
39
54
|
const responseText = yield* response.text;
|
|
40
|
-
const examples = yield* Schema.
|
|
55
|
+
const examples = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(GitHubContentsResponseSchema))(responseText).pipe(Effect.catch((error) => new NetworkError({
|
|
41
56
|
cause: error,
|
|
42
|
-
message: `Failed to parse GitHub API response: ${error}`,
|
|
57
|
+
message: `Failed to parse GitHub API response: ${String(error)}`,
|
|
43
58
|
})));
|
|
44
59
|
const exampleNames = examples
|
|
45
60
|
.filter((item) => item.type === 'dir')
|
|
46
61
|
.map((item) => item.name)
|
|
47
|
-
.
|
|
62
|
+
.toSorted();
|
|
48
63
|
yield* Effect.log(`Found ${exampleNames.length} examples: ${exampleNames.join(', ')}`);
|
|
49
64
|
return exampleNames;
|
|
50
65
|
});
|
|
51
66
|
// Interactive example selection
|
|
52
67
|
const selectExample = (examples) => Effect.gen(function* () {
|
|
53
68
|
if (examples.length === 0) {
|
|
54
|
-
return yield*
|
|
69
|
+
return yield* new NoExamplesError({ message: 'No examples available' });
|
|
55
70
|
}
|
|
56
71
|
const prompt = Cli.Prompt.select({
|
|
57
72
|
message: '📦 Select a LiveStore example to create:',
|
|
@@ -64,16 +79,17 @@ const selectExample = (examples) => Effect.gen(function* () {
|
|
|
64
79
|
return yield* Cli.Prompt.run(prompt);
|
|
65
80
|
});
|
|
66
81
|
// Download and extract example using tiged approach
|
|
67
|
-
const downloadExample = (exampleName,
|
|
68
|
-
yield* Console.log(`📥 Downloading example "${exampleName}" from
|
|
82
|
+
const downloadExample = (exampleName, ref, destinationPath) => Effect.gen(function* () {
|
|
83
|
+
yield* Console.log(`📥 Downloading example "${exampleName}" from ref "${ref}"...`);
|
|
84
|
+
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
69
85
|
const tempDir = yield* Effect.sync(() => os.tmpdir());
|
|
70
|
-
const tarballPath = nodePath.join(tempDir, `livestore-${
|
|
71
|
-
const tarballUrl = `https://api.github.com/repos/livestorejs/livestore/tarball/${
|
|
86
|
+
const tarballPath = nodePath.join(tempDir, `livestore-${sluggify(ref)}-${Date.now()}.tar.gz`);
|
|
87
|
+
const tarballUrl = `https://api.github.com/repos/livestorejs/livestore/tarball/${ref}`;
|
|
72
88
|
// Download tarball directly
|
|
73
|
-
const request =
|
|
74
|
-
const response = yield* HttpClient.execute(request).pipe(Effect.scoped, Effect.
|
|
89
|
+
const request = githubRequest(tarballUrl);
|
|
90
|
+
const response = yield* HttpClient.execute(request).pipe(Effect.scoped, Effect.catch((error) => new NetworkError({
|
|
75
91
|
cause: error,
|
|
76
|
-
message: `Failed to download tarball: ${error}`,
|
|
92
|
+
message: `Failed to download tarball: ${String(error)}`,
|
|
77
93
|
})));
|
|
78
94
|
const fs = yield* FileSystem.FileSystem;
|
|
79
95
|
// Write tarball to temp file
|
|
@@ -84,10 +100,10 @@ const downloadExample = (exampleName, branch, destinationPath) => Effect.gen(fun
|
|
|
84
100
|
// Extract the tarball to a temporary directory first
|
|
85
101
|
const extractDir = nodePath.join(tempDir, `extract-${Date.now()}`);
|
|
86
102
|
yield* fs.makeDirectory(extractDir, { recursive: true });
|
|
87
|
-
// Extract tarball using
|
|
88
|
-
yield*
|
|
103
|
+
// Extract tarball using a child process
|
|
104
|
+
yield* spawner.exitCode(ChildProcess.make('tar', ['-xzf', tarballPath, '-C', extractDir])).pipe(Effect.catch((error) => new NetworkError({
|
|
89
105
|
cause: error,
|
|
90
|
-
message: `Failed to extract tarball: ${error}`,
|
|
106
|
+
message: `Failed to extract tarball: ${String(error)}`,
|
|
91
107
|
})));
|
|
92
108
|
// Find the extracted directory (it will be named like livestorejs-livestore-{hash})
|
|
93
109
|
const extractedDirs = yield* fs.readDirectory(extractDir);
|
|
@@ -101,32 +117,32 @@ const downloadExample = (exampleName, branch, destinationPath) => Effect.gen(fun
|
|
|
101
117
|
const exampleSourcePath = nodePath.join(repoDir, 'examples', exampleName);
|
|
102
118
|
// Check if the example exists
|
|
103
119
|
const exampleExists = yield* fs.exists(exampleSourcePath);
|
|
104
|
-
if (
|
|
120
|
+
if (exampleExists === false) {
|
|
105
121
|
return yield* new ExampleNotFoundError({
|
|
106
122
|
exampleName,
|
|
107
123
|
availableExamples: [],
|
|
108
124
|
message: `Example "${exampleName}" not found in the extracted repository`,
|
|
109
125
|
});
|
|
110
126
|
}
|
|
111
|
-
// Copy the example directory contents to the destination using
|
|
112
|
-
yield*
|
|
127
|
+
// Copy the example directory contents to the destination using a child process
|
|
128
|
+
yield* spawner.exitCode(ChildProcess.make('cp', ['-r', `${exampleSourcePath}/.`, destinationPath])).pipe(Effect.catch((error) => new NetworkError({
|
|
113
129
|
cause: error,
|
|
114
|
-
message: `Failed to copy example files: ${error}`,
|
|
130
|
+
message: `Failed to copy example files: ${String(error)}`,
|
|
115
131
|
})));
|
|
116
132
|
// Clean up extract directory
|
|
117
|
-
yield* fs.remove(extractDir, { recursive: true }).pipe(Effect.
|
|
133
|
+
yield* fs.remove(extractDir, { recursive: true }).pipe(Effect.catch(() => Effect.void));
|
|
118
134
|
// Clean up tarball
|
|
119
|
-
yield* fs.remove(tarballPath).pipe(Effect.
|
|
135
|
+
yield* fs.remove(tarballPath).pipe(Effect.catch(() => Effect.void));
|
|
120
136
|
yield* Console.log(`✅ Example "${exampleName}" created successfully at: ${destinationPath}`);
|
|
121
137
|
});
|
|
122
|
-
export const
|
|
123
|
-
example: Cli.
|
|
124
|
-
|
|
125
|
-
path: Cli.
|
|
126
|
-
}, Effect.fn(function* ({ example,
|
|
138
|
+
export const createCommand = Cli.Command.make('create', {
|
|
139
|
+
example: Cli.Flag.string('example').pipe(Cli.Flag.optional, Cli.Flag.withDescription('Example name to create (bypasses interactive selection)')),
|
|
140
|
+
ref: Cli.Flag.string('ref').pipe(Cli.Flag.withAlias('commit'), Cli.Flag.withAlias('branch'), Cli.Flag.withAlias('tag'), Cli.Flag.withDefault('main'), Cli.Flag.withDescription('The name of the commit/branch/tag to fetch examples from. Pull requests refs must be fully-formed (e.g., `refs/pull/123/merge`).')),
|
|
141
|
+
path: Cli.Argument.string('path').pipe(Cli.Argument.optional, Cli.Argument.withDescription('Destination path for the new project')),
|
|
142
|
+
}, Effect.fn(function* ({ example, ref, path, }) {
|
|
127
143
|
yield* Effect.log('🚀 Creating new LiveStore project...');
|
|
128
144
|
// Fetch available examples
|
|
129
|
-
const examples = yield* fetchExamples(
|
|
145
|
+
const examples = yield* fetchExamples(ref);
|
|
130
146
|
if (examples.length === 0) {
|
|
131
147
|
yield* Console.log('❌ No examples found in the repository');
|
|
132
148
|
return yield* new ExampleNotFoundError({
|
|
@@ -136,9 +152,9 @@ export const newProjectCommand = Cli.Command.make('new-project', {
|
|
|
136
152
|
});
|
|
137
153
|
}
|
|
138
154
|
// Select example (from CLI option or interactive prompt)
|
|
139
|
-
const selectedExample = Option.isSome(example) ? example.value : yield* selectExample(examples);
|
|
155
|
+
const selectedExample = Option.isSome(example) === true ? example.value : yield* selectExample(examples);
|
|
140
156
|
// Validate selected example exists
|
|
141
|
-
if (
|
|
157
|
+
if (examples.includes(selectedExample) === false) {
|
|
142
158
|
yield* Console.log(`❌ Example "${selectedExample}" not found`);
|
|
143
159
|
yield* Console.log(`Available examples: ${examples.join(', ')}`);
|
|
144
160
|
return yield* new ExampleNotFoundError({
|
|
@@ -148,16 +164,41 @@ export const newProjectCommand = Cli.Command.make('new-project', {
|
|
|
148
164
|
});
|
|
149
165
|
}
|
|
150
166
|
// Determine destination path
|
|
151
|
-
const destinationPath = Option.isSome(path) ? nodePath.resolve(path.value) : nodePath.resolve(selectedExample);
|
|
167
|
+
const destinationPath = Option.isSome(path) === true ? nodePath.resolve(path.value) : nodePath.resolve(selectedExample);
|
|
152
168
|
// Download and extract the example
|
|
153
|
-
yield* downloadExample(selectedExample,
|
|
154
|
-
//
|
|
169
|
+
yield* downloadExample(selectedExample, ref, destinationPath);
|
|
170
|
+
// Detect available run script (dev or start) from the created project's package.json.
|
|
171
|
+
// Some examples use "dev" (web projects), others use "start" (Expo projects),
|
|
172
|
+
// and some have no run script at all (e.g., node-effect-cli).
|
|
173
|
+
const fs = yield* FileSystem.FileSystem;
|
|
174
|
+
const packageJsonPath = nodePath.join(destinationPath, 'package.json');
|
|
175
|
+
const packageJsonContent = yield* fs.readFileString(packageJsonPath);
|
|
176
|
+
const runScript = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(PackageJsonScriptsSchema))(packageJsonContent).pipe(Effect.map((pkg) => ('dev' in pkg.scripts ? 'dev' : 'start')), Effect.orElseSucceed(() => undefined));
|
|
177
|
+
// Detect which package manager was used to invoke the CLI (via npm_config_user_agent).
|
|
178
|
+
// This ensures the "next steps" instructions match how the user ran the create command.
|
|
179
|
+
const pmResult = detectPackageManager();
|
|
155
180
|
yield* Console.log('\n🎉 Project created successfully!');
|
|
156
181
|
yield* Console.log(`📁 Location: ${destinationPath}`);
|
|
157
182
|
yield* Console.log('\n📋 Next steps:');
|
|
158
183
|
yield* Console.log(` cd ${nodePath.basename(destinationPath)}`);
|
|
159
|
-
|
|
160
|
-
|
|
184
|
+
// Yarn is not recommended for LiveStore projects. When detected, show a warning
|
|
185
|
+
// and suggest using bun instead for the next steps.
|
|
186
|
+
if (pmResult._tag === 'unsupported') {
|
|
187
|
+
yield* Console.log(' bun install # Install dependencies (yarn is not recommended)');
|
|
188
|
+
if (runScript !== undefined) {
|
|
189
|
+
yield* Console.log(` bun ${runScript} # Start development server`);
|
|
190
|
+
}
|
|
191
|
+
yield* Console.log('\n⚠️ Yarn is not recommended for LiveStore projects.');
|
|
192
|
+
yield* Console.log(' We recommend using bun, pnpm, or npm instead.');
|
|
193
|
+
yield* Console.log(' The commands above use bun by default.');
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
const pm = pmResult.pm;
|
|
197
|
+
yield* Console.log(` ${pmCommands.install[pm]} # Install dependencies`);
|
|
198
|
+
if (runScript !== undefined) {
|
|
199
|
+
yield* Console.log(` ${pmCommands.run[pm](runScript)} # Start development server`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
161
202
|
yield* Console.log('\n💡 Tip: Run `git init` if you want to initialize version control');
|
|
162
203
|
}));
|
|
163
204
|
//# sourceMappingURL=new-project.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new-project.js","sourceRoot":"","sources":["../../src/commands/new-project.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"new-project.js","sourceRoot":"","sources":["../../src/commands/new-project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,OAAO,EACP,MAAM,EACN,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,MAAM,EACN,MAAM,GACP,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAE3C,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAExE,iCAAiC;AACjC,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;CAC3C,CAAC,CAAA;AAEF,MAAM,4BAA4B,GAAG,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;AAEtE,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,EAAE;IACpC,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC,CAAA;IACrH,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAA;IAC9D,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,eAAe,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC,CAAA;AACtH,CAAC,CAAA;AAED,6DAA6D;AAC7D,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CACxG,CAAC,CAAA;AAEF,cAAc;AACd,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,CAC1D,sCAAsC,CACvC,CAAC,sBAAsB,EAAE;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM;IAC1B,iBAAiB,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9C,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAEL,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,CAAe,8BAA8B,CAAC,CAAC,cAAc,EAAE;IACjH,KAAK,EAAE,MAAM,CAAC,OAAO;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAEL,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,CAC1D,sCAAsC,CACvC,CAAC,sBAAsB,EAAE;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAEL,MAAM,OAAO,eAAgB,SAAQ,MAAM,CAAC,WAAW,CAAkB,iCAAiC,CAAC,CACzG,iBAAiB,EACjB;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG;AAEJ,uCAAuC;AACvC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,EAAE,CACpC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,GAAG,GAAG,4EAA4E,GAAG,EAAE,CAAA;IAE7F,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAA;IAEvD,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CACtD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,CACV,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,YAAY,CAAC;QACf,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,yCAAyC,MAAM,CAAC,KAAK,CAAC,EAAE;KAClE,CAAC,CACL,CACF,CAAA;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAA;IAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC,CACrG,YAAY,CACb,CAAC,IAAI,CACJ,MAAM,CAAC,KAAK,CACV,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,YAAY,CAAC;QACf,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,wCAAwC,MAAM,CAAC,KAAK,CAAC,EAAE;KACjE,CAAC,CACL,CACF,CAAA;IAED,MAAM,YAAY,GAAG,QAAQ;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC;SACrC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,QAAQ,EAAE,CAAA;IAEb,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,YAAY,CAAC,MAAM,cAAc,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEtF,OAAO,YAAY,CAAA;AACrB,CAAC,CAAC,CAAA;AAEJ,gCAAgC;AAChC,MAAM,aAAa,GAAG,CAAC,QAAkB,EAAE,EAAE,CAC3C,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,CAAC,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;QAC/B,OAAO,EAAE,0CAA0C;QACnD,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAClC,KAAK,EAAE,OAAO;YACd,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,kCAAkC,OAAO,UAAU;SACjE,CAAC,CAAC;KACJ,CAAC,CAAA;IAEF,OAAO,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACtC,CAAC,CAAC,CAAA;AAEJ,oDAAoD;AACpD,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAE,GAAW,EAAE,eAAuB,EAAE,EAAE,CACpF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,WAAW,eAAe,GAAG,MAAM,CAAC,CAAA;IAElF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,mBAAmB,CAAA;IAE9D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAA;IACrD,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IAC7F,MAAM,UAAU,GAAG,8DAA8D,GAAG,EAAE,CAAA;IAEtF,4BAA4B;IAC5B,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CACtD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,CACV,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,YAAY,CAAC;QACf,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,+BAA+B,MAAM,CAAC,KAAK,CAAC,EAAE;KACxD,CAAC,CACL,CACF,CAAA;IAED,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IAEvC,6BAA6B;IAC7B,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAA;IACjD,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC,CAAA;IAE/D,+BAA+B;IAC/B,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE7D,qDAAqD;IACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAClE,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAExD,wCAAwC;IACxC,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAC7F,MAAM,CAAC,KAAK,CACV,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,YAAY,CAAC;QACf,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,8BAA8B,MAAM,CAAC,KAAK,CAAC,EAAE;KACvD,CAAC,CACL,CACF,CAAA;IAED,oFAAoF;IACpF,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;IAEzD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC;YAC7B,KAAK,EAAE,8BAA8B;YACrC,OAAO,EAAE,+CAA+C;SACzD,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAE,CAAC,CAAA;IAC5D,MAAM,iBAAiB,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA;IAEzE,8BAA8B;IAC9B,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;IAEzD,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,CAAC,IAAI,oBAAoB,CAAC;YACrC,WAAW;YACX,iBAAiB,EAAE,EAAE;YACrB,OAAO,EAAE,YAAY,WAAW,yCAAyC;SAC1E,CAAC,CAAA;IACJ,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,iBAAiB,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CACtG,MAAM,CAAC,KAAK,CACV,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,YAAY,CAAC;QACf,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,iCAAiC,MAAM,CAAC,KAAK,CAAC,EAAE;KAC1D,CAAC,CACL,CACF,CAAA;IAED,6BAA6B;IAC7B,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IAEvF,mBAAmB;IACnB,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IAEnE,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,8BAA8B,eAAe,EAAE,CAAC,CAAA;AAC9F,CAAC,CAAC,CAAA;AAEJ,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAC3C,QAAQ,EACR;IACE,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CACtC,GAAG,CAAC,IAAI,CAAC,QAAQ,EACjB,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,yDAAyD,CAAC,CACpF;IACD,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAC9B,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAC5B,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAC5B,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EACzB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAC5B,GAAG,CAAC,IAAI,CAAC,eAAe,CACtB,kIAAkI,CACnI,CACF;IACD,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CACpC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EACrB,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,sCAAsC,CAAC,CACrE;CACF,EACD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EACnB,OAAO,EACP,GAAG,EACH,IAAI,GAKL;IACC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAA;IAEzD,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAA;QAC3D,OAAO,KAAK,CAAC,CAAC,IAAI,oBAAoB,CAAC;YACrC,WAAW,EAAE,EAAE;YACf,iBAAiB,EAAE,EAAE;YACrB,OAAO,EAAE,uBAAuB;SACjC,CAAC,CAAA;IACJ,CAAC;IAED,yDAAyD;IACzD,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;IAExG,mCAAmC;IACnC,IAAI,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,KAAK,EAAE,CAAC;QACjD,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,eAAe,aAAa,CAAC,CAAA;QAC9D,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChE,OAAO,KAAK,CAAC,CAAC,IAAI,oBAAoB,CAAC;YACrC,WAAW,EAAE,eAAe;YAC5B,iBAAiB,EAAE,QAAQ;YAC3B,OAAO,EAAE,YAAY,eAAe,aAAa;SAClD,CAAC,CAAA;IACJ,CAAC;IAED,6BAA6B;IAC7B,MAAM,eAAe,GACnB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IAEjG,mCAAmC;IACnC,KAAK,CAAC,CAAC,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,eAAe,CAAC,CAAA;IAE7D,sFAAsF;IACtF,8EAA8E;IAC9E,8DAA8D;IAC9D,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IACvC,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,CAAA;IACtE,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,eAAe,CAAC,CAAA;IACpE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC,CAClG,kBAAkB,CACnB,CAAC,IAAI,CACJ,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAE,KAAe,CAAC,CAAC,CAAE,OAAiB,CAAC,CAAC,EACnF,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CACtC,CAAA;IAED,uFAAuF;IACvF,wFAAwF;IACxF,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAA;IAEvC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;IACxD,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,eAAe,EAAE,CAAC,CAAA;IACrD,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;IACtC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAA;IAEjE,gFAAgF;IAChF,oDAAoD;IACpD,IAAI,QAAQ,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACpC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAA;QACxF,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,SAAS,oCAAoC,CAAC,CAAA;QAC7E,CAAC;QACD,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAA;QAC3E,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAA;QACtE,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;IACjE,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAA;QACtB,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,4BAA4B,CAAC,CAAA;QAC5E,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAA;QAC7F,CAAC;IACH,CAAC;IACD,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAA;AAC1F,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const architectureContent = "# LiveStore Architecture: Local-First Data Management\n\nLiveStore implements distributed systems principles from Martin Kleppmann's research on local-first software, ensuring data consistency, availability, and partition tolerance in collaborative applications.\n\n## Core Architectural Principles\n\n### 1. Local-First Data Storage\n- **Immediate Response**: All operations execute against local SQLite database first\n- **Offline Capability**: Full application functionality without network connectivity\n- **Data Ownership**: Users maintain complete control over their data\n- **Performance**: Sub-millisecond query responses from local storage\n\n### 2. Event Sourcing & CRDT-Inspired Conflict Resolution\n- **Immutable Event Log**: All changes recorded as immutable events\n- **Deterministic Replay**: State reconstruction from event sequence\n- **Conflict-Free Operations**: Events designed for commutative application\n- **Causal Ordering**: Lamport timestamps ensure causally consistent ordering\n\n### 3. Eventually Consistent Synchronization\n- **Asynchronous Replication**: Events sync when network available\n- **Convergence Guarantee**: All replicas converge to same state\n- **Conflict Resolution**: Last-write-wins with semantic merging strategies\n- **Incremental Sync**: Only transmit events since last synchronization\n\n## System Components\n\n### \uD83D\uDDC4\uFE0F State Layer (SQLite + Materializers)\n```typescript\n// Materialized views from event log\nconst materializers = State.SQLite.materializers(events, {\n 'TodoCreated': ({ id, text, createdAt })
|
|
1
|
+
export declare const architectureContent = "# LiveStore Architecture: Local-First Data Management\n\nLiveStore implements distributed systems principles from Martin Kleppmann's research on local-first software, ensuring data consistency, availability, and partition tolerance in collaborative applications.\n\n## Core Architectural Principles\n\n### 1. Local-First Data Storage\n- **Immediate Response**: All operations execute against local SQLite database first\n- **Offline Capability**: Full application functionality without network connectivity\n- **Data Ownership**: Users maintain complete control over their data\n- **Performance**: Sub-millisecond query responses from local storage\n\n### 2. Event Sourcing & CRDT-Inspired Conflict Resolution\n- **Immutable Event Log**: All changes recorded as immutable events\n- **Deterministic Replay**: State reconstruction from event sequence\n- **Conflict-Free Operations**: Events designed for commutative application\n- **Causal Ordering**: Lamport timestamps ensure causally consistent ordering\n\n### 3. Eventually Consistent Synchronization\n- **Asynchronous Replication**: Events sync when network available\n- **Convergence Guarantee**: All replicas converge to same state\n- **Conflict Resolution**: Last-write-wins with semantic merging strategies\n- **Incremental Sync**: Only transmit events since last synchronization\n\n## System Components\n\n### \uD83D\uDDC4\uFE0F State Layer (SQLite + Materializers)\n```typescript\n// Materialized views from event log\nconst materializers = State.SQLite.materializers(events, {\n 'TodoCreated': ({ id, text, createdAt }) =>\n tables.todos.insert({ id, text, completed: false, createdAt }),\n 'TodoCompleted': ({ id }) =>\n tables.todos.update({ completed: true }).where({ id })\n})\n```\n\n**Responsibilities:**\n- Maintain denormalized query-optimized state\n- Apply events to update materialized views\n- Support efficient reactive queries\n- Handle schema migrations\n\n### \uD83D\uDCDD Event System (Append-Only Log)\n```typescript\nconst events = {\n todoCompleted: Events.synced({\n name: 'v1.TodoCompleted',\n schema: Schema.Struct({\n id: Schema.String,\n completedAt: Schema.Date // For conflict resolution\n })\n })\n}\n```\n\n**Characteristics:**\n- Immutable event log (append-only)\n- Cryptographically signed events for integrity\n- Causal dependencies tracked via vector clocks\n- Schema versioning for backward compatibility\n\n### \uD83D\uDD04 Synchronization Engine\n```typescript\n// Conflict resolution during sync\nconst mergeResult = SyncState.merge({\n syncState: currentState,\n payload: incomingEvents,\n isEqualEvent: (a, b) => a.id === b.id && a.type === b.type\n})\n```\n\n**Merge Strategies:**\n- **Advance**: New events extend current state\n- **Rebase**: Rollback conflicting events, apply remote, replay local\n- **Reject**: Ignore events that violate invariants\n\n### \uD83C\uDF10 Network Layer & Adapters\n```typescript\n// Platform-specific sync adapters\nexport const WebAdapter = {\n storage: OPFSSQLiteStorage, // Origin Private File System\n transport: WebSocketSync,\n worker: SharedWorker // Cross-tab synchronization\n}\n```\n\n**Adapter Implementations:**\n- **Web**: OPFS storage, SharedWorker coordination, WebSocket sync\n- **Node**: File system storage, cluster coordination, HTTP/WebSocket\n- **Mobile**: Native SQLite, background sync, push notifications\n\n## Distributed Systems Properties\n\n### CAP Theorem Considerations\n- **Consistency**: Eventually consistent (not strongly consistent)\n- **Availability**: Always available for reads/writes (local-first)\n- **Partition Tolerance**: Continues operation during network partitions\n\n*Trade-off: Chooses Availability + Partition Tolerance over strong Consistency*\n\n### ACID Properties (Local Transactions)\n- **Atomicity**: Event application is atomic within SQLite transaction\n- **Consistency**: Materializers maintain data integrity constraints\n- **Isolation**: Concurrent operations isolated via SQLite WAL mode\n- **Durability**: Events persisted to disk before acknowledgment\n\n### Conflict Resolution Strategies\n\n1. **Semantic Conflict Resolution**\n - Application-specific merge logic\n - E.g., text editing uses operational transforms\n\n2. **Last-Write-Wins (LWW)**\n - Timestamps determine winner\n - Simple but can lose data\n\n3. **Multi-Value Registers**\n - Preserve all conflicting values\n - User or application resolves\n\n4. **Commutative Operations**\n - Operations designed to commute\n - E.g., increment/decrement counters\n\n## Performance & Scalability\n\n### Query Performance\n- **Reactive Queries**: Automatically update UI on data changes\n- **Indexed Access**: SQLite B-tree indexes for fast lookups\n- **Prepared Statements**: Query compilation cached for reuse\n- **Batch Operations**: Multiple events applied in single transaction\n\n### Memory Management\n- **Incremental Loading**: Large datasets loaded on-demand\n- **Query Result Caching**: Expensive query results cached\n- **Event Log Compaction**: Periodic snapshotting and log truncation\n- **Connection Pooling**: Database connections reused across operations\n\n### Network Optimization\n- **Delta Synchronization**: Only sync events since last checkpoint\n- **Compression**: Event payloads compressed for network transfer\n- **Batching**: Multiple events transmitted in single round-trip\n- **Exponential Backoff**: Retry failed sync with increasing delays\n\n## Security Model\n\n### Data Integrity\n- **Event Signatures**: Cryptographic signatures prevent tampering\n- **Merkle Trees**: Efficient verification of event log integrity\n- **Schema Validation**: All events validated against defined schemas\n\n### Access Control\n- **Client-Side Authorization**: Fine-grained permissions in local database\n- **Sync Filtering**: Server filters events based on user permissions\n- **Encryption**: End-to-end encryption for sensitive data\n\n## Observability\n\n### Distributed Tracing\n- **Event Causality**: Trace event propagation across replicas\n- **Sync Performance**: Monitor replication lag and throughput\n- **Conflict Metrics**: Track merge conflicts and resolution strategies\n\n### Health Monitoring\n- **Storage Usage**: Local database size and growth rate\n- **Network Health**: Connection quality and sync success rates\n- **Error Tracking**: Failed operations and their root causes\n\nThis architecture enables applications that work seamlessly offline, sync reliably when online, and provide immediate feedback to users while maintaining data consistency across all replicas.";
|
|
2
2
|
//# sourceMappingURL=architecture.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"architecture.d.ts","sourceRoot":"","sources":["../../src/mcp-content/architecture.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"architecture.d.ts","sourceRoot":"","sources":["../../src/mcp-content/architecture.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,w9MAyKgK,CAAA"}
|
|
@@ -28,9 +28,9 @@ LiveStore implements distributed systems principles from Martin Kleppmann's rese
|
|
|
28
28
|
\`\`\`typescript
|
|
29
29
|
// Materialized views from event log
|
|
30
30
|
const materializers = State.SQLite.materializers(events, {
|
|
31
|
-
'TodoCreated': ({ id, text, createdAt }) =>
|
|
31
|
+
'TodoCreated': ({ id, text, createdAt }) =>
|
|
32
32
|
tables.todos.insert({ id, text, completed: false, createdAt }),
|
|
33
|
-
'TodoCompleted': ({ id }) =>
|
|
33
|
+
'TodoCompleted': ({ id }) =>
|
|
34
34
|
tables.todos.update({ completed: true }).where({ id })
|
|
35
35
|
})
|
|
36
36
|
\`\`\`
|
|
@@ -46,7 +46,7 @@ const materializers = State.SQLite.materializers(events, {
|
|
|
46
46
|
const events = {
|
|
47
47
|
todoCompleted: Events.synced({
|
|
48
48
|
name: 'v1.TodoCompleted',
|
|
49
|
-
schema: Schema.Struct({
|
|
49
|
+
schema: Schema.Struct({
|
|
50
50
|
id: Schema.String,
|
|
51
51
|
completedAt: Schema.Date // For conflict resolution
|
|
52
52
|
})
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const featuresContent = "# LiveStore Features: Production-Ready Local-First Data\n\nLiveStore provides battle-tested primitives for building collaborative, offline-capable applications with the reliability and performance of modern distributed systems.\n\n## \uD83C\uDFE0 Local-First Architecture\n\n### Offline-First Operation\n- **Zero Latency**: All operations execute against local SQLite database\n- **Offline Capable**: Full application functionality without network connectivity\n- **Network Resilient**: Graceful degradation during connectivity issues\n- **Background Sync**: Automatic synchronization when network becomes available\n\n### Immediate Consistency\n- **Optimistic Updates**: UI updates immediately on user action\n- **Rollback on Conflict**: Automatic rollback and retry on merge conflicts\n- **Causal Consistency**: Operations maintain causal ordering across replicas\n\n## \uD83D\uDD04 Event-Driven Synchronization\n\n### Conflict-Free Event Model\n```typescript\n// Events designed for conflict-free merging\nconst events = {\n todoCreated: Events.synced({\n name: 'v1.TodoCreated',\n schema: Schema.Struct({\n id: Schema.String, // Deterministic ordering\n createdAt: Schema.Date, // Timestamp for LWW resolution\n position: Schema.Number // Fractional indexing for reordering\n })\n })\n}\n```\n\n### Sophisticated Merge Strategies\n- **Last-Write-Wins**: Timestamp-based conflict resolution\n- **Semantic Merging**: Application-specific merge logic\n- **Operational Transform**: Real-time collaborative text editing\n- **CRDT Integration**: Conflict-free replicated data types\n\n### Incremental Synchronization\n- **Delta Sync**: Only transmit changes since last synchronization\n- **Vector Clocks**: Efficient causal dependency tracking\n- **Merkle Trees**: Efficient integrity verification\n- **Batch Optimization**: Multiple events in single network round-trip\n\n## \uD83D\uDCCA Reactive Query Engine\n\n### Real-Time Reactivity\n```typescript\n// Queries automatically update when underlying data changes\nconst activeTodos$ = queryDb(\n tables.todos\n .select()\n .where({ completed: false, deletedAt: null })\n .orderBy('position'),\n { label: 'activeTodos' }\n)\n```\n\n### Advanced Query Capabilities\n- **Joins & Aggregations**: Full SQL expressiveness\n- **Reactive Subscriptions**: Automatic UI updates on data changes\n- **Query Optimization**: SQLite query planner with B-tree indexes\n- **Prepared Statements**: Cached query compilation for performance\n\n### Framework Integrations\n- **React**: `useLiveQuery()` hook for reactive components\n- **Vue**: Composables for reactive data binding\n- **Solid**: Reactive primitives integration\n- **Svelte**: Store-based reactive updates\n\n## \uD83D\uDD10 End-to-End Type Safety\n\n### Schema-First Development\n```typescript\n// Type safety from database to UI\nconst todoSchema = State.SQLite.table({\n name: 'todos',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n title: State.SQLite.text(),\n completed: State.SQLite.boolean()\n }\n})\n\n// Fully typed queries\ntype Todo = typeof todoSchema.select.Type // { id: string, title: string, completed: boolean }\n```\n\n### Runtime Validation\n- **Schema Validation**: All events validated against Effect schemas\n- **Migration Safety**: Type-safe schema evolution\n- **Parse Don't Validate**: Schema types flow through entire application\n\n## \uD83C\uDF10 Multi-Platform Support\n\n### Web Platform\n- **Origin Private File System**: Persistent storage in modern browsers\n- **SharedWorker**: Cross-tab synchronization and resource sharing\n- **IndexedDB Fallback**: Compatibility with older browsers\n- **Service Worker**: Background synchronization\n\n### Node.js Platform\n- **File System Storage**: Native SQLite database files\n- **Cluster Coordination**: Multi-process synchronization\n- **HTTP/WebSocket Sync**: Flexible transport protocols\n- **Background Jobs**: Scheduled synchronization tasks\n\n### Mobile Platforms (Expo/React Native)\n- **Native SQLite**: Platform-optimized database performance\n- **Background Sync**: Synchronization during app backgrounding\n- **Push Notifications**: Real-time update notifications\n- **Secure Storage**: Encrypted local data storage\n\n## \uD83D\uDE80 Performance & Scalability\n\n### Query Performance\n- **Sub-millisecond Queries**: Local SQLite performance\n- **Efficient Indexing**: Automatic index recommendations\n- **Result Set Streaming**: Large datasets loaded incrementally\n- **Query Result Caching**: Expensive computations cached\n\n### Memory Management\n- **Lazy Loading**: Data loaded on-demand\n- **Connection Pooling**: Database connections efficiently reused\n- **Event Log Compaction**: Periodic snapshots prevent unbounded growth\n- **Garbage Collection**: Automatic cleanup of obsolete data\n\n### Network Optimization\n- **Compression**: Event payloads compressed for transmission\n- **Request Batching**: Multiple operations in single request\n- **Connection Pooling**: HTTP/WebSocket connections reused\n- **Exponential Backoff**: Intelligent retry strategies\n\n## \uD83C\uDFD7\uFE0F Developer Experience\n\n### Testing & Debugging\n```typescript\n// Built-in testing utilities\nconst testStore = createTestStore(schema)\n\n// Deterministic event replay for testing\nawait testStore.replay([\n events.todoCreated({ id: '1', title: 'Test todo' }),\n events.todoCompleted({ id: '1' })\n])\n```\n\n### Developer Tools\n- **Event Inspector**: Real-time event log visualization\n- **Query Profiler**: Performance analysis for slow queries
|
|
1
|
+
export declare const featuresContent = "# LiveStore Features: Production-Ready Local-First Data\n\nLiveStore provides battle-tested primitives for building collaborative, offline-capable applications with the reliability and performance of modern distributed systems.\n\n## \uD83C\uDFE0 Local-First Architecture\n\n### Offline-First Operation\n- **Zero Latency**: All operations execute against local SQLite database\n- **Offline Capable**: Full application functionality without network connectivity\n- **Network Resilient**: Graceful degradation during connectivity issues\n- **Background Sync**: Automatic synchronization when network becomes available\n\n### Immediate Consistency\n- **Optimistic Updates**: UI updates immediately on user action\n- **Rollback on Conflict**: Automatic rollback and retry on merge conflicts\n- **Causal Consistency**: Operations maintain causal ordering across replicas\n\n## \uD83D\uDD04 Event-Driven Synchronization\n\n### Conflict-Free Event Model\n```typescript\n// Events designed for conflict-free merging\nconst events = {\n todoCreated: Events.synced({\n name: 'v1.TodoCreated',\n schema: Schema.Struct({\n id: Schema.String, // Deterministic ordering\n createdAt: Schema.Date, // Timestamp for LWW resolution\n position: Schema.Number // Fractional indexing for reordering\n })\n })\n}\n```\n\n### Sophisticated Merge Strategies\n- **Last-Write-Wins**: Timestamp-based conflict resolution\n- **Semantic Merging**: Application-specific merge logic\n- **Operational Transform**: Real-time collaborative text editing\n- **CRDT Integration**: Conflict-free replicated data types\n\n### Incremental Synchronization\n- **Delta Sync**: Only transmit changes since last synchronization\n- **Vector Clocks**: Efficient causal dependency tracking\n- **Merkle Trees**: Efficient integrity verification\n- **Batch Optimization**: Multiple events in single network round-trip\n\n## \uD83D\uDCCA Reactive Query Engine\n\n### Real-Time Reactivity\n```typescript\n// Queries automatically update when underlying data changes\nconst activeTodos$ = queryDb(\n tables.todos\n .select()\n .where({ completed: false, deletedAt: null })\n .orderBy('position'),\n { label: 'activeTodos' }\n)\n```\n\n### Advanced Query Capabilities\n- **Joins & Aggregations**: Full SQL expressiveness\n- **Reactive Subscriptions**: Automatic UI updates on data changes\n- **Query Optimization**: SQLite query planner with B-tree indexes\n- **Prepared Statements**: Cached query compilation for performance\n\n### Framework Integrations\n- **React**: `useLiveQuery()` hook for reactive components\n- **Vue**: Composables for reactive data binding\n- **Solid**: Reactive primitives integration\n- **Svelte**: Store-based reactive updates\n\n## \uD83D\uDD10 End-to-End Type Safety\n\n### Schema-First Development\n```typescript\n// Type safety from database to UI\nconst todoSchema = State.SQLite.table({\n name: 'todos',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n title: State.SQLite.text(),\n completed: State.SQLite.boolean()\n }\n})\n\n// Fully typed queries\ntype Todo = typeof todoSchema.select.Type // { id: string, title: string, completed: boolean }\n```\n\n### Runtime Validation\n- **Schema Validation**: All events validated against Effect schemas\n- **Migration Safety**: Type-safe schema evolution\n- **Parse Don't Validate**: Schema types flow through entire application\n\n## \uD83C\uDF10 Multi-Platform Support\n\n### Web Platform\n- **Origin Private File System**: Persistent storage in modern browsers\n- **SharedWorker**: Cross-tab synchronization and resource sharing\n- **IndexedDB Fallback**: Compatibility with older browsers\n- **Service Worker**: Background synchronization\n\n### Node.js Platform\n- **File System Storage**: Native SQLite database files\n- **Cluster Coordination**: Multi-process synchronization\n- **HTTP/WebSocket Sync**: Flexible transport protocols\n- **Background Jobs**: Scheduled synchronization tasks\n\n### Mobile Platforms (Expo/React Native)\n- **Native SQLite**: Platform-optimized database performance\n- **Background Sync**: Synchronization during app backgrounding\n- **Push Notifications**: Real-time update notifications\n- **Secure Storage**: Encrypted local data storage\n\n## \uD83D\uDE80 Performance & Scalability\n\n### Query Performance\n- **Sub-millisecond Queries**: Local SQLite performance\n- **Efficient Indexing**: Automatic index recommendations\n- **Result Set Streaming**: Large datasets loaded incrementally\n- **Query Result Caching**: Expensive computations cached\n\n### Memory Management\n- **Lazy Loading**: Data loaded on-demand\n- **Connection Pooling**: Database connections efficiently reused\n- **Event Log Compaction**: Periodic snapshots prevent unbounded growth\n- **Garbage Collection**: Automatic cleanup of obsolete data\n\n### Network Optimization\n- **Compression**: Event payloads compressed for transmission\n- **Request Batching**: Multiple operations in single request\n- **Connection Pooling**: HTTP/WebSocket connections reused\n- **Exponential Backoff**: Intelligent retry strategies\n\n## \uD83C\uDFD7\uFE0F Developer Experience\n\n### Testing & Debugging\n```typescript\n// Built-in testing utilities\nconst testStore = createTestStore(schema)\n\n// Deterministic event replay for testing\nawait testStore.replay([\n events.todoCreated({ id: '1', title: 'Test todo' }),\n events.todoCompleted({ id: '1' })\n])\n```\n\n### Developer Tools\n- **Event Inspector**: Real-time event log visualization\n- **Query Profiler**: Performance analysis for slow queries\n- **Sync Monitor**: Network synchronization health dashboard\n- **Schema Explorer**: Interactive database schema browsing\n\n### Production Monitoring\n- **Distributed Tracing**: Event propagation across replicas\n- **Performance Metrics**: Query latency and throughput monitoring\n- **Error Tracking**: Comprehensive error reporting and alerting\n- **Health Checks**: Automated system health verification\n\n## \uD83D\uDD12 Security & Privacy\n\n### Data Protection\n- **End-to-End Encryption**: Client-side encryption before transmission\n- **Event Signatures**: Cryptographic integrity verification\n- **Access Control**: Fine-grained permission system\n- **Audit Logging**: Comprehensive security event logging\n\n### Privacy by Design\n- **Local Data Control**: Users maintain complete data ownership\n- **Selective Sync**: Fine-grained control over data sharing\n- **Data Minimization**: Only sync necessary data\n- **GDPR Compliance**: Built-in privacy compliance features\n\nLiveStore combines the reliability of traditional databases with the performance and user experience of local-first applications, enabling you to build applications that users love while maintaining the technical rigor of distributed systems.";
|
|
2
2
|
//# sourceMappingURL=features.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/mcp-content/features.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/mcp-content/features.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,8qNA+KuN,CAAA"}
|
|
@@ -149,7 +149,7 @@ await testStore.replay([
|
|
|
149
149
|
|
|
150
150
|
### Developer Tools
|
|
151
151
|
- **Event Inspector**: Real-time event log visualization
|
|
152
|
-
- **Query Profiler**: Performance analysis for slow queries
|
|
152
|
+
- **Query Profiler**: Performance analysis for slow queries
|
|
153
153
|
- **Sync Monitor**: Network synchronization health dashboard
|
|
154
154
|
- **Schema Explorer**: Interactive database schema browsing
|
|
155
155
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const gettingStartedContent = "# Getting Started with LiveStore\n\nBuild your first local-first application with LiveStore in minutes. This guide walks through creating a real-time collaborative todo app that works offline and syncs when online.\n\n## Quick Start\n\n### 1. Installation\n\n```bash\n# Install LiveStore core\nnpm install @livestore/livestore\n\n# Choose your platform adapter\nnpm install @livestore/adapter-web # For web applications\nnpm install @livestore/adapter-node # For Node.js applications\nnpm install @livestore/adapter-expo # For React Native/Expo apps\n```\n\n### 2. Define Your Schema\n\nLiveStore uses an event-driven architecture where all changes are recorded as immutable events and applied to materialized SQLite tables.\n\n```typescript\n// schema.ts\nimport { Events, makeSchema, Schema, SessionIdSymbol, State } from '@livestore/livestore'\n\n// Define your state as SQLite tables\nexport const tables = {\n todos: State.SQLite.table({\n name: 'todos',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n text: State.SQLite.text({ default: '' }),\n completed: State.SQLite.boolean({ default: false }),\n deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n \n // Client-only state (not synced)\n uiState: State.SQLite.clientDocument({\n name: 'uiState',\n schema: Schema.Struct({ \n newTodoText: Schema.String, \n filter: Schema.Literal('all', 'active', 'completed') \n }),\n default: { id: SessionIdSymbol, value: { newTodoText: '', filter: 'all' } },\n }),\n}\n\n// Define events that represent state changes\nexport const events = {\n todoCreated: Events.synced({\n name: 'v1.TodoCreated',\n schema: Schema.Struct({ \n id: Schema.String, \n text: Schema.String,\n createdAt: Schema.Date \n }),\n }),\n todoCompleted: Events.synced({\n name: 'v1.TodoCompleted',\n schema: Schema.Struct({ id: Schema.String }),\n }),\n todoUncompleted: Events.synced({\n name: 'v1.TodoUncompleted',\n schema: Schema.Struct({ id: Schema.String }),\n }),\n todoDeleted: Events.synced({\n name: 'v1.TodoDeleted',\n schema: Schema.Struct({ id: Schema.String, deletedAt: Schema.Date }),\n }),\n \n // UI state events (local only)\n uiStateSet: tables.uiState.set,\n}\n\n// Materializers map events to state changes\nconst materializers = State.SQLite.materializers(events, {\n 'v1.TodoCreated': ({ id, text, createdAt }) => \n tables.todos.insert({ id, text, completed: false, createdAt }),\n \n 'v1.TodoCompleted': ({ id }) => \n tables.todos.update({ completed: true }).where({ id }),\n \n 'v1.TodoUncompleted': ({ id }) => \n tables.todos.update({ completed: false }).where({ id }),\n \n 'v1.TodoDeleted': ({ id, deletedAt }) => \n tables.todos.update({ deletedAt }).where({ id }),\n})\n\nconst state = State.SQLite.makeState({ tables, materializers })\n\nexport const schema = makeSchema({ events, state })\n```\n\n### 3. Create Reactive Queries\n\nLiveStore queries automatically update your UI when underlying data changes.\n\n```typescript\n// queries.ts\nimport { queryDb } from '@livestore/livestore'\nimport { tables } from './schema.js'\n\n// Reactive query for all active todos\nexport const activeTodos$ = queryDb(\n tables.todos\n .select()\n .where({ deletedAt: null, completed: false })\n .orderBy('createdAt'),\n { label: 'activeTodos' }\n)\n\n// Reactive query for completed todos\nexport const completedTodos$ = queryDb(\n tables.todos\n .select()\n .where({ deletedAt: null, completed: true })\n .orderBy('createdAt'),\n { label: 'completedTodos' }\n)\n\n// UI state query\nexport const uiState$ = queryDb(\n tables.uiState.get(),\n { label: 'uiState' }\n)\n```\n\n### 4. Connect to Your UI Framework\n\n#### React Integration\n\n```typescript\n// TodoApp.tsx\nimport React from 'react'\nimport { useLiveQuery, dispatchEvent } from '@livestore/react'\nimport { activeTodos$, completedTodos$, uiState$ } from './queries.js'\nimport { events } from './schema.js'\n\nconst TodoApp: React.FC = () => {\n const activeTodos = useLiveQuery(activeTodos$)\n const completedTodos = useLiveQuery(completedTodos$)\n const uiState = useLiveQuery(uiState$)\n \n const createTodo = (text: string) => {\n const id = crypto.randomUUID()\n dispatchEvent(events.todoCreated({ id, text, createdAt: new Date() }))\n }\n \n const toggleTodo = (id: string, completed: boolean) => {\n dispatchEvent(\n completed \n ? events.todoCompleted({ id })\n : events.todoUncompleted({ id })\n )\n }\n \n const deleteTodo = (id: string) => {\n dispatchEvent(events.todoDeleted({ id, deletedAt: new Date() }))\n }\n \n return (\n <div className=\"todo-app\">\n <h1>Local-First Todos</h1>\n \n {/* Add todo form */}\n <form onSubmit={(e) => {\n e.preventDefault()\n const form = e.target as HTMLFormElement\n const input = form.elements.namedItem('todo') as HTMLInputElement\n if (input.value.trim()) {\n createTodo(input.value.trim())\n input.value = ''\n }\n }}>\n <input name=\"todo\" placeholder=\"What needs to be done?\" />\n <button type=\"submit\">Add Todo</button>\n </form>\n \n {/* Active todos */}\n <div className=\"todo-list\">\n <h2>Active ({activeTodos.length})</h2>\n {activeTodos.map(todo => (\n <div key={todo.id} className=\"todo-item\">\n <input \n type=\"checkbox\"\n checked={false}\n onChange={() => toggleTodo(todo.id, true)}\n />\n <span>{todo.text}</span>\n <button onClick={() => deleteTodo(todo.id)}>Delete</button>\n </div>\n ))}\n </div>\n \n {/* Completed todos */}\n <div className=\"todo-list\">\n <h2>Completed ({completedTodos.length})</h2>\n {completedTodos.map(todo => (\n <div key={todo.id} className=\"todo-item completed\">\n <input \n type=\"checkbox\"\n checked={true}\n onChange={() => toggleTodo(todo.id, false)}\n />\n <span>{todo.text}</span>\n <button onClick={() => deleteTodo(todo.id)}>Delete</button>\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nexport default TodoApp\n```\n\n#### Vue Integration\n\n```vue\n<!-- TodoApp.vue -->\n<template>\n <div class=\"todo-app\">\n <h1>Local-First Todos</h1>\n \n <form @submit.prevent=\"createTodo\">\n <input v-model=\"newTodoText\" placeholder=\"What needs to be done?\" />\n <button type=\"submit\">Add Todo</button>\n </form>\n \n <div class=\"todo-list\">\n <h2>Active ({{ activeTodos.length }})</h2>\n <div v-for=\"todo in activeTodos\" :key=\"todo.id\" class=\"todo-item\">\n <input \n type=\"checkbox\"\n :checked=\"false\"\n @change=\"toggleTodo(todo.id, true)\"\n />\n <span>{{ todo.text }}</span>\n <button @click=\"deleteTodo(todo.id)\">Delete</button>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useLiveQuery, dispatchEvent } from '@livestore/vue'\nimport { activeTodos$ } from './queries.js'\nimport { events } from './schema.js'\n\nconst activeTodos = useLiveQuery(activeTodos$)\nconst newTodoText = ref('')\n\nconst createTodo = () => {\n if (newTodoText.value.trim()) {\n const id = crypto.randomUUID()\n dispatchEvent(events.todoCreated({ \n id, \n text: newTodoText.value.trim(), \n createdAt: new Date() \n }))\n newTodoText.value = ''\n }\n}\n\nconst toggleTodo = (id: string, completed: boolean) => {\n dispatchEvent(\n completed \n ? events.todoCompleted({ id })\n : events.todoUncompleted({ id })\n )\n}\n\nconst deleteTodo = (id: string) => {\n dispatchEvent(events.todoDeleted({ id, deletedAt: new Date() }))\n}\n</script>\n```\n\n### 5. Initialize Your Application\n\n```typescript\n// main.ts\nimport { LiveStore } from '@livestore/livestore'\nimport { WebAdapter } from '@livestore/adapter-web'\nimport { schema } from './schema.js'\n\n// Initialize LiveStore with your schema\nconst liveStore = LiveStore.create({\n schema,\n adapter: WebAdapter({\n databaseName: 'todo-app',\n // Optional: Add sync configuration\n sync: {\n url: 'wss://your-sync-server.com',\n auth: { token: 'your-auth-token' }\n }\n })\n})\n\n// Start your application\nconst app = document.getElementById('app')\nif (app) {\n // Your framework-specific initialization\n // React: createRoot(app).render(<TodoApp />)\n // Vue: createApp(TodoApp).mount(app)\n}\n```\n\n## Advanced Features\n\n### Offline Support\n\nYour app automatically works offline. All operations execute against the local database, and changes sync when connectivity returns.\n\n```typescript\n// Check online status\nconst isOnline$ = queryDb(\n LiveStore.connectionStatus(),\n { label: 'connectionStatus' }\n)\n```\n\n### Real-Time Collaboration\n\nMultiple users can collaborate in real-time. Conflicts are automatically resolved using last-write-wins or custom merge strategies.\n\n```typescript\n// Custom conflict resolution\nconst materializers = State.SQLite.materializers(events, {\n 'v1.TodoTextChanged': ({ id, text, editedAt }) => \n // Use timestamp for conflict resolution\n tables.todos\n .update({ text, editedAt })\n .where({ id })\n .and(tables.todos.column('editedAt').lt(editedAt))\n})\n```\n\n### Testing\n\n```typescript\n// todo.test.ts\nimport { createTestStore } from '@livestore/testing'\nimport { schema, events } from './schema.js'\n\ntest('creating and completing todos', async () => {\n const store = createTestStore(schema)\n \n // Dispatch events\n await store.dispatch([\n events.todoCreated({ id: '1', text: 'Test todo', createdAt: new Date() }),\n events.todoCompleted({ id: '1' })\n ])\n \n // Query final state\n const completedTodos = await store.query(\n tables.todos.select().where({ completed: true })\n )\n \n expect(completedTodos).toHaveLength(1)\n expect(completedTodos[0].text).toBe('Test todo')\n})\n```\n\n## Next Steps\n\n### Production Deployment\n1. **Set up sync server**: Deploy LiveStore sync server for real-time collaboration\n2. **Configure authentication**: Add user authentication and authorization\n3. **Add monitoring**: Set up distributed tracing and performance monitoring\n4. **Optimize performance**: Add indexes and query optimization\n\n### Advanced Patterns\n- **Multi-user collaboration**: User permissions and access control\n- **Rich text editing**: Operational transforms for collaborative editing\n- **File synchronization**: Binary data and file attachment handling\n- **Schema migrations**: Evolving your data model over time\n\n### Platform-Specific Guides\n- **Web deployment**: Service workers, PWA configuration, OPFS optimization\n- **Mobile apps**: Background sync, push notifications, native storage\n- **Desktop apps**: Electron integration, native file system access\n\n## Examples Repository\n\nExplore complete working examples:\n- **TodoMVC**: Classic todo app with real-time sync\n- **Collaborative Editor**: Rich text editing with operational transforms\n- **Chat Application**: Real-time messaging with presence indicators\n- **E-commerce**: Product catalog with shopping cart and orders\n\n```bash\n# Clone examples repository\ngit clone https://github.com/livestorejs/examples.git\ncd examples/web-todomvc\nnpm install && npm run dev\n```\n\nVisit [docs.livestore.dev](https://docs.livestore.dev) for comprehensive documentation, API reference, and advanced patterns.";
|
|
1
|
+
export declare const gettingStartedContent = "# Getting Started with LiveStore\n\nBuild your first local-first application with LiveStore in minutes. This guide walks through creating a real-time collaborative todo app that works offline and syncs when online.\n\n## Quick Start\n\n### 1. Installation\n\n```bash\n# Install LiveStore core\nnpm install @livestore/livestore\n\n# Choose your platform adapter\nnpm install @livestore/adapter-web # For web applications\nnpm install @livestore/adapter-node # For Node.js applications\nnpm install @livestore/adapter-expo # For React Native/Expo apps\n```\n\n### 2. Define Your Schema\n\nLiveStore uses an event-driven architecture where all changes are recorded as immutable events and applied to materialized SQLite tables.\n\n```typescript\n// schema.ts\nimport { Events, makeSchema, Schema, SessionIdSymbol, State } from '@livestore/livestore'\n\n// Define your state as SQLite tables\nexport const tables = {\n todos: State.SQLite.table({\n name: 'todos',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n text: State.SQLite.text({ default: '' }),\n completed: State.SQLite.boolean({ default: false }),\n deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n\n // Client-only state (not synced)\n uiState: State.SQLite.clientDocument({\n name: 'uiState',\n schema: Schema.Struct({\n newTodoText: Schema.String,\n filter: Schema.Literal('all', 'active', 'completed')\n }),\n default: { id: SessionIdSymbol, value: { newTodoText: '', filter: 'all' } },\n }),\n}\n\n// Define events that represent state changes\nexport const events = {\n todoCreated: Events.synced({\n name: 'v1.TodoCreated',\n schema: Schema.Struct({\n id: Schema.String,\n text: Schema.String,\n createdAt: Schema.Date\n }),\n }),\n todoCompleted: Events.synced({\n name: 'v1.TodoCompleted',\n schema: Schema.Struct({ id: Schema.String }),\n }),\n todoUncompleted: Events.synced({\n name: 'v1.TodoUncompleted',\n schema: Schema.Struct({ id: Schema.String }),\n }),\n todoDeleted: Events.synced({\n name: 'v1.TodoDeleted',\n schema: Schema.Struct({ id: Schema.String, deletedAt: Schema.Date }),\n }),\n\n // UI state events (local only)\n uiStateSet: tables.uiState.set,\n}\n\n// Materializers map events to state changes\nconst materializers = State.SQLite.materializers(events, {\n 'v1.TodoCreated': ({ id, text, createdAt }) =>\n tables.todos.insert({ id, text, completed: false, createdAt }),\n\n 'v1.TodoCompleted': ({ id }) =>\n tables.todos.update({ completed: true }).where({ id }),\n\n 'v1.TodoUncompleted': ({ id }) =>\n tables.todos.update({ completed: false }).where({ id }),\n\n 'v1.TodoDeleted': ({ id, deletedAt }) =>\n tables.todos.update({ deletedAt }).where({ id }),\n})\n\nconst state = State.SQLite.makeState({ tables, materializers })\n\nexport const schema = makeSchema({ events, state })\n```\n\n### 3. Create Reactive Queries\n\nLiveStore queries automatically update your UI when underlying data changes.\n\n```typescript\n// queries.ts\nimport { queryDb } from '@livestore/livestore'\nimport { tables } from './schema.js'\n\n// Reactive query for all active todos\nexport const activeTodos$ = queryDb(\n tables.todos\n .select()\n .where({ deletedAt: null, completed: false })\n .orderBy('createdAt'),\n { label: 'activeTodos' }\n)\n\n// Reactive query for completed todos\nexport const completedTodos$ = queryDb(\n tables.todos\n .select()\n .where({ deletedAt: null, completed: true })\n .orderBy('createdAt'),\n { label: 'completedTodos' }\n)\n\n// UI state query\nexport const uiState$ = queryDb(\n tables.uiState.get(),\n { label: 'uiState' }\n)\n```\n\n### 4. Connect to Your UI Framework\n\n#### React Integration\n\n```typescript\n// TodoApp.tsx\nimport React from 'react'\nimport { useLiveQuery, dispatchEvent } from '@livestore/react'\nimport { activeTodos$, completedTodos$, uiState$ } from './queries.js'\nimport { events } from './schema.js'\n\nconst TodoApp: React.FC = () => {\n const activeTodos = useLiveQuery(activeTodos$)\n const completedTodos = useLiveQuery(completedTodos$)\n const uiState = useLiveQuery(uiState$)\n\n const createTodo = (text: string) => {\n const id = crypto.randomUUID()\n dispatchEvent(events.todoCreated({ id, text, createdAt: new Date() }))\n }\n\n const toggleTodo = (id: string, completed: boolean) => {\n dispatchEvent(\n completed\n ? events.todoCompleted({ id })\n : events.todoUncompleted({ id })\n )\n }\n\n const deleteTodo = (id: string) => {\n dispatchEvent(events.todoDeleted({ id, deletedAt: new Date() }))\n }\n\n return (\n <div className=\"todo-app\">\n <h1>Local-First Todos</h1>\n\n {/* Add todo form */}\n <form onSubmit={(e) => {\n e.preventDefault()\n const form = e.target as HTMLFormElement\n const input = form.elements.namedItem('todo') as HTMLInputElement\n if (input.value.trim()) {\n createTodo(input.value.trim())\n input.value = ''\n }\n }}>\n <input name=\"todo\" placeholder=\"What needs to be done?\" />\n <button type=\"submit\">Add Todo</button>\n </form>\n\n {/* Active todos */}\n <div className=\"todo-list\">\n <h2>Active ({activeTodos.length})</h2>\n {activeTodos.map(todo => (\n <div key={todo.id} className=\"todo-item\">\n <input\n type=\"checkbox\"\n checked={false}\n onChange={() => toggleTodo(todo.id, true)}\n />\n <span>{todo.text}</span>\n <button onClick={() => deleteTodo(todo.id)}>Delete</button>\n </div>\n ))}\n </div>\n\n {/* Completed todos */}\n <div className=\"todo-list\">\n <h2>Completed ({completedTodos.length})</h2>\n {completedTodos.map(todo => (\n <div key={todo.id} className=\"todo-item completed\">\n <input\n type=\"checkbox\"\n checked={true}\n onChange={() => toggleTodo(todo.id, false)}\n />\n <span>{todo.text}</span>\n <button onClick={() => deleteTodo(todo.id)}>Delete</button>\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nexport default TodoApp\n```\n\n#### Vue Integration\n\n```vue\n<!-- TodoApp.vue -->\n<template>\n <div class=\"todo-app\">\n <h1>Local-First Todos</h1>\n\n <form @submit.prevent=\"createTodo\">\n <input v-model=\"newTodoText\" placeholder=\"What needs to be done?\" />\n <button type=\"submit\">Add Todo</button>\n </form>\n\n <div class=\"todo-list\">\n <h2>Active ({{ activeTodos.length }})</h2>\n <div v-for=\"todo in activeTodos\" :key=\"todo.id\" class=\"todo-item\">\n <input\n type=\"checkbox\"\n :checked=\"false\"\n @change=\"toggleTodo(todo.id, true)\"\n />\n <span>{{ todo.text }}</span>\n <button @click=\"deleteTodo(todo.id)\">Delete</button>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useLiveQuery, dispatchEvent } from '@livestore/vue'\nimport { activeTodos$ } from './queries.js'\nimport { events } from './schema.js'\n\nconst activeTodos = useLiveQuery(activeTodos$)\nconst newTodoText = ref('')\n\nconst createTodo = () => {\n if (newTodoText.value.trim()) {\n const id = crypto.randomUUID()\n dispatchEvent(events.todoCreated({\n id,\n text: newTodoText.value.trim(),\n createdAt: new Date()\n }))\n newTodoText.value = ''\n }\n}\n\nconst toggleTodo = (id: string, completed: boolean) => {\n dispatchEvent(\n completed\n ? events.todoCompleted({ id })\n : events.todoUncompleted({ id })\n )\n}\n\nconst deleteTodo = (id: string) => {\n dispatchEvent(events.todoDeleted({ id, deletedAt: new Date() }))\n}\n</script>\n```\n\n### 5. Initialize Your Application\n\n```typescript\n// main.ts\nimport { LiveStore } from '@livestore/livestore'\nimport { WebAdapter } from '@livestore/adapter-web'\nimport { schema } from './schema.js'\n\n// Initialize LiveStore with your schema\nconst liveStore = LiveStore.create({\n schema,\n adapter: WebAdapter({\n databaseName: 'todo-app',\n // Optional: Add sync configuration\n sync: {\n url: 'wss://your-sync-server.com',\n auth: { token: 'your-auth-token' }\n }\n })\n})\n\n// Start your application\nconst app = document.getElementById('app')\nif (app) {\n // Your framework-specific initialization\n // React: createRoot(app).render(<TodoApp />)\n // Vue: createApp(TodoApp).mount(app)\n}\n```\n\n## Advanced Features\n\n### Offline Support\n\nYour app automatically works offline. All operations execute against the local database, and changes sync when connectivity returns.\n\n```typescript\n// Check online status\nconst isOnline$ = queryDb(\n LiveStore.connectionStatus(),\n { label: 'connectionStatus' }\n)\n```\n\n### Real-Time Collaboration\n\nMultiple users can collaborate in real-time. Conflicts are automatically resolved using last-write-wins or custom merge strategies.\n\n```typescript\n// Custom conflict resolution\nconst materializers = State.SQLite.materializers(events, {\n 'v1.TodoTextChanged': ({ id, text, editedAt }) =>\n // Use timestamp for conflict resolution\n tables.todos\n .update({ text, editedAt })\n .where({ id })\n .and(tables.todos.column('editedAt').lt(editedAt))\n})\n```\n\n### Testing\n\n```typescript\n// todo.test.ts\nimport { createTestStore } from '@livestore/testing'\nimport { schema, events } from './schema.js'\n\ntest('creating and completing todos', async () => {\n const store = createTestStore(schema)\n\n // Dispatch events\n await store.dispatch([\n events.todoCreated({ id: '1', text: 'Test todo', createdAt: new Date() }),\n events.todoCompleted({ id: '1' })\n ])\n\n // Query final state\n const completedTodos = await store.query(\n tables.todos.select().where({ completed: true })\n )\n\n expect(completedTodos).toHaveLength(1)\n expect(completedTodos[0].text).toBe('Test todo')\n})\n```\n\n## Next Steps\n\n### Production Deployment\n1. **Set up sync server**: Deploy LiveStore sync server for real-time collaboration\n2. **Configure authentication**: Add user authentication and authorization\n3. **Add monitoring**: Set up distributed tracing and performance monitoring\n4. **Optimize performance**: Add indexes and query optimization\n\n### Advanced Patterns\n- **Multi-user collaboration**: User permissions and access control\n- **Rich text editing**: Operational transforms for collaborative editing\n- **File synchronization**: Binary data and file attachment handling\n- **Schema migrations**: Evolving your data model over time\n\n### Platform-Specific Guides\n- **Web deployment**: Service workers, PWA configuration, OPFS optimization\n- **Mobile apps**: Background sync, push notifications, native storage\n- **Desktop apps**: Electron integration, native file system access\n\n## Examples Repository\n\nExplore complete working examples:\n- **TodoMVC**: Classic todo app with real-time sync\n- **Collaborative Editor**: Rich text editing with operational transforms\n- **Chat Application**: Real-time messaging with presence indicators\n- **E-commerce**: Product catalog with shopping cart and orders\n\n```bash\n# Clone examples repository\ngit clone https://github.com/livestorejs/examples.git\ncd examples/web-todomvc\nnpm install && npm run dev\n```\n\nVisit [docs.livestore.dev](https://docs.livestore.dev) for comprehensive documentation, API reference, and advanced patterns.";
|
|
2
2
|
//# sourceMappingURL=getting-started.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getting-started.d.ts","sourceRoot":"","sources":["../../src/mcp-content/getting-started.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,
|
|
1
|
+
{"version":3,"file":"getting-started.d.ts","sourceRoot":"","sources":["../../src/mcp-content/getting-started.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,gkXAmZ4F,CAAA"}
|