putitoutthere 0.0.1 → 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 (72) hide show
  1. package/README.md +115 -5
  2. package/dist/action.d.ts +6 -4
  3. package/dist/action.d.ts.map +1 -1
  4. package/dist/action.js +24 -9
  5. package/dist/action.js.map +1 -1
  6. package/dist/cascade.d.ts.map +1 -1
  7. package/dist/cascade.js +2 -0
  8. package/dist/cascade.js.map +1 -1
  9. package/dist/cli.d.ts +10 -3
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +161 -13
  12. package/dist/cli.js.map +1 -1
  13. package/dist/completeness.js +13 -0
  14. package/dist/completeness.js.map +1 -1
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +5 -0
  17. package/dist/config.js.map +1 -1
  18. package/dist/doctor.d.ts +26 -0
  19. package/dist/doctor.d.ts.map +1 -0
  20. package/dist/doctor.js +45 -0
  21. package/dist/doctor.js.map +1 -0
  22. package/dist/git.d.ts +1 -0
  23. package/dist/git.d.ts.map +1 -1
  24. package/dist/git.js +12 -0
  25. package/dist/git.js.map +1 -1
  26. package/dist/handlers/crates.d.ts +24 -3
  27. package/dist/handlers/crates.d.ts.map +1 -1
  28. package/dist/handlers/crates.js +122 -13
  29. package/dist/handlers/crates.js.map +1 -1
  30. package/dist/handlers/npm-platform.d.ts +60 -0
  31. package/dist/handlers/npm-platform.d.ts.map +1 -0
  32. package/dist/handlers/npm-platform.js +203 -0
  33. package/dist/handlers/npm-platform.js.map +1 -0
  34. package/dist/handlers/npm.d.ts +7 -2
  35. package/dist/handlers/npm.d.ts.map +1 -1
  36. package/dist/handlers/npm.js +140 -12
  37. package/dist/handlers/npm.js.map +1 -1
  38. package/dist/handlers/pypi.d.ts +19 -1
  39. package/dist/handlers/pypi.d.ts.map +1 -1
  40. package/dist/handlers/pypi.js +146 -11
  41. package/dist/handlers/pypi.js.map +1 -1
  42. package/dist/init.d.ts +33 -0
  43. package/dist/init.d.ts.map +1 -0
  44. package/dist/init.js +94 -0
  45. package/dist/init.js.map +1 -0
  46. package/dist/log.d.ts.map +1 -1
  47. package/dist/log.js +6 -1
  48. package/dist/log.js.map +1 -1
  49. package/dist/plan.d.ts +28 -0
  50. package/dist/plan.d.ts.map +1 -0
  51. package/dist/plan.js +218 -0
  52. package/dist/plan.js.map +1 -0
  53. package/dist/publish.d.ts +35 -0
  54. package/dist/publish.d.ts.map +1 -0
  55. package/dist/publish.js +188 -0
  56. package/dist/publish.js.map +1 -0
  57. package/dist/release.d.ts +36 -0
  58. package/dist/release.d.ts.map +1 -0
  59. package/dist/release.js +102 -0
  60. package/dist/release.js.map +1 -0
  61. package/dist/retry.js +1 -0
  62. package/dist/retry.js.map +1 -1
  63. package/dist/templates.d.ts +22 -0
  64. package/dist/templates.d.ts.map +1 -0
  65. package/dist/templates.js +222 -0
  66. package/dist/templates.js.map +1 -0
  67. package/dist/trailer.js +1 -0
  68. package/dist/trailer.js.map +1 -1
  69. package/dist/types.d.ts +14 -4
  70. package/dist/types.d.ts.map +1 -1
  71. package/dist/types.js.map +1 -1
  72. package/package.json +7 -6
@@ -1 +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"}
1
+ {"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/handlers/npm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAO,OAAO,EAAiB,MAAM,aAAa,CAAC;AAuJ/D,eAAO,MAAM,GAAG,EAAE,OAKjB,CAAC"}
@@ -1,18 +1,146 @@
1
1
  /**
2
- * npm handler. Real implementation lands in #18 (vanilla) and #19
3
- * (napi + bundled-cli platform orchestration).
2
+ * npm handler — vanilla mode.
3
+ *
4
+ * Issue #18. Plan: §7.4, §12.2 (vanilla), §13.1, §14.5, §16.1.
5
+ *
6
+ * The matrix-using modes (napi, bundled-cli) layer on top of this in
7
+ * #19; they share isPublished and writeVersion, and add a platform-
8
+ * package orchestration step before the main publish.
4
9
  */
