@skhema/cli 0.3.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.
Files changed (168) hide show
  1. package/README.md +163 -0
  2. package/bin/skhema.js +2 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +92 -0
  6. package/dist/commands/agent.d.ts +3 -0
  7. package/dist/commands/agent.d.ts.map +1 -0
  8. package/dist/commands/agent.js +154 -0
  9. package/dist/commands/api.d.ts +19 -0
  10. package/dist/commands/api.d.ts.map +1 -0
  11. package/dist/commands/api.js +97 -0
  12. package/dist/commands/auth.d.ts +3 -0
  13. package/dist/commands/auth.d.ts.map +1 -0
  14. package/dist/commands/auth.js +403 -0
  15. package/dist/commands/component.d.ts +3 -0
  16. package/dist/commands/component.d.ts.map +1 -0
  17. package/dist/commands/component.js +221 -0
  18. package/dist/commands/contribute.d.ts +3 -0
  19. package/dist/commands/contribute.d.ts.map +1 -0
  20. package/dist/commands/contribute.js +318 -0
  21. package/dist/commands/element.d.ts +7 -0
  22. package/dist/commands/element.d.ts.map +1 -0
  23. package/dist/commands/element.js +167 -0
  24. package/dist/commands/export.d.ts +9 -0
  25. package/dist/commands/export.d.ts.map +1 -0
  26. package/dist/commands/export.js +42 -0
  27. package/dist/commands/init.d.ts +49 -0
  28. package/dist/commands/init.d.ts.map +1 -0
  29. package/dist/commands/init.js +275 -0
  30. package/dist/commands/link.d.ts +8 -0
  31. package/dist/commands/link.d.ts.map +1 -0
  32. package/dist/commands/link.js +70 -0
  33. package/dist/commands/resource.d.ts +3 -0
  34. package/dist/commands/resource.d.ts.map +1 -0
  35. package/dist/commands/resource.js +88 -0
  36. package/dist/commands/skills.d.ts +3 -0
  37. package/dist/commands/skills.d.ts.map +1 -0
  38. package/dist/commands/skills.js +113 -0
  39. package/dist/commands/strategy.d.ts +3 -0
  40. package/dist/commands/strategy.d.ts.map +1 -0
  41. package/dist/commands/strategy.js +143 -0
  42. package/dist/commands/webhook.d.ts +3 -0
  43. package/dist/commands/webhook.d.ts.map +1 -0
  44. package/dist/commands/webhook.js +77 -0
  45. package/dist/commands/workspace.d.ts +8 -0
  46. package/dist/commands/workspace.d.ts.map +1 -0
  47. package/dist/commands/workspace.js +219 -0
  48. package/dist/index.d.ts +2 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +1 -0
  51. package/dist/lib/api/client.d.ts +27 -0
  52. package/dist/lib/api/client.d.ts.map +1 -0
  53. package/dist/lib/api/client.js +71 -0
  54. package/dist/lib/api/command-helpers.d.ts +27 -0
  55. package/dist/lib/api/command-helpers.d.ts.map +1 -0
  56. package/dist/lib/api/command-helpers.js +77 -0
  57. package/dist/lib/api/credential-context.d.ts +3 -0
  58. package/dist/lib/api/credential-context.d.ts.map +1 -0
  59. package/dist/lib/api/credential-context.js +13 -0
  60. package/dist/lib/api/export-cli.d.ts +14 -0
  61. package/dist/lib/api/export-cli.d.ts.map +1 -0
  62. package/dist/lib/api/export-cli.js +26 -0
  63. package/dist/lib/api/formats.d.ts +12 -0
  64. package/dist/lib/api/formats.d.ts.map +1 -0
  65. package/dist/lib/api/formats.js +18 -0
  66. package/dist/lib/api/passthrough.d.ts +34 -0
  67. package/dist/lib/api/passthrough.d.ts.map +1 -0
  68. package/dist/lib/api/passthrough.js +106 -0
  69. package/dist/lib/api/payload.d.ts +16 -0
  70. package/dist/lib/api/payload.d.ts.map +1 -0
  71. package/dist/lib/api/payload.js +53 -0
  72. package/dist/lib/api/run-command.d.ts +69 -0
  73. package/dist/lib/api/run-command.d.ts.map +1 -0
  74. package/dist/lib/api/run-command.js +127 -0
  75. package/dist/lib/api/scope.d.ts +8 -0
  76. package/dist/lib/api/scope.d.ts.map +1 -0
  77. package/dist/lib/api/scope.js +16 -0
  78. package/dist/lib/api/transfer.d.ts +57 -0
  79. package/dist/lib/api/transfer.d.ts.map +1 -0
  80. package/dist/lib/api/transfer.js +153 -0
  81. package/dist/lib/auth/api-key-admin.d.ts +39 -0
  82. package/dist/lib/auth/api-key-admin.d.ts.map +1 -0
  83. package/dist/lib/auth/api-key-admin.js +66 -0
  84. package/dist/lib/auth/api-key-store.d.ts +8 -0
  85. package/dist/lib/auth/api-key-store.d.ts.map +1 -0
  86. package/dist/lib/auth/api-key-store.js +109 -0
  87. package/dist/lib/auth/device-flow.d.ts +4 -0
  88. package/dist/lib/auth/device-flow.d.ts.map +1 -0
  89. package/dist/lib/auth/device-flow.js +109 -0
  90. package/dist/lib/auth/entitlements.d.ts +16 -0
  91. package/dist/lib/auth/entitlements.d.ts.map +1 -0
  92. package/dist/lib/auth/entitlements.js +89 -0
  93. package/dist/lib/auth/localhost-flow.d.ts +4 -0
  94. package/dist/lib/auth/localhost-flow.d.ts.map +1 -0
  95. package/dist/lib/auth/localhost-flow.js +134 -0
  96. package/dist/lib/auth/oauth-client.d.ts +33 -0
  97. package/dist/lib/auth/oauth-client.d.ts.map +1 -0
  98. package/dist/lib/auth/oauth-client.js +96 -0
  99. package/dist/lib/auth/token-store.d.ts +6 -0
  100. package/dist/lib/auth/token-store.d.ts.map +1 -0
  101. package/dist/lib/auth/token-store.js +136 -0
  102. package/dist/lib/auth/types.d.ts +49 -0
  103. package/dist/lib/auth/types.d.ts.map +1 -0
  104. package/dist/lib/auth/types.js +1 -0
  105. package/dist/lib/banner.d.ts +2 -0
  106. package/dist/lib/banner.d.ts.map +1 -0
  107. package/dist/lib/banner.js +82 -0
  108. package/dist/lib/config-store.d.ts +23 -0
  109. package/dist/lib/config-store.d.ts.map +1 -0
  110. package/dist/lib/config-store.js +53 -0
  111. package/dist/lib/config.d.ts +20 -0
  112. package/dist/lib/config.d.ts.map +1 -0
  113. package/dist/lib/config.js +33 -0
  114. package/dist/lib/contribute/author-resolver.d.ts +13 -0
  115. package/dist/lib/contribute/author-resolver.d.ts.map +1 -0
  116. package/dist/lib/contribute/author-resolver.js +63 -0
  117. package/dist/lib/contribute/embed-generator.d.ts +4 -0
  118. package/dist/lib/contribute/embed-generator.d.ts.map +1 -0
  119. package/dist/lib/contribute/embed-generator.js +108 -0
  120. package/dist/lib/contribute/link-generator.d.ts +11 -0
  121. package/dist/lib/contribute/link-generator.d.ts.map +1 -0
  122. package/dist/lib/contribute/link-generator.js +119 -0
  123. package/dist/lib/contribute/method-schema.d.ts +239 -0
  124. package/dist/lib/contribute/method-schema.d.ts.map +1 -0
  125. package/dist/lib/contribute/method-schema.js +172 -0
  126. package/dist/lib/contribute/profile-resolver.d.ts +2 -0
  127. package/dist/lib/contribute/profile-resolver.d.ts.map +1 -0
  128. package/dist/lib/contribute/profile-resolver.js +25 -0
  129. package/dist/lib/contribute/types.d.ts +91 -0
  130. package/dist/lib/contribute/types.d.ts.map +1 -0
  131. package/dist/lib/contribute/types.js +1 -0
  132. package/dist/lib/mcp/registrar.d.ts +26 -0
  133. package/dist/lib/mcp/registrar.d.ts.map +1 -0
  134. package/dist/lib/mcp/registrar.js +69 -0
  135. package/dist/lib/mcp/registry.d.ts +54 -0
  136. package/dist/lib/mcp/registry.d.ts.map +1 -0
  137. package/dist/lib/mcp/registry.js +105 -0
  138. package/dist/lib/open.d.ts +2 -0
  139. package/dist/lib/open.d.ts.map +1 -0
  140. package/dist/lib/open.js +24 -0
  141. package/dist/lib/output.d.ts +25 -0
  142. package/dist/lib/output.d.ts.map +1 -0
  143. package/dist/lib/output.js +74 -0
  144. package/dist/lib/skills/installer.d.ts +4 -0
  145. package/dist/lib/skills/installer.d.ts.map +1 -0
  146. package/dist/lib/skills/installer.js +100 -0
  147. package/dist/lib/skills/lock.d.ts +4 -0
  148. package/dist/lib/skills/lock.d.ts.map +1 -0
  149. package/dist/lib/skills/lock.js +28 -0
  150. package/dist/lib/skills/platform-detect.d.ts +4 -0
  151. package/dist/lib/skills/platform-detect.d.ts.map +1 -0
  152. package/dist/lib/skills/platform-detect.js +89 -0
  153. package/dist/lib/skills/types.d.ts +29 -0
  154. package/dist/lib/skills/types.d.ts.map +1 -0
  155. package/dist/lib/skills/types.js +1 -0
  156. package/dist/postinstall.d.ts +2 -0
  157. package/dist/postinstall.d.ts.map +1 -0
  158. package/dist/postinstall.js +11 -0
  159. package/package.json +67 -0
  160. package/skills/.manifest.json +15 -0
  161. package/skills/skhema-challenge-framing/SKILL.md +28 -0
  162. package/skills/skhema-coherence-check/SKILL.md +28 -0
  163. package/skills/skhema-element-decomposition/SKILL.md +28 -0
  164. package/skills/skhema-element-writer/SKILL.md +20 -0
  165. package/skills/skhema-judgment-audit/SKILL.md +28 -0
  166. package/skills/skhema-semantic-sharpening/SKILL.md +28 -0
  167. package/skills/skhema-strategy-advisor/SKILL.md +20 -0
  168. package/skills/skhema-workspace-navigator/SKILL.md +20 -0
