@qorejs/qore 0.7.2 → 0.9.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.
Files changed (47) hide show
  1. package/README.md +294 -5
  2. package/dist/src/core/owner.d.ts +14 -0
  3. package/dist/src/core/owner.js +66 -0
  4. package/dist/src/core/response-runtime.js +5 -5
  5. package/dist/src/core/response-state.d.ts +4 -0
  6. package/dist/src/core/response-state.js +67 -2
  7. package/dist/src/core/signal-context.js +19 -9
  8. package/dist/src/core/signal-nodes.d.ts +5 -0
  9. package/dist/src/core/signal-nodes.js +51 -21
  10. package/dist/src/core/signal-types.d.ts +2 -0
  11. package/dist/src/core/signal.d.ts +1 -0
  12. package/dist/src/core/signal.js +2 -0
  13. package/dist/src/core/stream-types.d.ts +12 -0
  14. package/dist/src/core/stream.d.ts +1 -1
  15. package/dist/src/core/stream.js +144 -0
  16. package/dist/src/dom/app.js +2 -3
  17. package/dist/src/dom/dom.d.ts +1 -0
  18. package/dist/src/dom/dom.js +96 -9
  19. package/dist/src/dom/scope.d.ts +3 -1
  20. package/dist/src/dom/scope.js +10 -3
  21. package/dist/src/index.d.ts +10 -4
  22. package/dist/src/index.js +7 -2
  23. package/dist/src/providers/anthropic.js +6 -4
  24. package/dist/src/providers/deepseek.d.ts +2 -0
  25. package/dist/src/providers/deepseek.js +90 -0
  26. package/dist/src/providers/line-adapter.d.ts +2 -0
  27. package/dist/src/providers/line-adapter.js +83 -0
  28. package/dist/src/providers/line-parser.d.ts +5 -0
  29. package/dist/src/providers/line-parser.js +103 -0
  30. package/dist/src/providers/metadata.d.ts +8 -0
  31. package/dist/src/providers/metadata.js +193 -0
  32. package/dist/src/providers/ollama.d.ts +2 -0
  33. package/dist/src/providers/ollama.js +82 -0
  34. package/dist/src/providers/openai.js +6 -4
  35. package/dist/src/providers/openrouter.d.ts +2 -0
  36. package/dist/src/providers/openrouter.js +90 -0
  37. package/dist/src/providers/sse-adapter.js +129 -44
  38. package/dist/src/providers/sse-parser.d.ts +1 -1
  39. package/dist/src/providers/sse-parser.js +74 -38
  40. package/dist/src/providers/sse.d.ts +7 -1
  41. package/dist/src/providers/sse.js +6 -0
  42. package/dist/src/providers/types.d.ts +145 -0
  43. package/dist/src/server/sse-response.d.ts +16 -0
  44. package/dist/src/server/sse-response.js +102 -0
  45. package/dist/src/shared/utils.d.ts +1 -0
  46. package/dist/src/shared/utils.js +8 -1
  47. package/package.json +9 -2
@@ -0,0 +1,102 @@
1
+ import { toAsyncIterable } from '../core/iterable.js';
2
+ import { normalizeAbortReason, normalizeError } from '../shared/utils.js';
3
+ const encoder = new TextEncoder();
4
+ function normalizeFrame(chunk, index, options) {
5
+ if (typeof options.encode === 'function') {
6
+ return Promise.resolve(options.encode(chunk, index));
7
+ }
8
+ return Promise.resolve({
9
+ ...(options.event ? { event: options.event } : {}),
10
+ data: typeof chunk === 'string' ? chunk : JSON.stringify(chunk)
11
+ });
12
+ }
13
+ function formatSSEFrame(frame) {
14
+ if (typeof frame === 'string') {
15
+ return frame.endsWith('\n\n') ? frame : `${frame}\n\n`;
16
+ }
17
+ const lines = [];
18
+ if (frame.event) {
19
+ lines.push(`event: ${frame.event}`);
20
+ }
21
+ if (frame.id) {
22
+ lines.push(`id: ${frame.id}`);
23
+ }
24
+ if (typeof frame.retry === 'number') {
25
+ lines.push(`retry: ${frame.retry}`);
26
+ }
27
+ const payloadLines = String(frame.data).split('\n');
28
+ for (const line of payloadLines) {
29
+ lines.push(`data: ${line}`);
30
+ }
31
+ return `${lines.join('\n')}\n\n`;
32
+ }
33
+ function mergeResponseHeaders(headers = {}) {
34
+ const merged = new Headers({
35
+ 'cache-control': 'no-cache, no-transform',
36
+ connection: 'keep-alive',
37
+ 'content-type': 'text/event-stream; charset=utf-8',
38
+ ...headers
39
+ });
40
+ return merged;
41
+ }
42
+ export function createSSEResponse(source, options = {}) {
43
+ const { signal, headers, doneFrame = 'data: [DONE]\n\n', onError = (error) => ({
44
+ event: 'error',
45
+ data: error.message
46
+ }) } = options;
47
+ const body = new ReadableStream({
48
+ async start(controller) {
49
+ let index = 0;
50
+ const close = () => {
51
+ if (doneFrame) {
52
+ controller.enqueue(encoder.encode(typeof doneFrame === 'string' ? doneFrame : 'data: [DONE]\n\n'));
53
+ }
54
+ controller.close();
55
+ };
56
+ if (signal?.aborted) {
57
+ controller.error(normalizeAbortReason(signal.reason, 'SSE response aborted'));
58
+ return;
59
+ }
60
+ const abortHandler = () => {
61
+ try {
62
+ controller.close();
63
+ }
64
+ catch {
65
+ // Ignore close races after the stream has already settled.
66
+ }
67
+ };
68
+ signal?.addEventListener('abort', abortHandler, { once: true });
69
+ try {
70
+ for await (const chunk of toAsyncIterable(source)) {
71
+ if (signal?.aborted) {
72
+ close();
73
+ return;
74
+ }
75
+ const frame = await normalizeFrame(chunk, index, options);
76
+ controller.enqueue(encoder.encode(formatSSEFrame(frame)));
77
+ index += 1;
78
+ }
79
+ close();
80
+ }
81
+ catch (error) {
82
+ if (signal?.aborted) {
83
+ abortHandler();
84
+ return;
85
+ }
86
+ const normalizedError = normalizeError(error);
87
+ const errorFrame = await onError(normalizedError);
88
+ if (errorFrame !== false) {
89
+ controller.enqueue(encoder.encode(formatSSEFrame(errorFrame)));
90
+ }
91
+ controller.close();
92
+ }
93
+ finally {
94
+ signal?.removeEventListener('abort', abortHandler);
95
+ }
96
+ }
97
+ });
98
+ return new Response(body, {
99
+ status: 200,
100
+ headers: mergeResponseHeaders(headers)
101
+ });
102
+ }
@@ -1,2 +1,3 @@
1
1
  export declare function normalizeError(error: unknown): Error;