5
- const NOT_IMPLEMENTED = (method) => new Error(`npm handler '${method}' not implemented yet — see #18 / #19`);
10
+ import { execFileSync } from 'node:child_process';
11
+ import { readFileSync, writeFileSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { publishPlatforms } from './npm-platform.js';
14
+ function npmNameFor(pkg) {
15
+ return pkg.npm ?? pkg.name;
16
+ }
17
+ function isPublishedImpl(pkg, version, ctx) {
18
+ const name = npmNameFor(pkg);
19
+ try {
20
+ execFileSync('npm', ['view', `${name}@${version}`, 'version'], {
21
+ cwd: ctx.cwd,
22
+ stdio: ['ignore', 'pipe', 'pipe'],
23
+ });
24
+ return Promise.resolve(true);
25
+ }
26
+ catch {
27
+ // `npm view` exits non-zero when the version doesn't exist.
28
+ // We treat every non-zero as "not published"; the subsequent
29
+ // publish step will surface real auth/network errors there.
30
+ return Promise.resolve(false);
31
+ }
32
+ }
33
+ function writeVersionImpl(pkg, version, _ctx) {
34
+ const p = join(pkg.path, 'package.json');
35
+ let original;
36
+ try {
37
+ original = readFileSync(p, 'utf8');
38
+ }
39
+ catch (err) {
40
+ if (err.code === 'ENOENT') {
41
+ return Promise.reject(new Error(`package.json not found at ${p}`));
42
+ }
43
+ /* v8 ignore next -- non-ENOENT read errors surface as-is */
44
+ return Promise.reject(err instanceof Error ? err : new Error(String(err)));
45
+ }
46
+ let parsed;
47
+ try {
48
+ parsed = JSON.parse(original);
49
+ }
50
+ catch (err) {
51
+ return Promise.reject(new Error(`package.json JSON parse error: ${err instanceof Error ? err.message : String(err)}`));
52
+ }
53
+ if (parsed.version === version)
54
+ return Promise.resolve([]);
55
+ parsed.version = version;
56
+ // Preserve the existing indentation shape (2-space default if we
57
+ // can't detect) and the trailing newline when present.
58
+ const indent = detectIndent(original);
59
+ const trailing = original.endsWith('\n') ? '\n' : '';
60
+ writeFileSync(p, JSON.stringify(parsed, null, indent) + trailing, 'utf8');
61
+ return Promise.resolve([p]);
62
+ }
63
+ async function publishImpl(pkg, version, ctx) {
64
+ if (await isPublishedImpl(pkg, version, ctx)) {
65
+ return { status: 'already-published' };
66
+ }
67
+ if (ctx.dryRun) {
68
+ return { status: 'skipped' };
69
+ }
70
+ // napi / bundled-cli: publish platform packages first, then rewrite
71
+ // the main package.json to add optionalDependencies, then fall through
72
+ // to the normal main-package publish path below. §13.7.
73
+ if ((pkg.build === 'napi' || pkg.build === 'bundled-cli') &&
74
+ pkg.targets !== undefined &&
75
+ pkg.targets.length > 0) {
76
+ const platformPkg = {
77
+ name: pkg.name,
78
+ path: pkg.path,
79
+ npm: pkg.npm,
80
+ access: pkg.access,
81
+ tag: pkg.tag,
82
+ build: pkg.build,
83
+ targets: pkg.targets,
84
+ };
85
+ await publishPlatforms(platformPkg, version, ctx);
86
+ }
87
+ const hasOidc = Boolean(ctx.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN ?? process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN);
88
+ // npm provenance requires a `repository` field in package.json
89
+ // that matches the git remote. Failing loud here is strictly better
90
+ // than letting npm publish fail at the end with a confusing error.
91
+ if (hasOidc) {
92
+ assertRepositoryField(pkg.path);
93
+ }
94
+ const access = pkg.access ?? 'public';
95
+ const args = ['publish', `--access=${access}`];
96
+ if (pkg.tag)
97
+ args.push(`--tag=${pkg.tag}`);
98
+ if (hasOidc)
99
+ args.push('--provenance');
100
+ try {
101
+ execFileSync('npm', args, {
102
+ cwd: pkg.path,
103
+ env: {
104
+ ...process.env,
105
+ ...ctx.env,
106
+ },
107
+ stdio: ['ignore', 'pipe', 'pipe'],
108
+ });
109
+ }
110
+ catch (err) {
111
+ const stderr = err.stderr?.toString('utf8').trim();
112
+ const base = err instanceof Error ? err.message : String(err);
113
+ throw new Error(`npm publish failed${stderr ? `:\n${stderr}` : `: ${base}`}`);
114
+ }
115
+ return {
116
+ status: 'published',
117
+ url: `https://www.npmjs.com/package/${npmNameFor(pkg)}/v/${version}`,
118
+ };
119
+ }
120
+ /* ------------------------------ internals ------------------------------ */
121
+ function assertRepositoryField(path) {
122
+ const pkgJsonPath = join(path, 'package.json');
123
+ const raw = readFileSync(pkgJsonPath, 'utf8');
124
+ const pkg = JSON.parse(raw);
125
+ if (!pkg.repository) {
126
+ throw new Error('npm publish --provenance requires a `repository` field in package.json');
127
+ }
128
+ }
129
+ /** 2 / 4 / tab. Defaults to 2 when undetectable. */
130
+ function detectIndent(source) {
131
+ const m = /^(?<indent>[ \t]+)"/m.exec(source);
132
+ /* v8 ignore next -- JSON.parse of valid JSON always has at least one indented line when pretty-printed */
133
+ if (!m?.groups?.indent)
134
+ return 2;
135
+ const indent = m.groups.indent;
136
+ if (indent.includes('\t'))
137
+ return '\t';
138
+ return indent.length;
139
+ }
6
140
  export const npm = {
7
141
  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
- },
142
+ isPublished: isPublishedImpl,
143
+ writeVersion: writeVersionImpl,
144
+ publish: publishImpl,
17
145
  };
