@treeseed/sdk 0.1.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 (63) hide show
  1. package/README.md +565 -0
  2. package/dist/cli-tools.js +44 -0
  3. package/dist/content-store.js +237 -0
  4. package/dist/d1-store.js +549 -0
  5. package/dist/frontmatter.js +33 -0
  6. package/dist/git-runtime.js +67 -0
  7. package/dist/index.js +12 -0
  8. package/dist/model-registry.js +164 -0
  9. package/dist/runtime.js +36 -0
  10. package/dist/scripts/.ts-run-1775616845195-odh4xzphk3l.js +22 -0
  11. package/dist/scripts/.ts-run-1775616848931-9386s6kwrl.js +126 -0
  12. package/dist/scripts/assert-release-tag-version.d.ts +1 -0
  13. package/dist/scripts/assert-release-tag-version.js +23 -0
  14. package/dist/scripts/build-dist.d.ts +1 -0
  15. package/dist/scripts/build-dist.js +114 -0
  16. package/dist/scripts/package-tools.d.ts +15 -0
  17. package/dist/scripts/package-tools.js +76 -0
  18. package/dist/scripts/publish-package.d.ts +1 -0
  19. package/dist/scripts/publish-package.js +20 -0
  20. package/dist/scripts/release-verify.d.ts +1 -0
  21. package/dist/scripts/release-verify.js +49 -0
  22. package/dist/scripts/run-ts.js +45 -0
  23. package/dist/scripts/test-smoke.d.ts +1 -0
  24. package/dist/scripts/test-smoke.js +77 -0
  25. package/dist/sdk-filters.js +77 -0
  26. package/dist/sdk-types.js +24 -0
  27. package/dist/sdk.js +232 -0
  28. package/dist/src/cli-tools.d.ts +3 -0
  29. package/dist/src/content-store.d.ts +24 -0
  30. package/dist/src/d1-store.d.ts +108 -0
  31. package/dist/src/frontmatter.d.ts +6 -0
  32. package/dist/src/git-runtime.d.ts +16 -0
  33. package/dist/src/index.d.ts +6 -0
  34. package/dist/src/model-registry.d.ts +4 -0
  35. package/dist/src/runtime.d.ts +1 -0
  36. package/dist/src/sdk-filters.d.ts +4 -0
  37. package/dist/src/sdk-types.d.ts +285 -0
  38. package/dist/src/sdk.d.ts +109 -0
  39. package/dist/src/stores/cursor-store.d.ts +10 -0
  40. package/dist/src/stores/envelopes.d.ts +116 -0
  41. package/dist/src/stores/helpers.d.ts +12 -0
  42. package/dist/src/stores/lease-store.d.ts +18 -0
  43. package/dist/src/stores/message-store.d.ts +12 -0
  44. package/dist/src/stores/run-store.d.ts +10 -0
  45. package/dist/src/stores/subscription-store.d.ts +9 -0
  46. package/dist/src/types/agents.d.ts +100 -0
  47. package/dist/src/types/cloudflare.d.ts +32 -0
  48. package/dist/src/wrangler-d1.d.ts +25 -0
  49. package/dist/stores/cursor-store.js +158 -0
  50. package/dist/stores/envelopes.js +219 -0
  51. package/dist/stores/helpers.js +42 -0
  52. package/dist/stores/lease-store.js +183 -0
  53. package/dist/stores/message-store.js +249 -0
  54. package/dist/stores/run-store.js +166 -0
  55. package/dist/stores/subscription-store.js +171 -0
  56. package/dist/test/test-fixture.d.ts +1 -0
  57. package/dist/test/utils/envelopes.test.d.ts +1 -0
  58. package/dist/test/utils/sdk.test.d.ts +1 -0
  59. package/dist/types/agents.js +40 -0
  60. package/dist/types/cloudflare.js +0 -0
  61. package/dist/vitest.config.d.ts +2 -0
  62. package/dist/wrangler-d1.js +84 -0
  63. package/package.json +130 -0
