@luckystack/devkit 0.6.7 → 0.7.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/CHANGELOG.md +90 -0
- package/CLAUDE.md +129 -125
- package/LICENSE +21 -21
- package/README.md +44 -44
- package/dist/{chunk-EU2RFSLO.js → chunk-BZTCJ7JY.js} +1 -1
- package/dist/chunk-BZTCJ7JY.js.map +1 -0
- package/dist/cli/validateDeploy.js +1 -1
- package/dist/cli/validateDeploy.js.map +1 -1
- package/dist/index.js +257 -35
- package/dist/index.js.map +1 -1
- package/dist/supervisor.js +96 -45
- package/dist/supervisor.js.map +1 -1
- package/dist/templates/api.template.ts +54 -54
- package/dist/templates/page_dashboard.template.tsx +35 -35
- package/dist/templates/page_plain.template.tsx +32 -32
- package/dist/templates/sync_client.template.ts +40 -40
- package/dist/templates/sync_client_paired.template.ts +38 -38
- package/dist/templates/sync_client_standalone.template.ts +36 -36
- package/dist/templates/sync_server.template.ts +64 -64
- package/docs/cli.md +245 -245
- package/docs/hot-reload.md +365 -365
- package/docs/loader-pipeline.md +324 -324
- package/docs/runtime-type-resolver.md +258 -258
- package/docs/supervisor.md +292 -292
- package/docs/ts-program-cache.md +200 -199
- package/docs/type-map-generation.md +410 -392
- package/package.json +10 -4
- package/dist/chunk-EU2RFSLO.js.map +0 -1
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
/* eslint-disable unicorn/no-abusive-eslint-disable */
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
|
|
4
|
-
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
5
|
-
import { Functions, SyncClientResponse, SyncClientInput, SyncServerOutput, MaybePromise, SyncClientStreamEmitter } from '{{REL_PATH}}src/_sockets/apiTypes.generated';
|
|
6
|
-
|
|
7
|
-
// Types are imported from the generated file based on the _server_v{number}.ts definition
|
|
8
|
-
type PagePath = '{{PAGE_PATH}}';
|
|
9
|
-
type SyncName = '{{SYNC_NAME}}';
|
|
10
|
-
|
|
11
|
-
export interface SyncParams {
|
|
12
|
-
clientInput: SyncClientInput<PagePath, SyncName>;
|
|
13
|
-
serverOutput: SyncServerOutput<PagePath, SyncName>;
|
|
14
|
-
token: string | null; // target client's session token (fetch session only when needed)
|
|
15
|
-
functions: Functions; // contains all functions that are available on the server in the functions folder
|
|
16
|
-
roomCode: string; // room code
|
|
17
|
-
stream: SyncClientStreamEmitter;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const main = ({ }: SyncParams): MaybePromise<SyncClientResponse> => {
|
|
21
|
-
// PAIRED SYNC: Types are shared with the _server_v{number}.ts file
|
|
22
|
-
// clientInput type comes from _server_v{number}.ts SyncParams
|
|
23
|
-
// serverOutput type is inferred from _server_v{number}.ts return value
|
|
24
|
-
// stream payload types are generated from your stream(...) calls in this file
|
|
25
|
-
// Use functions.session.getSession(token) when you need session data for this target client.
|
|
26
|
-
// Returning error here only affects the current target client and does not stop other clients.
|
|
27
|
-
|
|
28
|
-
// Example: Only allow users on set page to receive the event
|
|
29
|
-
// const targetUser = token ? await functions.session.getSession(token) : null;
|
|
30
|
-
// if (targetUser?.location?.pathName === '/your-page') {
|
|
31
|
-
// return { status: 'success' };
|
|
32
|
-
// }
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
status: 'success',
|
|
36
|
-
// Add any additional data to pass to the client
|
|
37
|
-
};
|
|
38
|
-
};
|
|
1
|
+
/* eslint-disable unicorn/no-abusive-eslint-disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
5
|
+
import { Functions, SyncClientResponse, SyncClientInput, SyncServerOutput, MaybePromise, SyncClientStreamEmitter } from '{{REL_PATH}}src/_sockets/apiTypes.generated';
|
|
6
|
+
|
|
7
|
+
// Types are imported from the generated file based on the _server_v{number}.ts definition
|
|
8
|
+
type PagePath = '{{PAGE_PATH}}';
|
|
9
|
+
type SyncName = '{{SYNC_NAME}}';
|
|
10
|
+
|
|
11
|
+
export interface SyncParams {
|
|
12
|
+
clientInput: SyncClientInput<PagePath, SyncName>;
|
|
13
|
+
serverOutput: SyncServerOutput<PagePath, SyncName>;
|
|
14
|
+
token: string | null; // target client's session token (fetch session only when needed)
|
|
15
|
+
functions: Functions; // contains all functions that are available on the server in the functions folder
|
|
16
|
+
roomCode: string; // room code
|
|
17
|
+
stream: SyncClientStreamEmitter;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const main = ({ }: SyncParams): MaybePromise<SyncClientResponse> => {
|
|
21
|
+
// PAIRED SYNC: Types are shared with the _server_v{number}.ts file
|
|
22
|
+
// clientInput type comes from _server_v{number}.ts SyncParams
|
|
23
|
+
// serverOutput type is inferred from _server_v{number}.ts return value
|
|
24
|
+
// stream payload types are generated from your stream(...) calls in this file
|
|
25
|
+
// Use functions.session.getSession(token) when you need session data for this target client.
|
|
26
|
+
// Returning error here only affects the current target client and does not stop other clients.
|
|
27
|
+
|
|
28
|
+
// Example: Only allow users on set page to receive the event
|
|
29
|
+
// const targetUser = token ? await functions.session.getSession(token) : null;
|
|
30
|
+
// if (targetUser?.location?.pathName === '/your-page') {
|
|
31
|
+
// return { status: 'success' };
|
|
32
|
+
// }
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
status: 'success',
|
|
36
|
+
// Add any additional data to pass to the client
|
|
37
|
+
};
|
|
38
|
+
};
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
/* eslint-disable unicorn/no-abusive-eslint-disable */
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
|
|
4
|
-
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
5
|
-
import { Functions, SyncClientResponse, MaybePromise, SyncClientStreamEmitter } from '{{REL_PATH}}src/_sockets/apiTypes.generated';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface SyncParams {
|
|
9
|
-
clientInput: {
|
|
10
|
-
// Define the data shape sent from the client e.g.
|
|
11
|
-
// message: string;
|
|
12
|
-
};
|
|
13
|
-
// Note: No serverOutput in client-only syncs (no _server_v{number}.ts file)
|
|
14
|
-
token: string | null; // target client's session token (fetch session only when needed)
|
|
15
|
-
functions: Functions; // contains all functions that are available on the server in the functions folder
|
|
16
|
-
roomCode: string; // room code
|
|
17
|
-
stream: SyncClientStreamEmitter;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const main = ({ }: SyncParams): MaybePromise<SyncClientResponse> => {
|
|
21
|
-
// CLIENT-ONLY SYNC: No server processing, runs for each client in the room
|
|
22
|
-
// stream payload types are generated from your stream(...) calls in this file
|
|
23
|
-
// Use functions.session.getSession(token) when you need session data for this target client.
|
|
24
|
-
// Returning error here only affects the current target client and does not stop other clients.
|
|
25
|
-
|
|
26
|
-
// Example: Only allow users on set page to receive the event
|
|
27
|
-
// const targetUser = token ? await functions.session.getSession(token) : null;
|
|
28
|
-
// if (targetUser?.location?.pathName === '/your-page') {
|
|
29
|
-
// return { status: 'success' };
|
|
30
|
-
// }
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
status: 'success',
|
|
34
|
-
// Add any additional data to pass to the client
|
|
35
|
-
};
|
|
36
|
-
};
|
|
1
|
+
/* eslint-disable unicorn/no-abusive-eslint-disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
5
|
+
import { Functions, SyncClientResponse, MaybePromise, SyncClientStreamEmitter } from '{{REL_PATH}}src/_sockets/apiTypes.generated';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export interface SyncParams {
|
|
9
|
+
clientInput: {
|
|
10
|
+
// Define the data shape sent from the client e.g.
|
|
11
|
+
// message: string;
|
|
12
|
+
};
|
|
13
|
+
// Note: No serverOutput in client-only syncs (no _server_v{number}.ts file)
|
|
14
|
+
token: string | null; // target client's session token (fetch session only when needed)
|
|
15
|
+
functions: Functions; // contains all functions that are available on the server in the functions folder
|
|
16
|
+
roomCode: string; // room code
|
|
17
|
+
stream: SyncClientStreamEmitter;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const main = ({ }: SyncParams): MaybePromise<SyncClientResponse> => {
|
|
21
|
+
// CLIENT-ONLY SYNC: No server processing, runs for each client in the room
|
|
22
|
+
// stream payload types are generated from your stream(...) calls in this file
|
|
23
|
+
// Use functions.session.getSession(token) when you need session data for this target client.
|
|
24
|
+
// Returning error here only affects the current target client and does not stop other clients.
|
|
25
|
+
|
|
26
|
+
// Example: Only allow users on set page to receive the event
|
|
27
|
+
// const targetUser = token ? await functions.session.getSession(token) : null;
|
|
28
|
+
// if (targetUser?.location?.pathName === '/your-page') {
|
|
29
|
+
// return { status: 'success' };
|
|
30
|
+
// }
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
status: 'success',
|
|
34
|
+
// Add any additional data to pass to the client
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
/* eslint-disable unicorn/no-abusive-eslint-disable */
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
|
|
4
|
-
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
5
|
-
import { AuthProps, SessionLayout } from '{{REL_PATH}}config';
|
|
6
|
-
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
7
|
-
import { Functions, SyncServerResponse, MaybePromise, SyncServerStreamEmitter, SyncBroadcastStreamEmitter, SyncStreamToEmitter } from '{{REL_PATH}}src/_sockets/apiTypes.generated';
|
|
8
|
-
|
|
9
|
-
export const auth: AuthProps = {
|
|
10
|
-
login: true,
|
|
11
|
-
additional: []
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export interface SyncParams {
|
|
15
|
-
clientInput: {
|
|
16
|
-
// Define the data shape sent from the client e.g.
|
|
17
|
-
// message: string;
|
|
18
|
-
// targetUserId: string;
|
|
19
|
-
};
|
|
20
|
-
user: SessionLayout; // session data of the user who called the sync event
|
|
21
|
-
functions: Functions; // functions object
|
|
22
|
-
roomCode: string; // room code
|
|
23
|
-
//? Stream primitives — pick whichever audience matches your use case:
|
|
24
|
-
//? stream → originator only (cheapest)
|
|
25
|
-
//? broadcastStream → every socket in the receiver room (live AI chat, collab)
|
|
26
|
-
//? streamTo → specific session tokens only (selective subscribers)
|
|
27
|
-
stream: SyncServerStreamEmitter;
|
|
28
|
-
broadcastStream: SyncBroadcastStreamEmitter;
|
|
29
|
-
streamTo: SyncStreamToEmitter;
|
|
30
|
-
//? Aborts on client-side cancel (`syncRequest({ signal })`) or socket
|
|
31
|
-
//? disconnect. Check `abortSignal.aborted` in long-running loops and bail
|
|
32
|
-
//? out — already-emitted chunks are not unsent, but new ones are
|
|
33
|
-
//? short-circuited automatically by the stream emitters.
|
|
34
|
-
abortSignal: AbortSignal;
|
|
35
|
-
//? Awaitable backpressure helper. Resolves once the worst-case write
|
|
36
|
-
//? buffer across affected sockets drops below the threshold (default 1 MB).
|
|
37
|
-
//? Use opt-in between batches of stream chunks to keep memory bounded.
|
|
38
|
-
flushPressure: (options?: { thresholdBytes?: number }) => Promise<void>;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const main = ({ }: SyncParams): MaybePromise<SyncServerResponse> => {
|
|
42
|
-
// THIS FILE RUNS JUST ONCE ON THE SERVER
|
|
43
|
-
|
|
44
|
-
// Stream payload types are generated from your stream(...) calls.
|
|
45
|
-
// stream({ phase: 'validate', progress: 10 }); // → originator only
|
|
46
|
-
// broadcastStream({ chunk: 'hello' }); // → everyone in the room
|
|
47
|
-
// streamTo([adminToken], { audit: 'event' }); // → specific tokens
|
|
48
|
-
|
|
49
|
-
// For LLM token streams, coalesce small pieces with createStreamThrottle:
|
|
50
|
-
// import { createStreamThrottle } from '@luckystack/sync';
|
|
51
|
-
// const throttle = createStreamThrottle({ flushEveryMs: 50, flushAtChars: 32 });
|
|
52
|
-
// for await (const piece of aiStream) throttle.push(piece.text, broadcastStream);
|
|
53
|
-
// throttle.flush(broadcastStream);
|
|
54
|
-
|
|
55
|
-
// Return { status: 'error', message: '...' } OR { status: 'error', errorCode: '...' }
|
|
56
|
-
// Returning error here aborts the full sync flow.
|
|
57
|
-
|
|
58
|
-
// Please validate clientInput here and dont just send the data back to the other clients
|
|
59
|
-
// optional: database action or something else
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
status: 'success',
|
|
63
|
-
// Add any data you want to broadcast to clients
|
|
64
|
-
};
|
|
1
|
+
/* eslint-disable unicorn/no-abusive-eslint-disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
5
|
+
import { AuthProps, SessionLayout } from '{{REL_PATH}}config';
|
|
6
|
+
//@ts-ignore We replace {{REL_PATH}} with the relative path to the project root at scaffold time.
|
|
7
|
+
import { Functions, SyncServerResponse, MaybePromise, SyncServerStreamEmitter, SyncBroadcastStreamEmitter, SyncStreamToEmitter } from '{{REL_PATH}}src/_sockets/apiTypes.generated';
|
|
8
|
+
|
|
9
|
+
export const auth: AuthProps = {
|
|
10
|
+
login: true,
|
|
11
|
+
additional: []
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export interface SyncParams {
|
|
15
|
+
clientInput: {
|
|
16
|
+
// Define the data shape sent from the client e.g.
|
|
17
|
+
// message: string;
|
|
18
|
+
// targetUserId: string;
|
|
19
|
+
};
|
|
20
|
+
user: SessionLayout; // session data of the user who called the sync event
|
|
21
|
+
functions: Functions; // functions object
|
|
22
|
+
roomCode: string; // room code
|
|
23
|
+
//? Stream primitives — pick whichever audience matches your use case:
|
|
24
|
+
//? stream → originator only (cheapest)
|
|
25
|
+
//? broadcastStream → every socket in the receiver room (live AI chat, collab)
|
|
26
|
+
//? streamTo → specific session tokens only (selective subscribers)
|
|
27
|
+
stream: SyncServerStreamEmitter;
|
|
28
|
+
broadcastStream: SyncBroadcastStreamEmitter;
|
|
29
|
+
streamTo: SyncStreamToEmitter;
|
|
30
|
+
//? Aborts on client-side cancel (`syncRequest({ signal })`) or socket
|
|
31
|
+
//? disconnect. Check `abortSignal.aborted` in long-running loops and bail
|
|
32
|
+
//? out — already-emitted chunks are not unsent, but new ones are
|
|
33
|
+
//? short-circuited automatically by the stream emitters.
|
|
34
|
+
abortSignal: AbortSignal;
|
|
35
|
+
//? Awaitable backpressure helper. Resolves once the worst-case write
|
|
36
|
+
//? buffer across affected sockets drops below the threshold (default 1 MB).
|
|
37
|
+
//? Use opt-in between batches of stream chunks to keep memory bounded.
|
|
38
|
+
flushPressure: (options?: { thresholdBytes?: number }) => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const main = ({ }: SyncParams): MaybePromise<SyncServerResponse> => {
|
|
42
|
+
// THIS FILE RUNS JUST ONCE ON THE SERVER
|
|
43
|
+
|
|
44
|
+
// Stream payload types are generated from your stream(...) calls.
|
|
45
|
+
// stream({ phase: 'validate', progress: 10 }); // → originator only
|
|
46
|
+
// broadcastStream({ chunk: 'hello' }); // → everyone in the room
|
|
47
|
+
// streamTo([adminToken], { audit: 'event' }); // → specific tokens
|
|
48
|
+
|
|
49
|
+
// For LLM token streams, coalesce small pieces with createStreamThrottle:
|
|
50
|
+
// import { createStreamThrottle } from '@luckystack/sync';
|
|
51
|
+
// const throttle = createStreamThrottle({ flushEveryMs: 50, flushAtChars: 32 });
|
|
52
|
+
// for await (const piece of aiStream) throttle.push(piece.text, broadcastStream);
|
|
53
|
+
// throttle.flush(broadcastStream);
|
|
54
|
+
|
|
55
|
+
// Return { status: 'error', message: '...' } OR { status: 'error', errorCode: '...' }
|
|
56
|
+
// Returning error here aborts the full sync flow.
|
|
57
|
+
|
|
58
|
+
// Please validate clientInput here and dont just send the data back to the other clients
|
|
59
|
+
// optional: database action or something else
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
status: 'success',
|
|
63
|
+
// Add any data you want to broadcast to clients
|
|
64
|
+
};
|
|
65
65
|
};
|