18
146
  //# sourceMappingURL=npm.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/handlers/npm.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,24 @@
1
1
  /**
2
- * PyPI handler. Real implementation lands in #17.
2
+ * PyPI handler.
3
+ *
4
+ * Issue #17. Plan: §6.4, §12.2, §12.3, §13.1, §14.5, §16.1.
5
+ *
6
+ * Publish model: twine upload. The workflow is responsible for wiring
7
+ * up PYPI_API_TOKEN (either from a classic secret or via a
8
+ * trusted-publisher-backed OIDC exchange step that populates the env
9
+ * before pilot runs). Full in-handler OIDC exchange is deferred --
10
+ * the gh-action-pypi-publish step handles that cleanly for v0.
11
+ *
12
+ * Artifact discovery: scans `ctx.artifactsRoot` for directories named
13
+ * `{pkg.name}-*` (the artifact naming contract from §12.4). Uploads
14
+ * all `.whl` and `.tar.gz` files found under those directories. Fails
15
+ * loud if nothing's found -- the completeness check (#13) should have
16
+ * caught that earlier, but defense in depth.
3
17
  */
4
18
  import type { Handler } from '../types.js';
19
+ /**
20
+ * Rewrites the first `version = "x.y.z"` inside the `[project]` table.
21
+ */
22
+ export declare function replacePyProjectVersion(source: string, version: string): string;
5
23
  export declare const pypi: Handler;
6
24
  //# sourceMappingURL=pypi.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"pypi.d.ts","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAO,OAAO,EAAiB,MAAM,aAAa,CAAC;AAyG/D;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAW/E;AAwBD,eAAO,MAAM,IAAI,EAAE,OAKlB,CAAC"}