@@ -0,0 +1,164 @@
1
+ import path from "node:path";
2
+ import { resolveSdkRepoRoot } from "./runtime.js";
3
+ function contentRoot() {
4
+ return process.env.TREESEED_AGENT_CONTENT_ROOT ? path.resolve(process.env.TREESEED_AGENT_CONTENT_ROOT) : path.resolve(resolveSdkRepoRoot(), "src", "content");
5
+ }
6
+ function buildModelRegistry() {
7
+ const root = contentRoot();
8
+ return {
9
+ page: {
10
+ name: "page",
11
+ aliases: ["pages"],
12
+ storage: "content",
13
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
14
+ filterableFields: ["title", "slug", "status", "audience", "updated"],
15
+ sortableFields: ["title", "updated"],
16
+ pickField: "updated",
17
+ contentCollection: "pages",
18
+ contentDir: path.join(root, "pages")
19
+ },
20
+ note: {
21
+ name: "note",
22
+ aliases: ["notes"],
23
+ storage: "content",
24
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
25
+ filterableFields: ["title", "status", "author", "tags", "date", "updated"],
26
+ sortableFields: ["title", "date", "updated"],
27
+ pickField: "date",
28
+ contentCollection: "notes",
29
+ contentDir: path.join(root, "notes")
30
+ },
31
+ question: {
32
+ name: "question",
33
+ aliases: ["questions"],
34
+ storage: "content",
35
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
36
+ filterableFields: ["title", "status", "tags", "date", "questionType", "relatedObjectives", "relatedBooks"],
37
+ sortableFields: ["title", "date", "updated"],
38
+ pickField: "date",
39
+ contentCollection: "questions",
40
+ contentDir: path.join(root, "questions")
41
+ },
42
+ book: {
43
+ name: "book",
44
+ aliases: ["books"],
45
+ storage: "content",
46
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
47
+ filterableFields: ["title", "slug", "tags", "sectionLabel"],
48
+ sortableFields: ["title", "order", "updated"],
49
+ pickField: "order",
50
+ contentCollection: "books",
51
+ contentDir: path.join(root, "books")
52
+ },
53
+ knowledge: {
54
+ name: "knowledge",
55
+ aliases: ["knowledge-base", "docs"],
56
+ storage: "content",
57
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
58
+ filterableFields: ["title", "tags", "updated", "slug"],
59
+ sortableFields: ["title", "updated"],
60
+ pickField: "updated",
61
+ contentCollection: "docs",
62
+ contentDir: path.join(root, "knowledge")
63
+ },
64
+ objective: {
65
+ name: "objective",
66
+ aliases: ["objectives"],
67
+ storage: "content",
68
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
69
+ filterableFields: ["title", "status", "tags", "date", "timeHorizon", "relatedQuestions", "relatedBooks"],
70
+ sortableFields: ["title", "date", "updated"],
71
+ pickField: "date",
72
+ contentCollection: "objectives",
73
+ contentDir: path.join(root, "objectives")
74
+ },
75
+ person: {
76
+ name: "person",
77
+ aliases: ["people", "persons"],
78
+ storage: "content",
79
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
80
+ filterableFields: ["name", "role", "affiliation", "status", "tags"],
81
+ sortableFields: ["name", "updated"],
82
+ pickField: "updated",
83
+ contentCollection: "people",
84
+ contentDir: path.join(root, "people")
85
+ },
86
+ subscription: {
87
+ name: "subscription",
88
+ aliases: ["subscriptions", "subscriber", "subscribers"],
89
+ storage: "d1",
90
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
91
+ filterableFields: ["email", "status", "source", "created_at", "updated_at"],
92
+ sortableFields: ["email", "created_at", "updated_at"],
93
+ pickField: "updated_at"
94
+ },
95
+ message: {
96
+ name: "message",
97
+ aliases: ["messages"],
98
+ storage: "d1",
99
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
100
+ filterableFields: ["type", "status", "related_model", "related_id", "priority", "available_at"],
101
+ sortableFields: ["priority", "available_at", "created_at", "updated_at"],
102
+ pickField: "available_at"
103
+ },
104
+ agent: {
105
+ name: "agent",
106
+ aliases: ["agents"],
107
+ storage: "content",
108
+ operations: ["get", "read", "search", "follow", "pick", "create", "update"],
109
+ filterableFields: ["slug", "runtimeStatus", "tags", "operator"],
110
+ sortableFields: ["name", "slug", "updated"],
111
+ pickField: "updated",
112
+ contentCollection: "agents",
113
+ contentDir: path.join(root, "agents")
114
+ },
115
+ agent_run: {
116
+ name: "agent_run",
117
+ aliases: ["agent_runs", "run", "runs"],
118
+ storage: "d1",
119
+ operations: ["get", "read", "search", "follow", "create", "update"],
120
+ filterableFields: ["run_id", "agent_slug", "status", "started_at", "finished_at"],
121
+ sortableFields: ["started_at", "finished_at"],
122
+ pickField: "started_at"
123
+ },
124
+ agent_cursor: {
125
+ name: "agent_cursor",
126
+ aliases: ["agent_cursors", "cursor", "cursors"],
127
+ storage: "d1",
128
+ operations: ["get", "read", "search", "follow", "create", "update"],
129
+ filterableFields: ["agent_slug", "cursor_key", "cursor_value", "updated_at"],
130
+ sortableFields: ["updated_at", "agent_slug", "cursor_key"],
131
+ pickField: "updated_at"
132
+ },
133
+ content_lease: {
134
+ name: "content_lease",
135
+ aliases: ["content_leases", "lease", "leases"],
136
+ storage: "d1",
137
+ operations: ["get", "read", "search", "follow", "create", "update"],
138
+ filterableFields: ["model", "item_key", "claimed_by", "lease_expires_at"],
139
+ sortableFields: ["lease_expires_at", "claimed_at"],
140
+ pickField: "lease_expires_at"
141
+ }
142
+ };
143
+ }
144
+ const MODEL_REGISTRY = buildModelRegistry();
145
+ function resolveModelDefinition(model) {
146
+ const registry = buildModelRegistry();
147
+ const directMatch = registry[model];
148
+ if (directMatch) {
149
+ return directMatch;
150
+ }
151
+ const normalized = model.trim().toLowerCase();
152
+ const aliasMatch = Object.values(registry).find(
153
+ (definition) => definition.aliases.includes(normalized) || definition.name === normalized
154
+ );
155
+ if (!aliasMatch) {
156
+ throw new Error(`Unknown SDK model "${model}".`);
157
+ }
158
+ return aliasMatch;
159
+ }
160
+ export {
161
+ MODEL_REGISTRY,
162
+ buildModelRegistry,
163
+ resolveModelDefinition
164
+ };
@@ -0,0 +1,36 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ function findContentRoot(start) {
4
+ let current = path.resolve(start);
5
+ for (; ; ) {
6
+ if (existsSync(path.join(current, "fixture", "src", "content"))) {
7
+ return path.join(current, "fixture");
8
+ }
9
+ if (existsSync(path.join(current, "src", "content"))) {
10
+ return current;
11
+ }
12
+ if (existsSync(path.join(current, "docs", "src", "content"))) {
13
+ return path.join(current, "docs");
14
+ }
15
+ const parent = path.dirname(current);
16
+ if (parent === current) {
17
+ return null;
18
+ }
19
+ current = parent;
20
+ }
21
+ }
22
+ function resolveSdkRepoRoot(repoRoot) {
23
+ if (repoRoot) {
24
+ return path.resolve(repoRoot);
25
+ }
26
+ if (process.env.TREESEED_SDK_CONTENT_ROOT) {
27
+ return path.resolve(process.env.TREESEED_SDK_CONTENT_ROOT);
28
+ }
29
+ if (process.env.TREESEED_SDK_REPO_ROOT) {
30
+ return path.resolve(process.env.TREESEED_SDK_REPO_ROOT);
31
+ }
32
+ return findContentRoot(process.cwd()) ?? process.cwd();
33
+ }
34
+ export {
35
+ resolveSdkRepoRoot
36
+ };
@@ -0,0 +1,22 @@
1
+ // scripts/publish-package.ts
2
+ import { spawnSync } from "node:child_process";
3
+ import { resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ var packageRoot = resolve(fileURLToPath(new URL("..", import.meta.url)));
6
+ var extraArgs = process.argv.slice(2);
7
+ var npmArgs = ["publish", ".", "--access", "public"];
8
+ if (process.env.GITHUB_ACTIONS === "true") {
9
+ npmArgs.push("--provenance");
10
+ }
11
+ npmArgs.push(...extraArgs);
12
+ var result = spawnSync("npm", npmArgs, {
13
+ cwd: packageRoot,
14
+ stdio: "inherit",
15
+ env: process.env
16
+ });
17
+ if (result.error) {
18
+ console.error(result.error.message);
19
+ process.exit(1);
20
+ }
21
+ process.exit(result.status ?? 1);
22
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicHVibGlzaC1wYWNrYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuXG5jb25zdCBwYWNrYWdlUm9vdCA9IHJlc29sdmUoZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuLicsIGltcG9ydC5tZXRhLnVybCkpKTtcbmNvbnN0IGV4dHJhQXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcblxuY29uc3QgbnBtQXJncyA9IFsncHVibGlzaCcsICcuJywgJy0tYWNjZXNzJywgJ3B1YmxpYyddO1xuXG5pZiAocHJvY2Vzcy5lbnYuR0lUSFVCX0FDVElPTlMgPT09ICd0cnVlJykge1xuXHRucG1BcmdzLnB1c2goJy0tcHJvdmVuYW5jZScpO1xufVxuXG5ucG1BcmdzLnB1c2goLi4uZXh0cmFBcmdzKTtcblxuY29uc3QgcmVzdWx0ID0gc3Bhd25TeW5jKCducG0nLCBucG1BcmdzLCB7XG5cdGN3ZDogcGFja2FnZVJvb3QsXG5cdHN0ZGlvOiAnaW5oZXJpdCcsXG5cdGVudjogcHJvY2Vzcy5lbnYsXG59KTtcblxuaWYgKHJlc3VsdC5lcnJvcikge1xuXHRjb25zb2xlLmVycm9yKHJlc3VsdC5lcnJvci5tZXNzYWdlKTtcblx0cHJvY2Vzcy5leGl0KDEpO1xufVxuXG5wcm9jZXNzLmV4aXQocmVzdWx0LnN0YXR1cyA/PyAxKTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBQSxTQUFTLGlCQUFpQjtBQUMxQixTQUFTLGVBQWU7QUFDeEIsU0FBUyxxQkFBcUI7QUFFOUIsSUFBTSxjQUFjLFFBQVEsY0FBYyxJQUFJLElBQUksTUFBTSxZQUFZLEdBQUcsQ0FBQyxDQUFDO0FBQ3pFLElBQU0sWUFBWSxRQUFRLEtBQUssTUFBTSxDQUFDO0FBRXRDLElBQU0sVUFBVSxDQUFDLFdBQVcsS0FBSyxZQUFZLFFBQVE7QUFFckQsSUFBSSxRQUFRLElBQUksbUJBQW1CLFFBQVE7QUFDMUMsVUFBUSxLQUFLLGNBQWM7QUFDNUI7QUFFQSxRQUFRLEtBQUssR0FBRyxTQUFTO0FBRXpCLElBQU0sU0FBUyxVQUFVLE9BQU8sU0FBUztBQUFBLEVBQ3hDLEtBQUs7QUFBQSxFQUNMLE9BQU87QUFBQSxFQUNQLEtBQUssUUFBUTtBQUNkLENBQUM7QUFFRCxJQUFJLE9BQU8sT0FBTztBQUNqQixVQUFRLE1BQU0sT0FBTyxNQUFNLE9BQU87QUFDbEMsVUFBUSxLQUFLLENBQUM7QUFDZjtBQUVBLFFBQVEsS0FBSyxPQUFPLFVBQVUsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,126 @@
1
+ // scripts/build-dist.ts
2
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { dirname as dirname2, extname as extname2, join, relative, resolve as resolve2 } from "node:path";
4
+ import { build } from "esbuild";
5
+ import ts from "typescript";
6
+
7
+ // scripts/package-tools.ts
8
+ import { dirname, extname, resolve } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { createRequire } from "node:module";
11
+ var require2 = createRequire(import.meta.url);
12
+ var scriptRoot = dirname(fileURLToPath(import.meta.url));
13
+ var packageCandidate = resolve(scriptRoot, "..");
14
+ var packageRoot = packageCandidate.endsWith("/dist") ? resolve(packageCandidate, "..") : packageCandidate;
15
+ var packageScriptRoot = packageCandidate.endsWith("/dist") ? resolve(packageCandidate, "scripts") : resolve(packageRoot, "scripts");
16
+
17
+ // scripts/build-dist.ts
18
+ var srcRoot = resolve2(packageRoot, "src");
19
+ var scriptsRoot = resolve2(packageRoot, "scripts");
20
+ var distRoot = resolve2(packageRoot, "dist");
21
+ var COPY_EXTENSIONS = /* @__PURE__ */ new Set([".d.js", ".json", ".md"]);
22
+ function walkFiles(root) {
23
+ const files = [];
24
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
25
+ const fullPath = join(root, entry.name);
26
+ if (entry.isDirectory()) {
27
+ files.push(...walkFiles(fullPath));
28
+ continue;
29
+ }
30
+ files.push(fullPath);
31
+ }
32
+ return files;
33
+ }
34
+ function ensureDir(filePath) {
35
+ mkdirSync(dirname2(filePath), { recursive: true });
36
+ }
37
+ function rewriteRuntimeSpecifiers(contents) {
38
+ return contents.replace(/(['"`])(\.[^'"`\n]+)\.(mjs|ts)\1/g, "$1$2.js$1");
39
+ }
40
+ async function compileModule(filePath, sourceRoot, outputRoot) {
41
+ const relativePath = relative(sourceRoot, filePath);
42
+ const outputFile = resolve2(outputRoot, relativePath.replace(/\.(mjs|ts)$/u, ".js"));
43
+ ensureDir(outputFile);
44
+ await build({
45
+ entryPoints: [filePath],
46
+ outfile: outputFile,
47
+ platform: "node",
48
+ format: "esm",
49
+ bundle: false,
50
+ logLevel: "silent"
51
+ });
52
+ const builtSource = readFileSync(outputFile, "utf8");
53
+ writeFileSync(outputFile, rewriteRuntimeSpecifiers(builtSource), "utf8");
54
+ }
55
+ function copyAsset(filePath, sourceRoot, outputRoot) {
56
+ const outputFile = resolve2(outputRoot, relative(sourceRoot, filePath));
57
+ ensureDir(outputFile);
58
+ copyFileSync(filePath, outputFile);
59
+ if (outputFile.endsWith(".d.js")) {
60
+ const contents = readFileSync(outputFile, "utf8");
61
+ writeFileSync(outputFile, rewriteRuntimeSpecifiers(contents), "utf8");
62
+ }
63
+ }
64
+ function transpileScript(filePath) {
65
+ const source = readFileSync(filePath, "utf8");
66
+ const relativePath = relative(scriptsRoot, filePath);
67
+ const outputFile = resolve2(distRoot, "scripts", relativePath.replace(/\.(mjs|ts)$/u, ".js"));
68
+ const transformed = extname2(filePath) === ".ts" ? ts.transpileModule(source, {
69
+ compilerOptions: {
70
+ module: ts.ModuleKind.ESNext,
71
+ target: ts.ScriptTarget.ES2022
72
+ }
73
+ }).outputText : source;
74
+ ensureDir(outputFile);
75
+ writeFileSync(outputFile, rewriteRuntimeSpecifiers(transformed), "utf8");
76
+ }
77
+ function emitDeclarations() {
78
+ const configPath = ts.findConfigFile(packageRoot, ts.sys.fileExists, "tsconfig.json");
79
+ if (!configPath) {
80
+ throw new Error("Unable to locate tsconfig.json for declaration build.");
81
+ }
82
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
83
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, packageRoot);
84
+ const program = ts.createProgram({
85
+ rootNames: parsed.fileNames,
86
+ options: {
87
+ ...parsed.options,
88
+ declaration: true,
89
+ emitDeclarationOnly: true,
90
+ declarationDir: distRoot,
91
+ noEmit: false
92
+ }
93
+ });
94
+ const result = program.emit();
95
+ if (result.emitSkipped) {
96
+ const diagnostics = ts.formatDiagnosticsWithColorAndContext(result.diagnostics, {
97
+ getCanonicalFileName: (fileName) => fileName,
98
+ getCurrentDirectory: () => process.cwd(),
99
+ getNewLine: () => "\n"
100
+ });
101
+ throw new Error(`Declaration build failed.
102
+ ${diagnostics}`);
103
+ }
104
+ }
105
+ rmSync(distRoot, { recursive: true, force: true });
106
+ for (const filePath of walkFiles(srcRoot)) {
107
+ const extension = extname2(filePath);
108
+ if (extension === ".ts") {
109
+ await compileModule(filePath, srcRoot, distRoot);
110
+ continue;
111
+ }
112
+ if (COPY_EXTENSIONS.has(extension)) {
113
+ copyAsset(filePath, srcRoot, distRoot);
114
+ }
115
+ }
116
+ for (const filePath of walkFiles(scriptsRoot)) {
117
+ const extension = extname2(filePath);
118
+ if (extension === ".ts" || extension === ".mjs") {
119
+ transpileScript(filePath);
120
+ }
121
+ }
122
+ emitDeclarations();
123
+ if (existsSync(resolve2(packageRoot, "README.md"))) {
124
+ copyFileSync(resolve2(packageRoot, "README.md"), resolve2(distRoot, "..", "README.md"));
125
+ }
126
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiYnVpbGQtZGlzdC50cyIsICJwYWNrYWdlLXRvb2xzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBjb3B5RmlsZVN5bmMsIGV4aXN0c1N5bmMsIG1rZGlyU3luYywgcmVhZGRpclN5bmMsIHJlYWRGaWxlU3luYywgcm1TeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBkaXJuYW1lLCBleHRuYW1lLCBqb2luLCByZWxhdGl2ZSwgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBidWlsZCB9IGZyb20gJ2VzYnVpbGQnO1xuaW1wb3J0IHRzIGZyb20gJ3R5cGVzY3JpcHQnO1xuaW1wb3J0IHsgcGFja2FnZVJvb3QgfSBmcm9tICcuL3BhY2thZ2UtdG9vbHMudHMnO1xuXG5jb25zdCBzcmNSb290ID0gcmVzb2x2ZShwYWNrYWdlUm9vdCwgJ3NyYycpO1xuY29uc3Qgc2NyaXB0c1Jvb3QgPSByZXNvbHZlKHBhY2thZ2VSb290LCAnc2NyaXB0cycpO1xuY29uc3QgZGlzdFJvb3QgPSByZXNvbHZlKHBhY2thZ2VSb290LCAnZGlzdCcpO1xuXG5jb25zdCBDT1BZX0VYVEVOU0lPTlMgPSBuZXcgU2V0KFsnLmQudHMnLCAnLmpzb24nLCAnLm1kJ10pO1xuXG5mdW5jdGlvbiB3YWxrRmlsZXMocm9vdCkge1xuXHRjb25zdCBmaWxlcyA9IFtdO1xuXHRmb3IgKGNvbnN0IGVudHJ5IG9mIHJlYWRkaXJTeW5jKHJvb3QsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KSkge1xuXHRcdGNvbnN0IGZ1bGxQYXRoID0gam9pbihyb290LCBlbnRyeS5uYW1lKTtcblx0XHRpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuXHRcdFx0ZmlsZXMucHVzaCguLi53YWxrRmlsZXMoZnVsbFBhdGgpKTtcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRmaWxlcy5wdXNoKGZ1bGxQYXRoKTtcblx0fVxuXHRyZXR1cm4gZmlsZXM7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZURpcihmaWxlUGF0aCkge1xuXHRta2RpclN5bmMoZGlybmFtZShmaWxlUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuXG5mdW5jdGlvbiByZXdyaXRlUnVudGltZVNwZWNpZmllcnMoY29udGVudHMpIHtcblx0cmV0dXJuIGNvbnRlbnRzLnJlcGxhY2UoLyhbJ1wiYF0pKFxcLlteJ1wiYFxcbl0rKVxcLihtanN8dHMpXFwxL2csICckMSQyLmpzJDEnKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29tcGlsZU1vZHVsZShmaWxlUGF0aCwgc291cmNlUm9vdCwgb3V0cHV0Um9vdCkge1xuXHRjb25zdCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZShzb3VyY2VSb290LCBmaWxlUGF0aCk7XG5cdGNvbnN0IG91dHB1dEZpbGUgPSByZXNvbHZlKG91dHB1dFJvb3QsIHJlbGF0aXZlUGF0aC5yZXBsYWNlKC9cXC4obWpzfHRzKSQvdSwgJy5qcycpKTtcblx0ZW5zdXJlRGlyKG91dHB1dEZpbGUpO1xuXG5cdGF3YWl0IGJ1aWxkKHtcblx0XHRlbnRyeVBvaW50czogW2ZpbGVQYXRoXSxcblx0XHRvdXRmaWxlOiBvdXRwdXRGaWxlLFxuXHRcdHBsYXRmb3JtOiAnbm9kZScsXG5cdFx0Zm9ybWF0OiAnZXNtJyxcblx0XHRidW5kbGU6IGZhbHNlLFxuXHRcdGxvZ0xldmVsOiAnc2lsZW50Jyxcblx0fSk7XG5cblx0Y29uc3QgYnVpbHRTb3VyY2UgPSByZWFkRmlsZVN5bmMob3V0cHV0RmlsZSwgJ3V0ZjgnKTtcblx0d3JpdGVGaWxlU3luYyhvdXRwdXRGaWxlLCByZXdyaXRlUnVudGltZVNwZWNpZmllcnMoYnVpbHRTb3VyY2UpLCAndXRmOCcpO1xufVxuXG5mdW5jdGlvbiBjb3B5QXNzZXQoZmlsZVBhdGgsIHNvdXJjZVJvb3QsIG91dHB1dFJvb3QpIHtcblx0Y29uc3Qgb3V0cHV0RmlsZSA9IHJlc29sdmUob3V0cHV0Um9vdCwgcmVsYXRpdmUoc291cmNlUm9vdCwgZmlsZVBhdGgpKTtcblx0ZW5zdXJlRGlyKG91dHB1dEZpbGUpO1xuXHRjb3B5RmlsZVN5bmMoZmlsZVBhdGgsIG91dHB1dEZpbGUpO1xuXG5cdGlmIChvdXRwdXRGaWxlLmVuZHNXaXRoKCcuZC50cycpKSB7XG5cdFx0Y29uc3QgY29udGVudHMgPSByZWFkRmlsZVN5bmMob3V0cHV0RmlsZSwgJ3V0ZjgnKTtcblx0XHR3cml0ZUZpbGVTeW5jKG91dHB1dEZpbGUsIHJld3JpdGVSdW50aW1lU3BlY2lmaWVycyhjb250ZW50cyksICd1dGY4Jyk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdHJhbnNwaWxlU2NyaXB0KGZpbGVQYXRoKSB7XG5cdGNvbnN0IHNvdXJjZSA9IHJlYWRGaWxlU3luYyhmaWxlUGF0aCwgJ3V0ZjgnKTtcblx0Y29uc3QgcmVsYXRpdmVQYXRoID0gcmVsYXRpdmUoc2NyaXB0c1Jvb3QsIGZpbGVQYXRoKTtcblx0Y29uc3Qgb3V0cHV0RmlsZSA9IHJlc29sdmUoZGlzdFJvb3QsICdzY3JpcHRzJywgcmVsYXRpdmVQYXRoLnJlcGxhY2UoL1xcLihtanN8dHMpJC91LCAnLmpzJykpO1xuXHRjb25zdCB0cmFuc2Zvcm1lZCA9IGV4dG5hbWUoZmlsZVBhdGgpID09PSAnLnRzJ1xuXHRcdD8gdHMudHJhbnNwaWxlTW9kdWxlKHNvdXJjZSwge1xuXHRcdFx0XHRjb21waWxlck9wdGlvbnM6IHtcblx0XHRcdFx0XHRtb2R1bGU6IHRzLk1vZHVsZUtpbmQuRVNOZXh0LFxuXHRcdFx0XHRcdHRhcmdldDogdHMuU2NyaXB0VGFyZ2V0LkVTMjAyMixcblx0XHRcdFx0fSxcblx0XHRcdH0pLm91dHB1dFRleHRcblx0XHQ6IHNvdXJjZTtcblxuXHRlbnN1cmVEaXIob3V0cHV0RmlsZSk7XG5cdHdyaXRlRmlsZVN5bmMob3V0cHV0RmlsZSwgcmV3cml0ZVJ1bnRpbWVTcGVjaWZpZXJzKHRyYW5zZm9ybWVkKSwgJ3V0ZjgnKTtcbn1cblxuZnVuY3Rpb24gZW1pdERlY2xhcmF0aW9ucygpIHtcblx0Y29uc3QgY29uZmlnUGF0aCA9IHRzLmZpbmRDb25maWdGaWxlKHBhY2thZ2VSb290LCB0cy5zeXMuZmlsZUV4aXN0cywgJ3RzY29uZmlnLmpzb24nKTtcblx0aWYgKCFjb25maWdQYXRoKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gbG9jYXRlIHRzY29uZmlnLmpzb24gZm9yIGRlY2xhcmF0aW9uIGJ1aWxkLicpO1xuXHR9XG5cblx0Y29uc3QgY29uZmlnRmlsZSA9IHRzLnJlYWRDb25maWdGaWxlKGNvbmZpZ1BhdGgsIHRzLnN5cy5yZWFkRmlsZSk7XG5cdGNvbnN0IHBhcnNlZCA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KGNvbmZpZ0ZpbGUuY29uZmlnLCB0cy5zeXMsIHBhY2thZ2VSb290KTtcblx0Y29uc3QgcHJvZ3JhbSA9IHRzLmNyZWF0ZVByb2dyYW0oe1xuXHRcdHJvb3ROYW1lczogcGFyc2VkLmZpbGVOYW1lcyxcblx0XHRvcHRpb25zOiB7XG5cdFx0XHQuLi5wYXJzZWQub3B0aW9ucyxcblx0XHRcdGRlY2xhcmF0aW9uOiB0cnVlLFxuXHRcdFx0ZW1pdERlY2xhcmF0aW9uT25seTogdHJ1ZSxcblx0XHRcdGRlY2xhcmF0aW9uRGlyOiBkaXN0Um9vdCxcblx0XHRcdG5vRW1pdDogZmFsc2UsXG5cdFx0fSxcblx0fSk7XG5cblx0Y29uc3QgcmVzdWx0ID0gcHJvZ3JhbS5lbWl0KCk7XG5cdGlmIChyZXN1bHQuZW1pdFNraXBwZWQpIHtcblx0XHRjb25zdCBkaWFnbm9zdGljcyA9IHRzLmZvcm1hdERpYWdub3N0aWNzV2l0aENvbG9yQW5kQ29udGV4dChyZXN1bHQuZGlhZ25vc3RpY3MsIHtcblx0XHRcdGdldENhbm9uaWNhbEZpbGVOYW1lOiAoZmlsZU5hbWUpID0+IGZpbGVOYW1lLFxuXHRcdFx0Z2V0Q3VycmVudERpcmVjdG9yeTogKCkgPT4gcHJvY2Vzcy5jd2QoKSxcblx0XHRcdGdldE5ld0xpbmU6ICgpID0+ICdcXG4nLFxuXHRcdH0pO1xuXHRcdHRocm93IG5ldyBFcnJvcihgRGVjbGFyYXRpb24gYnVpbGQgZmFpbGVkLlxcbiR7ZGlhZ25vc3RpY3N9YCk7XG5cdH1cbn1cblxucm1TeW5jKGRpc3RSb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG5cbmZvciAoY29uc3QgZmlsZVBhdGggb2Ygd2Fsa0ZpbGVzKHNyY1Jvb3QpKSB7XG5cdGNvbnN0IGV4dGVuc2lvbiA9IGV4dG5hbWUoZmlsZVBhdGgpO1xuXHRpZiAoZXh0ZW5zaW9uID09PSAnLnRzJykge1xuXHRcdGF3YWl0IGNvbXBpbGVNb2R1bGUoZmlsZVBhdGgsIHNyY1Jvb3QsIGRpc3RSb290KTtcblx0XHRjb250aW51ZTtcblx0fVxuXG5cdGlmIChDT1BZX0VYVEVOU0lPTlMuaGFzKGV4dGVuc2lvbikpIHtcblx0XHRjb3B5QXNzZXQoZmlsZVBhdGgsIHNyY1Jvb3QsIGRpc3RSb290KTtcblx0fVxufVxuXG5mb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdhbGtGaWxlcyhzY3JpcHRzUm9vdCkpIHtcblx0Y29uc3QgZXh0ZW5zaW9uID0gZXh0bmFtZShmaWxlUGF0aCk7XG5cdGlmIChleHRlbnNpb24gPT09ICcudHMnIHx8IGV4dGVuc2lvbiA9PT0gJy5tanMnKSB7XG5cdFx0dHJhbnNwaWxlU2NyaXB0KGZpbGVQYXRoKTtcblx0fVxufVxuXG5lbWl0RGVjbGFyYXRpb25zKCk7XG5cbmlmIChleGlzdHNTeW5jKHJlc29sdmUocGFja2FnZVJvb3QsICdSRUFETUUubWQnKSkpIHtcblx0Y29weUZpbGVTeW5jKHJlc29sdmUocGFja2FnZVJvb3QsICdSRUFETUUubWQnKSwgcmVzb2x2ZShkaXN0Um9vdCwgJy4uJywgJ1JFQURNRS5tZCcpKTtcbn1cbiIsICJpbXBvcnQgeyByZWFkRmlsZVN5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IGV4aXN0c1N5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IGRpcm5hbWUsIGV4dG5hbWUsIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcbmltcG9ydCB7IHNwYXduLCBzcGF3blN5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJztcblxuY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKTtcbmNvbnN0IHNjcmlwdFJvb3QgPSBkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5jb25zdCBwYWNrYWdlQ2FuZGlkYXRlID0gcmVzb2x2ZShzY3JpcHRSb290LCAnLi4nKTtcblxuZXhwb3J0IGNvbnN0IHBhY2thZ2VSb290ID0gcGFja2FnZUNhbmRpZGF0ZS5lbmRzV2l0aCgnL2Rpc3QnKVxuXHQ/IHJlc29sdmUocGFja2FnZUNhbmRpZGF0ZSwgJy4uJylcblx0OiBwYWNrYWdlQ2FuZGlkYXRlO1xuZXhwb3J0IGNvbnN0IHBhY2thZ2VTY3JpcHRSb290ID0gcGFja2FnZUNhbmRpZGF0ZS5lbmRzV2l0aCgnL2Rpc3QnKVxuXHQ/IHJlc29sdmUocGFja2FnZUNhbmRpZGF0ZSwgJ3NjcmlwdHMnKVxuXHQ6IHJlc29sdmUocGFja2FnZVJvb3QsICdzY3JpcHRzJyk7XG5cbmZ1bmN0aW9uIHJlc29sdmVQYWNrYWdlQmluYXJ5KHBhY2thZ2VOYW1lLCBiaW5OYW1lID0gcGFja2FnZU5hbWUpIHtcblx0Y29uc3QgcGFja2FnZUpzb25QYXRoID0gcmVxdWlyZS5yZXNvbHZlKGAke3BhY2thZ2VOYW1lfS9wYWNrYWdlLmpzb25gKTtcblx0Y29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhwYWNrYWdlSnNvblBhdGgsICd1dGY4JykpO1xuXHRjb25zdCBiaW5GaWVsZCA9IHBhY2thZ2VKc29uLmJpbjtcblx0Y29uc3QgcmVsYXRpdmVQYXRoID1cblx0XHR0eXBlb2YgYmluRmllbGQgPT09ICdzdHJpbmcnXG5cdFx0XHQ/IGJpbkZpZWxkXG5cdFx0XHQ6IGJpbkZpZWxkPy5bYmluTmFtZV07XG5cblx0aWYgKCFyZWxhdGl2ZVBhdGgpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byByZXNvbHZlIGJpbmFyeSBcIiR7YmluTmFtZX1cIiBmcm9tIHBhY2thZ2UgXCIke3BhY2thZ2VOYW1lfVwiLmApO1xuXHR9XG5cblx0cmV0dXJuIHJlc29sdmUoZGlybmFtZShwYWNrYWdlSnNvblBhdGgpLCByZWxhdGl2ZVBhdGgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUFzdHJvQmluKCkge1xuXHRyZXR1cm4gcmVzb2x2ZVBhY2thZ2VCaW5hcnkoJ2FzdHJvJywgJ2FzdHJvJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlV3JhbmdsZXJCaW4oKSB7XG5cdHJldHVybiByZXNvbHZlUGFja2FnZUJpbmFyeSgnd3JhbmdsZXInLCAnd3JhbmdsZXInKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVByb2R1Y3Rpb25CdWlsZEVudihleHRyYUVudiA9IHt9KSB7XG5cdHJldHVybiB7XG5cdFx0VFJFRVNFRURfTE9DQUxfREVWX01PREU6ICdjbG91ZGZsYXJlJyxcblx0XHRUUkVFU0VFRF9QVUJMSUNfRk9STVNfTE9DQUxfQllQQVNTX1RVUk5TVElMRTogJycsXG5cdFx0VFJFRVNFRURfRk9STVNfTE9DQUxfQllQQVNTX1RVUk5TVElMRTogJycsXG5cdFx0VFJFRVNFRURfRk9STVNfTE9DQUxfQllQQVNTX0NMT1VERkxBUkVfR1VBUkRTOiAnJyxcblx0XHRUUkVFU0VFRF9QVUJMSUNfREVWX1dBVENIX1JFTE9BRDogJycsXG5cdFx0Li4uZXh0cmFFbnYsXG5cdH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYWNrYWdlU2NyaXB0UGF0aChzY3JpcHROYW1lKSB7XG5cdGlmIChleHRuYW1lKHNjcmlwdE5hbWUpKSB7XG5cdFx0cmV0dXJuIHJlc29sdmUocGFja2FnZVNjcmlwdFJvb3QsIHNjcmlwdE5hbWUpO1xuXHR9XG5cblx0Zm9yIChjb25zdCBleHRlbnNpb24gb2YgWycuanMnLCAnLnRzJywgJy5tanMnXSkge1xuXHRcdGNvbnN0IGNhbmRpZGF0ZSA9IHJlc29sdmUocGFja2FnZVNjcmlwdFJvb3QsIGAke3NjcmlwdE5hbWV9JHtleHRlbnNpb259YCk7XG5cdFx0aWYgKGV4aXN0c1N5bmMoY2FuZGlkYXRlKSkge1xuXHRcdFx0cmV0dXJuIGNhbmRpZGF0ZTtcblx0XHR9XG5cdH1cblxuXHR0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byByZXNvbHZlIHBhY2thZ2Ugc2NyaXB0IFwiJHtzY3JpcHROYW1lfVwiLmApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuTm9kZUJpbmFyeShiaW5QYXRoLCBhcmdzLCBvcHRpb25zID0ge30pIHtcblx0Y29uc3QgcmVzdWx0ID0gc3Bhd25TeW5jKHByb2Nlc3MuZXhlY1BhdGgsIFtiaW5QYXRoLCAuLi5hcmdzXSwge1xuXHRcdHN0ZGlvOiBvcHRpb25zLnN0ZGlvID8/ICdpbmhlcml0Jyxcblx0XHRjd2Q6IG9wdGlvbnMuY3dkID8/IHByb2Nlc3MuY3dkKCksXG5cdFx0ZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi4ob3B0aW9ucy5lbnYgPz8ge30pIH0sXG5cdH0pO1xuXG5cdGlmIChyZXN1bHQuc3RhdHVzICE9PSAwKSB7XG5cdFx0cHJvY2Vzcy5leGl0KHJlc3VsdC5zdGF0dXMgPz8gMSk7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1bk5vZGVTY3JpcHQoc2NyaXB0UGF0aCwgYXJncyA9IFtdLCBvcHRpb25zID0ge30pIHtcblx0cmV0dXJuIHJ1bk5vZGVCaW5hcnkoc2NyaXB0UGF0aCwgYXJncywgb3B0aW9ucyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzcGF3bk5vZGVCaW5hcnkoYmluUGF0aCwgYXJncywgb3B0aW9ucyA9IHt9KSB7XG5cdHJldHVybiBzcGF3bihwcm9jZXNzLmV4ZWNQYXRoLCBbYmluUGF0aCwgLi4uYXJnc10sIHtcblx0XHRzdGRpbzogb3B0aW9ucy5zdGRpbyA/PyAnaW5oZXJpdCcsXG5cdFx0Y3dkOiBvcHRpb25zLmN3ZCA/PyBwcm9jZXNzLmN3ZCgpLFxuXHRcdGVudjogeyAuLi5wcm9jZXNzLmVudiwgLi4uKG9wdGlvbnMuZW52ID8/IHt9KSB9LFxuXHRcdGRldGFjaGVkOiBvcHRpb25zLmRldGFjaGVkID8/IGZhbHNlLFxuXHR9KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBQSxTQUFTLGNBQWMsWUFBWSxXQUFXLGFBQWEsY0FBYyxRQUFRLHFCQUFxQjtBQUN0RyxTQUFTLFdBQUFBLFVBQVMsV0FBQUMsVUFBUyxNQUFNLFVBQVUsV0FBQUMsZ0JBQWU7QUFDMUQsU0FBUyxhQUFhO0FBQ3RCLE9BQU8sUUFBUTs7O0FDRGYsU0FBUyxTQUFTLFNBQVMsZUFBZTtBQUMxQyxTQUFTLHFCQUFxQjtBQUU5QixTQUFTLHFCQUFxQjtBQUU5QixJQUFNQyxXQUFVLGNBQWMsWUFBWSxHQUFHO0FBQzdDLElBQU0sYUFBYSxRQUFRLGNBQWMsWUFBWSxHQUFHLENBQUM7QUFDekQsSUFBTSxtQkFBbUIsUUFBUSxZQUFZLElBQUk7QUFFMUMsSUFBTSxjQUFjLGlCQUFpQixTQUFTLE9BQU8sSUFDekQsUUFBUSxrQkFBa0IsSUFBSSxJQUM5QjtBQUNJLElBQU0sb0JBQW9CLGlCQUFpQixTQUFTLE9BQU8sSUFDL0QsUUFBUSxrQkFBa0IsU0FBUyxJQUNuQyxRQUFRLGFBQWEsU0FBUzs7O0FEVmpDLElBQU0sVUFBVUMsU0FBUSxhQUFhLEtBQUs7QUFDMUMsSUFBTSxjQUFjQSxTQUFRLGFBQWEsU0FBUztBQUNsRCxJQUFNLFdBQVdBLFNBQVEsYUFBYSxNQUFNO0FBRTVDLElBQU0sa0JBQWtCLG9CQUFJLElBQUksQ0FBQyxTQUFTLFNBQVMsS0FBSyxDQUFDO0FBRXpELFNBQVMsVUFBVSxNQUFNO0FBQ3hCLFFBQU0sUUFBUSxDQUFDO0FBQ2YsYUFBVyxTQUFTLFlBQVksTUFBTSxFQUFF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Q3ZDLFlBQVksTUFBTTtBQUFBLElBQ25CLENBQUM7QUFDRCxVQUFNLElBQUksTUFBTTtBQUFBLEVBQThCLFdBQVcsRUFBRTtBQUFBLEVBQzVEO0FBQ0Q7QUFFQSxPQUFPLFVBQVUsRUFBRSxXQUFXLE1BQU0sT0FBTyxLQUFLLENBQUM7QUFFakQsV0FBVyxZQUFZLFVBQVUsT0FBTyxHQUFHO0FBQzFDLFFBQU0sWUFBWUEsU0FBUSxRQUFRO0FBQ2xDLE1BQUksY0FBYyxPQUFPO0FBQ3hCLFVBQU0sY0FBYyxVQUFVLFNBQVMsUUFBUTtBQUMvQztBQUFBLEVBQ0Q7QUFFQSxNQUFJLGdCQUFnQixJQUFJLFNBQVMsR0FBRztBQUNuQyxjQUFVLFVBQVUsU0FBUyxRQUFRO0FBQUEsRUFDdEM7QUFDRDtBQUVBLFdBQVcsWUFBWSxVQUFVLFdBQVcsR0FBRztBQUM5QyxRQUFNLFlBQVlBLFNBQVEsUUFBUTtBQUNsQyxNQUFJLGNBQWMsU0FBUyxjQUFjLFFBQVE7QUFDaEQsb0JBQWdCLFFBQVE7QUFBQSxFQUN6QjtBQUNEO0FBRUEsaUJBQWlCO0FBRWpCLElBQUksV0FBV0YsU0FBUSxhQUFhLFdBQVcsQ0FBQyxHQUFHO0FBQ2xELGVBQWFBLFNBQVEsYUFBYSxXQUFXLEdBQUdBLFNBQVEsVUFBVSxNQUFNLFdBQVcsQ0FBQztBQUNyRjsiLAogICJuYW1lcyI6IFsiZGlybmFtZSIsICJleHRuYW1lIiwgInJlc29sdmUiLCAicmVxdWlyZSIsICJyZXNvbHZlIiwgImRpcm5hbWUiLCAiZXh0bmFtZSJdCn0K
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const semverTagPattern = /^\d+\.\d+\.\d+$/;
5
+ const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)));
6
+ const packageJsonPath = resolve(packageRoot, 'package.json');
7
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
8
+ const packageVersion = packageJson.version;
9
+ const tagName = process.argv[2] || process.env.GITHUB_REF_NAME;
10
+ if (!tagName) {
11
+ console.error('Release tag validation requires a tag name argument or GITHUB_REF_NAME.');
12
+ process.exit(1);
13
+ }
14
+ if (!semverTagPattern.test(tagName)) {
15
+ console.error(`Release tag "${tagName}" must use the "{MAJOR}.{MINOR}.{PATCH}" format, for example "${packageVersion}".`);
16
+ process.exit(1);
17
+ }
18
+ const taggedVersion = tagName;
19
+ if (taggedVersion !== packageVersion) {
20
+ console.error(`Release tag version "${taggedVersion}" does not match @treeseed/sdk version "${packageVersion}".`);
21
+ process.exit(1);
22
+ }
23
+ console.log(`Release tag "${tagName}" matches @treeseed/sdk version "${packageVersion}".`);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,114 @@
1
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { dirname, extname, join, relative, resolve } from 'node:path';
3
+ import { build } from 'esbuild';
4
+ import ts from 'typescript';
5
+ import { packageRoot } from './package-tools.js';
6
+ const srcRoot = resolve(packageRoot, 'src');
7
+ const scriptsRoot = resolve(packageRoot, 'scripts');
8
+ const distRoot = resolve(packageRoot, 'dist');
9
+ const COPY_EXTENSIONS = new Set(['.d.js', '.json', '.md']);
10
+ function walkFiles(root) {
11
+ const files = [];
12
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
13
+ const fullPath = join(root, entry.name);
14
+ if (entry.isDirectory()) {
15
+ files.push(...walkFiles(fullPath));
16
+ continue;
17
+ }
18
+ files.push(fullPath);
19
+ }
20
+ return files;
21
+ }
22
+ function ensureDir(filePath) {
23
+ mkdirSync(dirname(filePath), { recursive: true });
24
+ }
25
+ function rewriteRuntimeSpecifiers(contents) {
26
+ return contents.replace(/(['"`])(\.[^'"`\n]+)\.(mjs|ts)\1/g, '$1$2.js$1');
27
+ }
28
+ async function compileModule(filePath, sourceRoot, outputRoot) {
29
+ const relativePath = relative(sourceRoot, filePath);
30
+ const outputFile = resolve(outputRoot, relativePath.replace(/\.(mjs|ts)$/u, '.js'));
31
+ ensureDir(outputFile);
32
+ await build({
33
+ entryPoints: [filePath],
34
+ outfile: outputFile,
35
+ platform: 'node',
36
+ format: 'esm',
37
+ bundle: false,
38
+ logLevel: 'silent',
39
+ });
40
+ const builtSource = readFileSync(outputFile, 'utf8');
41
+ writeFileSync(outputFile, rewriteRuntimeSpecifiers(builtSource), 'utf8');
42
+ }
43
+ function copyAsset(filePath, sourceRoot, outputRoot) {
44
+ const outputFile = resolve(outputRoot, relative(sourceRoot, filePath));
45
+ ensureDir(outputFile);
46
+ copyFileSync(filePath, outputFile);
47
+ if (outputFile.endsWith('.d.js')) {
48
+ const contents = readFileSync(outputFile, 'utf8');
49
+ writeFileSync(outputFile, rewriteRuntimeSpecifiers(contents), 'utf8');
50
+ }
51
+ }
52
+ function transpileScript(filePath) {
53
+ const source = readFileSync(filePath, 'utf8');
54
+ const relativePath = relative(scriptsRoot, filePath);
55
+ const outputFile = resolve(distRoot, 'scripts', relativePath.replace(/\.(mjs|ts)$/u, '.js'));
56
+ const transformed = extname(filePath) === '.ts'
57
+ ? ts.transpileModule(source, {
58
+ compilerOptions: {
59
+ module: ts.ModuleKind.ESNext,
60
+ target: ts.ScriptTarget.ES2022,
61
+ },
62
+ }).outputText
63
+ : source;
64
+ ensureDir(outputFile);
65
+ writeFileSync(outputFile, rewriteRuntimeSpecifiers(transformed), 'utf8');
66
+ }
67
+ function emitDeclarations() {
68
+ const configPath = ts.findConfigFile(packageRoot, ts.sys.fileExists, 'tsconfig.json');
69
+ if (!configPath) {
70
+ throw new Error('Unable to locate tsconfig.json for declaration build.');
71
+ }
72
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
73
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, packageRoot);
74
+ const program = ts.createProgram({
75
+ rootNames: parsed.fileNames,
76
+ options: {
77
+ ...parsed.options,
78
+ declaration: true,
79
+ emitDeclarationOnly: true,
80
+ declarationDir: distRoot,
81
+ noEmit: false,
82
+ },
83
+ });
84
+ const result = program.emit();
85
+ if (result.emitSkipped) {
86
+ const diagnostics = ts.formatDiagnosticsWithColorAndContext(result.diagnostics, {
87
+ getCanonicalFileName: (fileName) => fileName,
88
+ getCurrentDirectory: () => process.cwd(),
89
+ getNewLine: () => '\n',
90
+ });
91
+ throw new Error(`Declaration build failed.\n${diagnostics}`);
92
+ }
93
+ }
94
+ rmSync(distRoot, { recursive: true, force: true });
95
+ for (const filePath of walkFiles(srcRoot)) {
96
+ const extension = extname(filePath);
97
+ if (extension === '.ts') {
98
+ await compileModule(filePath, srcRoot, distRoot);
99
+ continue;
100
+ }
101
+ if (COPY_EXTENSIONS.has(extension)) {
102
+ copyAsset(filePath, srcRoot, distRoot);
103
+ }
104
+ }
105
+ for (const filePath of walkFiles(scriptsRoot)) {
106
+ const extension = extname(filePath);
107
+ if (extension === '.ts' || extension === '.mjs') {
108
+ transpileScript(filePath);
109
+ }
110
+ }
111
+ emitDeclarations();
112
+ if (existsSync(resolve(packageRoot, 'README.md'))) {
113
+ copyFileSync(resolve(packageRoot, 'README.md'), resolve(distRoot, '..', 'README.md'));
114
+ }
@@ -0,0 +1,15 @@
1
+ export declare const packageRoot: string;
2
+ export declare const packageScriptRoot: string;
3
+ export declare function resolveAstroBin(): string;
4
+ export declare function resolveWranglerBin(): string;
5
+ export declare function createProductionBuildEnv(extraEnv?: {}): {
6
+ TREESEED_LOCAL_DEV_MODE: string;
7
+ TREESEED_PUBLIC_FORMS_LOCAL_BYPASS_TURNSTILE: string;
8
+ TREESEED_FORMS_LOCAL_BYPASS_TURNSTILE: string;
9
+ TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS: string;
10
+ TREESEED_PUBLIC_DEV_WATCH_RELOAD: string;
11
+ };
12
+ export declare function packageScriptPath(scriptName: any): string;
13
+ export declare function runNodeBinary(binPath: any, args: any, options?: {}): void;
14
+ export declare function runNodeScript(scriptPath: any, args?: never[], options?: {}): void;
15
+ export declare function spawnNodeBinary(binPath: any, args: any, options?: {}): import("child_process").ChildProcessWithoutNullStreams;
@@ -0,0 +1,76 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { existsSync } from 'node:fs';
3
+ import { dirname, extname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { spawn, spawnSync } from 'node:child_process';
6
+ import { createRequire } from 'node:module';
7
+ const require = createRequire(import.meta.url);
8
+ const scriptRoot = dirname(fileURLToPath(import.meta.url));
9
+ const packageCandidate = resolve(scriptRoot, '..');
10
+ export const packageRoot = packageCandidate.endsWith('/dist')
11
+ ? resolve(packageCandidate, '..')
12
+ : packageCandidate;
13
+ export const packageScriptRoot = packageCandidate.endsWith('/dist')
14
+ ? resolve(packageCandidate, 'scripts')
15
+ : resolve(packageRoot, 'scripts');
16
+ function resolvePackageBinary(packageName, binName = packageName) {
17
+ const packageJsonPath = require.resolve(`${packageName}/package.json`);
18
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
19
+ const binField = packageJson.bin;
20
+ const relativePath = typeof binField === 'string'
21
+ ? binField
22
+ : binField?.[binName];
23
+ if (!relativePath) {
24
+ throw new Error(`Unable to resolve binary "${binName}" from package "${packageName}".`);
25
+ }
26
+ return resolve(dirname(packageJsonPath), relativePath);
27
+ }
28
+ export function resolveAstroBin() {
29
+ return resolvePackageBinary('astro', 'astro');
30
+ }
31
+ export function resolveWranglerBin() {
32
+ return resolvePackageBinary('wrangler', 'wrangler');
33
+ }
34
+ export function createProductionBuildEnv(extraEnv = {}) {
35
+ return {
36
+ TREESEED_LOCAL_DEV_MODE: 'cloudflare',
37
+ TREESEED_PUBLIC_FORMS_LOCAL_BYPASS_TURNSTILE: '',
38
+ TREESEED_FORMS_LOCAL_BYPASS_TURNSTILE: '',
39
+ TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS: '',
40
+ TREESEED_PUBLIC_DEV_WATCH_RELOAD: '',
41
+ ...extraEnv,
42
+ };
43
+ }
44
+ export function packageScriptPath(scriptName) {
45
+ if (extname(scriptName)) {
46
+ return resolve(packageScriptRoot, scriptName);
47
+ }
48
+ for (const extension of ['.js', '.ts', '.mjs']) {
49
+ const candidate = resolve(packageScriptRoot, `${scriptName}${extension}`);
50
+ if (existsSync(candidate)) {
51
+ return candidate;
52
+ }
53
+ }
54
+ throw new Error(`Unable to resolve package script "${scriptName}".`);
55
+ }
56
+ export function runNodeBinary(binPath, args, options = {}) {
57
+ const result = spawnSync(process.execPath, [binPath, ...args], {
58
+ stdio: options.stdio ?? 'inherit',
59
+ cwd: options.cwd ?? process.cwd(),
60
+ env: { ...process.env, ...(options.env ?? {}) },
61
+ });
62
+ if (result.status !== 0) {
63
+ process.exit(result.status ?? 1);
64
+ }
65
+ }
66
+ export function runNodeScript(scriptPath, args = [], options = {}) {
67
+ return runNodeBinary(scriptPath, args, options);
68
+ }
69
+ export function spawnNodeBinary(binPath, args, options = {}) {
70
+ return spawn(process.execPath, [binPath, ...args], {
71
+ stdio: options.stdio ?? 'inherit',
72
+ cwd: options.cwd ?? process.cwd(),
73
+ env: { ...process.env, ...(options.env ?? {}) },
74
+ detached: options.detached ?? false,
75
+ });
76
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)));
5
+ const extraArgs = process.argv.slice(2);
6
+ const npmArgs = ['publish', '.', '--access', 'public'];
7
+ if (process.env.GITHUB_ACTIONS === 'true') {
8
+ npmArgs.push('--provenance');
9
+ }
10
+ npmArgs.push(...extraArgs);
11
+ const result = spawnSync('npm', npmArgs, {
12
+ cwd: packageRoot,
13
+ stdio: 'inherit',
14
+ env: process.env,
15
+ });
16
+ if (result.error) {
17
+ console.error(result.error.message);
18
+ process.exit(1);
19
+ }
20
+ process.exit(result.status ?? 1);
@@ -0,0 +1 @@
1
+ export {};