@yg-toolkit/datapull 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 (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +74 -0
  3. package/dist/cli/program.d.ts +4 -0
  4. package/dist/cli/program.d.ts.map +1 -0
  5. package/dist/cli/program.js +540 -0
  6. package/dist/cli/program.js.map +1 -0
  7. package/dist/config/dotenv.d.ts +4 -0
  8. package/dist/config/dotenv.d.ts.map +1 -0
  9. package/dist/config/dotenv.js +47 -0
  10. package/dist/config/dotenv.js.map +1 -0
  11. package/dist/config/paths.d.ts +8 -0
  12. package/dist/config/paths.d.ts.map +1 -0
  13. package/dist/config/paths.js +24 -0
  14. package/dist/config/paths.js.map +1 -0
  15. package/dist/config/schema.d.ts +59 -0
  16. package/dist/config/schema.d.ts.map +1 -0
  17. package/dist/config/schema.js +73 -0
  18. package/dist/config/schema.js.map +1 -0
  19. package/dist/config/security.d.ts +12 -0
  20. package/dist/config/security.d.ts.map +1 -0
  21. package/dist/config/security.js +86 -0
  22. package/dist/config/security.js.map +1 -0
  23. package/dist/config/store.d.ts +19 -0
  24. package/dist/config/store.d.ts.map +1 -0
  25. package/dist/config/store.js +120 -0
  26. package/dist/config/store.js.map +1 -0
  27. package/dist/connections/service.d.ts +34 -0
  28. package/dist/connections/service.d.ts.map +1 -0
  29. package/dist/connections/service.js +220 -0
  30. package/dist/connections/service.js.map +1 -0
  31. package/dist/core/errors.d.ts +9 -0
  32. package/dist/core/errors.d.ts.map +1 -0
  33. package/dist/core/errors.js +29 -0
  34. package/dist/core/errors.js.map +1 -0
  35. package/dist/core/output.d.ts +16 -0
  36. package/dist/core/output.d.ts.map +1 -0
  37. package/dist/core/output.js +91 -0
  38. package/dist/core/output.js.map +1 -0
  39. package/dist/core/runtime.d.ts +3 -0
  40. package/dist/core/runtime.d.ts.map +1 -0
  41. package/dist/core/runtime.js +14 -0
  42. package/dist/core/runtime.js.map +1 -0
  43. package/dist/doctor/service.d.ts +9 -0
  44. package/dist/doctor/service.d.ts.map +1 -0
  45. package/dist/doctor/service.js +81 -0
  46. package/dist/doctor/service.js.map +1 -0
  47. package/dist/exporters/exporter.d.ts +10 -0
  48. package/dist/exporters/exporter.d.ts.map +1 -0
  49. package/dist/exporters/exporter.js +2 -0
  50. package/dist/exporters/exporter.js.map +1 -0
  51. package/dist/exporters/factory.d.ts +4 -0
  52. package/dist/exporters/factory.d.ts.map +1 -0
  53. package/dist/exporters/factory.js +11 -0
  54. package/dist/exporters/factory.js.map +1 -0
  55. package/dist/exporters/mysql.d.ts +16 -0
  56. package/dist/exporters/mysql.d.ts.map +1 -0
  57. package/dist/exporters/mysql.js +177 -0
  58. package/dist/exporters/mysql.js.map +1 -0
  59. package/dist/exporters/objects.d.ts +4 -0
  60. package/dist/exporters/objects.d.ts.map +1 -0
  61. package/dist/exporters/objects.js +32 -0
  62. package/dist/exporters/objects.js.map +1 -0
  63. package/dist/exporters/postgresql.d.ts +16 -0
  64. package/dist/exporters/postgresql.d.ts.map +1 -0
  65. package/dist/exporters/postgresql.js +228 -0
  66. package/dist/exporters/postgresql.js.map +1 -0
  67. package/dist/exporters/sql.d.ts +5 -0
  68. package/dist/exporters/sql.d.ts.map +1 -0
  69. package/dist/exporters/sql.js +14 -0
  70. package/dist/exporters/sql.js.map +1 -0
  71. package/dist/exporters/sqlserver.d.ts +11 -0
  72. package/dist/exporters/sqlserver.d.ts.map +1 -0
  73. package/dist/exporters/sqlserver.js +126 -0
  74. package/dist/exporters/sqlserver.js.map +1 -0
  75. package/dist/index.d.ts +3 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +71 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/interactive/connections.d.ts +16 -0
  80. package/dist/interactive/connections.d.ts.map +1 -0
  81. package/dist/interactive/connections.js +97 -0
  82. package/dist/interactive/connections.js.map +1 -0
  83. package/dist/interactive/wizard.d.ts +4 -0
  84. package/dist/interactive/wizard.d.ts.map +1 -0
  85. package/dist/interactive/wizard.js +284 -0
  86. package/dist/interactive/wizard.js.map +1 -0
  87. package/dist/output/transaction.d.ts +39 -0
  88. package/dist/output/transaction.d.ts.map +1 -0
  89. package/dist/output/transaction.js +329 -0
  90. package/dist/output/transaction.js.map +1 -0
  91. package/dist/process/runner.d.ts +14 -0
  92. package/dist/process/runner.d.ts.map +1 -0
  93. package/dist/process/runner.js +43 -0
  94. package/dist/process/runner.js.map +1 -0
  95. package/dist/pull/service.d.ts +24 -0
  96. package/dist/pull/service.d.ts.map +1 -0
  97. package/dist/pull/service.js +102 -0
  98. package/dist/pull/service.js.map +1 -0
  99. package/dist/skills/installer.d.ts +25 -0
  100. package/dist/skills/installer.d.ts.map +1 -0
  101. package/dist/skills/installer.js +177 -0
  102. package/dist/skills/installer.js.map +1 -0
  103. package/dist/skills/targets.d.ts +12 -0
  104. package/dist/skills/targets.d.ts.map +1 -0
  105. package/dist/skills/targets.js +37 -0
  106. package/dist/skills/targets.js.map +1 -0
  107. package/dist/tools/catalog.d.ts +17 -0
  108. package/dist/tools/catalog.d.ts.map +1 -0
  109. package/dist/tools/catalog.js +161 -0
  110. package/dist/tools/catalog.js.map +1 -0
  111. package/dist/tools/manager.d.ts +21 -0
  112. package/dist/tools/manager.d.ts.map +1 -0
  113. package/dist/tools/manager.js +110 -0
  114. package/dist/tools/manager.js.map +1 -0
  115. package/dist/types.d.ts +51 -0
  116. package/dist/types.d.ts.map +1 -0
  117. package/dist/types.js +3 -0
  118. package/dist/types.js.map +1 -0
  119. package/dist/utils/fs.d.ts +3 -0
  120. package/dist/utils/fs.d.ts.map +1 -0
  121. package/dist/utils/fs.js +43 -0
  122. package/dist/utils/fs.js.map +1 -0
  123. package/dist/utils/path.d.ts +4 -0
  124. package/dist/utils/path.d.ts.map +1 -0
  125. package/dist/utils/path.js +47 -0
  126. package/dist/utils/path.js.map +1 -0
  127. package/package.json +68 -0
  128. package/resources/ci/mysql-seed.sql +36 -0
  129. package/resources/ci/postgresql-seed.sql +45 -0
  130. package/resources/ci/sqlserver-seed.sql +57 -0
  131. package/resources/compatibility-matrix.json +315 -0
  132. package/resources/export-sqlserver.ps1 +257 -0
  133. package/skill/SKILL.md +42 -0
  134. package/skill/agents/openai.yaml +6 -0
@@ -0,0 +1,51 @@
1
+ export declare const ENGINES: readonly ["mysql", "postgresql", "sqlserver"];
2
+ export type Engine = (typeof ENGINES)[number];
3
+ export declare const AUTH_MODES: readonly ["password", "url", "integrated"];
4
+ export type AuthMode = (typeof AUTH_MODES)[number];
5
+ export interface ConnectionConfig {
6
+ alias: string;
7
+ engine: Engine;
8
+ authMode: AuthMode;
9
+ host?: string | undefined;
10
+ port?: number | undefined;
11
+ username?: string | undefined;
12
+ credentialRef?: string | undefined;
13
+ urlRef?: string | undefined;
14
+ sslMode?: string | undefined;
15
+ recentDatabases: string[];
16
+ favoriteDatabases: string[];
17
+ tls?: {
18
+ encrypt: true;
19
+ trustServerCertificate: boolean;
20
+ } | undefined;
21
+ }
22
+ export interface GlobalConfig {
23
+ version: 1;
24
+ onboarding: {
25
+ skillPrompted: boolean;
26
+ };
27
+ connections: ConnectionConfig[];
28
+ }
29
+ export interface ResolvedConnection extends ConnectionConfig {
30
+ database?: string | undefined;
31
+ password?: string | undefined;
32
+ secretUrl?: string | undefined;
33
+ }
34
+ export interface DatabaseObject {
35
+ type: string;
36
+ schema?: string | undefined;
37
+ name: string;
38
+ identity?: string | undefined;
39
+ ddl: string;
40
+ }
41
+ export interface PullResult {
42
+ connectionAlias: string;
43
+ engine: Engine;
44
+ database: string;
45
+ projectRoot: string;
46
+ outputPath: string;
47
+ updatedTypes: string[];
48
+ preservedTypes: string[];
49
+ objectCounts: Record<string, number>;
50
+ }
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,YAAI,OAAO,EAAE,YAAY,EAAE,WAAW,CAAU,CAAC;AACrE,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,eAAO,MAAM,UAAU,YAAI,UAAU,EAAE,KAAK,EAAE,YAAY,CAAU,CAAC;AACrE,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,GAAG,CAAC,EACA;QACE,OAAO,EAAE,IAAI,CAAC;QACd,sBAAsB,EAAE,OAAO,CAAC;KACjC,GACD,SAAS,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE;QACV,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ export const ENGINES = ["mysql", "postgresql", "sqlserver"];
2
+ export const AUTH_MODES = ["password", "url", "integrated"];
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAU,CAAC;AAGrE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,CAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function pathExists(path: string): Promise<boolean>;
2
+ export declare function atomicWriteFile(path: string, content: string, mode?: number): Promise<void>;
3
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAuBf"}
@@ -0,0 +1,43 @@
1
+ import { constants } from "node:fs";
2
+ import { access, mkdir, rename, rm, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { randomUUID } from "node:crypto";
5
+ export async function pathExists(path) {
6
+ try {
7
+ await access(path, constants.F_OK);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ export async function atomicWriteFile(path, content, mode) {
15
+ await mkdir(dirname(path), { recursive: true });
16
+ const temporary = `${path}.${randomUUID()}.tmp`;
17
+ await writeFile(temporary, content, {
18
+ encoding: "utf8",
19
+ ...(mode === undefined ? {} : { mode }),
20
+ });
21
+ try {
22
+ await rename(temporary, path);
23
+ }
24
+ catch (error) {
25
+ if (!(await pathExists(path)))
26
+ throw error;
27
+ const previous = `${path}.${randomUUID()}.previous`;
28
+ await rename(path, previous);
29
+ try {
30
+ await rename(temporary, path);
31
+ await rm(previous, { force: true });
32
+ }
33
+ catch (replaceError) {
34
+ if (await pathExists(previous))
35
+ await rename(previous, path);
36
+ throw replaceError;
37
+ }
38
+ }
39
+ finally {
40
+ await rm(temporary, { force: true });
41
+ }
42
+ }
43
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,OAAe,EACf,IAAa;IAEb,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;IAChD,MAAM,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE;QAClC,QAAQ,EAAE,MAAM;QAChB,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;KACxC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;YAAE,MAAM,KAAK,CAAC;QAC3C,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,WAAW,CAAC;QACpD,MAAM,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC9B,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,YAAY,EAAE,CAAC;YACtB,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC;gBAAE,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC7D,MAAM,YAAY,CAAC;QACrB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function validatePathSegment(value: string, label: string): string;
2
+ export declare function safeFileName(value: string, identity: string, forceHash?: boolean): string;
3
+ export declare function discoverProjectRoot(start?: string): Promise<string>;
4
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAQA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBxE;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,GAChB,MAAM,CAWR;AAED,wBAAsB,mBAAmB,CAAC,KAAK,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUhF"}
@@ -0,0 +1,47 @@
1
+ import { createHash } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import { execa } from "execa";
4
+ import { DataPullError } from "../core/errors.js";
5
+ const WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\..*)?$/i;
6
+ const INVALID_SEGMENT = /[<>:"/\\|?*\u0000-\u001f]/gu;
7
+ export function validatePathSegment(value, label) {
8
+ const normalized = value.trim();
9
+ if (normalized.length === 0 ||
10
+ normalized === "." ||
11
+ normalized === ".." ||
12
+ INVALID_SEGMENT.test(normalized) ||
13
+ WINDOWS_RESERVED.test(normalized) ||
14
+ normalized.endsWith(".") ||
15
+ normalized.endsWith(" ")) {
16
+ throw new DataPullError(label === "数据库名" ? "INVALID_DATABASE_NAME" : "OUTPUT_PATH_UNSAFE", `${label}不是安全的单级路径名称:${value}`, label === "数据库名" ? 2 : 5);
17
+ }
18
+ return normalized;
19
+ }
20
+ export function safeFileName(value, identity, forceHash = false) {
21
+ let readable = value
22
+ .replace(INVALID_SEGMENT, "_")
23
+ .replace(/\s+/gu, "_")
24
+ .replace(/^[._ ]+|[._ ]+$/gu, "");
25
+ if (readable.length === 0 || WINDOWS_RESERVED.test(readable))
26
+ readable = "object";
27
+ if (readable.length > 100)
28
+ readable = readable.slice(0, 100).replace(/[. ]+$/gu, "");
29
+ const changed = readable !== value;
30
+ if (!changed && !forceHash)
31
+ return `${readable}.sql`;
32
+ const hash = createHash("sha256").update(identity).digest("hex").slice(0, 10);
33
+ return `${readable}--${hash}.sql`;
34
+ }
35
+ export async function discoverProjectRoot(start = process.cwd()) {
36
+ try {
37
+ const result = await execa("git", ["rev-parse", "--show-toplevel"], {
38
+ cwd: start,
39
+ reject: true,
40
+ });
41
+ return resolve(result.stdout.trim());
42
+ }
43
+ catch {
44
+ return resolve(start);
45
+ }
46
+ }
47
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,gBAAgB,GAAG,iDAAiD,CAAC;AAC3E,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAEtD,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,KAAa;IAC9D,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IACE,UAAU,CAAC,MAAM,KAAK,CAAC;QACvB,UAAU,KAAK,GAAG;QAClB,UAAU,KAAK,IAAI;QACnB,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC;QAChC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC;QACjC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxB,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EACxB,CAAC;QACD,MAAM,IAAI,aAAa,CACrB,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,oBAAoB,EACjE,GAAG,KAAK,eAAe,KAAK,EAAE,EAC9B,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACzB,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAa,EACb,QAAgB,EAChB,SAAS,GAAG,KAAK;IAEjB,IAAI,QAAQ,GAAG,KAAK;SACjB,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;SAC7B,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,QAAQ,GAAG,QAAQ,CAAC;IAClF,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG;QAAE,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,QAAQ,KAAK,KAAK,CAAC;IACnC,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS;QAAE,OAAO,GAAG,QAAQ,MAAM,CAAC;IACrD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,OAAO,GAAG,QAAQ,KAAK,IAAI,MAAM,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE;YAClE,GAAG,EAAE,KAAK;YACV,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@yg-toolkit/datapull",
3
+ "version": "0.1.0",
4
+ "description": "面向人类交互、同时支持 Agent 自动化的数据库结构文件拉取 CLI",
5
+ "type": "module",
6
+ "bin": {
7
+ "datapull": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "resources",
12
+ "skill",
13
+ "LICENSE"
14
+ ],
15
+ "engines": {
16
+ "node": ">=22.12.0"
17
+ },
18
+ "scripts": {
19
+ "build": "node scripts/clean.mjs && tsc -p tsconfig.build.json",
20
+ "check": "tsc -p tsconfig.json --noEmit",
21
+ "clean": "node scripts/clean.mjs",
22
+ "ci:compatibility": "node scripts/ci/run-compatibility.mjs",
23
+ "dev": "tsx src/index.ts",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "skill:sync": "node scripts/sync-skill.mjs",
27
+ "skill:check": "node scripts/check-skill-sync.mjs",
28
+ "prepack": "npm run check && npm test && npm run build && npm run skill:check",
29
+ "release:check": "node scripts/check-release-matrix.mjs",
30
+ "prepublishOnly": "npm run prepack && npm run release:check"
31
+ },
32
+ "keywords": [
33
+ "database",
34
+ "schema",
35
+ "ddl",
36
+ "mysql",
37
+ "postgresql",
38
+ "sqlserver",
39
+ "cli"
40
+ ],
41
+ "license": "MIT",
42
+ "author": "约格",
43
+ "homepage": "https://github.com/phoben/agent-skills#readme",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/phoben/agent-skills.git",
47
+ "directory": "cli/datapull"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/phoben/agent-skills/issues"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "dependencies": {
56
+ "@inquirer/prompts": "7.10.1",
57
+ "commander": "15.0.0",
58
+ "execa": "10.0.1",
59
+ "listr2": "10.1.1",
60
+ "zod": "4.6.5"
61
+ },
62
+ "devDependencies": {
63
+ "@types/node": "24.13.5",
64
+ "tsx": "4.23.13",
65
+ "typescript": "7.0.2",
66
+ "vitest": "5.0.1"
67
+ }
68
+ }
@@ -0,0 +1,36 @@
1
+ CREATE TABLE datapull_ci_item (
2
+ id bigint NOT NULL AUTO_INCREMENT,
3
+ code varchar(32) NOT NULL,
4
+ payload varchar(255) NULL,
5
+ PRIMARY KEY (id),
6
+ UNIQUE KEY uk_datapull_ci_item_code (code)
7
+ );
8
+
9
+ INSERT INTO datapull_ci_item (code, payload)
10
+ VALUES ('seed', 'DATAPULL_BUSINESS_DATA_MUST_NOT_APPEAR');
11
+
12
+ CREATE VIEW datapull_ci_item_view AS
13
+ SELECT id, code FROM datapull_ci_item;
14
+
15
+ DELIMITER $$
16
+
17
+ CREATE FUNCTION datapull_ci_echo(input_value int)
18
+ RETURNS int
19
+ DETERMINISTIC
20
+ RETURN input_value$$
21
+
22
+ CREATE PROCEDURE datapull_ci_count(OUT item_count bigint)
23
+ READS SQL DATA
24
+ SELECT COUNT(*) INTO item_count FROM datapull_ci_item$$
25
+
26
+ CREATE TRIGGER datapull_ci_item_before_insert
27
+ BEFORE INSERT ON datapull_ci_item
28
+ FOR EACH ROW
29
+ SET NEW.code = TRIM(NEW.code)$$
30
+
31
+ CREATE EVENT datapull_ci_daily_event
32
+ ON SCHEDULE EVERY 1 DAY
33
+ STARTS CURRENT_TIMESTAMP + INTERVAL 1 DAY
34
+ DO DELETE FROM datapull_ci_item WHERE id < 0$$
35
+
36
+ DELIMITER ;
@@ -0,0 +1,45 @@
1
+ CREATE SCHEMA datapull_ci;
2
+ CREATE SCHEMA datapull_ci_ext;
3
+ CREATE EXTENSION hstore WITH SCHEMA datapull_ci_ext;
4
+
5
+ CREATE TYPE datapull_ci.item_state AS ENUM ('active', 'disabled');
6
+ CREATE DOMAIN datapull_ci.item_code AS text
7
+ CONSTRAINT item_code_not_blank CHECK (length(VALUE) > 0);
8
+ CREATE TYPE datapull_ci.item_pair AS (left_value integer, right_value integer);
9
+ CREATE TYPE datapull_ci.item_range AS RANGE (subtype = integer);
10
+ CREATE SEQUENCE datapull_ci.item_sequence START WITH 100;
11
+
12
+ CREATE TABLE datapull_ci.item (
13
+ id bigint PRIMARY KEY DEFAULT nextval('datapull_ci.item_sequence'),
14
+ code datapull_ci.item_code NOT NULL,
15
+ state datapull_ci.item_state NOT NULL DEFAULT 'active',
16
+ payload text
17
+ );
18
+
19
+ INSERT INTO datapull_ci.item (code, payload)
20
+ VALUES ('seed', 'DATAPULL_BUSINESS_DATA_MUST_NOT_APPEAR');
21
+
22
+ CREATE VIEW datapull_ci.item_view AS
23
+ SELECT id, code, state FROM datapull_ci.item;
24
+
25
+ CREATE MATERIALIZED VIEW datapull_ci.item_materialized_view AS
26
+ SELECT state, count(*) AS item_count FROM datapull_ci.item GROUP BY state;
27
+
28
+ CREATE FUNCTION datapull_ci.echo(input_value integer)
29
+ RETURNS integer
30
+ LANGUAGE sql
31
+ IMMUTABLE
32
+ AS $$ SELECT input_value $$;
33
+
34
+ CREATE PROCEDURE datapull_ci.noop()
35
+ LANGUAGE plpgsql
36
+ AS $$ BEGIN NULL; END $$;
37
+
38
+ CREATE FUNCTION datapull_ci.normalize_code()
39
+ RETURNS trigger
40
+ LANGUAGE plpgsql
41
+ AS $$ BEGIN NEW.code := btrim(NEW.code); RETURN NEW; END $$;
42
+
43
+ CREATE TRIGGER item_before_insert
44
+ BEFORE INSERT ON datapull_ci.item
45
+ FOR EACH ROW EXECUTE FUNCTION datapull_ci.normalize_code();
@@ -0,0 +1,57 @@
1
+ CREATE SCHEMA datapull_ci;
2
+ GO
3
+
4
+ CREATE TYPE datapull_ci.code_type FROM nvarchar(32) NOT NULL;
5
+ GO
6
+
7
+ CREATE SEQUENCE datapull_ci.item_sequence
8
+ AS bigint
9
+ START WITH 100
10
+ INCREMENT BY 1;
11
+ GO
12
+
13
+ CREATE TABLE datapull_ci.item (
14
+ id bigint NOT NULL CONSTRAINT df_datapull_ci_item_id DEFAULT NEXT VALUE FOR datapull_ci.item_sequence,
15
+ code datapull_ci.code_type,
16
+ payload nvarchar(255) NULL,
17
+ CONSTRAINT pk_datapull_ci_item PRIMARY KEY (id),
18
+ CONSTRAINT uq_datapull_ci_item_code UNIQUE (code)
19
+ );
20
+ GO
21
+
22
+ INSERT INTO datapull_ci.item (code, payload)
23
+ VALUES (N'seed', N'DATAPULL_BUSINESS_DATA_MUST_NOT_APPEAR');
24
+ GO
25
+
26
+ CREATE VIEW datapull_ci.item_view
27
+ AS
28
+ SELECT id, code FROM datapull_ci.item;
29
+ GO
30
+
31
+ CREATE FUNCTION datapull_ci.echo (@input_value int)
32
+ RETURNS int
33
+ AS
34
+ BEGIN
35
+ RETURN @input_value;
36
+ END;
37
+ GO
38
+
39
+ CREATE PROCEDURE datapull_ci.item_count
40
+ AS
41
+ BEGIN
42
+ SET NOCOUNT ON;
43
+ SELECT COUNT_BIG(*) AS item_count FROM datapull_ci.item;
44
+ END;
45
+ GO
46
+
47
+ CREATE TRIGGER datapull_ci.item_after_insert
48
+ ON datapull_ci.item
49
+ AFTER INSERT
50
+ AS
51
+ BEGIN
52
+ SET NOCOUNT ON;
53
+ END;
54
+ GO
55
+
56
+ CREATE SYNONYM datapull_ci.item_synonym FOR datapull_ci.item;
57
+ GO