putitoutthere 0.0.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 (79) hide show
  1. package/README.md +10 -0
  2. package/action.yml +24 -0
  3. package/dist/action.d.ts +9 -0
  4. package/dist/action.d.ts.map +1 -0
  5. package/dist/action.js +19 -0
  6. package/dist/action.js.map +1 -0
  7. package/dist/cascade.d.ts +30 -0
  8. package/dist/cascade.d.ts.map +1 -0
  9. package/dist/cascade.js +92 -0
  10. package/dist/cascade.js.map +1 -0
  11. package/dist/cli.d.ts +10 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +57 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/completeness.d.ts +34 -0
  16. package/dist/completeness.d.ts.map +1 -0
  17. package/dist/completeness.js +121 -0
  18. package/dist/completeness.js.map +1 -0
  19. package/dist/config.d.ts +132 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +128 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/git.d.ts +35 -0
  24. package/dist/git.d.ts.map +1 -0
  25. package/dist/git.js +98 -0
  26. package/dist/git.js.map +1 -0
  27. package/dist/glob.d.ts +15 -0
  28. package/dist/glob.d.ts.map +1 -0
  29. package/dist/glob.js +29 -0
  30. package/dist/glob.js.map +1 -0
  31. package/dist/handlers/crates.d.ts +8 -0
  32. package/dist/handlers/crates.d.ts.map +1 -0
  33. package/dist/handlers/crates.js +19 -0
  34. package/dist/handlers/crates.js.map +1 -0
  35. package/dist/handlers/index.d.ts +7 -0
  36. package/dist/handlers/index.d.ts.map +1 -0
  37. package/dist/handlers/index.js +22 -0
  38. package/dist/handlers/index.js.map +1 -0
  39. package/dist/handlers/npm.d.ts +7 -0
  40. package/dist/handlers/npm.d.ts.map +1 -0
  41. package/dist/handlers/npm.js +18 -0
  42. package/dist/handlers/npm.js.map +1 -0
  43. package/dist/handlers/pypi.d.ts +6 -0
  44. package/dist/handlers/pypi.d.ts.map +1 -0
  45. package/dist/handlers/pypi.js +17 -0
  46. package/dist/handlers/pypi.js.map +1 -0
  47. package/dist/index.d.ts +10 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +9 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/log.d.ts +31 -0
  52. package/dist/log.d.ts.map +1 -0
  53. package/dist/log.js +81 -0
  54. package/dist/log.js.map +1 -0
  55. package/dist/preflight.d.ts +30 -0
  56. package/dist/preflight.d.ts.map +1 -0
  57. package/dist/preflight.js +55 -0
  58. package/dist/preflight.js.map +1 -0
  59. package/dist/retry.d.ts +26 -0
  60. package/dist/retry.d.ts.map +1 -0
  61. package/dist/retry.js +91 -0
  62. package/dist/retry.js.map +1 -0
  63. package/dist/trailer.d.ts +26 -0
  64. package/dist/trailer.d.ts.map +1 -0
  65. package/dist/trailer.js +84 -0
  66. package/dist/trailer.js.map +1 -0
  67. package/dist/types.d.ts +73 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +17 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/verbose.d.ts +47 -0
  72. package/dist/verbose.d.ts.map +1 -0
  73. package/dist/verbose.js +84 -0
  74. package/dist/verbose.js.map +1 -0
  75. package/dist/version.d.ts +27 -0
  76. package/dist/version.d.ts.map +1 -0
  77. package/dist/version.js +51 -0
  78. package/dist/version.js.map +1 -0
  79. package/package.json +58 -0
