@mdsnai/sdk 0.1.0 → 0.2.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 (78) hide show
  1. package/README.md +40 -0
  2. package/dist/core/document/markdown.js +2 -4
  3. package/dist/core/document/page-definition.js +1 -2
  4. package/dist/core/index.d.ts +2 -1
  5. package/dist/core/index.js +9 -1
  6. package/dist/core/model/block.d.ts +4 -8
  7. package/dist/core/model/block.js +6 -0
  8. package/dist/core/model/document.d.ts +0 -2
  9. package/dist/core/model/index.d.ts +1 -2
  10. package/dist/core/model/input.d.ts +1 -2
  11. package/dist/core/protocol/mdsn.d.ts +0 -2
  12. package/dist/core/protocol/mdsn.js +3 -17
  13. package/dist/core/protocol/statements.d.ts +3 -8
  14. package/dist/core/protocol/statements.js +46 -71
  15. package/dist/core/protocol/validation.d.ts +2 -3
  16. package/dist/core/protocol/validation.js +21 -11
  17. package/dist/core/utils/html.d.ts +6 -0
  18. package/dist/core/utils/html.js +28 -0
  19. package/dist/core/utils/index.d.ts +2 -0
  20. package/dist/core/utils/index.js +12 -0
  21. package/dist/core/utils/logger.d.ts +12 -0
  22. package/dist/core/utils/logger.js +45 -0
  23. package/dist/framework/create-framework-app.d.ts +1 -0
  24. package/dist/framework/create-framework-app.js +1 -0
  25. package/dist/framework/hosted-app.d.ts +21 -0
  26. package/dist/framework/hosted-app.js +123 -33
  27. package/dist/framework/index.d.ts +2 -0
  28. package/dist/framework/index.js +3 -1
  29. package/dist/framework/site-app.d.ts +1 -0
  30. package/dist/framework/site-app.js +1 -0
  31. package/dist/index.d.ts +5 -5
  32. package/dist/index.js +18 -1
  33. package/dist/server/action-context.d.ts +11 -0
  34. package/dist/server/action-context.js +26 -0
  35. package/dist/server/action-host.d.ts +2 -3
  36. package/dist/server/action-host.js +4 -2
  37. package/dist/server/action-inputs.d.ts +3 -0
  38. package/dist/server/action-inputs.js +178 -0
  39. package/dist/server/action-runtime.d.ts +3 -3
  40. package/dist/server/action-runtime.js +2 -21
  41. package/dist/server/action.d.ts +1 -9
  42. package/dist/server/action.js +5 -1
  43. package/dist/server/build.js +4 -0
  44. package/dist/server/error-fragments.d.ts +46 -0
  45. package/dist/server/error-fragments.js +77 -0
  46. package/dist/server/index.d.ts +9 -2
  47. package/dist/server/index.js +17 -1
  48. package/dist/server/init.js +13 -13
  49. package/dist/server/markdown.d.ts +2 -6
  50. package/dist/server/markdown.js +11 -10
  51. package/dist/server/server.d.ts +2 -1
  52. package/dist/server/server.js +17 -8
  53. package/dist/server/session.d.ts +40 -0
  54. package/dist/server/session.js +220 -0
  55. package/dist/web/block-runtime.js +15 -17
  56. package/dist/web/fragment-render.d.ts +0 -2
  57. package/dist/web/fragment-render.js +0 -1
  58. package/dist/web/i18n.d.ts +0 -2
  59. package/dist/web/i18n.js +0 -4
  60. package/dist/web/index.d.ts +1 -1
  61. package/dist/web/index.js +2 -1
  62. package/dist/web/page-bootstrap.js +0 -1
  63. package/dist/web/page-client-runtime.d.ts +2 -13
  64. package/dist/web/page-client-runtime.js +1 -16
  65. package/dist/web/page-client-script.d.ts +0 -1
  66. package/dist/web/page-client-script.js +172 -160
  67. package/dist/web/page-html.js +4 -11
  68. package/dist/web/page-render.d.ts +1 -1
  69. package/dist/web/page-render.js +13 -21
  70. package/package.json +1 -1
  71. package/dist/core/action/execution.d.ts +0 -4
  72. package/dist/core/action/execution.js +0 -57
  73. package/dist/core/action/index.d.ts +0 -2
  74. package/dist/core/action/index.js +0 -7
  75. package/dist/core/action/types.d.ts +0 -19
  76. package/dist/core/action/types.js +0 -2
  77. package/dist/core/model/schema.d.ts +0 -4
  78. package/dist/core/model/schema.js +0 -2
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpCookieJar = void 0;
4
+ exports.parseCookieHeader = parseCookieHeader;
5
+ exports.requireSessionFromCookie = requireSessionFromCookie;
6
+ const error_fragments_1 = require("./error-fragments");
7
+ function decodeCookieComponentSafe(value) {
8
+ try {
9
+ return decodeURIComponent(value);
10
+ }
11
+ catch {
12
+ // Keep malformed cookie values as raw text instead of throwing.
13
+ return value;
14
+ }
15
+ }
16
+ function parseCookieHeader(cookieHeader) {
17
+ if (!cookieHeader) {
18
+ return {};
19
+ }
20
+ return Object.fromEntries(cookieHeader
21
+ .split(";")
22
+ .map((part) => part.trim())
23
+ .filter(Boolean)
24
+ .map((part) => {
25
+ const eq = part.indexOf("=");
26
+ if (eq === -1) {
27
+ return [part, ""];
28
+ }
29
+ return [part.slice(0, eq), decodeCookieComponentSafe(part.slice(eq + 1))];
30
+ }));
31
+ }
32
+ function splitCombinedSetCookieHeader(setCookieHeader) {
33
+ const results = [];
34
+ let current = "";
35
+ let inExpires = false;
36
+ for (let index = 0; index < setCookieHeader.length; index += 1) {
37
+ const character = setCookieHeader[index];
38
+ if (!character) {
39
+ continue;
40
+ }
41
+ if (character === ",") {
42
+ if (inExpires) {
43
+ current += character;
44
+ continue;
45
+ }
46
+ results.push(current.trim());
47
+ current = "";
48
+ continue;
49
+ }
50
+ current += character;
51
+ if (character === ";") {
52
+ inExpires = false;
53
+ continue;
54
+ }
55
+ if (!inExpires && /expires=/iu.test(current.slice(-8))) {
56
+ inExpires = true;
57
+ }
58
+ }
59
+ if (current.trim().length > 0) {
60
+ results.push(current.trim());
61
+ }
62
+ return results.filter(Boolean);
63
+ }
64
+ function parseSetCookieLine(line) {
65
+ const segments = line.split(";").map((segment) => segment.trim()).filter(Boolean);
66
+ if (segments.length === 0) {
67
+ return null;
68
+ }
69
+ const pair = segments[0] ?? "";
70
+ const eq = pair.indexOf("=");
71
+ if (eq <= 0) {
72
+ return null;
73
+ }
74
+ const name = pair.slice(0, eq).trim();
75
+ const value = pair.slice(eq + 1).trim();
76
+ if (!name) {
77
+ return null;
78
+ }
79
+ const attributes = {};
80
+ for (const attributeSegment of segments.slice(1)) {
81
+ const attributeEq = attributeSegment.indexOf("=");
82
+ if (attributeEq === -1) {
83
+ attributes[attributeSegment.toLowerCase()] = "true";
84
+ continue;
85
+ }
86
+ const key = attributeSegment.slice(0, attributeEq).trim().toLowerCase();
87
+ const attributeValue = attributeSegment.slice(attributeEq + 1).trim();
88
+ attributes[key] = attributeValue;
89
+ }
90
+ return {
91
+ name,
92
+ value,
93
+ attributes,
94
+ };
95
+ }
96
+ function shouldDeleteCookie(parsed) {
97
+ if (parsed.value === "") {
98
+ return true;
99
+ }
100
+ const maxAge = parsed.attributes["max-age"];
101
+ if (typeof maxAge === "string") {
102
+ const numeric = Number(maxAge);
103
+ if (Number.isFinite(numeric) && numeric <= 0) {
104
+ return true;
105
+ }
106
+ }
107
+ const expires = parsed.attributes.expires;
108
+ if (typeof expires === "string") {
109
+ const expiresAt = Date.parse(expires);
110
+ if (Number.isFinite(expiresAt) && expiresAt <= Date.now()) {
111
+ return true;
112
+ }
113
+ }
114
+ return false;
115
+ }
116
+ function normalizeSetCookieHeader(input) {
117
+ if (!input) {
118
+ return [];
119
+ }
120
+ if (Array.isArray(input)) {
121
+ return input.flatMap((entry) => splitCombinedSetCookieHeader(entry));
122
+ }
123
+ return splitCombinedSetCookieHeader(input);
124
+ }
125
+ class HttpCookieJar {
126
+ constructor(initialValues) {
127
+ this.values = new Map();
128
+ if (initialValues) {
129
+ for (const [name, value] of Object.entries(initialValues)) {
130
+ this.values.set(name, value);
131
+ }
132
+ }
133
+ }
134
+ get(name) {
135
+ return this.values.get(name);
136
+ }
137
+ set(name, value) {
138
+ this.values.set(name, value);
139
+ }
140
+ delete(name) {
141
+ this.values.delete(name);
142
+ }
143
+ clear() {
144
+ this.values.clear();
145
+ }
146
+ toCookieHeader() {
147
+ return Array.from(this.values.entries()).map(([name, value]) => `${name}=${value}`).join("; ");
148
+ }
149
+ applyToHeaders(headers = {}) {
150
+ const cookieHeader = this.toCookieHeader();
151
+ if (!cookieHeader) {
152
+ return { ...headers };
153
+ }
154
+ const existing = headers.Cookie ?? headers.cookie;
155
+ if (!existing || String(existing).trim().length === 0) {
156
+ return {
157
+ ...headers,
158
+ Cookie: cookieHeader,
159
+ };
160
+ }
161
+ return {
162
+ ...headers,
163
+ Cookie: `${String(existing)}; ${cookieHeader}`,
164
+ };
165
+ }
166
+ ingestSetCookieHeader(setCookieHeader) {
167
+ for (const line of normalizeSetCookieHeader(setCookieHeader)) {
168
+ const parsed = parseSetCookieLine(line);
169
+ if (!parsed) {
170
+ continue;
171
+ }
172
+ if (shouldDeleteCookie(parsed)) {
173
+ this.values.delete(parsed.name);
174
+ continue;
175
+ }
176
+ this.values.set(parsed.name, parsed.value);
177
+ }
178
+ }
179
+ ingestFromResponse(response) {
180
+ const headers = response.headers;
181
+ const getSetCookie = headers.getSetCookie;
182
+ if (typeof getSetCookie === "function") {
183
+ this.ingestSetCookieHeader(getSetCookie.call(headers));
184
+ return;
185
+ }
186
+ this.ingestSetCookieHeader(headers.get("set-cookie"));
187
+ }
188
+ }
189
+ exports.HttpCookieJar = HttpCookieJar;
190
+ function requireSessionFromCookie(options) {
191
+ const cookies = parseCookieHeader(options.cookieHeader);
192
+ const sessionId = cookies[options.cookieName];
193
+ if (!sessionId) {
194
+ return {
195
+ ok: false,
196
+ status: 401,
197
+ cookies,
198
+ markdown: options.unauthorizedMarkdown ?? (0, error_fragments_1.renderAuthRequiredFragment)({
199
+ message: options.unauthorizedMessage ?? "Login required: sign in before continuing.",
200
+ }),
201
+ };
202
+ }
203
+ const session = options.resolveSession(sessionId);
204
+ if (!session) {
205
+ return {
206
+ ok: false,
207
+ status: 401,
208
+ cookies,
209
+ markdown: options.unauthorizedMarkdown ?? (0, error_fragments_1.renderAuthRequiredFragment)({
210
+ message: options.unauthorizedMessage ?? "Session expired: sign in again to continue.",
211
+ }),
212
+ };
213
+ }
214
+ return {
215
+ ok: true,
216
+ cookies,
217
+ sessionId,
218
+ session,
219
+ };
220
+ }
@@ -2,26 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createBlockRegionMarkup = createBlockRegionMarkup;
4
4
  exports.replaceBlockRegionMarkup = replaceBlockRegionMarkup;
