@mdsnai/sdk 0.1.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 (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/cli/args.d.ts +8 -0
  4. package/dist/cli/args.js +63 -0
  5. package/dist/cli/commands/build.d.ts +5 -0
  6. package/dist/cli/commands/build.js +19 -0
  7. package/dist/cli/commands/create.d.ts +2 -0
  8. package/dist/cli/commands/create.js +39 -0
  9. package/dist/cli/commands/dev.d.ts +10 -0
  10. package/dist/cli/commands/dev.js +13 -0
  11. package/dist/cli/commands/start.d.ts +9 -0
  12. package/dist/cli/commands/start.js +13 -0
  13. package/dist/cli/entry.d.ts +2 -0
  14. package/dist/cli/entry.js +8 -0
  15. package/dist/cli/index.d.ts +9 -0
  16. package/dist/cli/index.js +58 -0
  17. package/dist/core/action/execution.d.ts +4 -0
  18. package/dist/core/action/execution.js +57 -0
  19. package/dist/core/action/index.d.ts +2 -0
  20. package/dist/core/action/index.js +7 -0
  21. package/dist/core/action/types.d.ts +19 -0
  22. package/dist/core/action/types.js +2 -0
  23. package/dist/core/document/frontmatter.d.ts +5 -0
  24. package/dist/core/document/frontmatter.js +41 -0
  25. package/dist/core/document/markdown.d.ts +5 -0
  26. package/dist/core/document/markdown.js +83 -0
  27. package/dist/core/document/page-definition.d.ts +2 -0
  28. package/dist/core/document/page-definition.js +24 -0
  29. package/dist/core/index.d.ts +3 -0
  30. package/dist/core/index.js +5 -0
  31. package/dist/core/model/block.d.ts +30 -0
  32. package/dist/core/model/block.js +2 -0
  33. package/dist/core/model/document.d.ts +13 -0
  34. package/dist/core/model/document.js +2 -0
  35. package/dist/core/model/fragment.d.ts +4 -0
  36. package/dist/core/model/fragment.js +2 -0
  37. package/dist/core/model/index.d.ts +5 -0
  38. package/dist/core/model/index.js +2 -0
  39. package/dist/core/model/input.d.ts +11 -0
  40. package/dist/core/model/input.js +2 -0
  41. package/dist/core/model/schema.d.ts +4 -0
  42. package/dist/core/model/schema.js +2 -0
  43. package/dist/core/protocol/mdsn.d.ts +6 -0
  44. package/dist/core/protocol/mdsn.js +80 -0
  45. package/dist/core/protocol/statements.d.ts +12 -0
  46. package/dist/core/protocol/statements.js +140 -0
  47. package/dist/core/protocol/validation.d.ts +4 -0
  48. package/dist/core/protocol/validation.js +60 -0
  49. package/dist/framework/create-framework-app.d.ts +12 -0
  50. package/dist/framework/create-framework-app.js +11 -0
  51. package/dist/framework/hosted-app.d.ts +13 -0
  52. package/dist/framework/hosted-app.js +133 -0
  53. package/dist/framework/index.d.ts +4 -0
  54. package/dist/framework/index.js +7 -0
  55. package/dist/framework/site-app.d.ts +12 -0
  56. package/dist/framework/site-app.js +146 -0
  57. package/dist/index.d.ts +8 -0
  58. package/dist/index.js +18 -0
  59. package/dist/server/action-host.d.ts +3 -0
  60. package/dist/server/action-host.js +8 -0
  61. package/dist/server/action-runtime.d.ts +8 -0
  62. package/dist/server/action-runtime.js +81 -0
  63. package/dist/server/action.d.ts +41 -0
  64. package/dist/server/action.js +97 -0
  65. package/dist/server/build.d.ts +10 -0
  66. package/dist/server/build.js +166 -0
  67. package/dist/server/config.d.ts +56 -0
  68. package/dist/server/config.js +42 -0
  69. package/dist/server/dev.d.ts +48 -0
  70. package/dist/server/dev.js +90 -0
  71. package/dist/server/index.d.ts +8 -0
  72. package/dist/server/index.js +16 -0
  73. package/dist/server/init.d.ts +1 -0
  74. package/dist/server/init.js +176 -0
  75. package/dist/server/layout.d.ts +17 -0
  76. package/dist/server/layout.js +40 -0
  77. package/dist/server/markdown.d.ts +53 -0
  78. package/dist/server/markdown.js +76 -0
  79. package/dist/server/module-loader.d.ts +4 -0
  80. package/dist/server/module-loader.js +71 -0
  81. package/dist/server/negotiate.d.ts +3 -0
  82. package/dist/server/negotiate.js +55 -0
  83. package/dist/server/page-host.d.ts +21 -0
  84. package/dist/server/page-host.js +66 -0
  85. package/dist/server/page-links.d.ts +10 -0
  86. package/dist/server/page-links.js +80 -0
  87. package/dist/server/route-matcher.d.ts +6 -0
  88. package/dist/server/route-matcher.js +73 -0
  89. package/dist/server/routes.d.ts +6 -0
  90. package/dist/server/routes.js +73 -0
  91. package/dist/server/server.d.ts +27 -0
  92. package/dist/server/server.js +152 -0
  93. package/dist/server/site.d.ts +11 -0
  94. package/dist/server/site.js +59 -0
  95. package/dist/server/targets.d.ts +7 -0
  96. package/dist/server/targets.js +21 -0
  97. package/dist/web/block-runtime.d.ts +2 -0
  98. package/dist/web/block-runtime.js +27 -0
  99. package/dist/web/fragment-render.d.ts +10 -0
  100. package/dist/web/fragment-render.js +59 -0
  101. package/dist/web/headless.d.ts +95 -0
  102. package/dist/web/headless.js +370 -0
  103. package/dist/web/i18n.d.ts +31 -0
  104. package/dist/web/i18n.js +69 -0
  105. package/dist/web/index.d.ts +11 -0
  106. package/dist/web/index.js +22 -0
  107. package/dist/web/navigation.d.ts +3 -0
  108. package/dist/web/navigation.js +32 -0
  109. package/dist/web/page-bootstrap.d.ts +6 -0
  110. package/dist/web/page-bootstrap.js +29 -0
  111. package/dist/web/page-client-runtime.d.ts +15 -0
  112. package/dist/web/page-client-runtime.js +22 -0
  113. package/dist/web/page-client-script.d.ts +2 -0
  114. package/dist/web/page-client-script.js +567 -0
  115. package/dist/web/page-html.d.ts +8 -0
  116. package/dist/web/page-html.js +49 -0
  117. package/dist/web/page-render.d.ts +20 -0
  118. package/dist/web/page-render.js +92 -0
  119. package/dist/web/public-client-runtime.d.ts +1 -0
  120. package/dist/web/public-client-runtime.js +5 -0
  121. package/dist/web/public-render.d.ts +12 -0
  122. package/dist/web/public-render.js +18 -0
  123. package/dist/web/target-path.d.ts +1 -0
  124. package/dist/web/target-path.js +35 -0
  125. package/package.json +91 -0
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineConfig = defineConfig;
4
+ exports.resolveConfig = resolveConfig;
5
+ function defineConfig(config) {
6
+ return config;
7
+ }
8
+ function resolveConfig(config) {
9
+ const locales = (config.i18n?.locales ?? ["en"]).filter((item) => item.trim().length > 0);
10
+ const defaultLocale = config.i18n?.defaultLocale ?? locales[0] ?? "en";
11
+ const normalizedLocales = locales.length > 0 ? locales : [defaultLocale];
12
+ if (!normalizedLocales.includes(defaultLocale)) {
13
+ normalizedLocales.unshift(defaultLocale);
14
+ }
15
+ return {
16
+ site: {
17
+ title: config.site?.title,
18
+ description: config.site?.description,
19
+ baseUrl: config.site?.baseUrl,
20
+ },
21
+ server: {
22
+ port: config.server?.port ?? 3000,
23
+ },
24
+ dirs: {
25
+ pages: config.dirs?.pages ?? "pages",
26
+ server: config.dirs?.server ?? "server",
27
+ public: config.dirs?.public ?? "public",
28
+ layouts: config.dirs?.layouts ?? "layouts",
29
+ },
30
+ markdown: {
31
+ linkify: config.markdown?.linkify ?? true,
32
+ typographer: config.markdown?.typographer ?? false,
33
+ },
34
+ dev: {
35
+ openBrowser: config.dev?.openBrowser ?? true,
36
+ },
37
+ i18n: {
38
+ defaultLocale,
39
+ locales: normalizedLocales,
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,48 @@
1
+ export type DevChange = {
2
+ version: number;
3
+ path: string;
4
+ changedAt: number;
5
+ };
6
+ export type DevParseError = {
7
+ path: string;
8
+ message: string;
9
+ timestamp: number;
10
+ };
11
+ export type DevActionError = {
12
+ actionId: string;
13
+ message: string;
14
+ timestamp: number;
15
+ };
16
+ export type DevActionRun = {
17
+ actionId: string;
18
+ pathname: string;
19
+ inputSummary: string;
20
+ status: "ok" | "failure" | "error";
21
+ timestamp: number;
22
+ };
23
+ export type DevEvent = {
24
+ type: "file-change";
25
+ version: number;
26
+ path: string;
27
+ timestamp: number;
28
+ } | ({
29
+ type: "parse-error";
30
+ } & DevParseError) | ({
31
+ type: "action-error";
32
+ } & DevActionError) | ({
33
+ type: "action-run";
34
+ } & DevActionRun);
35
+ export type DevState = {
36
+ getVersion: () => number;
37
+ getLastChangedAt: () => number | null;
38
+ getRecentChanges: () => DevChange[];
39
+ getRecentActionRuns: () => DevActionRun[];
40
+ getRecentEvents: () => DevEvent[];
41
+ getLatestParseError: () => DevParseError | null;
42
+ getLatestActionError: () => DevActionError | null;
43
+ recordActionRun: (run: DevActionRun) => void;
44
+ setLatestParseError: (error: DevParseError | null) => void;
45
+ setLatestActionError: (error: DevActionError | null) => void;
46
+ bumpVersion: (changedPath?: string) => number;
47
+ };
48
+ export declare function createDevState(): DevState;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDevState = createDevState;
4
+ function createDevState() {
5
+ let version = 0;
6
+ let lastChangedAt = null;
7
+ const recentChanges = [];
8
+ const recentActionRuns = [];
9
+ const recentEvents = [];
10
+ let latestParseError = null;
11
+ let latestActionError = null;
12
+ function recordEvent(event) {
13
+ recentEvents.unshift(event);
14
+ if (recentEvents.length > 20) {
15
+ recentEvents.length = 20;
16
+ }
17
+ }
18
+ return {
19
+ getVersion() {
20
+ return version;
21
+ },
22
+ getLastChangedAt() {
23
+ return lastChangedAt;
24
+ },
25
+ getRecentChanges() {
26
+ return [...recentChanges];
27
+ },
28
+ getRecentActionRuns() {
29
+ return [...recentActionRuns];
30
+ },
31
+ getRecentEvents() {
32
+ return [...recentEvents];
33
+ },
34
+ getLatestParseError() {
35
+ return latestParseError;
36
+ },
37
+ getLatestActionError() {
38
+ return latestActionError;
39
+ },
40
+ recordActionRun(run) {
41
+ recentActionRuns.unshift(run);
42
+ if (recentActionRuns.length > 10) {
43
+ recentActionRuns.length = 10;
44
+ }
45
+ recordEvent({
46
+ type: "action-run",
47
+ ...run,
48
+ });
49
+ },
50
+ setLatestParseError(error) {
51
+ latestParseError = error;
52
+ if (error) {
53
+ recordEvent({
54
+ type: "parse-error",
55
+ ...error,
56
+ });
57
+ }
58
+ },
59
+ setLatestActionError(error) {
60
+ latestActionError = error;
61
+ if (error) {
62
+ recordEvent({
63
+ type: "action-error",
64
+ ...error,
65
+ });
66
+ }
67
+ },
68
+ bumpVersion(changedPath) {
69
+ version += 1;
70
+ lastChangedAt = Date.now();
71
+ if (changedPath) {
72
+ recentChanges.unshift({
73
+ version,
74
+ path: changedPath,
75
+ changedAt: lastChangedAt,
76
+ });
77
+ if (recentChanges.length > 10) {
78
+ recentChanges.length = 10;
79
+ }
80
+ recordEvent({
81
+ type: "file-change",
82
+ version,
83
+ path: changedPath,
84
+ timestamp: lastChangedAt,
85
+ });
86
+ }
87
+ return version;
88
+ },
89
+ };
90
+ }
@@ -0,0 +1,8 @@
1
+ export { defineAction, defineActions } from "./action";
2
+ export { renderMarkdownFragment, renderMarkdownValue, serializeBlock, } from "./markdown";
3
+ export { wantsHtml } from "./negotiate";
4
+ export { executeActionHandler } from "./action-host";
5
+ export { renderHostedPage } from "./page-host";
6
+ export type { ActionContext, ActionDefinition, ActionDefinitionMap, ActionResult, } from "./action";
7
+ export type { MarkdownImageValue, MarkdownTableValue, MarkdownValueType, RenderMarkdownFragmentOptions, SerializableBlock, SerializableInput, SerializableRead, SerializableRedirect, SerializableWrite, } from "./markdown";
8
+ export type { HostedPageResponse } from "./page-host";
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderHostedPage = exports.executeActionHandler = exports.wantsHtml = exports.serializeBlock = exports.renderMarkdownValue = exports.renderMarkdownFragment = exports.defineActions = exports.defineAction = void 0;
4
+ var action_1 = require("./action");
5
+ Object.defineProperty(exports, "defineAction", { enumerable: true, get: function () { return action_1.defineAction; } });
6
+ Object.defineProperty(exports, "defineActions", { enumerable: true, get: function () { return action_1.defineActions; } });
7
+ var markdown_1 = require("./markdown");
8
+ Object.defineProperty(exports, "renderMarkdownFragment", { enumerable: true, get: function () { return markdown_1.renderMarkdownFragment; } });
9
+ Object.defineProperty(exports, "renderMarkdownValue", { enumerable: true, get: function () { return markdown_1.renderMarkdownValue; } });
10
+ Object.defineProperty(exports, "serializeBlock", { enumerable: true, get: function () { return markdown_1.serializeBlock; } });
11
+ var negotiate_1 = require("./negotiate");
12
+ Object.defineProperty(exports, "wantsHtml", { enumerable: true, get: function () { return negotiate_1.wantsHtml; } });
13
+ var action_host_1 = require("./action-host");
14
+ Object.defineProperty(exports, "executeActionHandler", { enumerable: true, get: function () { return action_host_1.executeActionHandler; } });
15
+ var page_host_1 = require("./page-host");
16
+ Object.defineProperty(exports, "renderHostedPage", { enumerable: true, get: function () { return page_host_1.renderHostedPage; } });
@@ -0,0 +1 @@
1
+ export declare function createStarterSite(targetDir: string): void;
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createStarterSite = createStarterSite;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ function ensureEmptyDirectory(targetDir) {
10
+ if (!(0, node_fs_1.existsSync)(targetDir)) {
11
+ (0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
12
+ return;
13
+ }
14
+ if ((0, node_fs_1.readdirSync)(targetDir).length > 0) {
15
+ throw new Error(`Target directory is not empty: ${targetDir}`);
16
+ }
17
+ }
18
+ function createStarterSite(targetDir) {
19
+ ensureEmptyDirectory(targetDir);
20
+ (0, node_fs_1.mkdirSync)(node_path_1.default.join(targetDir, "pages"), { recursive: true });
21
+ (0, node_fs_1.mkdirSync)(node_path_1.default.join(targetDir, "server"), { recursive: true });
22
+ const packageName = node_path_1.default.basename(targetDir).toLowerCase().replace(/[^a-z0-9-]+/g, "-") || "mdsn-site";
23
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(targetDir, "package.json"), JSON.stringify({
24
+ name: packageName,
25
+ private: true,
26
+ scripts: {
27
+ dev: "mdsn dev",
28
+ build: "mdsn build",
29
+ start: "mdsn start",
30
+ },
31
+ dependencies: {
32
+ "@mdsnai/sdk": "^0.1.0",
33
+ },
34
+ }, null, 2) + "\n", "utf8");
35
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(targetDir, "pages", "index.md"), `---
36
+ id: guestbook
37
+ title: Guestbook
38
+ description: A runnable MDSN guestbook starter
39
+ ---
40
+
41
+ # Guestbook
42
+
43
+ Start with a working guestbook and reshape it into your own app.
44
+
45
+ - \`read\` / \`write\` both return Markdown fragments
46
+ - the Host only replaces the current \`guestbook\` block region
47
+ - page content stays static while the block keeps updating
48
+
49
+ <!-- mdsn:block guestbook -->
50
+
51
+ \`\`\`mdsn
52
+ block guestbook {
53
+ input nickname: text
54
+ input message!: text
55
+ read refresh: "/list"
56
+ write submit: "/post" (nickname, message)
57
+ }
58
+ \`\`\`
59
+ `, "utf8");
60
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(targetDir, "server", "actions.cjs"), `const {
61
+ defineAction,
62
+ defineActions,
63
+ renderMarkdownFragment,
64
+ renderMarkdownValue,
65
+ } = require("@mdsnai/sdk/server");
66
+
67
+ const guestbookBlock = {
68
+ name: "guestbook",
69
+ inputs: [
70
+ { name: "nickname", type: "text" },
71
+ { name: "message", type: "text", required: true },
72
+ ],
73
+ reads: [{ name: "refresh", target: "/list" }],
74
+ writes: [{ name: "submit", target: "/post", inputs: ["nickname", "message"] }],
75
+ };
76
+
77
+ function getGuestbookStore() {
78
+ if (!globalThis.__mdsnStarterGuestbookMessages) {
79
+ globalThis.__mdsnStarterGuestbookMessages = [];
80
+ }
81
+
82
+ return globalThis.__mdsnStarterGuestbookMessages;
83
+ }
84
+
85
+ function listGuestbookMessages() {
86
+ return getGuestbookStore().map((entry) => ({ ...entry }));
87
+ }
88
+
89
+ function renderGuestbookFragment(messages) {
90
+ return renderMarkdownFragment({
91
+ body: [
92
+ "## Messages",
93
+ messages.length > 0
94
+ ? renderMarkdownValue(
95
+ "list",
96
+ messages.map((entry) => \`**\${entry.nickname}**: \${entry.message}\`),
97
+ )
98
+ : "_No messages yet._",
99
+ ],
100
+ block: guestbookBlock,
101
+ });
102
+ }
103
+
104
+ function addGuestbookMessage(message) {
105
+ const store = getGuestbookStore();
106
+ const entry = {
107
+ id: \`\${Date.now()}-\${Math.random().toString(36).slice(2, 8)}\`,
108
+ nickname: message.nickname,
109
+ message: message.message,
110
+ createdAt: new Date().toISOString(),
111
+ };
112
+
113
+ store.unshift(entry);
114
+ if (store.length > 20) {
115
+ store.length = 20;
116
+ }
117
+
118
+ return { ...entry };
119
+ }
120
+
121
+ module.exports = defineActions({
122
+ list: defineAction({
123
+ async run() {
124
+ return renderGuestbookFragment(listGuestbookMessages());
125
+ },
126
+ }),
127
+ post: defineAction({
128
+ async run(ctx) {
129
+ const nickname = String(ctx.inputs.nickname ?? "").trim() || "Guest";
130
+ const message = String(ctx.inputs.message ?? "").trim();
131
+
132
+ if (!message) {
133
+ return {
134
+ ok: false,
135
+ errorCode: "EMPTY_MESSAGE",
136
+ fieldErrors: {
137
+ message: "Please enter a message.",
138
+ },
139
+ };
140
+ }
141
+
142
+ addGuestbookMessage({ nickname, message });
143
+ return renderGuestbookFragment(listGuestbookMessages());
144
+ },
145
+ }),
146
+ });
147
+ `, "utf8");
148
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(targetDir, "README.md"), `# ${packageName}
149
+
150
+ Starter: runnable guestbook
151
+
152
+ ## Commands
153
+
154
+ \`\`\`bash
155
+ npm run dev
156
+ npm run build
157
+ npm run start
158
+ \`\`\`
159
+
160
+ Open:
161
+
162
+ \`\`\`text
163
+ http://localhost:3000/
164
+ \`\`\`
165
+
166
+ Key files:
167
+
168
+ - \`pages/index.md\`
169
+ - \`server/actions.cjs\`
170
+
171
+ Optional next steps:
172
+
173
+ - Add \`mdsn.config.cjs\` when you need custom settings
174
+ - Add \`layouts/default.html\` when you want a custom layout
175
+ `, "utf8");
176
+ }
@@ -0,0 +1,17 @@
1
+ export type LayoutTemplateContext = {
2
+ title: string;
3
+ description: string;
4
+ content: string;
5
+ locale: string;
6
+ defaultLocale: string;
7
+ pathname?: string;
8
+ canonicalUrl?: string;
9
+ ogImageUrl?: string;
10
+ siteName?: string;
11
+ markdownAlternateUrl?: string;
12
+ hreflangLinks?: string;
13
+ posthogProjectApiKey?: string;
14
+ posthogHost?: string;
15
+ };
16
+ export declare function applyLayoutTemplate(template: string, context: LayoutTemplateContext): string;
17
+ export declare function resolveLocaleForRoutePath(routePath: string, locales: string[], defaultLocale: string): string;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyLayoutTemplate = applyLayoutTemplate;
4
+ exports.resolveLocaleForRoutePath = resolveLocaleForRoutePath;
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
+ }
13
+ function applyLayoutTemplate(template, context) {
14
+ const replacementByKey = {
15
+ title: escapeHtml(context.title),
16
+ description: escapeHtml(context.description),
17
+ content: context.content,
18
+ lang: escapeHtml(context.locale),
19
+ locale: escapeHtml(context.locale),
20
+ defaultLocale: escapeHtml(context.defaultLocale),
21
+ pathname: escapeHtml(context.pathname ?? ""),
22
+ canonical_url: escapeHtml(context.canonicalUrl ?? ""),
23
+ og_image_url: escapeHtml(context.ogImageUrl ?? ""),
24
+ site_name: escapeHtml(context.siteName ?? ""),
25
+ markdown_alternate_url: escapeHtml(context.markdownAlternateUrl ?? ""),
26
+ hreflang_links: context.hreflangLinks ?? "",
27
+ posthog_project_api_key: escapeHtml(context.posthogProjectApiKey ?? ""),
28
+ posthog_host: escapeHtml(context.posthogHost ?? ""),
29
+ };
30
+ return template.replace(/\{\{\s*([a-zA-Z_][\w-]*)\s*\}\}/g, (_match, key) => {
31
+ return replacementByKey[key] ?? "";
32
+ });
33
+ }
34
+ function resolveLocaleForRoutePath(routePath, locales, defaultLocale) {
35
+ const firstSegment = routePath.split("/").filter(Boolean)[0];
36
+ if (firstSegment && locales.includes(firstSegment)) {
37
+ return firstSegment;
38
+ }
39
+ return defaultLocale;
40
+ }
@@ -0,0 +1,53 @@
1
+ import type { InputType } from "../core";
2
+ export type MarkdownValueType = "text" | "list" | "table" | "json" | "image";
3
+ export type MarkdownTableValue = {
4
+ columns: string[];
5
+ rows: Array<Array<string | number | boolean | null | undefined>>;
6
+ };
7
+ export type MarkdownImageValue = string | {
8
+ src: string;
9
+ alt?: string;
10
+ title?: string;
11
+ };
12
+ export type MarkdownValue = string | string[] | Record<string, unknown> | MarkdownTableValue | MarkdownImageValue;
13
+ export type SerializableInput = {
14
+ name: string;
15
+ type: InputType;
16
+ required?: boolean;
17
+ secret?: boolean;
18
+ options?: string[];
19
+ schema?: string;
20
+ };
21
+ export type SerializableRead = {
22
+ name: string;
23
+ target: string;
24
+ inputs?: string[];
25
+ };
26
+ export type SerializableWrite = {
27
+ name: string;
28
+ target: string;
29
+ inputs?: string[];
30
+ };
31
+ export type SerializableRedirect = {
32
+ target: string;
33
+ };
34
+ export type SerializableBlock = {
35
+ name: string;
36
+ inputs?: SerializableInput[];
37
+ reads?: SerializableRead[];
38
+ writes?: SerializableWrite[];
39
+ redirects?: SerializableRedirect[];
40
+ };
41
+ export type RenderMarkdownFragmentOptions = {
42
+ body?: string | string[];
43
+ block?: SerializableBlock;
44
+ };
45
+ export declare function renderMarkdownValue(type: "text", value: string, options?: never): string;
46
+ export declare function renderMarkdownValue(type: "list", value: string[], options?: never): string;
47
+ export declare function renderMarkdownValue(type: "table", value: MarkdownTableValue, options?: never): string;
48
+ export declare function renderMarkdownValue(type: "json", value: Record<string, unknown>, options?: {
49
+ indent?: number;
50
+ }): string;
51
+ export declare function renderMarkdownValue(type: "image", value: MarkdownImageValue, options?: never): string;
52
+ export declare function serializeBlock(block: SerializableBlock): string;
53
+ export declare function renderMarkdownFragment(options: RenderMarkdownFragmentOptions): string;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderMarkdownValue = renderMarkdownValue;
4
+ exports.serializeBlock = serializeBlock;
5
+ exports.renderMarkdownFragment = renderMarkdownFragment;
6
+ function joinBody(body) {
7
+ if (!body) {
8
+ return "";
9
+ }
10
+ return Array.isArray(body)
11
+ ? body.filter((part) => part.trim().length > 0).join("\n\n")
12
+ : body.trim();
13
+ }
14
+ function escapeTableCell(value) {
15
+ return String(value ?? "").replace(/\|/g, "\\|").replace(/\n/g, "<br />");
16
+ }
17
+ function formatIdentifierList(inputs) {
18
+ return inputs && inputs.length > 0 ? ` (${inputs.join(", ")})` : "";
19
+ }
20
+ function renderMarkdownValue(type, value, options) {
21
+ switch (type) {
22
+ case "text":
23
+ return String(value);
24
+ case "list":
25
+ return value.map((item) => `- ${item}`).join("\n");
26
+ case "table": {
27
+ const table = value;
28
+ const header = `| ${table.columns.map(escapeTableCell).join(" | ")} |`;
29
+ const divider = `| ${table.columns.map(() => "---").join(" | ")} |`;
30
+ const rows = table.rows.map((row) => `| ${row.map(escapeTableCell).join(" | ")} |`);
31
+ return [header, divider, ...rows].join("\n");
32
+ }
33
+ case "json":
34
+ return `\`\`\`json\n${JSON.stringify(value, null, options?.indent ?? 2)}\n\`\`\``;
35
+ case "image": {
36
+ const image = value;
37
+ if (typeof image === "string") {
38
+ return `![](${image})`;
39
+ }
40
+ const title = image.title ? ` "${image.title.replace(/"/g, '\\"')}"` : "";
41
+ return `![${image.alt ?? ""}](${image.src}${title})`;
42
+ }
43
+ }
44
+ }
45
+ function serializeBlock(block) {
46
+ const lines = ["```mdsn", `block ${block.name} {`];
47
+ for (const input of block.inputs ?? []) {
48
+ const requiredMarker = input.required ? "!" : "";
49
+ const secretMarker = input.secret ? " secret" : "";
50
+ const optionsLiteral = input.options ? ` ${JSON.stringify(input.options)}` : "";
51
+ const schemaName = input.schema ? ` ${input.schema}` : "";
52
+ lines.push(` input ${input.name}${requiredMarker}: ${input.type}${secretMarker}${optionsLiteral}${schemaName}`);
53
+ }
54
+ for (const read of block.reads ?? []) {
55
+ lines.push(` read ${read.name}: "${read.target}"${formatIdentifierList(read.inputs)}`);
56
+ }
57
+ for (const write of block.writes ?? []) {
58
+ lines.push(` write ${write.name}: "${write.target}"${formatIdentifierList(write.inputs)}`);
59
+ }
60
+ for (const redirect of block.redirects ?? []) {
61
+ lines.push(` redirect "${redirect.target}"`);
62
+ }
63
+ lines.push("}", "```");
64
+ return lines.join("\n");
65
+ }
66
+ function renderMarkdownFragment(options) {
67
+ const parts = [];
68
+ const body = joinBody(options.body);
69
+ if (body) {
70
+ parts.push(body);
71
+ }
72
+ if (options.block) {
73
+ parts.push(serializeBlock(options.block));
74
+ }
75
+ return parts.join("\n\n").trimEnd() + "\n";
76
+ }
@@ -0,0 +1,4 @@
1
+ export type ImportModuleFromFileOptions = {
2
+ fresh?: boolean;
3
+ };
4
+ export declare function importModuleFromFile(filePath: string, options?: ImportModuleFromFileOptions): Promise<Record<string, unknown>>;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.importModuleFromFile = importModuleFromFile;
40
+ const node_module_1 = require("node:module");
41
+ const node_path_1 = __importDefault(require("node:path"));
42
+ const node_url_1 = require("node:url");
43
+ const requireFromCwd = (0, node_module_1.createRequire)(node_path_1.default.join(process.cwd(), "package.json"));
44
+ function toImportSpecifier(filePath, options) {
45
+ const url = (0, node_url_1.pathToFileURL)(filePath);
46
+ if (options.fresh) {
47
+ url.searchParams.set("ts", String(Date.now()));
48
+ }
49
+ return url.href;
50
+ }
51
+ function requireModuleFromFile(filePath, options) {
52
+ if (!options.fresh) {
53
+ return requireFromCwd(filePath);
54
+ }
55
+ const resolvedPath = requireFromCwd.resolve(filePath);
56
+ delete requireFromCwd.cache[resolvedPath];
57
+ return requireFromCwd(filePath);
58
+ }
59
+ async function importModuleFromFile(filePath, options = {}) {
60
+ try {
61
+ return await Promise.resolve(`${toImportSpecifier(filePath, options)}`).then(s => __importStar(require(s)));
62
+ }
63
+ catch (importError) {
64
+ try {
65
+ return requireModuleFromFile(filePath, options);
66
+ }
67
+ catch {
68
+ throw importError;
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,3 @@
1
+ export declare function wantsHtml(acceptHeader?: string): boolean;
2
+ export declare function wantsMarkdown(acceptHeader?: string): boolean;
3
+ export declare function isNotAcceptableRequest(acceptHeader?: string): boolean;