@@ -1,17 +1,152 @@
1
1
  /**
2
- * PyPI handler. Real implementation lands in #17.
2
+ * PyPI handler.
3
+ *
4
+ * Issue #17. Plan: §6.4, §12.2, §12.3, §13.1, §14.5, §16.1.
5
+ *
6
+ * Publish model: twine upload. The workflow is responsible for wiring
7
+ * up PYPI_API_TOKEN (either from a classic secret or via a
8
+ * trusted-publisher-backed OIDC exchange step that populates the env
9
+ * before pilot runs). Full in-handler OIDC exchange is deferred --
10
+ * the gh-action-pypi-publish step handles that cleanly for v0.
11
+ *
12
+ * Artifact discovery: scans `ctx.artifactsRoot` for directories named
13
+ * `{pkg.name}-*` (the artifact naming contract from §12.4). Uploads
14
+ * all `.whl` and `.tar.gz` files found under those directories. Fails
15
+ * loud if nothing's found -- the completeness check (#13) should have
16
+ * caught that earlier, but defense in depth.
3
17
  */
4
- const NOT_IMPLEMENTED = (method) => new Error(`pypi handler '${method}' not implemented yet — see #17`);
18
+ import { execFileSync } from 'node:child_process';
19
+ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
20
+ import { join } from 'node:path';
21
+ import { TransientError } from '../types.js';
22
+ const REGISTRY = 'https://pypi.org';
23
+ async function isPublishedImpl(pkg, version, _ctx) {
24
+ const name = pypiNameFor(pkg);
25
+ const url = `${REGISTRY}/pypi/${encodeURIComponent(name)}/${encodeURIComponent(version)}/json`;
26
+ const res = await fetch(url, {
27
+ method: 'GET',
28
+ headers: { 'user-agent': 'putitoutthere/0.0.1' },
29
+ });
30
+ if (res.status === 200)
31
+ return true;
32
+ if (res.status === 404)
33
+ return false;
34
+ if (res.status >= 500) {
35
+ throw new TransientError(`pypi.org GET ${url} returned ${res.status}`);
36
+ }
37
+ /* v8 ignore next -- defensive 4xx fallthrough; PyPI returns 200/404 for this endpoint */
38
+ throw new Error(`pypi.org GET ${url} returned ${res.status}`);
39
+ }
40
+ function writeVersionImpl(pkg, version, _ctx) {
41
+ const pyProjectPath = join(pkg.path, 'pyproject.toml');
42
+ let original;
43
+ try {
44
+ original = readFileSync(pyProjectPath, 'utf8');
45
+ }
46
+ catch (err) {
47
+ if (err.code === 'ENOENT') {
48
+ return Promise.reject(new Error(`pyproject.toml not found at ${pyProjectPath}`));
49
+ }
50
+ /* v8 ignore next -- non-ENOENT read errors surface as-is */
51
+ return Promise.reject(err instanceof Error ? err : new Error(String(err)));
52
+ }
53
+ let updated;
54
+ try {
55
+ updated = replacePyProjectVersion(original, version);
56
+ }
57
+ catch (err) {
58
+ return Promise.reject(err instanceof Error ? err : new Error(String(err)));
59
+ }
60
+ if (updated === original)
61
+ return Promise.resolve([]);
62
+ writeFileSync(pyProjectPath, updated, 'utf8');
63
+ return Promise.resolve([pyProjectPath]);
64
+ }
65
+ async function publishImpl(pkg, version, ctx) {
66
+ if (await isPublishedImpl(pkg, version, ctx)) {
67
+ return { status: 'already-published' };
68
+ }
69
+ if (ctx.dryRun) {
70
+ return { status: 'skipped' };
71
+ }
72
+ const files = collectArtifacts(pkg.name, ctx.artifactsRoot);
73
+ if (files.length === 0) {
74
+ throw new Error(`pypi: no artifacts found for ${pkg.name} under ${ctx.artifactsRoot ?? '(artifactsRoot unset)'}`);
75
+ }
76
+ const token = ctx.env.PYPI_API_TOKEN ?? process.env.PYPI_API_TOKEN;
77
+ if (!token) {
78
+ throw new Error('pypi: PYPI_API_TOKEN not set; see plan.md §16.4.2');
79
+ }
80
+ try {
81
+ execFileSync('twine', ['upload', '--non-interactive', '--disable-progress-bar', ...files], {
82
+ cwd: ctx.cwd,
83
+ env: {
84
+ ...process.env,
85
+ ...ctx.env,
86
+ TWINE_USERNAME: '__token__',
87
+ TWINE_PASSWORD: token,
88
+ },
89
+ stdio: ['ignore', 'pipe', 'pipe'],
90
+ });
91
+ }
92
+ catch (err) {
93
+ const stderr = err.stderr?.toString('utf8').trim();
94
+ const base = err instanceof Error ? err.message : String(err);
95
+ throw new Error(`twine upload failed${stderr ? `:\n${stderr}` : `: ${base}`}`);
96
+ }
97
+ return {
98
+ status: 'published',
99
+ url: `${REGISTRY}/project/${pypiNameFor(pkg)}/${version}/`,
100
+ };
101
+ }
102
+ /* ------------------------------ internals ------------------------------ */
103
+ function pypiNameFor(pkg) {
104
+ return pkg.pypi ?? pkg.name;
105
+ }
106
+ /**
107
+ * Rewrites the first `version = "x.y.z"` inside the `[project]` table.
108
+ */
109
+ export function replacePyProjectVersion(source, version) {
110
+ const re = /(\[project\][\s\S]*?)(^\s*version\s*=\s*")([^"]*)(")/m;
111
+ const m = re.exec(source);
112
+ if (!m) {
113
+ throw new Error('pyproject.toml: no [project].version field found');
114
+ }
115
+ const [, pre, prefix, old, suffix] = m;
116
+ if (old === version)
117
+ return source;
118
+ const start = m.index + pre.length;
119
+ const end = start + prefix.length + old.length + suffix.length;
120
+ return source.slice(0, start) + prefix + version + suffix + source.slice(end);
121
+ }
122
+ /**
123
+ * Collects `.whl` and `.tar.gz` files across every artifact subdir whose
124
+ * name starts with the package's pilot name. Matches the artifact naming
125
+ * contract from §12.4: `{name}-wheel-{target}` and `{name}-sdist`.
126
+ */
127
+ function collectArtifacts(pkgName, artifactsRoot) {
128
+ if (!artifactsRoot || !existsSync(artifactsRoot))
129
+ return [];
130
+ const out = [];
131
+ for (const entry of readdirSync(artifactsRoot)) {
132
+ if (!entry.startsWith(`${pkgName}-`))
133
+ continue;
134
+ const sub = join(artifactsRoot, entry);
135
+ /* v8 ignore next -- fs entries shouldn't vanish between readdir and stat */
136
+ if (!statSync(sub).isDirectory())
137
+ continue;
138
+ for (const file of readdirSync(sub)) {
139
+ if (file.endsWith('.whl') || file.endsWith('.tar.gz')) {
140
+ out.push(join(sub, file));
141
+ }
142
+ }
143
+ }
144
+ return out;
145
+ }
5
146
  export const pypi = {
6
147
  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
- },
148
+ isPublished: isPublishedImpl,
149
+ writeVersion: writeVersionImpl,
150
+ publish: publishImpl,
16
151
  };