5
- function escapeHtml(value) {
6
- return value
7
- .replace(/&/g, "&amp;")
8
- .replace(/</g, "&lt;")
9
- .replace(/>/g, "&gt;")
10
- .replace(/"/g, "&quot;")
11
- .replace(/'/g, "&#39;");
12
- }
5
+ const core_1 = require("../core");
13
6
  function createRegionMarker(kind, blockName) {
14
- return `<!--mdsn:block-region:${kind}:${escapeHtml(blockName)}-->`;
7
+ return `<!--mdsn:block-region:${kind}:${(0, core_1.escapeHtml)(blockName)}-->`;
15
8
  }
16
9
  function createBlockRegionMarkup(blockName, innerHtml) {
17
- return `${createRegionMarker("start", blockName)}<section class="mdsn-block-region" data-mdsn-block-region="${escapeHtml(blockName)}">${innerHtml}</section>${createRegionMarker("end", blockName)}`;
10
+ return `${createRegionMarker("start", blockName)}<section class="mdsn-block-region" data-mdsn-block-region="${(0, core_1.escapeHtml)(blockName)}">${innerHtml}</section>${createRegionMarker("end", blockName)}`;
18
11
  }
19
- function replaceBlockRegionMarkup(html, blockName, replacementInnerHtml) {
20
- const escapedName = escapeHtml(blockName).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
21
- const pattern = new RegExp(`<!--mdsn:block-region:start:${escapedName}-->[\\s\\S]*?<!--mdsn:block-region:end:${escapedName}-->`, "g");
22
- if (pattern.test(html)) {
23
- return html.replace(pattern, createBlockRegionMarkup(blockName, replacementInnerHtml));
12
+ const blockRegionPatterns = new Map();
13
+ function getBlockRegionPattern(blockName) {
14
+ let pattern = blockRegionPatterns.get(blockName);
15
+ if (!pattern) {
16
+ const escapedName = (0, core_1.escapeRegExp)((0, core_1.escapeHtml)(blockName));
17
+ pattern = new RegExp(`<!--mdsn:block-region:start:${escapedName}-->[\\s\\S]*?<!--mdsn:block-region:end:${escapedName}-->`, "g");
18
+ blockRegionPatterns.set(blockName, pattern);
24
19
  }
25
- const legacyPattern = new RegExp(`<section class="mdsn-block-region" data-mdsn-block-region="${escapedName}">[\\s\\S]*?<\\/section>`, "g");
26
- return html.replace(legacyPattern, createBlockRegionMarkup(blockName, replacementInnerHtml));
20
+ return pattern;
21
+ }
22
+ function replaceBlockRegionMarkup(html, blockName, replacementInnerHtml) {
23
+ const pattern = getBlockRegionPattern(blockName);
24
+ return html.replace(pattern, createBlockRegionMarkup(blockName, replacementInnerHtml));
27
25
  }
@@ -1,9 +1,7 @@
1
1
  import type { BlockDefinition } from "../core/model/block";
2
- import type { SchemaDefinition } from "../core/model/schema";
3
2
  import { type CreatePageRenderOptions } from "./page-render";
4
3
  export interface ParsedBlockFragment {
5
4
  markdown: string;
6
- schemas: SchemaDefinition[];
7
5
  blocks: BlockDefinition[];
8
6
  }
9
7
  export declare function parseBlockFragment(raw: string): ParsedBlockFragment;
@@ -25,7 +25,6 @@ function parseBlockFragment(raw) {
25
25
  const parsed = (0, headless_1.parseFragment)(raw);
26
26
  return {
27
27
  markdown: parsed.containers.map((container) => container.markdown).join("\n\n").trim(),
28
- schemas: [],
29
28
  blocks: parsed.block ? [parsed.block] : [],
30
29
  };
31
30
  }
@@ -12,8 +12,6 @@ export type WebRuntimeMessages = {
12
12
  emptyImage: string;
13
13
  imageAltFallback: string;
14
14
  listItemFallback: string;
15
- jsonInputEmpty: string;
16
- jsonInputInvalid: string;
17
15
  missingInput: string;
18
16
  fillRequired: string;
19
17
  operationRunning: string;
package/dist/web/i18n.js CHANGED
@@ -17,8 +17,6 @@ exports.WEB_RUNTIME_MESSAGES = {
17
17
  emptyImage: "No image yet.",
18
18
  imageAltFallback: "image",
19
19
  listItemFallback: "item",
20
- jsonInputEmpty: "JSON input cannot be empty.",
21
- jsonInputInvalid: "Invalid JSON input.",
22
20
  missingInput: "Missing input: ",
23
21
  fillRequired: "Please fill: ",
24
22
  operationRunning: "Running: ",
@@ -43,8 +41,6 @@ exports.WEB_RUNTIME_MESSAGES = {
43
41
  emptyImage: "暂无图片。",
44
42
  imageAltFallback: "image",
45
43
  listItemFallback: "item",
46
- jsonInputEmpty: "JSON 输入不能为空。",
47
- jsonInputInvalid: "JSON 输入格式错误。",
48
44
  missingInput: "缺少输入:",
49
45
  fillRequired: "请先填写:",
50
46
  operationRunning: "执行中:",
@@ -1,7 +1,7 @@
1
1
  export { createRenderModel, renderDefaultHtmlDocument, renderPageHtml, } from "./public-render";
2
2
  export { getClientRuntimeScript } from "./public-client-runtime";
3
3
  export { createPageBootstrap } from "./page-bootstrap";
4
- export { parseBlockFragment } from "./fragment-render";
4
+ export { parseBlockFragment, renderBlockFragmentHtml } from "./fragment-render";
5
5
  export { createPageRenderModel } from "./page-render";
6
6
  export { parseFragment, parseMarkdown, parsePage, } from "./headless";
7
7
  export { createBlockRegionMarkup, replaceBlockRegionMarkup, } from "./block-runtime";
package/dist/web/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replaceBlockRegionMarkup = exports.createBlockRegionMarkup = exports.parsePage = exports.parseMarkdown = exports.parseFragment = exports.createPageRenderModel = exports.parseBlockFragment = exports.createPageBootstrap = exports.getClientRuntimeScript = exports.renderPageHtml = exports.renderDefaultHtmlDocument = exports.createRenderModel = void 0;
3
+ exports.replaceBlockRegionMarkup = exports.createBlockRegionMarkup = exports.parsePage = exports.parseMarkdown = exports.parseFragment = exports.createPageRenderModel = exports.renderBlockFragmentHtml = exports.parseBlockFragment = exports.createPageBootstrap = exports.getClientRuntimeScript = exports.renderPageHtml = exports.renderDefaultHtmlDocument = exports.createRenderModel = void 0;
4
4
  var public_render_1 = require("./public-render");
5
5
  Object.defineProperty(exports, "createRenderModel", { enumerable: true, get: function () { return public_render_1.createRenderModel; } });
6
6
  Object.defineProperty(exports, "renderDefaultHtmlDocument", { enumerable: true, get: function () { return public_render_1.renderDefaultHtmlDocument; } });
@@ -11,6 +11,7 @@ var page_bootstrap_1 = require("./page-bootstrap");
11
11
  Object.defineProperty(exports, "createPageBootstrap", { enumerable: true, get: function () { return page_bootstrap_1.createPageBootstrap; } });
12
12
  var fragment_render_1 = require("./fragment-render");
13
13
  Object.defineProperty(exports, "parseBlockFragment", { enumerable: true, get: function () { return fragment_render_1.parseBlockFragment; } });
14
+ Object.defineProperty(exports, "renderBlockFragmentHtml", { enumerable: true, get: function () { return fragment_render_1.renderBlockFragmentHtml; } });
14
15
  var page_render_1 = require("./page-render");
15
16
  Object.defineProperty(exports, "createPageRenderModel", { enumerable: true, get: function () { return page_render_1.createPageRenderModel; } });
16
17
  var headless_1 = require("./headless");
@@ -21,7 +21,6 @@ function createPageBootstrap(document) {
21
21
  version: "vNext",
22
22
  frontmatter: document.frontmatter,
23
23
  markdown: document.markdown,
24
- schemas: document.schemas,
25
24
  blocks: document.blocks,
26
25
  blockAnchors: document.blockAnchors,
27
26
  inputState,
@@ -1,15 +1,4 @@
1
- import type { ActionFailure, FragmentActionSuccess, RedirectActionSuccess } from "../core/action";
2
- type AppliedFragmentResult = {
3
- kind: "fragment";
1
+ export type PageActionTransportResult = {
4
2
  html: string;
5
3
  };
6
- type AppliedRedirectResult = {
7
- kind: "redirect";
8
- location: string;
9
- };
10
- export type AppliedPageActionResult = AppliedFragmentResult | AppliedRedirectResult;
11
- export type PageActionTransportResult = ActionFailure | RedirectActionSuccess | (FragmentActionSuccess & {
12
- html: string;
13
- });
14
- export declare function applyActionResultToPageHtml(currentHtml: string, blockName: string, result: PageActionTransportResult): AppliedPageActionResult;
15
- export {};
4
+ export declare function applyActionResultToPageHtml(currentHtml: string, blockName: string, result: PageActionTransportResult): string;
@@ -3,20 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.applyActionResultToPageHtml = applyActionResultToPageHtml;
4
4
  const block_runtime_1 = require("./block-runtime");
5
5
  function applyActionResultToPageHtml(currentHtml, blockName, result) {
6
- if (!result.ok) {
7
- return {
8
- kind: "fragment",
9
- html: currentHtml,
10
- };
11
- }
12
- if (result.kind === "redirect") {
13
- return {
14
- kind: "redirect",
15
- location: result.location,
16
- };
17
- }
18
- return {
19
- kind: "fragment",
20
- html: (0, block_runtime_1.replaceBlockRegionMarkup)(currentHtml, blockName, result.html),
21
- };
6
+ return (0, block_runtime_1.replaceBlockRegionMarkup)(currentHtml, blockName, result.html);
22
7
  }
@@ -1,2 +1 @@
1
1
  export declare function getPageClientRuntimeScript(): string;
2
- export declare function serializePageClientRuntimeScript(): string;