package/dist/config.js ADDED
@@ -0,0 +1,128 @@
1
+ /**
2
+ * `putitoutthere.toml` loader and validator.
3
+ *
4
+ * Shape per plan.md §6. Handler-specific fields per §6.4. `targets`
5
+ * cross-validation per §12.2: only meaningful for `maturin` / `napi` /
6
+ * `bundled-cli` builds.
7
+ *
8
+ * Two entry points:
9
+ * - `parseConfig(toml)` pure function over a TOML string; used in tests.
10
+ * - `loadConfig(path)` reads the file and calls parseConfig.
11
+ *
12
+ * Unknown fields are a hard error (no silent drops). Zod's `.strict()`
13
+ * enforces this at every level.
14
+ */
15
+ import { readFileSync } from 'node:fs';
16
+ import { parse as parseToml } from 'smol-toml';
17
+ import { z } from 'zod';
18
+ /* ------------------------------ schemas ------------------------------ */
19
+ const PILOT = z
20
+ .object({
21
+ version: z.literal(1),
22
+ cadence: z.enum(['immediate', 'scheduled']).optional(),
23
+ agents_path: z.string().optional(),
24
+ })
25
+ .strict();
26
+ // Fields every package carries, regardless of kind.
27
+ const PACKAGE_BASE = {
28
+ name: z.string().min(1),
29
+ path: z.string().min(1),
30
+ paths: z.array(z.string()).min(1),
31
+ depends_on: z.array(z.string()).default([]),
32
+ first_version: z.string().default('0.1.0'),
33
+ smoke: z.string().optional(),
34
+ };
35
+ const CRATES_PKG = z
36
+ .object({
37
+ ...PACKAGE_BASE,
38
+ kind: z.literal('crates'),
39
+ crate: z.string().optional(),
40
+ features: z.array(z.string()).optional(),
41
+ target: z.array(z.string()).optional(),
42
+ })
43
+ .strict();
44
+ const PYPI_BUILD = z.enum(['maturin', 'setuptools', 'hatch']);
45
+ const PYPI_PKG = z
46
+ .object({
47
+ ...PACKAGE_BASE,
48
+ kind: z.literal('pypi'),
49
+ pypi: z.string().optional(),
50
+ build: PYPI_BUILD.optional(),
51
+ wheels_artifact: z.string().optional(),
52
+ targets: z.array(z.string()).optional(),
53
+ })
54
+ .strict()
55
+ .refine((p) => p.targets === undefined || p.build === 'maturin',
56
+ // §12.2: targets only for maturin on pypi.
57
+ { message: 'targets is only valid when build = "maturin" on pypi packages' });
58
+ const NPM_BUILD = z.enum(['napi', 'bundled-cli']);
59
+ const NPM_PKG = z
60
+ .object({
61
+ ...PACKAGE_BASE,
62
+ kind: z.literal('npm'),
63
+ npm: z.string().optional(),
64
+ access: z.enum(['public', 'restricted']).optional(),
65
+ tag: z.string().optional(),
66
+ build: NPM_BUILD.optional(),
67
+ targets: z.array(z.string()).optional(),
68
+ })
69
+ .strict()
70
+ .refine((p) => p.targets === undefined || p.build === 'napi' || p.build === 'bundled-cli',
71
+ // §12.2: targets only for napi or bundled-cli on npm.
72
+ { message: 'targets is only valid when build = "napi" or "bundled-cli" on npm packages' });
73
+ const PACKAGE = z.discriminatedUnion('kind', [CRATES_PKG, PYPI_PKG, NPM_PKG]);
74
+ const FILE = z
75
+ .object({
76
+ putitoutthere: PILOT,
77
+ package: z.array(PACKAGE).min(1),
78
+ })
79
+ .strict();
80
+ /* ----------------------------- functions ----------------------------- */
81
+ export function parseConfig(toml) {
82
+ let raw;
83
+ try {
84
+ raw = parseToml(toml);
85
+ }
86
+ catch (err) {
87
+ throw new Error(`putitoutthere.toml: invalid TOML: ${err instanceof Error ? err.message : String(err)}`);
88
+ }
89
+ const result = FILE.safeParse(raw);
90
+ if (!result.success) {
91
+ throw new Error(`putitoutthere.toml: ${formatZodError(result.error)}`);
92
+ }
93
+ const parsed = result.data;
94
+ assertUniqueNames(parsed.package);
95
+ return {
96
+ putitoutthere: parsed.putitoutthere,
97
+ packages: parsed.package,
98
+ };
99
+ }
100
+ export function loadConfig(path) {
101
+ let text;
102
+ try {
103
+ text = readFileSync(path, 'utf8');
104
+ }
105
+ catch (err) {
106
+ throw new Error(`putitoutthere.toml: cannot read ${path}: ${err instanceof Error ? err.message : String(err)}`);
107
+ }
108
+ return parseConfig(text);
109
+ }
110
+ /* ----------------------------- internals ----------------------------- */
111
+ function assertUniqueNames(packages) {
112
+ const seen = new Set();
113
+ for (const p of packages) {
114
+ if (seen.has(p.name)) {
115
+ throw new Error(`putitoutthere.toml: duplicate package name: ${p.name}`);
116
+ }
117
+ seen.add(p.name);
118
+ }
119
+ }
120
+ function formatZodError(error) {
121
+ return error.issues
122
+ .map((issue) => {
123
+ const path = issue.path.length > 0 ? issue.path.join('.') : '<root>';
124
+ return `${path}: ${issue.message}`;
125
+ })
126
+ .join('; ');
127
+ }
128
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/git.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Thin wrapper around the `git` CLI for the ops putitoutthere needs.
3
+ *
4
+ * Sync-only, by design — the caller is either CI (which we don't mind
5
+ * blocking) or a doctor run (which is interactive). Stderr is captured
6
+ * and surfaced in thrown errors so failures are diagnosable without
7
+ * re-running with --verbose.
8
+ *
9
+ * Issue #9. Plan: §13.6 (no-push tag model), §14.2 (last-tag resolver).
10
+ */
11
+ export interface GitOptions {
12
+ cwd?: string;
13
+ }
14
+ interface TagOptions extends GitOptions {
15
+ message?: string;
16
+ }
17
+ export declare function headCommit(opts?: GitOptions): string;
18
+ export declare function commitBody(sha: string, opts?: GitOptions): string;
19
+ export declare function diffNames(from: string, to: string, opts?: GitOptions): string[];
20
+ export declare function tagList(glob: string, opts?: GitOptions): string[];
21
+ export declare function createTag(name: string, sha: string, opts?: TagOptions): void;
22
+ export declare function pushTag(name: string, opts?: GitOptions): void;
23
+ /**
24
+ * Find the highest-semver tag for a given package.
25
+ *
26
+ * Tag format is fixed (plan.md §14.1): `{packageName}-v{major}.{minor}.{patch}`.
27
+ * We glob-filter by prefix, parse each candidate, and return the highest.
28
+ * Malformed candidates that match the glob but not strict semver are
29
+ * skipped silently — they're operator noise, not tool output.
30
+ *
31
+ * Returns null when no tag for this package exists.
32
+ */
33
+ export declare function lastTag(packageName: string, opts?: GitOptions): string | null;
34
+ export {};
35
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,UAAW,SAAQ,UAAU;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuBD,wBAAgB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,MAAM,CAExD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CAGrE;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,UAAe,GACpB,MAAM,EAAE,CAIV;AAID,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAIrE;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,UAAe,GACpB,IAAI,CAGN;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,IAAI,CAEjE;AAID;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,GAAG,IAAI,CAmBjF"}
package/dist/git.js ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Thin wrapper around the `git` CLI for the ops putitoutthere needs.
3
+ *
4
+ * Sync-only, by design — the caller is either CI (which we don't mind
5
+ * blocking) or a doctor run (which is interactive). Stderr is captured
6
+ * and surfaced in thrown errors so failures are diagnosable without
7
+ * re-running with --verbose.
8
+ *
9
+ * Issue #9. Plan: §13.6 (no-push tag model), §14.2 (last-tag resolver).
10
+ */
11
+ import { execFileSync } from 'node:child_process';
12
+ import { parseSemver } from './version.js';
13
+ /* ------------------------------ core ------------------------------ */
14
+ function run(args, opts = {}) {
15
+ try {
16
+ return execFileSync('git', args, {
17
+ cwd: opts.cwd,
18
+ encoding: 'utf8',
19
+ stdio: ['ignore', 'pipe', 'pipe'],
20
+ }).trimEnd();
21
+ }
22
+ catch (err) {
23
+ // execFileSync throws an Error whose `stderr` field carries git's
24
+ // error output. Fold it into the thrown message so tests + logs
25
+ // see the root cause without separate plumbing.
26
+ const stderr = err.stderr?.toString('utf8').trim();
27
+ const base = err instanceof Error ? err.message : String(err);
28
+ throw new Error(stderr ? `${base}\n${stderr}` : base);
29
+ }
30
+ }
31
+ /* ---------------------------- observers ---------------------------- */
32
+ export function headCommit(opts = {}) {
33
+ return run(['rev-parse', 'HEAD'], opts);
34
+ }
35
+ export function commitBody(sha, opts = {}) {
36
+ // %B = raw body (subject + body, no trailer folding).
37
+ return run(['log', '-1', '--format=%B', sha], opts);
38
+ }
39
+ export function diffNames(from, to, opts = {}) {
40
+ const out = run(['diff', '--name-only', `${from}..${to}`], opts);
41
+ if (out === '')
42
+ return [];
43
+ return out.split('\n').filter((l) => l.length > 0);
44
+ }
45
+ /* ------------------------------ tags ------------------------------ */
46
+ export function tagList(glob, opts = {}) {
47
+ const out = run(['tag', '-l', glob], opts);
48
+ if (out === '')
49
+ return [];
50
+ return out.split('\n').filter((l) => l.length > 0);
51
+ }
52
+ export function createTag(name, sha, opts = {}) {
53
+ const message = opts.message ?? name;
54
+ run(['tag', '-a', '-m', message, name, sha], opts);
55
+ }
56
+ export function pushTag(name, opts = {}) {
57
+ run(['push', 'origin', name], opts);
58
+ }
59
+ /* -------------------------- last-tag resolver -------------------------- */
60
+ /**
61
+ * Find the highest-semver tag for a given package.
62
+ *
63
+ * Tag format is fixed (plan.md §14.1): `{packageName}-v{major}.{minor}.{patch}`.
64
+ * We glob-filter by prefix, parse each candidate, and return the highest.
65
+ * Malformed candidates that match the glob but not strict semver are
66
+ * skipped silently — they're operator noise, not tool output.
67
+ *
68
+ * Returns null when no tag for this package exists.
69
+ */
70
+ export function lastTag(packageName, opts = {}) {
71
+ const prefix = `${packageName}-v`;
72
+ const candidates = tagList(`${prefix}*.*.*`, opts);
73
+ let best = null;
74
+ for (const tag of candidates) {
75
+ if (!tag.startsWith(prefix))
76
+ continue;
77
+ const versionPart = tag.slice(prefix.length);
78
+ let parsed;
79
+ try {
80
+ parsed = parseSemver(versionPart);
81
+ }
82
+ catch {
83
+ continue; // skip malformed
84
+ }
85
+ if (!best || greater(parsed, best.version)) {
86
+ best = { tag, version: parsed };
87
+ }
88
+ }
89
+ return best?.tag ?? null;
90
+ }
91
+ function greater(a, b) {
92
+ if (a.major !== b.major)
93
+ return a.major > b.major;
94
+ if (a.minor !== b.minor)
95
+ return a.minor > b.minor;
96
+ return a.patch > b.patch;
97
+ }
98
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
package/dist/glob.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Glob matcher. Thin wrapper over minimatch with the flags putitoutthere
3
+ * needs everywhere.
4
+ *
5
+ * Flags per plan.md §11.4:
6
+ * - dot: true — real repos keep config under .github/, .config/, etc.
7
+ * - matchBase: false — patterns anchor at the repo root
8
+ *
9
+ * Double-star crosses directory boundaries; brace expansion is on.
10
+ *
11
+ * Issue #10.
12
+ */
13
+ export declare function matchesGlob(pattern: string, path: string): boolean;
14
+ export declare function matchesAny(patterns: readonly string[], path: string): boolean;
15
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7E"}
package/dist/glob.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Glob matcher. Thin wrapper over minimatch with the flags putitoutthere
3
+ * needs everywhere.
4
+ *
5
+ * Flags per plan.md §11.4:
6
+ * - dot: true — real repos keep config under .github/, .config/, etc.
7
+ * - matchBase: false — patterns anchor at the repo root
8
+ *
9
+ * Double-star crosses directory boundaries; brace expansion is on.
10
+ *
11
+ * Issue #10.
12
+ */
13
+ import { minimatch } from 'minimatch';
14
+ const OPTS = {
15
+ dot: true,
16
+ matchBase: false,
17
+ nocomment: true, // putitoutthere.toml patterns aren't shell comments
18
+ };
19
+ export function matchesGlob(pattern, path) {
20
+ return minimatch(path, pattern, OPTS);
21
+ }
22
+ export function matchesAny(patterns, path) {
23
+ for (const p of patterns) {
24
+ if (matchesGlob(p, path))
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,IAAI,GAAG;IACX,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,IAAI,EAAE,oDAAoD;CAC7D,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,OAAO,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAA2B,EAAE,IAAY;IAClE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACxC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * crates.io handler. Real implementation lands in #16.
3
+ * Scaffold: contract-shaped stub that throws on any method call so
4
+ * callers link against the expected surface.
5
+ */
6
+ import type { Handler } from '../types.js';
7
+ export declare const crates: Handler;
8
+ //# sourceMappingURL=crates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crates.d.ts","sourceRoot":"","sources":["../../src/handlers/crates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,MAAM,EAAE,OAWpB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * crates.io handler. Real implementation lands in #16.
3
+ * Scaffold: contract-shaped stub that throws on any method call so
4
+ * callers link against the expected surface.
5
+ */
6
+ const NOT_IMPLEMENTED = (method) => new Error(`crates handler '${method}' not implemented yet — see #16`);
7
+ export const crates = {
8
+ kind: 'crates',
9
+ isPublished() {
10
+ throw NOT_IMPLEMENTED('isPublished');
11
+ },
12
+ writeVersion() {
13
+ throw NOT_IMPLEMENTED('writeVersion');
14
+ },
15
+ publish() {
16
+ throw NOT_IMPLEMENTED('publish');
17
+ },
18
+ };
19
+ //# sourceMappingURL=crates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crates.js","sourceRoot":"","sources":["../../src/handlers/crates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,eAAe,GAAG,CAAC,MAAc,EAAS,EAAE,CAChD,IAAI,KAAK,CAAC,mBAAmB,MAAM,iCAAiC,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,MAAM,GAAY;IAC7B,IAAI,EAAE,QAAQ;IACd,WAAW;QACT,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IACD,YAAY;QACV,MAAM,eAAe,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IACD,OAAO;QACL,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Handler dispatch by `package.kind`. Real dispatcher lands in #12;
3
+ * per-handler impls in #16 (crates), #17 (pypi), #18–#19 (npm).
4
+ */
5
+ import type { Handler, Kind } from '../types.js';
6
+ export declare function handlerFor(kind: Kind): Handler;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAKjD,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAa9C"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Handler dispatch by `package.kind`. Real dispatcher lands in #12;
3
+ * per-handler impls in #16 (crates), #17 (pypi), #18–#19 (npm).
4
+ */
5
+ import { crates } from './crates.js';
6
+ import { npm } from './npm.js';
7
+ import { pypi } from './pypi.js';
8
+ export function handlerFor(kind) {
9
+ switch (kind) {
10
+ case 'crates':
11
+ return crates;
12
+ case 'pypi':
13
+ return pypi;
14
+ case 'npm':
15
+ return npm;
16
+ default: {
17
+ const exhaustive = kind;
18
+ throw new Error(`unknown package kind: ${String(exhaustive)}`);
19
+ }
20
+ }
21
+ }
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd,KAAK,KAAK;YACR,OAAO,GAAG,CAAC;QACb,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,UAAU,GAAU,IAAI,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * npm handler. Real implementation lands in #18 (vanilla) and #19
3
+ * (napi + bundled-cli platform orchestration).
4
+ */
5
+ import type { Handler } from '../types.js';
6
+ export declare const npm: Handler;
7
+ //# sourceMappingURL=npm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/handlers/npm.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,GAAG,EAAE,OAWjB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * npm handler. Real implementation lands in #18 (vanilla) and #19
3
+ * (napi + bundled-cli platform orchestration).
4
+ */
5
+ const NOT_IMPLEMENTED = (method) => new Error(`npm handler '${method}' not implemented yet — see #18 / #19`);
6
+ export const npm = {
7
+ kind: 'npm',
8
+ isPublished() {
9
+ throw NOT_IMPLEMENTED('isPublished');
10
+ },
11
+ writeVersion() {
12
+ throw NOT_IMPLEMENTED('writeVersion');
13
+ },
14
+ publish() {
15
+ throw NOT_IMPLEMENTED('publish');
16
+ },
17
+ };
18
+ //# sourceMappingURL=npm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/handlers/npm.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,eAAe,GAAG,CAAC,MAAc,EAAS,EAAE,CAChD,IAAI,KAAK,CAAC,gBAAgB,MAAM,uCAAuC,CAAC,CAAC;AAE3E,MAAM,CAAC,MAAM,GAAG,GAAY;IAC1B,IAAI,EAAE,KAAK;IACX,WAAW;QACT,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IACD,YAAY;QACV,MAAM,eAAe,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IACD,OAAO;QACL,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * PyPI handler. Real implementation lands in #17.
3
+ */
4
+ import type { Handler } from '../types.js';
5
+ export declare const pypi: Handler;
6
+ //# sourceMappingURL=pypi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pypi.d.ts","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,IAAI,EAAE,OAWlB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * PyPI handler. Real implementation lands in #17.
3
+ */
4
+ const NOT_IMPLEMENTED = (method) => new Error(`pypi handler '${method}' not implemented yet — see #17`);
5
+ export const pypi = {
6
+ kind: 'pypi',
7
+ isPublished() {
8
+ throw NOT_IMPLEMENTED('isPublished');
9
+ },
10
+ writeVersion() {
11
+ throw NOT_IMPLEMENTED('writeVersion');
12
+ },
13
+ publish() {
14
+ throw NOT_IMPLEMENTED('publish');
15
+ },
16
+ };
17
+ //# sourceMappingURL=pypi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pypi.js","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,eAAe,GAAG,CAAC,MAAc,EAAS,EAAE,CAChD,IAAI,KAAK,CAAC,iBAAiB,MAAM,iCAAiC,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,IAAI,GAAY;IAC3B,IAAI,EAAE,MAAM;IACZ,WAAW;QACT,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IACD,YAAY;QACV,MAAM,eAAe,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IACD,OAAO;QACL,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * SDK entry. This is what callers import as `putitoutthere`.
3
+ *
4
+ * Implementations land in follow-up issues; this file re-exports the
5
+ * public API surface so the CLI (#20–#23) and the GHA wrapper (#24)
6
+ * have a stable import site.
7
+ */
8
+ export type { ArtifactStore, Bump, Config, Ctx, Handler, Kind, Logger, PackageConfig, PublishResult, SmokeResult, } from './types.js';
9
+ export { AuthError, TransientError } from './types.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EACV,aAAa,EACb,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,IAAI,EACJ,MAAM,EACN,aAAa,EACb,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SDK entry. This is what callers import as `putitoutthere`.
3
+ *
4
+ * Implementations land in follow-up issues; this file re-exports the
5
+ * public API surface so the CLI (#20–#23) and the GHA wrapper (#24)
6
+ * have a stable import site.
7
+ */
8
+ export { AuthError, TransientError } from './types.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Structured logger for putitoutthere.
3
+ *
4
+ * JSON-per-line output in CI; human-readable text in TTYs. Every emitted
5
+ * line is passed through a redactor that replaces any occurrence of a
6
+ * known-secret env value (keys matching *TOKEN* / *SECRET* / *PASSWORD*
7
+ * / *KEY*, case-insensitive) with `[REDACTED]`.
8
+ *
9
+ * Substring redaction (rather than Pino-style field-path redaction) is
10
+ * deliberate: handlers capture child-process stdout/stderr and feed it
11
+ * through the logger. A token leaked inside that stream must not escape
12
+ * to CI logs regardless of which field it ended up in.
13
+ *
14
+ * Issue #11. Plan: §22.2, §22.5.
15
+ */
16
+ import type { Writable } from 'node:stream';
17
+ import type { Logger } from './types.js';
18
+ export type Level = 'debug' | 'info' | 'warn' | 'error';
19
+ export interface LoggerOptions {
20
+ stream?: Writable;
21
+ pretty?: boolean;
22
+ level?: Level;
23
+ }
24
+ export declare function createLogger(opts?: LoggerOptions): Logger;
25
+ /**
26
+ * Replace every occurrence of a known-secret env value with `[REDACTED]`.
27
+ * Empty / single-char values are skipped to avoid mangling unrelated
28
+ * characters. Called on every log write.
29
+ */
30
+ export declare function redact(s: string): string;
31
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AASxD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE,aAAkB,GAAG,MAAM,CAkB7D;AA0BD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAWxC"}
package/dist/log.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Structured logger for putitoutthere.
3
+ *
4
+ * JSON-per-line output in CI; human-readable text in TTYs. Every emitted
5
+ * line is passed through a redactor that replaces any occurrence of a
6
+ * known-secret env value (keys matching *TOKEN* / *SECRET* / *PASSWORD*
7
+ * / *KEY*, case-insensitive) with `[REDACTED]`.
8
+ *
9
+ * Substring redaction (rather than Pino-style field-path redaction) is
10
+ * deliberate: handlers capture child-process stdout/stderr and feed it
11
+ * through the logger. A token leaked inside that stream must not escape
12
+ * to CI logs regardless of which field it ended up in.
13
+ *
14
+ * Issue #11. Plan: §22.2, §22.5.
15
+ */
16
+ const LEVEL_ORDER = {
17
+ debug: 10,
18
+ info: 20,
19
+ warn: 30,
20
+ error: 40,
21
+ };
22
+ export function createLogger(opts = {}) {
23
+ const stream = opts.stream ?? process.stdout;
24
+ const pretty = opts.pretty ?? isTty(stream);
25
+ const minLevel = LEVEL_ORDER[opts.level ?? 'info'];
26
+ const emit = (level, msg, fields) => {
27
+ if (LEVEL_ORDER[level] < minLevel)
28
+ return;
29
+ const record = { level, time: new Date().toISOString(), msg, ...fields };
30
+ const raw = pretty ? formatPretty(record) : `${JSON.stringify(record)}\n`;
31
+ stream.write(redact(raw));
32
+ };
33
+ return {
34
+ debug: (msg, fields = {}) => emit('debug', msg, fields),
35
+ info: (msg, fields = {}) => emit('info', msg, fields),
36
+ warn: (msg, fields = {}) => emit('warn', msg, fields),
37
+ error: (msg, fields = {}) => emit('error', msg, fields),
38
+ };
39
+ }
40
+ function isTty(stream) {
41
+ return Boolean(stream.isTTY);
42
+ }
43
+ function formatPretty(record) {
44
+ const { level, time: _t, msg, ...fields } = record;
45
+ const pairs = Object.entries(fields)
46
+ .map(([k, v]) => `${k}=${formatScalar(v)}`)
47
+ .join(' ');
48
+ const prefix = `[${String(level).toUpperCase()}]`;
49
+ return pairs.length > 0 ? `${prefix} ${String(msg)} ${pairs}\n` : `${prefix} ${String(msg)}\n`;
50
+ }
51
+ function formatScalar(v) {
52
+ if (typeof v === 'string')
53
+ return v;
54
+ if (typeof v === 'number' || typeof v === 'boolean' || v === null)
55
+ return String(v);
56
+ return JSON.stringify(v);
57
+ }
58
+ /* ----------------------------- redaction ----------------------------- */
59
+ const SECRET_KEY = /TOKEN|SECRET|PASSWORD|KEY/i;
60
+ const REDACTED = '[REDACTED]';
61
+ /**
62
+ * Replace every occurrence of a known-secret env value with `[REDACTED]`.
63
+ * Empty / single-char values are skipped to avoid mangling unrelated
64
+ * characters. Called on every log write.
65
+ */
66
+ export function redact(s) {
67
+ let out = s;
68
+ for (const [k, v] of Object.entries(process.env)) {
69
+ if (!SECRET_KEY.test(k))
70
+ continue;
71
+ if (typeof v !== 'string' || v.length < 2)
72
+ continue;
73
+ if (!out.includes(v))
74
+ continue;
75
+ // String.replaceAll expects a literal or a RegExp; use split/join to
76
+ // avoid regex escaping every secret value.
77
+ out = out.split(v).join(REDACTED);
78
+ }
79
+ return out;
80
+ }
81
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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"}