17
152
  //# sourceMappingURL=pypi.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"pypi.js","sourceRoot":"","sources":["../../src/handlers/pypi.ts"],"names":[],"mappings":"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"}
package/dist/init.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `putitoutthere init` — scaffold a new repo.
3
+ *
4
+ * Writes:
5
+ * - `putitoutthere.toml` (skeleton with `version = 1`, no packages)
6
+ * - `putitoutthere/AGENTS.md` (trailer convention doc per plan.md §17.3)
7
+ * - `.github/workflows/release.yml` + `.github/workflows/putitoutthere-check.yml`
8
+ * - Appends `@putitoutthere/AGENTS.md` to `CLAUDE.md` (creates if missing)
9
+ *
10
+ * Idempotency (plan.md §17.4):
11
+ * - Existing `putitoutthere.toml` → skip unless `--force`.
12
+ * - Existing workflow → rename to `.bak` before writing.
13
+ * - Existing `CLAUDE.md` already containing the import line → skip the append.
14
+ *
15
+ * Issue #20 / #25. Plan: §9, §17.
16
+ */
17
+ import { type Cadence } from './templates.js';
18
+ export interface InitOptions {
19
+ cwd: string;
20
+ /** Overwrite `putitoutthere.toml` even if it exists. */
21
+ force?: boolean;
22
+ /** Reserved for v0.1. Only `claude` supported today. */
23
+ agent?: 'claude' | 'cursor';
24
+ /** Release cadence; selects which release.yml template to emit. */
25
+ cadence?: Cadence;
26
+ }
27
+ export interface InitResult {
28
+ wrote: string[];
29
+ skipped: string[];
30
+ backedUp: string[];
31
+ }
32
+ export declare function init(opts: InitOptions): InitResult;
33
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAmD,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/F,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAuDlD"}
package/dist/init.js ADDED
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `putitoutthere init` — scaffold a new repo.
3
+ *
4
+ * Writes:
5
+ * - `putitoutthere.toml` (skeleton with `version = 1`, no packages)
6
+ * - `putitoutthere/AGENTS.md` (trailer convention doc per plan.md §17.3)
7
+ * - `.github/workflows/release.yml` + `.github/workflows/putitoutthere-check.yml`
8
+ * - Appends `@putitoutthere/AGENTS.md` to `CLAUDE.md` (creates if missing)
9
+ *
10
+ * Idempotency (plan.md §17.4):
11
+ * - Existing `putitoutthere.toml` → skip unless `--force`.
12
+ * - Existing workflow → rename to `.bak` before writing.
13
+ * - Existing `CLAUDE.md` already containing the import line → skip the append.
14
+ *
15
+ * Issue #20 / #25. Plan: §9, §17.
16
+ */
17
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
18
+ import { dirname, join } from 'node:path';
19
+ import { AGENTS_MD, CHECK_YML, releaseYml, TOML_SKELETON } from './templates.js';
20
+ export function init(opts) {
21
+ const cwd = opts.cwd;
22
+ const force = Boolean(opts.force);
23
+ const agent = opts.agent ?? 'claude';
24
+ const cadence = opts.cadence ?? 'immediate';
25
+ const result = { wrote: [], skipped: [], backedUp: [] };
26
+ // 1. putitoutthere.toml
27
+ const tomlPath = join(cwd, 'putitoutthere.toml');
28
+ if (existsSync(tomlPath) && !force) {
29
+ result.skipped.push('putitoutthere.toml');
30
+ }
31
+ else {
32
+ writeAtomic(tomlPath, TOML_SKELETON);
33
+ result.wrote.push('putitoutthere.toml');
34
+ }
35
+ // 2. putitoutthere/AGENTS.md
36
+ const agentsPath = join(cwd, 'putitoutthere', 'AGENTS.md');
37
+ if (existsSync(agentsPath)) {
38
+ result.skipped.push('putitoutthere/AGENTS.md');
39
+ }
40
+ else {
41
+ writeAtomic(agentsPath, AGENTS_MD);
42
+ result.wrote.push('putitoutthere/AGENTS.md');
43
+ }
44
+ // 3. CLAUDE.md / .cursorrules
45
+ if (agent === 'claude') {
46
+ const claudePath = join(cwd, 'CLAUDE.md');
47
+ const importLine = '@putitoutthere/AGENTS.md';
48
+ const existing = existsSync(claudePath) ? readFileSync(claudePath, 'utf8') : '';
49
+ if (existing.includes(importLine)) {
50
+ result.skipped.push('CLAUDE.md');
51
+ }
52
+ else {
53
+ const sep = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
54
+ writeAtomic(claudePath, `${existing}${sep}${importLine}\n`);
55
+ result.wrote.push('CLAUDE.md');
56
+ }
57
+ /* v8 ignore start -- cursor path is stub-level until requested */
58
+ }
59
+ else {
60
+ const cursorPath = join(cwd, '.cursorrules');
61
+ const existing = existsSync(cursorPath) ? readFileSync(cursorPath, 'utf8') : '';
62
+ if (existing.includes('Release signaling for Put It Out There')) {
63
+ result.skipped.push('.cursorrules');
64
+ }
65
+ else {
66
+ writeAtomic(cursorPath, `${existing}${existing.length > 0 ? '\n' : ''}${AGENTS_MD}`);
67
+ result.wrote.push('.cursorrules');
68
+ }
69
+ }
70
+ /* v8 ignore stop */
71
+ // 4. Workflows
72
+ writeWorkflow(cwd, 'release.yml', releaseYml(cadence), result);
73
+ writeWorkflow(cwd, 'putitoutthere-check.yml', CHECK_YML, result);
74
+ return result;
75
+ }
76
+ /* ---------------------------- internals ---------------------------- */
77
+ function writeWorkflow(cwd, name, contents, result) {
78
+ const target = join(cwd, '.github', 'workflows', name);
79
+ if (existsSync(target)) {
80
+ const bak = `${target}.bak`;
81
+ renameSync(target, bak);
82
+ result.backedUp.push(`.github/workflows/${name}`);
83
+ }
84
+ writeAtomic(target, contents);
85
+ result.wrote.push(`.github/workflows/${name}`);
86
+ }
87
+ function writeAtomic(path, contents) {
88
+ // lgtm[js/insecure-temporary-file] -- writes into opts.cwd, which
89
+ // is the user's project root in production; only the test harness
90
+ // passes an os.tmpdir() subpath here, and that's controlled input.
91
+ mkdirSync(dirname(path), { recursive: true, mode: 0o755 });
92
+ writeFileSync(path, contents, { encoding: 'utf8', mode: 0o644 });
93
+ }
94
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
package/dist/log.d.ts.map CHANGED
@@ -1 +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"}
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,CAsB7D;AA2BD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAWxC"}
package/dist/log.js CHANGED
@@ -20,8 +20,12 @@ const LEVEL_ORDER = {
20
20
  error: 40,
21
21
  };