@@ -0,0 +1,20 @@
1
+ export declare const CLI_CLIENT_ID = "skhema-cli-native";
2
+ export declare const AUTH_BASE_URL: string;
3
+ export declare const OAUTH_SCOPES = "openid profile email";
4
+ export declare const DEVICE_POLL_INTERVAL = 5;
5
+ export declare const DEVICE_CODE_EXPIRY = 900;
6
+ export declare const LOGIN_TIMEOUT = 300000;
7
+ export declare const KEYCHAIN_SERVICE = "com.skhema.cli";
8
+ export declare const KEYCHAIN_ACCOUNT = "default";
9
+ export declare const KEYCHAIN_ACCOUNT_API_KEY = "api-key";
10
+ export declare const CREDENTIALS_DIR = ".skhema";
11
+ export declare const CREDENTIALS_FILE = "credentials.json";
12
+ export declare const API_KEY_FILE = "api-key.json";
13
+ export declare const CONFIG_FILE = "config.json";
14
+ export declare const SKILL_LOCK_FILE = ".skhema-skill-lock.json";
15
+ export declare const API_BASE_URL: string;
16
+ export declare const API_KEY_ENV_VAR = "SKHEMA_API_KEY";
17
+ export declare const MCP_SERVER_URL: string;
18
+ export declare const SUPABASE_URL: string;
19
+ export declare const SUPABASE_PUBLISHABLE_KEY: string;
20
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,sBAAsB,CAAA;AAChD,eAAO,MAAM,aAAa,QACgC,CAAA;AAC1D,eAAO,MAAM,YAAY,yBAAyB,CAAA;AAClD,eAAO,MAAM,oBAAoB,IAAI,CAAA;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAA;AACrC,eAAO,MAAM,aAAa,SAAU,CAAA;AACpC,eAAO,MAAM,gBAAgB,mBAAmB,CAAA;AAChD,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAGzC,eAAO,MAAM,wBAAwB,YAAY,CAAA;AACjD,eAAO,MAAM,eAAe,YAAY,CAAA;AACxC,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAClD,eAAO,MAAM,YAAY,iBAAiB,CAAA;AAC1C,eAAO,MAAM,WAAW,gBAAgB,CAAA;AACxC,eAAO,MAAM,eAAe,4BAA4B,CAAA;AAGxD,eAAO,MAAM,YAAY,QAC+B,CAAA;AAGxD,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAO/C,eAAO,MAAM,cAAc,QACwC,CAAA;AAMnE,eAAO,MAAM,YAAY,QACsD,CAAA;AAC/E,eAAO,MAAM,wBAAwB,QAEa,CAAA"}
@@ -0,0 +1,33 @@
1
+ export const CLI_CLIENT_ID = 'skhema-cli-native';
2
+ export const AUTH_BASE_URL = process.env.SKHEMA_AUTH_URL ?? 'https://auth.skhema.com';
3
+ export const OAUTH_SCOPES = 'openid profile email';
4
+ export const DEVICE_POLL_INTERVAL = 5; // seconds
5
+ export const DEVICE_CODE_EXPIRY = 900; // seconds (15 minutes)
6
+ export const LOGIN_TIMEOUT = 300000; // 5 minutes in ms
7
+ export const KEYCHAIN_SERVICE = 'com.skhema.cli';
8
+ export const KEYCHAIN_ACCOUNT = 'default';
9
+ // Distinct keychain account for the stored API key, so it lives alongside — but
10
+ // never overwrites — the OAuth session credential.
11
+ export const KEYCHAIN_ACCOUNT_API_KEY = 'api-key';
12
+ export const CREDENTIALS_DIR = '.skhema';
13
+ export const CREDENTIALS_FILE = 'credentials.json';
14
+ export const API_KEY_FILE = 'api-key.json';
15
+ export const CONFIG_FILE = 'config.json';
16
+ export const SKILL_LOCK_FILE = '.skhema-skill-lock.json';
17
+ // Public API gateway origin. Override via env for staging/preview environments.
18
+ export const API_BASE_URL = process.env.SKHEMA_API_URL ?? 'https://api.skhema.com';
19
+ // Environment variable an unattended CI/agent run sets to supply an API key.
20
+ export const API_KEY_ENV_VAR = 'SKHEMA_API_KEY';
21
+ // Public Skhema MCP server endpoint (Streamable HTTP transport). This is the
22
+ // protocol endpoint AI clients connect to — distinct from mcp.skhema.com (the
23
+ // management dashboard). Auth is per-client browser OAuth on first use, so the
24
+ // CLI only registers the URL; it never injects a credential here.
25
+ // Override via env for staging/preview environments.
26
+ export const MCP_SERVER_URL = process.env.SKHEMA_MCP_URL ?? 'https://mcp-server.skhema.com/mcp';
27
+ // Supabase project configuration.
28
+ // Publishable keys are safe to embed in client-side code (they are the new
29
+ // replacement for the legacy anon key and rely on RLS + server-side auth
30
+ // checks for security). Override via env for staging/preview environments.
31
+ export const SUPABASE_URL = process.env.SKHEMA_SUPABASE_URL ?? 'https://uiybgpcjjrdqmdbarqlx.supabase.co';
32
+ export const SUPABASE_PUBLISHABLE_KEY = process.env.SKHEMA_SUPABASE_PUBLISHABLE_KEY ??
33
+ 'sb_publishable_G9uXii5AYDLK6vUpyaqy3A_-NmdwQF1';
@@ -0,0 +1,13 @@
1
+ export interface ResolvedAuthor {
2
+ authorName: string;
3
+ authorSlug?: string;
4
+ }
5
+ /**
6
+ * Resolve author from sysauthElementAuthor for a published element.
7
+ */
8
+ export declare function resolveElementAuthor(elementId: string, accessToken: string): Promise<ResolvedAuthor | null>;
9
+ /**
10
+ * Resolve component-level author from the first element in the component.
11
+ */
12
+ export declare function resolveComponentAuthor(componentId: string, accessToken: string): Promise<ResolvedAuthor | null>;
13
+ //# sourceMappingURL=author-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"author-resolver.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/author-resolver.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAqCD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAEhC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA4BhC"}
@@ -0,0 +1,63 @@
1
+ import { SUPABASE_PUBLISHABLE_KEY, SUPABASE_URL } from '../config.js';
2
+ async function fetchAuthorForElementId(elementId, accessToken) {
3
+ const url = new URL(`${SUPABASE_URL}/rest/v1/sysauthElementAuthor`);
4
+ url.searchParams.set('elementId', `eq.${elementId}`);
5
+ url.searchParams.set('select', 'authorName,contributorSlug');
6
+ try {
7
+ const response = await fetch(url.toString(), {
8
+ headers: {
9
+ Authorization: `Bearer ${accessToken}`,
10
+ apikey: SUPABASE_PUBLISHABLE_KEY,
11
+ Accept: 'application/json',
12
+ },
13
+ });
14
+ if (!response.ok)
15
+ return null;
16
+ const rows = (await response.json());
17
+ const row = rows[0];
18
+ if (!row?.authorName)
19
+ return null;
20
+ return {
21
+ authorName: row.authorName,
22
+ authorSlug: row.contributorSlug ?? undefined,
23
+ };
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ /**
30
+ * Resolve author from sysauthElementAuthor for a published element.
31
+ */
32
+ export async function resolveElementAuthor(elementId, accessToken) {
33
+ return fetchAuthorForElementId(elementId, accessToken);
34
+ }
35
+ /**
36
+ * Resolve component-level author from the first element in the component.
37
+ */
38
+ export async function resolveComponentAuthor(componentId, accessToken) {
39
+ const junctionUrl = new URL(`${SUPABASE_URL}/rest/v1/sysauthComponentElement`);
40
+ junctionUrl.searchParams.set('componentId', `eq.${componentId}`);
41
+ junctionUrl.searchParams.set('select', 'elementId');
42
+ junctionUrl.searchParams.set('order', 'position.asc');
43
+ junctionUrl.searchParams.set('limit', '1');
44
+ try {
45
+ const junctionResponse = await fetch(junctionUrl.toString(), {
46
+ headers: {
47
+ Authorization: `Bearer ${accessToken}`,
48
+ apikey: SUPABASE_PUBLISHABLE_KEY,
49
+ Accept: 'application/json',
50
+ },
51
+ });
52
+ if (!junctionResponse.ok)
53
+ return null;
54
+ const junctionRows = (await junctionResponse.json());
55
+ const firstElementId = junctionRows[0]?.elementId;
56
+ if (!firstElementId)
57
+ return null;
58
+ return fetchAuthorForElementId(firstElementId, accessToken);
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
@@ -0,0 +1,4 @@
1
+ import type { GenerateComponentEmbedOptions, GenerateComponentEmbedResult, GenerateEmbedOptions, GenerateEmbedResult } from './types.js';
2
+ export declare function generateEmbed(options: GenerateEmbedOptions): GenerateEmbedResult;
3
+ export declare function generateComponentEmbed(options: GenerateComponentEmbedOptions): GenerateComponentEmbedResult;
4
+ //# sourceMappingURL=embed-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/embed-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,6BAA6B,EAC7B,4BAA4B,EAC5B,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAInB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CA8DrB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,4BAA4B,CA0G9B"}
@@ -0,0 +1,108 @@
1
+ import { COMPONENT_TYPES, ELEMENT_TYPES, SKHEMA_MAPPING, } from './method-schema.js';
2
+ const CDN_URL = 'https://unpkg.com/@skhema/embed';
3
+ export function generateEmbed(options) {
4
+ const { elementType, contributorId, authorName, authorSlug, content, theme, trackAnalytics, sourceUrl, } = options;
5
+ if (!contributorId?.trim()) {
6
+ throw new Error('contributorId is required');
7
+ }
8
+ if (!content?.trim()) {
9
+ throw new Error('content is required');
10
+ }
11
+ const validTypes = Object.values(ELEMENT_TYPES).map((t) => t.value);
12
+ if (!validTypes.includes(elementType)) {
13
+ throw new Error(`Invalid element type "${elementType}". Valid types: ${validTypes.join(', ')}`);
14
+ }
15
+ const attributes = {
16
+ 'element-type': elementType,
17
+ 'contributor-id': contributorId,
18
+ };
19
+ if (authorName) {
20
+ attributes['author-name'] = authorName;
21
+ }
22
+ if (authorSlug) {
23
+ attributes['author-slug'] = authorSlug;
24
+ }
25
+ if (theme && theme !== 'auto') {
26
+ attributes['theme'] = theme;
27
+ }
28
+ if (trackAnalytics === false) {
29
+ attributes['track-analytics'] = 'false';
30
+ }
31
+ if (sourceUrl) {
32
+ attributes['source-url'] = sourceUrl;
33
+ }
34
+ const attrLines = Object.entries(attributes)
35
+ .map(([key, value]) => ` ${key}="${value}"`)
36
+ .join('\n');
37
+ const snippet = `<script src="${CDN_URL}"></script>
38
+ <skhema-element
39
+ ${attrLines}>
40
+ ${content}
41
+ </skhema-element>`;
42
+ return { snippet, cdnUrl: CDN_URL, attributes };
43
+ }
44
+ export function generateComponentEmbed(options) {
45
+ const { componentType, contributorId, authorName, authorSlug, elements, title, theme, trackAnalytics, sourceUrl, } = options;
46
+ if (!contributorId?.trim()) {
47
+ throw new Error('contributorId is required');
48
+ }
49
+ if (!elements || elements.length === 0) {
50
+ throw new Error('At least one element is required');
51
+ }
52
+ const validComponentTypes = Object.values(COMPONENT_TYPES).map((t) => t.value);
53
+ if (!validComponentTypes.includes(componentType)) {
54
+ throw new Error(`Invalid component type "${componentType}". Valid types: ${validComponentTypes.join(', ')}`);
55
+ }
56
+ const validElementTypes = SKHEMA_MAPPING.elementFlow[componentType];
57
+ if (validElementTypes) {
58
+ const validValues = validElementTypes.map((t) => t.value);
59
+ for (const element of elements) {
60
+ if (!validValues.includes(element.elementType)) {
61
+ throw new Error(`Invalid element type "${element.elementType}" for component "${componentType}". Valid types: ${validValues.join(', ')}`);
62
+ }
63
+ if (!element.content?.trim()) {
64
+ throw new Error(`Element of type "${element.elementType}" has empty content`);
65
+ }
66
+ }
67
+ }
68
+ const attributes = {
69
+ 'component-type': componentType,
70
+ 'contributor-id': contributorId,
71
+ };
72
+ if (authorName) {
73
+ attributes['author-name'] = authorName;
74
+ }
75
+ if (authorSlug) {
76
+ attributes['author-slug'] = authorSlug;
77
+ }
78
+ if (title) {
79
+ attributes['title'] = title;
80
+ }
81
+ if (theme && theme !== 'auto') {
82
+ attributes['theme'] = theme;
83
+ }
84
+ if (trackAnalytics === false) {
85
+ attributes['track-analytics'] = 'false';
86
+ }
87
+ if (sourceUrl) {
88
+ attributes['source-url'] = sourceUrl;
89
+ }
90
+ const componentAttrLines = Object.entries(attributes)
91
+ .map(([key, value]) => ` ${key}="${value}"`)
92
+ .join('\n');
93
+ const elementSnippets = elements
94
+ .map((element) => {
95
+ const elementAttrLines = [
96
+ ` element-type="${element.elementType}"`,
97
+ ` contributor-id="${contributorId}"`,
98
+ ].join('\n');
99
+ return ` <skhema-element\n${elementAttrLines}>\n ${element.content}\n </skhema-element>`;
100
+ })
101
+ .join('\n');
102
+ const snippet = `<script src="${CDN_URL}"></script>
103
+ <skhema-component
104
+ ${componentAttrLines}>
105
+ ${elementSnippets}
106
+ </skhema-component>`;
107
+ return { snippet, cdnUrl: CDN_URL, attributes, elementCount: elements.length };
108
+ }
@@ -0,0 +1,11 @@
1
+ import type { GenerateComponentLinkOptions, GenerateComponentLinkResult, GenerateLinkOptions, GenerateLinkResult, PublishComponentShareLinkOptions, PublishComponentShareLinkResult, PublishShareLinkOptions, PublishShareLinkResult } from './types.js';
2
+ export declare function generateContentHash(content: string): string;
3
+ export declare function generateSaveElementLink(options: GenerateLinkOptions): GenerateLinkResult;
4
+ export declare function generateComponentHash(elements: Array<{
5
+ elementType: string;
6
+ content: string;
7
+ }>): string;
8
+ export declare function generateSaveComponentLink(options: GenerateComponentLinkOptions): GenerateComponentLinkResult;
9
+ export declare function publishAndGenerateElementShareLink(options: PublishShareLinkOptions): Promise<PublishShareLinkResult>;
10
+ export declare function publishAndGenerateComponentShareLink(options: PublishComponentShareLinkOptions): Promise<PublishComponentShareLinkResult>;
11
+ //# sourceMappingURL=link-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/link-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,mBAAmB,EACnB,kBAAkB,EAClB,gCAAgC,EAChC,+BAA+B,EAC/B,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AAInB,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAmBpB;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACxD,MAAM,CASR;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,4BAA4B,GACpC,2BAA2B,CAyB7B;AAED,wBAAsB,kCAAkC,CACtD,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CA6BjC;AAED,wBAAsB,oCAAoC,CACxD,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,+BAA+B,CAAC,CAgC1C"}
@@ -0,0 +1,119 @@
1
+ import { SUPABASE_PUBLISHABLE_KEY, SUPABASE_URL } from '../config.js';
2
+ const EMBED_MANAGE_URL = `${SUPABASE_URL}/functions/v1/embed-manage`;
3
+ export function generateContentHash(content) {
4
+ let hash = 0;
5
+ const cleanContent = content.trim().substring(0, 200);
6
+ for (let i = 0; i < cleanContent.length; i++) {
7
+ const char = cleanContent.charCodeAt(i);
8
+ hash = (hash << 5) - hash + char;
9
+ hash = hash & hash;
10
+ }
11
+ return Math.abs(hash).toString(36).substring(0, 12);
12
+ }
13
+ export function generateSaveElementLink(options) {
14
+ const contentHash = generateContentHash(options.content);
15
+ const sourceUrl = options.sourceUrl
16
+ ? encodeURIComponent(options.sourceUrl)
17
+ : '';
18
+ const timestamp = Date.now();
19
+ const params = new URLSearchParams({
20
+ source: sourceUrl,
21
+ t: timestamp.toString(),
22
+ utm_source: options.utmSource || 'web_component',
23
+ utm_medium: options.utmMedium || 'embedded',
24
+ utm_campaign: options.utmCampaign || options.elementType,
25
+ utm_content: options.contributorId,
26
+ });
27
+ const url = `https://app.skhema.com/save?type=contributor&contributor_id=${options.contributorId}&element_type=${options.elementType}&content_hash=${contentHash}&${params.toString()}`;
28
+ return { url, contentHash };
29
+ }
30
+ export function generateComponentHash(elements) {
31
+ const sorted = [...elements].sort((a, b) => {
32
+ const typeCompare = a.elementType.localeCompare(b.elementType);
33
+ if (typeCompare !== 0)
34
+ return typeCompare;
35
+ return a.content.localeCompare(b.content);
36
+ });
37
+ const combined = sorted.map((e) => `${e.elementType}:${e.content}`).join('|');
38
+ return generateContentHash(combined);
39
+ }
40
+ export function generateSaveComponentLink(options) {
41
+ const componentHash = generateComponentHash(options.elements);
42
+ const sourceUrl = options.sourceUrl
43
+ ? encodeURIComponent(options.sourceUrl)
44
+ : '';
45
+ const timestamp = Date.now();
46
+ const params = new URLSearchParams({
47
+ source: sourceUrl,
48
+ t: timestamp.toString(),
49
+ utm_source: options.utmSource || 'web_component',
50
+ utm_medium: options.utmMedium || 'embedded',
51
+ utm_campaign: options.utmCampaign || options.componentType,
52
+ utm_content: options.contributorId,
53
+ });
54
+ let url = `https://app.skhema.com/save?type=component&component_type=${options.componentType}&component_hash=${componentHash}&contributor_id=${options.contributorId}`;
55
+ if (options.title) {
56
+ url += `&title=${encodeURIComponent(options.title)}`;
57
+ }
58
+ url += `&${params.toString()}`;
59
+ return { url, componentHash };
60
+ }
61
+ export async function publishAndGenerateElementShareLink(options) {
62
+ const response = await fetch(EMBED_MANAGE_URL, {
63
+ method: 'POST',
64
+ headers: {
65
+ 'Content-Type': 'application/json',
66
+ apikey: SUPABASE_PUBLISHABLE_KEY,
67
+ Authorization: `Bearer ${options.accessToken}`,
68
+ },
69
+ body: JSON.stringify({
70
+ action: 'publish-for-share',
71
+ contributor_id: options.contributorId,
72
+ element_type: options.elementType,
73
+ content: options.content,
74
+ }),
75
+ });
76
+ if (!response.ok) {
77
+ const error = await response
78
+ .json()
79
+ .catch(() => ({ error: 'Unknown error' }));
80
+ throw new Error(error.error || `Publish failed: ${response.status}`);
81
+ }
82
+ const data = await response.json();
83
+ return {
84
+ shareUrl: `https://skhema.com/embed/e/${data.id}`,
85
+ elementId: data.id,
86
+ contentHash: data.content_hash,
87
+ };
88
+ }
89
+ export async function publishAndGenerateComponentShareLink(options) {
90
+ const response = await fetch(EMBED_MANAGE_URL, {
91
+ method: 'POST',
92
+ headers: {
93
+ 'Content-Type': 'application/json',
94
+ apikey: SUPABASE_PUBLISHABLE_KEY,
95
+ Authorization: `Bearer ${options.accessToken}`,
96
+ },
97
+ body: JSON.stringify({
98
+ action: 'publish-component-for-share',
99
+ contributor_id: options.contributorId,
100
+ component_type: options.componentType,
101
+ title: options.title || null,
102
+ elements: options.elements.map((el) => ({
103
+ element_type: el.elementType,
104
+ content: el.content,
105
+ })),
106
+ }),
107
+ });
108
+ if (!response.ok) {
109
+ const error = await response
110
+ .json()
111
+ .catch(() => ({ error: 'Unknown error' }));
112
+ throw new Error(error.error || `Publish failed: ${response.status}`);
113
+ }
114
+ const data = await response.json();
115
+ return {
116
+ shareUrl: `https://skhema.com/embed/c/${data.id}`,
117
+ componentId: data.id,
118
+ };
119
+ }
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Vendored from @skhema/types (src/schema/{elements,components,mapping}.ts).
3
+ *
4
+ * @skhema/types is a restricted npm package; @skhema/cli is public, so it must
5
+ * not depend on it at install time. This is the public method vocabulary (it
6
+ * renders verbatim in public embeds) — keep it in sync with @skhema/types when
7
+ * the method schema changes.
8
+ */
9
+ export declare const ELEMENT_TYPES: {
10
+ readonly KEY_CHALLENGE: {
11
+ readonly value: "key_challenge";
12
+ readonly label: "Key Challenge";
13
+ readonly acronym: "CHL";
14
+ };
15
+ readonly SUPPORTING_FACT: {
16
+ readonly value: "supporting_fact";
17
+ readonly label: "Supporting Fact";
18
+ readonly acronym: "FCT";
19
+ };
20
+ readonly IMPACT: {
21
+ readonly value: "impact";
22
+ readonly label: "Impact";
23
+ readonly acronym: "IMP";
24
+ };
25
+ readonly GUIDING_POLICY: {
26
+ readonly value: "guiding_policy";
27
+ readonly label: "Guiding Policy";
28
+ readonly acronym: "POL";
29
+ };
30
+ readonly COMPETITOR_MOVE: {
31
+ readonly value: "competitor_move";
32
+ readonly label: "Competitor Move";
33
+ readonly acronym: "CMV";
34
+ };
35
+ readonly SCOPE: {
36
+ readonly value: "scope";
37
+ readonly label: "Scope";
38
+ readonly acronym: "SCP";
39
+ };
40
+ readonly CONSTRAINT: {
41
+ readonly value: "constraint";
42
+ readonly label: "Constraint";
43
+ readonly acronym: "CST";
44
+ };
45
+ readonly SOLUTION: {
46
+ readonly value: "solution";
47
+ readonly label: "Solution";
48
+ readonly acronym: "SOL";
49
+ };
50
+ readonly ASSUMPTION_HYPOTHESIS: {
51
+ readonly value: "assumption_hypothesis";
52
+ readonly label: "Assumption Hypothesis";
53
+ readonly acronym: "HYP";
54
+ };
55
+ readonly EXPERIMENT: {
56
+ readonly value: "experiment";
57
+ readonly label: "Experiment";
58
+ readonly acronym: "EXP";
59
+ };
60
+ readonly ACTION: {
61
+ readonly value: "action";
62
+ readonly label: "Action";
63
+ readonly acronym: "ACT";
64
+ };
65
+ readonly INVESTMENT: {
66
+ readonly value: "investment";
67
+ readonly label: "Investment";
68
+ readonly acronym: "INV";
69
+ };
70
+ readonly ESTIMATE: {
71
+ readonly value: "estimate";
72
+ readonly label: "Estimate";
73
+ readonly acronym: "EST";
74
+ };
75
+ readonly BASELINE: {
76
+ readonly value: "baseline";
77
+ readonly label: "Baseline";
78
+ readonly acronym: "BSL";
79
+ };
80
+ readonly OUTCOME: {
81
+ readonly value: "outcome";
82
+ readonly label: "Outcome";
83
+ readonly acronym: "OCM";
84
+ };
85
+ readonly PERFORMANCE_VARIABLE: {
86
+ readonly value: "performance_variable";
87
+ readonly label: "Performance Variable";
88
+ readonly acronym: "VAR";
89
+ };
90
+ readonly CAPABILITY: {
91
+ readonly value: "capability";
92
+ readonly label: "Capability";
93
+ readonly acronym: "CAP";
94
+ };
95
+ readonly SYSTEM: {
96
+ readonly value: "system";
97
+ readonly label: "System";
98
+ readonly acronym: "SYS";
99
+ };
100
+ readonly PRINCIPLE: {
101
+ readonly value: "principle";
102
+ readonly label: "Principle";
103
+ readonly acronym: "PRN";
104
+ };
105
+ };
106
+ export declare const COMPONENT_TYPES: {
107
+ readonly DIAGNOSIS: {
108
+ readonly value: "diagnosis";
109
+ readonly label: "Diagnosis";
110
+ readonly acronym: "BD";
111
+ };
112
+ readonly METHOD: {
113
+ readonly value: "method";
114
+ readonly label: "Method & Positioning";
115
+ readonly acronym: "MP";
116
+ };
117
+ readonly INITIATIVES: {
118
+ readonly value: "initiatives";
119
+ readonly label: "Portfolio of Initiatives";
120
+ readonly acronym: "PI";
121
+ };
122
+ readonly MEASURES: {
123
+ readonly value: "measures";
124
+ readonly label: "Measures";
125
+ readonly acronym: "M";
126
+ };
127
+ readonly SUPPORT: {
128
+ readonly value: "support";
129
+ readonly label: "Support Structures";
130
+ readonly acronym: "SS";
131
+ };
132
+ };
133
+ export declare const SKHEMA_MAPPING: {
134
+ readonly componentFlow: readonly [{
135
+ readonly value: "diagnosis";
136
+ readonly label: "Diagnosis";
137
+ readonly acronym: "BD";
138
+ }, {
139
+ readonly value: "method";
140
+ readonly label: "Method & Positioning";
141
+ readonly acronym: "MP";
142
+ }, {
143
+ readonly value: "initiatives";
144
+ readonly label: "Portfolio of Initiatives";
145
+ readonly acronym: "PI";
146
+ }, {
147
+ readonly value: "measures";
148
+ readonly label: "Measures";
149
+ readonly acronym: "M";
150
+ }, {
151
+ readonly value: "support";
152
+ readonly label: "Support Structures";
153
+ readonly acronym: "SS";
154
+ }];
155
+ readonly elementFlow: {
156
+ readonly diagnosis: readonly [{
157
+ readonly value: "key_challenge";
158
+ readonly label: "Key Challenge";
159
+ readonly acronym: "CHL";
160
+ }, {
161
+ readonly value: "supporting_fact";
162
+ readonly label: "Supporting Fact";
163
+ readonly acronym: "FCT";
164
+ }, {
165
+ readonly value: "impact";
166
+ readonly label: "Impact";
167
+ readonly acronym: "IMP";
168
+ }];
169
+ readonly method: readonly [{
170
+ readonly value: "guiding_policy";
171
+ readonly label: "Guiding Policy";
172
+ readonly acronym: "POL";
173
+ }, {
174
+ readonly value: "competitor_move";
175
+ readonly label: "Competitor Move";
176
+ readonly acronym: "CMV";
177
+ }, {
178
+ readonly value: "scope";
179
+ readonly label: "Scope";
180
+ readonly acronym: "SCP";
181
+ }, {
182
+ readonly value: "constraint";
183
+ readonly label: "Constraint";
184
+ readonly acronym: "CST";
185
+ }];
186
+ readonly initiatives: readonly [{
187
+ readonly value: "solution";
188
+ readonly label: "Solution";
189
+ readonly acronym: "SOL";
190
+ }, {
191
+ readonly value: "assumption_hypothesis";
192
+ readonly label: "Assumption Hypothesis";
193
+ readonly acronym: "HYP";
194
+ }, {
195
+ readonly value: "experiment";
196
+ readonly label: "Experiment";
197
+ readonly acronym: "EXP";
198
+ }, {
199
+ readonly value: "action";
200
+ readonly label: "Action";
201
+ readonly acronym: "ACT";
202
+ }, {
203
+ readonly value: "estimate";
204
+ readonly label: "Estimate";
205
+ readonly acronym: "EST";
206
+ }, {
207
+ readonly value: "investment";
208
+ readonly label: "Investment";
209
+ readonly acronym: "INV";
210
+ }];
211
+ readonly measures: readonly [{
212
+ readonly value: "baseline";
213
+ readonly label: "Baseline";
214
+ readonly acronym: "BSL";
215
+ }, {
216
+ readonly value: "outcome";
217
+ readonly label: "Outcome";
218
+ readonly acronym: "OCM";
219
+ }, {
220
+ readonly value: "performance_variable";
221
+ readonly label: "Performance Variable";
222
+ readonly acronym: "VAR";
223
+ }];
224
+ readonly support: readonly [{
225
+ readonly value: "capability";
226
+ readonly label: "Capability";
227
+ readonly acronym: "CAP";
228
+ }, {
229
+ readonly value: "system";
230
+ readonly label: "System";
231
+ readonly acronym: "SYS";
232
+ }, {
233
+ readonly value: "principle";
234
+ readonly label: "Principle";
235
+ readonly acronym: "PRN";
236
+ }];
237
+ };
238
+ };
239
+ //# sourceMappingURL=method-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"method-schema.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/method-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGhB,CAAA;AAEV,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BlB,CAAA;AAEV,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCjB,CAAA"}