2
+ export declare function normalizeAbortReason(reason: unknown, fallbackMessage?: string): Error;
2
3
  export declare function sleep(ms: number, signal?: AbortSignal | null): Promise<void>;
@@ -8,6 +8,13 @@ export function normalizeError(error) {
8
8
  }
9
9
  return new Error('Unknown Qore error');
10
10
  }
11
+ // Convert abort reasons into stable Error instances for transport and runtime code.
12
+ export function normalizeAbortReason(reason, fallbackMessage = 'Operation aborted') {
13
+ if (reason == null) {
14
+ return new Error(fallbackMessage);
15
+ }
16
+ return normalizeError(reason);
17
+ }
11
18
  // Sleep for a fixed time and reject early if the surrounding operation is aborted.
12
19
  export function sleep(ms, signal) {
13
20
  return new Promise((resolve, reject) => {
@@ -17,7 +24,7 @@ export function sleep(ms, signal) {
17
24
  }, ms);
18
25
  const onAbort = () => {
19
26
  cleanup();
20
- reject(normalizeError(signal?.reason ?? 'Operation aborted'));
27
+ reject(normalizeAbortReason(signal?.reason, 'Operation aborted'));
21
28
  };
22
29
  const cleanup = () => {
23
30
  clearTimeout(timer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qorejs/qore",
3
- "version": "0.7.2",
3
+ "version": "0.9.0",
4
4
  "description": "Qore is a streaming-response framework where stream becomes signal.",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -23,13 +23,17 @@
23
23
  "browsers:install": "playwright install chromium",
24
24
  "typecheck": "node ./scripts/typecheck.mjs",
25
25
  "check:dist": "node ./scripts/check-dist-sync.mjs",
26
+ "check:api-surface": "node ./scripts/check-public-api.mjs",
27
+ "check:release-docs": "node ./scripts/check-release-docs.mjs",
26
28
  "test:browser": "node ./scripts/browser-smoke.mjs",
29
+ "test:benchmark": "node ./scripts/benchmark-gate.mjs",
27
30
  "smoke:package-types": "node ./scripts/package-type-smoke.mjs",
28
31
  "smoke:package-runtime": "node ./scripts/package-runtime-smoke.mjs",
29
32
  "test": "node ./scripts/test.mjs",
30
33
  "release:check": "node ./scripts/release-check.mjs",
34
+ "publish:preflight": "node ./scripts/publish-preflight.mjs",
31
35
  "publish:github": "npm publish --registry=https://npm.pkg.github.com",
32
- "publish:npm": "npm publish --access public",
36
+ "publish:npm": "node ./scripts/publish-npm.mjs",
33
37
  "prepublishOnly": "node ./scripts/release-check.mjs"
34
38
  },
35
39
  "engines": {
@@ -42,9 +46,12 @@
42
46
  "signal",
43
47
  "reactive",
44
48
  "sse",
49
+ "ndjson",
45
50
  "ai",
46
51
  "openai",
47
52
  "anthropic",
53
+ "deepseek",
54
+ "ollama",
48
55
  "framework",
49
56
  "async-iterable"
50
57
  ],