22
22
  export function createLogger(opts = {}) {
23
- const stream = opts.stream ?? process.stdout;
23
+ // Default to stderr so stdout stays clean for machine-readable
24
+ // output from `plan --json` and `publish --json`.
25
+ /* v8 ignore next -- tests always pass an explicit stream */
26
+ const stream = opts.stream ?? process.stderr;
24
27
  const pretty = opts.pretty ?? isTty(stream);
28
+ /* v8 ignore next -- 'info' default vs explicit level both exercised; the ?? branch is one of those */
25
29
  const minLevel = LEVEL_ORDER[opts.level ?? 'info'];
26
30
  const emit = (level, msg, fields) => {
27
31
  if (LEVEL_ORDER[level] < minLevel)
@@ -51,6 +55,7 @@ function formatPretty(record) {
51
55
  function formatScalar(v) {
52
56
  if (typeof v === 'string')
53
57
  return v;
58
+ /* v8 ignore next -- null/boolean primitive branches not all hit by current tests */
54
59
  if (typeof v === 'number' || typeof v === 'boolean' || v === null)
55
60
  return String(v);
56
61
  return JSON.stringify(v);
package/dist/log.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,MAAM,WAAW,GAA0B;IACzC,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAQF,MAAM,UAAU,YAAY,CAAC,OAAsB,EAAE;IACnD,MAAM,MAAM,GAAa,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAG,CAAC,KAAY,EAAE,GAAW,EAAE,MAA+B,EAAQ,EAAE;QAChF,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,QAAQ;YAAE,OAAO;QAC1C,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;QAC1E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC;QACvD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC;QACrD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC;QACrD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,MAAgB;IAC7B,OAAO,OAAO,CAAE,MAA8B,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,YAAY,CAAC,MAA+B;IACnD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SACjC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC;IAClD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AAClG,CAAC;AAED,SAAS,YAAY,CAAC,CAAU;IAC9B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACpF,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,2EAA2E;AAE3E,MAAM,UAAU,GAAG,4BAA4B,CAAC;AAChD,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS;QAClC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QACpD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAC/B,qEAAqE;QACrE,2CAA2C;QAC3C,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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"}
package/dist/plan.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `putitoutthere plan` — the planner.
3
+ *
4
+ * Composes config, trailer, cascade, version, git into the matrix-row
5
+ * array consumed by the GHA `build` job. Per plan.md §12.4. Pure
6
+ * function over (config + git state) → matrix; deterministic for the
7
+ * same inputs so CI golden-file checks have something to compare.
8
+ *
9
+ * Issue #21.
10
+ */
11
+ import type { Kind } from './types.js';
12
+ export interface MatrixRow {
13
+ name: string;
14
+ kind: Kind;
15
+ version: string;
16
+ target: string;
17
+ runs_on: string;
18
+ artifact_name: string;
19
+ artifact_path: string;
20
+ path: string;
21
+ build?: string;
22
+ }
23
+ export interface PlanOptions {
24
+ cwd: string;
25
+ configPath?: string;
26
+ }
27
+ export declare function plan(opts: PlanOptions): Promise<MatrixRow[]>;
28
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAQ,IAAI,EAAE,MAAM,YAAY,CAAC;AAI7C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAmC5D"}