@pome-sh/cli 0.1.0 → 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.
- package/dist/build-info.json +3 -3
- package/dist/src/doctor/checks.js +2 -2
- package/node_modules/@pome-sh/sdk/dist/db.d.ts +4 -4
- package/node_modules/@pome-sh/sdk/dist/db.js +93 -25
- package/node_modules/@pome-sh/sdk/dist/db.js.map +1 -1
- package/node_modules/@pome-sh/sdk/package.json +2 -6
- package/node_modules/@pome-sh/twin-github/README.md +2 -1
- package/node_modules/@pome-sh/twin-github/package.json +2 -3
- package/node_modules/@pome-sh/twin-slack/package.json +2 -3
- package/node_modules/@pome-sh/twin-stripe/README.md +2 -2
- package/node_modules/@pome-sh/twin-stripe/package.json +2 -3
- package/package.json +6 -7
- package/dist/src/recorder/verdictArtifact.d.ts +0 -71
- package/dist/src/recorder/verdictArtifact.js +0 -207
- package/dist/src/score/view.d.ts +0 -38
- package/dist/src/score/view.js +0 -59
- package/dist/src/twin/github/app.d.ts +0 -10
- package/dist/src/twin/github/app.js +0 -316
- package/dist/src/twin/github/db/migrations.d.ts +0 -2
- package/dist/src/twin/github/db/migrations.js +0 -64
- package/dist/src/twin/github/db/openDatabase.d.ts +0 -2
- package/dist/src/twin/github/db/openDatabase.js +0 -13
- package/dist/src/twin/github/db/queries.d.ts +0 -77
- package/dist/src/twin/github/db/queries.js +0 -93
- package/dist/src/twin/github/domain/seed.d.ts +0 -74
- package/dist/src/twin/github/domain/seed.js +0 -104
- package/dist/src/twin/github/domain/serializers.d.ts +0 -113
- package/dist/src/twin/github/domain/serializers.js +0 -76
- package/dist/src/twin/github/types.d.ts +0 -66
- package/dist/src/twin/github/types.js +0 -1
- package/dist/src/twin-github/app.d.ts +0 -9
- package/dist/src/twin-github/app.js +0 -327
- package/dist/src/twin-github/auth.d.ts +0 -16
- package/dist/src/twin-github/auth.js +0 -142
- package/dist/src/twin-github/build-info.d.ts +0 -7
- package/dist/src/twin-github/build-info.js +0 -52
- package/dist/src/twin-github/db.d.ts +0 -4
- package/dist/src/twin-github/db.js +0 -362
- package/dist/src/twin-github/domain.d.ts +0 -1649
- package/dist/src/twin-github/domain.js +0 -957
- package/dist/src/twin-github/errors.d.ts +0 -14
- package/dist/src/twin-github/errors.js +0 -34
- package/dist/src/twin-github/index.d.ts +0 -9
- package/dist/src/twin-github/index.js +0 -7
- package/dist/src/twin-github/mcp.d.ts +0 -17
- package/dist/src/twin-github/mcp.js +0 -281
- package/dist/src/twin-github/recorder.d.ts +0 -2
- package/dist/src/twin-github/recorder.js +0 -29
- package/dist/src/twin-github/seed.d.ts +0 -74
- package/dist/src/twin-github/seed.js +0 -107
- package/dist/src/twin-github/serializers.d.ts +0 -449
- package/dist/src/twin-github/serializers.js +0 -429
- package/dist/src/twin-github/server.d.ts +0 -1
- package/dist/src/twin-github/server.js +0 -34
- package/dist/src/twin-github/tools.d.ts +0 -1545
- package/dist/src/twin-github/tools.js +0 -347
- package/dist/src/twin-github/types.d.ts +0 -198
- package/dist/src/twin-github/types.js +0 -1
- package/dist/src/twin-github/unsupported-envelope.d.ts +0 -10
- package/dist/src/twin-github/unsupported-envelope.js +0 -29
- package/dist/src/twin-github/util.d.ts +0 -13
- package/dist/src/twin-github/util.js +0 -61
- package/dist/src/twin-slack/app.d.ts +0 -17
- package/dist/src/twin-slack/app.js +0 -683
- package/dist/src/twin-slack/auth.d.ts +0 -38
- package/dist/src/twin-slack/auth.js +0 -219
- package/dist/src/twin-slack/build-info.d.ts +0 -7
- package/dist/src/twin-slack/build-info.js +0 -9
- package/dist/src/twin-slack/db.d.ts +0 -4
- package/dist/src/twin-slack/db.js +0 -213
- package/dist/src/twin-slack/domain.d.ts +0 -236
- package/dist/src/twin-slack/domain.js +0 -1293
- package/dist/src/twin-slack/errors.d.ts +0 -16
- package/dist/src/twin-slack/errors.js +0 -60
- package/dist/src/twin-slack/index.d.ts +0 -8
- package/dist/src/twin-slack/index.js +0 -8
- package/dist/src/twin-slack/mcp.d.ts +0 -17
- package/dist/src/twin-slack/mcp.js +0 -226
- package/dist/src/twin-slack/recorder.d.ts +0 -2
- package/dist/src/twin-slack/recorder.js +0 -15
- package/dist/src/twin-slack/seed.d.ts +0 -49
- package/dist/src/twin-slack/seed.js +0 -139
- package/dist/src/twin-slack/serializers.d.ts +0 -141
- package/dist/src/twin-slack/serializers.js +0 -377
- package/dist/src/twin-slack/tools.d.ts +0 -97
- package/dist/src/twin-slack/tools.js +0 -171
- package/dist/src/twin-slack/types.d.ts +0 -164
- package/dist/src/twin-slack/types.js +0 -1
- package/dist/src/twin-slack/unsupported-envelope.d.ts +0 -12
- package/dist/src/twin-slack/unsupported-envelope.js +0 -61
- package/dist/src/twin-slack/upstream-types.d.ts +0 -19
- package/dist/src/twin-slack/upstream-types.js +0 -1
- package/dist/src/twin-slack/util.d.ts +0 -31
- package/dist/src/twin-slack/util.js +0 -136
- package/node_modules/base64-js/LICENSE +0 -21
- package/node_modules/base64-js/README.md +0 -34
- package/node_modules/base64-js/base64js.min.js +0 -1
- package/node_modules/base64-js/index.d.ts +0 -3
- package/node_modules/base64-js/index.js +0 -150
- package/node_modules/base64-js/package.json +0 -47
- package/node_modules/better-sqlite3/LICENSE +0 -21
- package/node_modules/better-sqlite3/README.md +0 -99
- package/node_modules/better-sqlite3/binding.gyp +0 -38
- package/node_modules/better-sqlite3/build/Release/better_sqlite3.node +0 -0
- package/node_modules/better-sqlite3/deps/common.gypi +0 -68
- package/node_modules/better-sqlite3/deps/copy.js +0 -31
- package/node_modules/better-sqlite3/deps/defines.gypi +0 -42
- package/node_modules/better-sqlite3/deps/download.sh +0 -123
- package/node_modules/better-sqlite3/deps/patches/1208.patch +0 -15
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.c +0 -269395
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.h +0 -14347
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3ext.h +0 -739
- package/node_modules/better-sqlite3/deps/sqlite3.gyp +0 -80
- package/node_modules/better-sqlite3/deps/test_extension.c +0 -21
- package/node_modules/better-sqlite3/lib/database.js +0 -90
- package/node_modules/better-sqlite3/lib/index.js +0 -3
- package/node_modules/better-sqlite3/lib/methods/aggregate.js +0 -43
- package/node_modules/better-sqlite3/lib/methods/backup.js +0 -67
- package/node_modules/better-sqlite3/lib/methods/function.js +0 -31
- package/node_modules/better-sqlite3/lib/methods/inspect.js +0 -7
- package/node_modules/better-sqlite3/lib/methods/pragma.js +0 -12
- package/node_modules/better-sqlite3/lib/methods/serialize.js +0 -16
- package/node_modules/better-sqlite3/lib/methods/table.js +0 -189
- package/node_modules/better-sqlite3/lib/methods/transaction.js +0 -78
- package/node_modules/better-sqlite3/lib/methods/wrappers.js +0 -54
- package/node_modules/better-sqlite3/lib/sqlite-error.js +0 -20
- package/node_modules/better-sqlite3/lib/util.js +0 -12
- package/node_modules/better-sqlite3/package.json +0 -59
- package/node_modules/better-sqlite3/src/addon.cpp +0 -47
- package/node_modules/better-sqlite3/src/better_sqlite3.cpp +0 -74
- package/node_modules/better-sqlite3/src/objects/backup.cpp +0 -120
- package/node_modules/better-sqlite3/src/objects/backup.hpp +0 -36
- package/node_modules/better-sqlite3/src/objects/database.cpp +0 -417
- package/node_modules/better-sqlite3/src/objects/database.hpp +0 -103
- package/node_modules/better-sqlite3/src/objects/statement-iterator.cpp +0 -113
- package/node_modules/better-sqlite3/src/objects/statement-iterator.hpp +0 -50
- package/node_modules/better-sqlite3/src/objects/statement.cpp +0 -383
- package/node_modules/better-sqlite3/src/objects/statement.hpp +0 -58
- package/node_modules/better-sqlite3/src/util/bind-map.cpp +0 -73
- package/node_modules/better-sqlite3/src/util/binder.cpp +0 -193
- package/node_modules/better-sqlite3/src/util/constants.cpp +0 -172
- package/node_modules/better-sqlite3/src/util/custom-aggregate.cpp +0 -121
- package/node_modules/better-sqlite3/src/util/custom-function.cpp +0 -59
- package/node_modules/better-sqlite3/src/util/custom-table.cpp +0 -409
- package/node_modules/better-sqlite3/src/util/data-converter.cpp +0 -17
- package/node_modules/better-sqlite3/src/util/data.cpp +0 -194
- package/node_modules/better-sqlite3/src/util/helpers.cpp +0 -109
- package/node_modules/better-sqlite3/src/util/macros.cpp +0 -90
- package/node_modules/better-sqlite3/src/util/query-macros.cpp +0 -71
- package/node_modules/better-sqlite3/src/util/row-builder.cpp +0 -49
- package/node_modules/bindings/LICENSE.md +0 -22
- package/node_modules/bindings/README.md +0 -98
- package/node_modules/bindings/bindings.js +0 -221
- package/node_modules/bindings/package.json +0 -28
- package/node_modules/bl/.travis.yml +0 -17
- package/node_modules/bl/BufferList.js +0 -396
- package/node_modules/bl/LICENSE.md +0 -13
- package/node_modules/bl/README.md +0 -247
- package/node_modules/bl/bl.js +0 -84
- package/node_modules/bl/package.json +0 -37
- package/node_modules/bl/test/convert.js +0 -21
- package/node_modules/bl/test/indexOf.js +0 -492
- package/node_modules/bl/test/isBufferList.js +0 -32
- package/node_modules/bl/test/test.js +0 -869
- package/node_modules/buffer/AUTHORS.md +0 -70
- package/node_modules/buffer/LICENSE +0 -21
- package/node_modules/buffer/README.md +0 -410
- package/node_modules/buffer/index.d.ts +0 -186
- package/node_modules/buffer/index.js +0 -1817
- package/node_modules/buffer/package.json +0 -96
- package/node_modules/chownr/LICENSE +0 -15
- package/node_modules/chownr/README.md +0 -3
- package/node_modules/chownr/chownr.js +0 -167
- package/node_modules/chownr/package.json +0 -29
- package/node_modules/decompress-response/index.d.ts +0 -22
- package/node_modules/decompress-response/index.js +0 -58
- package/node_modules/decompress-response/license +0 -9
- package/node_modules/decompress-response/package.json +0 -56
- package/node_modules/decompress-response/readme.md +0 -48
- package/node_modules/deep-extend/CHANGELOG.md +0 -46
- package/node_modules/deep-extend/LICENSE +0 -20
- package/node_modules/deep-extend/README.md +0 -91
- package/node_modules/deep-extend/index.js +0 -1
- package/node_modules/deep-extend/lib/deep-extend.js +0 -150
- package/node_modules/deep-extend/package.json +0 -62
- package/node_modules/detect-libc/LICENSE +0 -201
- package/node_modules/detect-libc/README.md +0 -163
- package/node_modules/detect-libc/index.d.ts +0 -14
- package/node_modules/detect-libc/lib/detect-libc.js +0 -313
- package/node_modules/detect-libc/lib/elf.js +0 -39
- package/node_modules/detect-libc/lib/filesystem.js +0 -51
- package/node_modules/detect-libc/lib/process.js +0 -24
- package/node_modules/detect-libc/package.json +0 -44
- package/node_modules/end-of-stream/LICENSE +0 -21
- package/node_modules/end-of-stream/README.md +0 -54
- package/node_modules/end-of-stream/index.js +0 -96
- package/node_modules/end-of-stream/package.json +0 -37
- package/node_modules/expand-template/.travis.yml +0 -6
- package/node_modules/expand-template/LICENSE +0 -21
- package/node_modules/expand-template/README.md +0 -43
- package/node_modules/expand-template/index.js +0 -26
- package/node_modules/expand-template/package.json +0 -29
- package/node_modules/expand-template/test.js +0 -67
- package/node_modules/file-uri-to-path/.npmignore +0 -1
- package/node_modules/file-uri-to-path/.travis.yml +0 -30
- package/node_modules/file-uri-to-path/History.md +0 -21
- package/node_modules/file-uri-to-path/LICENSE +0 -20
- package/node_modules/file-uri-to-path/README.md +0 -74
- package/node_modules/file-uri-to-path/index.d.ts +0 -2
- package/node_modules/file-uri-to-path/index.js +0 -66
- package/node_modules/file-uri-to-path/package.json +0 -32
- package/node_modules/file-uri-to-path/test/test.js +0 -24
- package/node_modules/file-uri-to-path/test/tests.json +0 -13
- package/node_modules/fs-constants/LICENSE +0 -21
- package/node_modules/fs-constants/README.md +0 -26
- package/node_modules/fs-constants/browser.js +0 -1
- package/node_modules/fs-constants/index.js +0 -1
- package/node_modules/fs-constants/package.json +0 -19
- package/node_modules/github-from-package/.travis.yml +0 -4
- package/node_modules/github-from-package/LICENSE +0 -18
- package/node_modules/github-from-package/example/package.json +0 -8
- package/node_modules/github-from-package/example/url.js +0 -3
- package/node_modules/github-from-package/index.js +0 -17
- package/node_modules/github-from-package/package.json +0 -30
- package/node_modules/github-from-package/readme.markdown +0 -53
- package/node_modules/github-from-package/test/a.json +0 -8
- package/node_modules/github-from-package/test/b.json +0 -5
- package/node_modules/github-from-package/test/c.json +0 -5
- package/node_modules/github-from-package/test/d.json +0 -7
- package/node_modules/github-from-package/test/e.json +0 -5
- package/node_modules/github-from-package/test/url.js +0 -19
- package/node_modules/ieee754/LICENSE +0 -11
- package/node_modules/ieee754/README.md +0 -51
- package/node_modules/ieee754/index.d.ts +0 -10
- package/node_modules/ieee754/index.js +0 -85
- package/node_modules/ieee754/package.json +0 -52
- package/node_modules/inherits/LICENSE +0 -16
- package/node_modules/inherits/README.md +0 -42
- package/node_modules/inherits/inherits.js +0 -9
- package/node_modules/inherits/inherits_browser.js +0 -27
- package/node_modules/inherits/package.json +0 -29
- package/node_modules/ini/LICENSE +0 -15
- package/node_modules/ini/README.md +0 -102
- package/node_modules/ini/ini.js +0 -206
- package/node_modules/ini/package.json +0 -33
- package/node_modules/mimic-response/index.d.ts +0 -17
- package/node_modules/mimic-response/index.js +0 -77
- package/node_modules/mimic-response/license +0 -9
- package/node_modules/mimic-response/package.json +0 -42
- package/node_modules/mimic-response/readme.md +0 -78
- package/node_modules/minimist/.eslintrc +0 -29
- package/node_modules/minimist/.github/FUNDING.yml +0 -12
- package/node_modules/minimist/.nycrc +0 -14
- package/node_modules/minimist/CHANGELOG.md +0 -298
- package/node_modules/minimist/LICENSE +0 -18
- package/node_modules/minimist/README.md +0 -121
- package/node_modules/minimist/example/parse.js +0 -4
- package/node_modules/minimist/index.js +0 -263
- package/node_modules/minimist/package.json +0 -75
- package/node_modules/minimist/test/all_bool.js +0 -34
- package/node_modules/minimist/test/bool.js +0 -177
- package/node_modules/minimist/test/dash.js +0 -43
- package/node_modules/minimist/test/default_bool.js +0 -37
- package/node_modules/minimist/test/dotted.js +0 -24
- package/node_modules/minimist/test/kv_short.js +0 -32
- package/node_modules/minimist/test/long.js +0 -33
- package/node_modules/minimist/test/num.js +0 -38
- package/node_modules/minimist/test/parse.js +0 -209
- package/node_modules/minimist/test/parse_modified.js +0 -11
- package/node_modules/minimist/test/proto.js +0 -64
- package/node_modules/minimist/test/short.js +0 -69
- package/node_modules/minimist/test/stop_early.js +0 -17
- package/node_modules/minimist/test/unknown.js +0 -104
- package/node_modules/minimist/test/whitespace.js +0 -10
- package/node_modules/mkdirp-classic/LICENSE +0 -21
- package/node_modules/mkdirp-classic/README.md +0 -18
- package/node_modules/mkdirp-classic/index.js +0 -98
- package/node_modules/mkdirp-classic/package.json +0 -18
- package/node_modules/napi-build-utils/.github/workflows/run-npm-tests.yml +0 -31
- package/node_modules/napi-build-utils/LICENSE +0 -21
- package/node_modules/napi-build-utils/README.md +0 -52
- package/node_modules/napi-build-utils/index.js +0 -214
- package/node_modules/napi-build-utils/index.md +0 -0
- package/node_modules/napi-build-utils/package.json +0 -42
- package/node_modules/node-abi/LICENSE +0 -21
- package/node_modules/node-abi/README.md +0 -54
- package/node_modules/node-abi/abi_registry.json +0 -453
- package/node_modules/node-abi/index.js +0 -179
- package/node_modules/node-abi/package.json +0 -45
- package/node_modules/once/LICENSE +0 -15
- package/node_modules/once/README.md +0 -79
- package/node_modules/once/once.js +0 -42
- package/node_modules/once/package.json +0 -33
- package/node_modules/prebuild-install/CHANGELOG.md +0 -131
- package/node_modules/prebuild-install/CONTRIBUTING.md +0 -6
- package/node_modules/prebuild-install/LICENSE +0 -21
- package/node_modules/prebuild-install/README.md +0 -163
- package/node_modules/prebuild-install/asset.js +0 -44
- package/node_modules/prebuild-install/bin.js +0 -78
- package/node_modules/prebuild-install/download.js +0 -142
- package/node_modules/prebuild-install/error.js +0 -14
- package/node_modules/prebuild-install/help.txt +0 -16
- package/node_modules/prebuild-install/index.js +0 -1
- package/node_modules/prebuild-install/log.js +0 -33
- package/node_modules/prebuild-install/package.json +0 -67
- package/node_modules/prebuild-install/proxy.js +0 -35
- package/node_modules/prebuild-install/rc.js +0 -64
- package/node_modules/prebuild-install/util.js +0 -143
- package/node_modules/pump/.github/FUNDING.yml +0 -2
- package/node_modules/pump/.travis.yml +0 -5
- package/node_modules/pump/LICENSE +0 -21
- package/node_modules/pump/README.md +0 -74
- package/node_modules/pump/SECURITY.md +0 -5
- package/node_modules/pump/empty.js +0 -1
- package/node_modules/pump/index.js +0 -86
- package/node_modules/pump/package.json +0 -30
- package/node_modules/pump/test-browser.js +0 -66
- package/node_modules/pump/test-node.js +0 -53
- package/node_modules/rc/LICENSE.APACHE2 +0 -15
- package/node_modules/rc/LICENSE.BSD +0 -26
- package/node_modules/rc/LICENSE.MIT +0 -24
- package/node_modules/rc/README.md +0 -227
- package/node_modules/rc/browser.js +0 -7
- package/node_modules/rc/cli.js +0 -4
- package/node_modules/rc/index.js +0 -53
- package/node_modules/rc/lib/utils.js +0 -104
- package/node_modules/rc/package.json +0 -29
- package/node_modules/rc/test/ini.js +0 -16
- package/node_modules/rc/test/nested-env-vars.js +0 -50
- package/node_modules/rc/test/test.js +0 -59
- package/node_modules/readable-stream/CONTRIBUTING.md +0 -38
- package/node_modules/readable-stream/GOVERNANCE.md +0 -136
- package/node_modules/readable-stream/LICENSE +0 -47
- package/node_modules/readable-stream/README.md +0 -106
- package/node_modules/readable-stream/errors-browser.js +0 -127
- package/node_modules/readable-stream/errors.js +0 -116
- package/node_modules/readable-stream/experimentalWarning.js +0 -17
- package/node_modules/readable-stream/lib/_stream_duplex.js +0 -126
- package/node_modules/readable-stream/lib/_stream_passthrough.js +0 -37
- package/node_modules/readable-stream/lib/_stream_readable.js +0 -1027
- package/node_modules/readable-stream/lib/_stream_transform.js +0 -190
- package/node_modules/readable-stream/lib/_stream_writable.js +0 -641
- package/node_modules/readable-stream/lib/internal/streams/async_iterator.js +0 -180
- package/node_modules/readable-stream/lib/internal/streams/buffer_list.js +0 -183
- package/node_modules/readable-stream/lib/internal/streams/destroy.js +0 -96
- package/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +0 -86
- package/node_modules/readable-stream/lib/internal/streams/from-browser.js +0 -3
- package/node_modules/readable-stream/lib/internal/streams/from.js +0 -52
- package/node_modules/readable-stream/lib/internal/streams/pipeline.js +0 -86
- package/node_modules/readable-stream/lib/internal/streams/state.js +0 -22
- package/node_modules/readable-stream/lib/internal/streams/stream-browser.js +0 -1
- package/node_modules/readable-stream/lib/internal/streams/stream.js +0 -1
- package/node_modules/readable-stream/package.json +0 -68
- package/node_modules/readable-stream/readable-browser.js +0 -9
- package/node_modules/readable-stream/readable.js +0 -16
- package/node_modules/safe-buffer/LICENSE +0 -21
- package/node_modules/safe-buffer/README.md +0 -584
- package/node_modules/safe-buffer/index.d.ts +0 -187
- package/node_modules/safe-buffer/index.js +0 -65
- package/node_modules/safe-buffer/package.json +0 -51
- package/node_modules/semver/LICENSE +0 -15
- package/node_modules/semver/README.md +0 -680
- package/node_modules/semver/bin/semver.js +0 -195
- package/node_modules/semver/classes/comparator.js +0 -143
- package/node_modules/semver/classes/index.js +0 -7
- package/node_modules/semver/classes/range.js +0 -577
- package/node_modules/semver/classes/semver.js +0 -350
- package/node_modules/semver/functions/clean.js +0 -8
- package/node_modules/semver/functions/cmp.js +0 -54
- package/node_modules/semver/functions/coerce.js +0 -62
- package/node_modules/semver/functions/compare-build.js +0 -9
- package/node_modules/semver/functions/compare-loose.js +0 -5
- package/node_modules/semver/functions/compare.js +0 -7
- package/node_modules/semver/functions/diff.js +0 -60
- package/node_modules/semver/functions/eq.js +0 -5
- package/node_modules/semver/functions/gt.js +0 -5
- package/node_modules/semver/functions/gte.js +0 -5
- package/node_modules/semver/functions/inc.js +0 -21
- package/node_modules/semver/functions/lt.js +0 -5
- package/node_modules/semver/functions/lte.js +0 -5
- package/node_modules/semver/functions/major.js +0 -5
- package/node_modules/semver/functions/minor.js +0 -5
- package/node_modules/semver/functions/neq.js +0 -5
- package/node_modules/semver/functions/parse.js +0 -18
- package/node_modules/semver/functions/patch.js +0 -5
- package/node_modules/semver/functions/prerelease.js +0 -8
- package/node_modules/semver/functions/rcompare.js +0 -5
- package/node_modules/semver/functions/rsort.js +0 -5
- package/node_modules/semver/functions/satisfies.js +0 -12
- package/node_modules/semver/functions/sort.js +0 -5
- package/node_modules/semver/functions/truncate.js +0 -48
- package/node_modules/semver/functions/valid.js +0 -8
- package/node_modules/semver/index.js +0 -93
- package/node_modules/semver/internal/constants.js +0 -37
- package/node_modules/semver/internal/debug.js +0 -11
- package/node_modules/semver/internal/identifiers.js +0 -29
- package/node_modules/semver/internal/lrucache.js +0 -42
- package/node_modules/semver/internal/parse-options.js +0 -17
- package/node_modules/semver/internal/re.js +0 -223
- package/node_modules/semver/package.json +0 -78
- package/node_modules/semver/preload.js +0 -4
- package/node_modules/semver/range.bnf +0 -17
- package/node_modules/semver/ranges/gtr.js +0 -6
- package/node_modules/semver/ranges/intersects.js +0 -9
- package/node_modules/semver/ranges/ltr.js +0 -6
- package/node_modules/semver/ranges/max-satisfying.js +0 -27
- package/node_modules/semver/ranges/min-satisfying.js +0 -26
- package/node_modules/semver/ranges/min-version.js +0 -63
- package/node_modules/semver/ranges/outside.js +0 -82
- package/node_modules/semver/ranges/simplify.js +0 -49
- package/node_modules/semver/ranges/subset.js +0 -249
- package/node_modules/semver/ranges/to-comparators.js +0 -10
- package/node_modules/semver/ranges/valid.js +0 -13
- package/node_modules/simple-concat/.travis.yml +0 -3
- package/node_modules/simple-concat/LICENSE +0 -20
- package/node_modules/simple-concat/README.md +0 -44
- package/node_modules/simple-concat/index.js +0 -15
- package/node_modules/simple-concat/package.json +0 -47
- package/node_modules/simple-concat/test/basic.js +0 -41
- package/node_modules/simple-get/.github/dependabot.yml +0 -15
- package/node_modules/simple-get/.github/workflows/ci.yml +0 -23
- package/node_modules/simple-get/LICENSE +0 -20
- package/node_modules/simple-get/README.md +0 -333
- package/node_modules/simple-get/index.js +0 -108
- package/node_modules/simple-get/package.json +0 -67
- package/node_modules/string_decoder/LICENSE +0 -48
- package/node_modules/string_decoder/README.md +0 -47
- package/node_modules/string_decoder/lib/string_decoder.js +0 -296
- package/node_modules/string_decoder/package.json +0 -34
- package/node_modules/strip-json-comments/index.js +0 -70
- package/node_modules/strip-json-comments/license +0 -21
- package/node_modules/strip-json-comments/package.json +0 -42
- package/node_modules/strip-json-comments/readme.md +0 -64
- package/node_modules/tar-fs/.travis.yml +0 -6
- package/node_modules/tar-fs/LICENSE +0 -21
- package/node_modules/tar-fs/README.md +0 -165
- package/node_modules/tar-fs/index.js +0 -392
- package/node_modules/tar-fs/package.json +0 -46
- package/node_modules/tar-fs/test/fixtures/a/hello.txt +0 -1
- package/node_modules/tar-fs/test/fixtures/b/a/test.txt +0 -1
- package/node_modules/tar-fs/test/fixtures/d/file1 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/file2 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/sub-dir/file5 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/sub-files/file3 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/sub-files/file4 +0 -0
- package/node_modules/tar-fs/test/fixtures/e/directory/.ignore +0 -0
- package/node_modules/tar-fs/test/fixtures/e/file +0 -0
- package/node_modules/tar-fs/test/fixtures/invalid.tar +0 -0
- package/node_modules/tar-fs/test/index.js +0 -457
- package/node_modules/tar-stream/LICENSE +0 -21
- package/node_modules/tar-stream/README.md +0 -168
- package/node_modules/tar-stream/extract.js +0 -257
- package/node_modules/tar-stream/headers.js +0 -295
- package/node_modules/tar-stream/index.js +0 -2
- package/node_modules/tar-stream/pack.js +0 -255
- package/node_modules/tar-stream/package.json +0 -58
- package/node_modules/tar-stream/sandbox.js +0 -11
- package/node_modules/tunnel-agent/LICENSE +0 -55
- package/node_modules/tunnel-agent/README.md +0 -4
- package/node_modules/tunnel-agent/index.js +0 -244
- package/node_modules/tunnel-agent/package.json +0 -22
- package/node_modules/util-deprecate/History.md +0 -16
- package/node_modules/util-deprecate/LICENSE +0 -24
- package/node_modules/util-deprecate/README.md +0 -53
- package/node_modules/util-deprecate/browser.js +0 -67
- package/node_modules/util-deprecate/node.js +0 -6
- package/node_modules/util-deprecate/package.json +0 -27
- package/node_modules/wrappy/LICENSE +0 -15
- package/node_modules/wrappy/README.md +0 -36
- package/node_modules/wrappy/package.json +0 -29
- package/node_modules/wrappy/wrappy.js +0 -33
|
@@ -1,957 +0,0 @@
|
|
|
1
|
-
import { conflict, notFound, validationFailed } from "./errors.js";
|
|
2
|
-
import { fileSha, linesChanged, makeSha, nowIso, paginate, treeSha } from "./util.js";
|
|
3
|
-
import { defaultSeedState } from "./seed.js";
|
|
4
|
-
import { branchJson, branchState, checkRunJson, checkRunState, combinedStatusJson, commitJson, commitStatusState, contentDirectoryEntryJson, contentFileJson, fileState, issueAssigneesState, issueCommentJson, issueCommentState, issueJson, issueLabelsState, issueState, labelJson, labelState, pullRequestFileJson, pullRequestJson, pullRequestReviewState, pullRequestState, repoJson, repoState, reviewJson, statusJson, userJson } from "./serializers.js";
|
|
5
|
-
import { resetDatabase } from "./db.js";
|
|
6
|
-
export class GitHubDomain {
|
|
7
|
-
db;
|
|
8
|
-
constructor(db) {
|
|
9
|
-
this.db = db;
|
|
10
|
-
}
|
|
11
|
-
seed(seed = defaultSeedState(), onDelta) {
|
|
12
|
-
const before = this.summarizeRepositories();
|
|
13
|
-
const tx = this.db.transaction(() => {
|
|
14
|
-
resetDatabase(this.db);
|
|
15
|
-
const users = new Set(seed.users?.map((user) => user.login) ?? []);
|
|
16
|
-
for (const repo of seed.repositories) {
|
|
17
|
-
users.add(repo.owner);
|
|
18
|
-
for (const login of repo.collaborators ?? [])
|
|
19
|
-
users.add(login);
|
|
20
|
-
for (const issue of repo.issues ?? [])
|
|
21
|
-
for (const login of issue.assignees ?? [])
|
|
22
|
-
users.add(login);
|
|
23
|
-
}
|
|
24
|
-
users.add("pome-agent");
|
|
25
|
-
for (const user of seed.users ?? []) {
|
|
26
|
-
this.upsertUser(user.login, user.type ?? "User", user.name ?? "");
|
|
27
|
-
}
|
|
28
|
-
for (const login of users) {
|
|
29
|
-
this.upsertUser(login, login === "acme" ? "Organization" : "User", login);
|
|
30
|
-
}
|
|
31
|
-
for (const repoSeed of seed.repositories) {
|
|
32
|
-
const repo = this.insertRepository({
|
|
33
|
-
owner: repoSeed.owner,
|
|
34
|
-
name: repoSeed.name,
|
|
35
|
-
description: repoSeed.description ?? "",
|
|
36
|
-
private: repoSeed.private ?? false,
|
|
37
|
-
defaultBranch: repoSeed.default_branch ?? "main",
|
|
38
|
-
fork: false,
|
|
39
|
-
parentFullName: null
|
|
40
|
-
});
|
|
41
|
-
for (const login of repoSeed.collaborators ?? [])
|
|
42
|
-
this.addCollaborator(repo.id, login);
|
|
43
|
-
this.addCollaborator(repo.id, "pome-agent");
|
|
44
|
-
for (const label of repoSeed.labels ?? []) {
|
|
45
|
-
this.createLabel(repo, label.name, label.color ?? "ededed", label.description ?? "");
|
|
46
|
-
}
|
|
47
|
-
this.createBranchInternal(repo, repo.default_branch, null);
|
|
48
|
-
const files = repoSeed.files?.filter((file) => (file.branch ?? repo.default_branch) === repo.default_branch) ?? [];
|
|
49
|
-
this.commitFiles(repo, repo.default_branch, "Initial seed commit", files, "pome-agent");
|
|
50
|
-
const nonDefaultBranches = new Set((repoSeed.files ?? []).map((file) => file.branch ?? repo.default_branch).filter((branch) => branch !== repo.default_branch));
|
|
51
|
-
for (const branch of nonDefaultBranches) {
|
|
52
|
-
this.createBranch({ owner: repo.owner, repo: repo.name, branch, from_branch: repo.default_branch });
|
|
53
|
-
const branchFiles = repoSeed.files?.filter((file) => (file.branch ?? repo.default_branch) === branch) ?? [];
|
|
54
|
-
this.commitFiles(repo, branch, `Seed ${branch}`, branchFiles, "pome-agent");
|
|
55
|
-
}
|
|
56
|
-
for (const issue of repoSeed.issues ?? []) {
|
|
57
|
-
const legacyAssignee = issue.assignee;
|
|
58
|
-
const assignees = issue.assignees ?? (legacyAssignee ? [legacyAssignee] : []);
|
|
59
|
-
const created = this.createIssue({ owner: repo.owner, repo: repo.name, title: issue.title, body: issue.body ?? "", labels: issue.labels ?? [], assignees });
|
|
60
|
-
if (issue.number && issue.number !== created.number) {
|
|
61
|
-
this.db.prepare("UPDATE issues SET number = ? WHERE repo_id = ? AND number = ?").run(issue.number, repo.id, created.number);
|
|
62
|
-
this.bumpEntityCounter(repo.id, issue.number);
|
|
63
|
-
}
|
|
64
|
-
if (issue.state === "closed")
|
|
65
|
-
this.updateIssue({ owner: repo.owner, repo: repo.name, issue_number: issue.number ?? created.number, state: "closed" });
|
|
66
|
-
}
|
|
67
|
-
for (const pull of repoSeed.pull_requests ?? []) {
|
|
68
|
-
const createdPr = this.createPullRequest({ owner: repo.owner, repo: repo.name, title: pull.title, body: pull.body ?? "", head: pull.head, base: pull.base ?? repo.default_branch, actor: pull.author });
|
|
69
|
-
const prNumber = createdPr.number;
|
|
70
|
-
// Seed reviews directly into pull_request_reviews so we can record
|
|
71
|
-
// the author and state honestly. Going through createPullRequestReview
|
|
72
|
-
// would hardcode user_login = "pome-agent" and lose author identity.
|
|
73
|
-
for (const review of pull.reviews ?? []) {
|
|
74
|
-
users.add(review.author);
|
|
75
|
-
this.upsertUser(review.author, "User", review.author);
|
|
76
|
-
const prRow = this.requirePullRequest(repo.id, prNumber);
|
|
77
|
-
const headRepo = this.requireRepoById(prRow.head_repo_id);
|
|
78
|
-
const headSha = this.requireBranch(headRepo.id, prRow.head_ref).head_sha;
|
|
79
|
-
this.db.prepare("INSERT INTO pull_request_reviews (repo_id, pull_number, user_login, state, body, commit_sha, submitted_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(repo.id, prNumber, review.author, review.state, review.body ?? "", headSha, nowIso());
|
|
80
|
-
}
|
|
81
|
-
// Seed commit statuses on the PR head SHA. Same shape as
|
|
82
|
-
// createStatus() so merge_pull_request's required-status check
|
|
83
|
-
// sees the seeded value.
|
|
84
|
-
if ((pull.statuses ?? []).length > 0) {
|
|
85
|
-
const prRow = this.requirePullRequest(repo.id, prNumber);
|
|
86
|
-
const headRepo = this.requireRepoById(prRow.head_repo_id);
|
|
87
|
-
const headSha = this.requireBranch(headRepo.id, prRow.head_ref).head_sha ?? "";
|
|
88
|
-
for (const status of pull.statuses ?? []) {
|
|
89
|
-
this.createStatus({
|
|
90
|
-
owner: headRepo.owner,
|
|
91
|
-
repo: headRepo.name,
|
|
92
|
-
sha: headSha,
|
|
93
|
-
state: status.state ?? "success",
|
|
94
|
-
context: status.context ?? "ci/build",
|
|
95
|
-
description: status.description ?? ""
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
this.audit("seed", null, { repositories: seed.repositories.length });
|
|
102
|
-
});
|
|
103
|
-
tx();
|
|
104
|
-
onDelta?.({
|
|
105
|
-
before: { repositories: before },
|
|
106
|
-
after: { repositories: this.summarizeRepositories() }
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
summarizeRepositories() {
|
|
110
|
-
const rows = this.db.prepare("SELECT owner, name FROM repositories ORDER BY full_name ASC").all();
|
|
111
|
-
return rows;
|
|
112
|
-
}
|
|
113
|
-
exportState() {
|
|
114
|
-
const repos = this.db.prepare("SELECT * FROM repositories ORDER BY full_name ASC").all();
|
|
115
|
-
return {
|
|
116
|
-
repositories: repos.map((repo) => ({
|
|
117
|
-
...repo,
|
|
118
|
-
branches: this.listBranches(repo.id),
|
|
119
|
-
files: this.db.prepare("SELECT * FROM files WHERE repo_id = ? ORDER BY branch, path").all(repo.id),
|
|
120
|
-
labels: this.listLabels(repo.id),
|
|
121
|
-
issues: this.listIssuesRows(repo.id).map((issue) => ({
|
|
122
|
-
...issue,
|
|
123
|
-
labels: this.listIssueLabels(repo.id, issue.number),
|
|
124
|
-
assignees: this.listIssueAssignees(repo.id, issue.number),
|
|
125
|
-
comments: this.listIssueCommentRows(repo.id, issue.number)
|
|
126
|
-
})),
|
|
127
|
-
pull_requests: this.listPullRequestRows(repo.id).map((pull) => ({
|
|
128
|
-
...pull,
|
|
129
|
-
files: this.listPullRequestFileRows(repo.id, pull.number),
|
|
130
|
-
reviews: this.listPullRequestReviewRows(repo.id, pull.number),
|
|
131
|
-
review_comments: this.listPullRequestReviewCommentRows(repo.id, pull.number)
|
|
132
|
-
})),
|
|
133
|
-
commit_statuses: this.db.prepare("SELECT * FROM commit_statuses WHERE repo_id = ? ORDER BY id ASC").all(repo.id),
|
|
134
|
-
check_runs: this.db.prepare("SELECT * FROM check_runs WHERE repo_id = ? ORDER BY id ASC").all(repo.id)
|
|
135
|
-
}))
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
getRepository(input) {
|
|
139
|
-
return repoJson(this.requireRepo(input.owner, input.repo));
|
|
140
|
-
}
|
|
141
|
-
createRepository(input, onDelta) {
|
|
142
|
-
const owner = input.owner ?? "pome-agent";
|
|
143
|
-
const repo = this.transaction(() => {
|
|
144
|
-
this.upsertUser(owner, "Organization", owner);
|
|
145
|
-
if (this.getRepo(owner, input.name))
|
|
146
|
-
validationFailed("name", "already_exists", input.name);
|
|
147
|
-
const created = this.insertRepository({
|
|
148
|
-
owner,
|
|
149
|
-
name: input.name,
|
|
150
|
-
description: input.description ?? "",
|
|
151
|
-
private: input.private ?? false,
|
|
152
|
-
defaultBranch: "main",
|
|
153
|
-
fork: false,
|
|
154
|
-
parentFullName: null
|
|
155
|
-
});
|
|
156
|
-
this.addCollaborator(created.id, "pome-agent");
|
|
157
|
-
this.createBranchInternal(created, "main", null);
|
|
158
|
-
this.commitFiles(created, "main", "Initial commit", [{ path: "README.md", content: `# ${input.name}\n` }], "pome-agent");
|
|
159
|
-
return created;
|
|
160
|
-
});
|
|
161
|
-
this.audit("create_repository", repo.full_name, input);
|
|
162
|
-
const final = this.requireRepo(owner, input.name);
|
|
163
|
-
onDelta?.({ before: null, after: repoState(final) });
|
|
164
|
-
return repoJson(final);
|
|
165
|
-
}
|
|
166
|
-
forkRepository(input, onDelta) {
|
|
167
|
-
const source = this.requireRepo(input.owner, input.repo);
|
|
168
|
-
const owner = input.organization ?? "pome-agent";
|
|
169
|
-
const fork = this.transaction(() => {
|
|
170
|
-
this.upsertUser(owner, owner === input.organization ? "Organization" : "User", owner);
|
|
171
|
-
if (this.getRepo(owner, source.name))
|
|
172
|
-
validationFailed("name", "already_exists", source.name);
|
|
173
|
-
const created = this.insertRepository({
|
|
174
|
-
owner,
|
|
175
|
-
name: source.name,
|
|
176
|
-
description: source.description,
|
|
177
|
-
private: Boolean(source.private),
|
|
178
|
-
defaultBranch: source.default_branch,
|
|
179
|
-
fork: true,
|
|
180
|
-
parentFullName: source.full_name
|
|
181
|
-
});
|
|
182
|
-
this.addCollaborator(created.id, "pome-agent");
|
|
183
|
-
const commitShaMap = this.copyForkCommits(source, created);
|
|
184
|
-
for (const branch of this.listBranches(source.id)) {
|
|
185
|
-
this.createBranchInternal(created, branch.name, branch.head_sha ? commitShaMap.get(branch.head_sha) ?? null : null);
|
|
186
|
-
const files = this.db.prepare("SELECT * FROM files WHERE repo_id = ? AND branch = ?").all(source.id, branch.name);
|
|
187
|
-
for (const file of files) {
|
|
188
|
-
this.db.prepare("INSERT INTO files (repo_id, branch, path, content, sha, size, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(created.id, file.branch, file.path, file.content, file.sha, file.size, nowIso());
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return created;
|
|
192
|
-
});
|
|
193
|
-
this.audit("fork_repository", fork.full_name, input);
|
|
194
|
-
onDelta?.({ before: null, after: repoState(fork) });
|
|
195
|
-
return repoJson(fork);
|
|
196
|
-
}
|
|
197
|
-
searchRepositories(input) {
|
|
198
|
-
const query = (input.query ?? input.q ?? "").toLowerCase();
|
|
199
|
-
const repos = this.db.prepare("SELECT * FROM repositories ORDER BY full_name ASC").all().filter((repo) => !query || repo.full_name.toLowerCase().includes(query) || repo.description.toLowerCase().includes(query));
|
|
200
|
-
const items = paginate(repos, input.page, input.per_page ?? input.perPage).map(repoJson);
|
|
201
|
-
return { total_count: repos.length, incomplete_results: false, items };
|
|
202
|
-
}
|
|
203
|
-
searchUsers(input) {
|
|
204
|
-
const query = (input.query ?? input.q ?? "").toLowerCase();
|
|
205
|
-
const rows = this.db.prepare("SELECT login, type FROM users ORDER BY login ASC").all();
|
|
206
|
-
const users = rows.filter((user) => !query || user.login.toLowerCase().includes(query));
|
|
207
|
-
return { total_count: users.length, incomplete_results: false, items: paginate(users, input.page, input.per_page ?? input.perPage).map((user) => userJson(user.login, user.type)) };
|
|
208
|
-
}
|
|
209
|
-
searchCode(input) {
|
|
210
|
-
const query = (input.query ?? input.q ?? "").toLowerCase();
|
|
211
|
-
let rows = this.db
|
|
212
|
-
.prepare("SELECT files.*, repositories.owner, repositories.name, repositories.full_name, repositories.description, repositories.private, repositories.default_branch, repositories.fork, repositories.parent_full_name, repositories.entity_counter, repositories.created_at, repositories.updated_at FROM files INNER JOIN repositories ON files.repo_id = repositories.id WHERE files.branch = repositories.default_branch ORDER BY repositories.full_name, files.path")
|
|
213
|
-
.all();
|
|
214
|
-
if (input.owner)
|
|
215
|
-
rows = rows.filter((row) => row.owner === input.owner);
|
|
216
|
-
if (input.repo)
|
|
217
|
-
rows = rows.filter((row) => row.name === input.repo);
|
|
218
|
-
rows = rows.filter((row) => !query || row.path.toLowerCase().includes(query) || row.content.toLowerCase().includes(query));
|
|
219
|
-
return {
|
|
220
|
-
total_count: rows.length,
|
|
221
|
-
incomplete_results: false,
|
|
222
|
-
items: paginate(rows, input.page, input.per_page ?? input.perPage).map((row) => ({
|
|
223
|
-
name: row.path.split("/").at(-1),
|
|
224
|
-
path: row.path,
|
|
225
|
-
sha: row.sha,
|
|
226
|
-
url: `https://api.github.com/repos/${row.full_name}/contents/${row.path}`,
|
|
227
|
-
git_url: `https://api.github.com/repos/${row.full_name}/git/blobs/${row.sha}`,
|
|
228
|
-
html_url: `https://github.com/${row.full_name}/blob/${row.branch}/${row.path}`,
|
|
229
|
-
repository: repoJson(row)
|
|
230
|
-
}))
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
getFileContents(input) {
|
|
234
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
235
|
-
const branch = input.ref ?? repo.default_branch;
|
|
236
|
-
this.requireBranch(repo.id, branch);
|
|
237
|
-
const path = normalizePath(input.path ?? "");
|
|
238
|
-
const direct = this.getFile(repo.id, branch, path);
|
|
239
|
-
if (direct)
|
|
240
|
-
return contentFileJson(direct, repo);
|
|
241
|
-
const children = this.listDirectory(repo, branch, path);
|
|
242
|
-
if (children.length === 0)
|
|
243
|
-
notFound("Not Found");
|
|
244
|
-
return children;
|
|
245
|
-
}
|
|
246
|
-
listCommits(input) {
|
|
247
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
248
|
-
const branch = input.sha ?? repo.default_branch;
|
|
249
|
-
const branchRow = this.requireBranch(repo.id, branch);
|
|
250
|
-
const allRows = this.db.prepare("SELECT * FROM commits WHERE repo_id = ?").all(repo.id);
|
|
251
|
-
const bySha = new Map(allRows.map((commit) => [commit.sha, commit]));
|
|
252
|
-
const rows = [];
|
|
253
|
-
for (let sha = branchRow.head_sha; sha;) {
|
|
254
|
-
const commit = bySha.get(sha);
|
|
255
|
-
if (!commit)
|
|
256
|
-
break;
|
|
257
|
-
rows.push(commit);
|
|
258
|
-
sha = commit.parent_sha;
|
|
259
|
-
}
|
|
260
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map((commit) => commitJson(commit, repo));
|
|
261
|
-
}
|
|
262
|
-
createOrUpdateFile(input, options = {}, onDelta) {
|
|
263
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
264
|
-
const branch = input.branch ?? repo.default_branch;
|
|
265
|
-
let before = null;
|
|
266
|
-
let afterFile = null;
|
|
267
|
-
const result = this.transaction(() => {
|
|
268
|
-
this.requireBranch(repo.id, branch);
|
|
269
|
-
const path = normalizePath(input.path);
|
|
270
|
-
const existing = this.getFile(repo.id, branch, path);
|
|
271
|
-
before = existing ? fileState(existing, repo) : null;
|
|
272
|
-
if (existing && !input.sha)
|
|
273
|
-
validationFailed("sha", "missing", path);
|
|
274
|
-
if (existing && input.sha !== existing.sha)
|
|
275
|
-
validationFailed("sha", "invalid", input.sha);
|
|
276
|
-
const content = input.encoding === "base64" ? Buffer.from(input.content, "base64").toString("utf8") : input.content;
|
|
277
|
-
const commit = this.commitFiles(repo, branch, input.message, [{ path, content }], options.actor ?? "pome-agent");
|
|
278
|
-
const file = this.getFile(repo.id, branch, path);
|
|
279
|
-
afterFile = file;
|
|
280
|
-
return { content: contentFileJson(file, repo), commit: commitJson(commit, repo) };
|
|
281
|
-
});
|
|
282
|
-
this.audit("create_or_update_file", repo.full_name, { ...input, content: "[redacted]" });
|
|
283
|
-
onDelta?.({ before, after: afterFile ? fileState(afterFile, repo) : null });
|
|
284
|
-
return result;
|
|
285
|
-
}
|
|
286
|
-
pushFiles(input, options = {}, onDelta) {
|
|
287
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
288
|
-
const branch = input.branch ?? repo.default_branch;
|
|
289
|
-
this.requireBranch(repo.id, branch);
|
|
290
|
-
if (input.files.length === 0)
|
|
291
|
-
validationFailed("files", "missing");
|
|
292
|
-
const paths = new Set();
|
|
293
|
-
const files = input.files.map((file) => {
|
|
294
|
-
const path = normalizePath(file.path);
|
|
295
|
-
if (paths.has(path))
|
|
296
|
-
validationFailed("files.path", "duplicate", path);
|
|
297
|
-
paths.add(path);
|
|
298
|
-
return { path, content: file.encoding === "base64" ? Buffer.from(file.content, "base64").toString("utf8") : file.content };
|
|
299
|
-
});
|
|
300
|
-
const beforeFiles = files.map((file) => {
|
|
301
|
-
const existing = this.getFile(repo.id, branch, file.path);
|
|
302
|
-
return { path: file.path, sha: existing?.sha ?? null };
|
|
303
|
-
});
|
|
304
|
-
const commit = this.transaction(() => this.commitFiles(repo, branch, input.message, files, options.actor ?? "pome-agent"));
|
|
305
|
-
this.audit("push_files", repo.full_name, { ...input, files: files.map((file) => file.path) });
|
|
306
|
-
const afterFiles = files.map((file) => {
|
|
307
|
-
const updated = this.getFile(repo.id, branch, file.path);
|
|
308
|
-
return { path: file.path, sha: updated.sha };
|
|
309
|
-
});
|
|
310
|
-
onDelta?.({
|
|
311
|
-
before: { repo: repo.full_name, branch, files: beforeFiles },
|
|
312
|
-
after: { repo: repo.full_name, branch, files: afterFiles, commit_sha: commit.sha }
|
|
313
|
-
});
|
|
314
|
-
return { commit: commitJson(commit, repo), files: files.map((file) => contentFileJson(this.getFile(repo.id, branch, file.path), repo)) };
|
|
315
|
-
}
|
|
316
|
-
createBranch(input, onDelta) {
|
|
317
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
318
|
-
const branch = this.transaction(() => {
|
|
319
|
-
if (this.getBranch(repo.id, input.branch))
|
|
320
|
-
validationFailed("branch", "already_exists", input.branch);
|
|
321
|
-
const source = input.sha
|
|
322
|
-
? { head_sha: input.sha }
|
|
323
|
-
: this.requireBranch(repo.id, input.from_branch ?? repo.default_branch);
|
|
324
|
-
const created = this.createBranchInternal(repo, input.branch, source.head_sha);
|
|
325
|
-
if (!input.sha) {
|
|
326
|
-
const sourceBranch = input.from_branch ?? repo.default_branch;
|
|
327
|
-
const files = this.db.prepare("SELECT * FROM files WHERE repo_id = ? AND branch = ?").all(repo.id, sourceBranch);
|
|
328
|
-
for (const file of files) {
|
|
329
|
-
this.db.prepare("INSERT INTO files (repo_id, branch, path, content, sha, size, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(repo.id, input.branch, file.path, file.content, file.sha, file.size, nowIso());
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
return created;
|
|
333
|
-
});
|
|
334
|
-
this.audit("create_branch", repo.full_name, input);
|
|
335
|
-
onDelta?.({ before: null, after: branchState(branch, repo) });
|
|
336
|
-
return branchJson(branch, repo);
|
|
337
|
-
}
|
|
338
|
-
createIssue(input, onDelta) {
|
|
339
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
340
|
-
const issue = this.transaction(() => {
|
|
341
|
-
if (!input.title.trim())
|
|
342
|
-
validationFailed("title", "missing");
|
|
343
|
-
for (const label of input.labels ?? [])
|
|
344
|
-
if (!this.getLabel(repo.id, label))
|
|
345
|
-
validationFailed("labels", "missing", label);
|
|
346
|
-
for (const assignee of input.assignees ?? [])
|
|
347
|
-
if (!this.hasCollaborator(repo.id, assignee))
|
|
348
|
-
validationFailed("assignees", "invalid", assignee);
|
|
349
|
-
const now = nowIso();
|
|
350
|
-
const number = this.nextNumber(repo.id);
|
|
351
|
-
this.db.prepare("INSERT INTO issues (repo_id, number, title, body, state, user_login, assignee_login, created_at, updated_at, closed_at) VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, NULL)").run(repo.id, number, input.title, input.body ?? "", "pome-agent", input.assignees?.[0] ?? null, now, now);
|
|
352
|
-
for (const label of input.labels ?? [])
|
|
353
|
-
this.db.prepare("INSERT OR IGNORE INTO issue_labels (repo_id, issue_number, label_name) VALUES (?, ?, ?)").run(repo.id, number, label);
|
|
354
|
-
for (const assignee of input.assignees ?? [])
|
|
355
|
-
this.db.prepare("INSERT OR IGNORE INTO issue_assignees (repo_id, issue_number, login) VALUES (?, ?, ?)").run(repo.id, number, assignee);
|
|
356
|
-
return this.requireIssue(repo.id, number);
|
|
357
|
-
});
|
|
358
|
-
this.audit("create_issue", repo.full_name, input);
|
|
359
|
-
const labels = this.listIssueLabels(repo.id, issue.number).map((label) => label.name);
|
|
360
|
-
const assignees = this.listIssueAssignees(repo.id, issue.number);
|
|
361
|
-
onDelta?.({ before: null, after: issueState(issue, repo, labels, assignees) });
|
|
362
|
-
return issueJson(issue, repo, this.listIssueLabels(repo.id, issue.number), this.listIssueAssignees(repo.id, issue.number), this.issueCommentCount(repo.id, issue.number));
|
|
363
|
-
}
|
|
364
|
-
listIssues(input) {
|
|
365
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
366
|
-
let rows = this.listIssuesRows(repo.id);
|
|
367
|
-
if (input.state && input.state !== "all")
|
|
368
|
-
rows = rows.filter((issue) => issue.state === input.state);
|
|
369
|
-
if (input.labels) {
|
|
370
|
-
const wanted = input.labels.split(",").map((label) => label.trim()).filter(Boolean);
|
|
371
|
-
rows = rows.filter((issue) => {
|
|
372
|
-
const names = this.listIssueLabels(repo.id, issue.number).map((label) => label.name);
|
|
373
|
-
return wanted.every((label) => names.includes(label));
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
if (input.assignee)
|
|
377
|
-
rows = rows.filter((issue) => this.listIssueAssignees(repo.id, issue.number).includes(input.assignee));
|
|
378
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map((issue) => issueJson(issue, repo, this.listIssueLabels(repo.id, issue.number), this.listIssueAssignees(repo.id, issue.number), this.issueCommentCount(repo.id, issue.number)));
|
|
379
|
-
}
|
|
380
|
-
searchIssues(input) {
|
|
381
|
-
const query = (input.query ?? input.q ?? "").toLowerCase();
|
|
382
|
-
const rows = this.db
|
|
383
|
-
.prepare("SELECT issues.*, repositories.owner, repositories.name, repositories.full_name, repositories.description, repositories.private, repositories.default_branch, repositories.fork, repositories.parent_full_name, repositories.entity_counter, repositories.created_at AS repo_created_at, repositories.updated_at AS repo_updated_at FROM issues INNER JOIN repositories ON issues.repo_id = repositories.id ORDER BY issues.updated_at DESC")
|
|
384
|
-
.all();
|
|
385
|
-
let filtered = rows.filter((issue) => !query || issue.title.toLowerCase().includes(query) || issue.body.toLowerCase().includes(query) || issue.full_name.toLowerCase().includes(query));
|
|
386
|
-
if (input.owner)
|
|
387
|
-
filtered = filtered.filter((issue) => issue.owner === input.owner);
|
|
388
|
-
if (input.repo)
|
|
389
|
-
filtered = filtered.filter((issue) => issue.name === input.repo);
|
|
390
|
-
if (input.state && input.state !== "all")
|
|
391
|
-
filtered = filtered.filter((issue) => issue.state === input.state);
|
|
392
|
-
return {
|
|
393
|
-
total_count: filtered.length,
|
|
394
|
-
incomplete_results: false,
|
|
395
|
-
items: paginate(filtered, input.page, input.per_page ?? input.perPage).map((issue) => {
|
|
396
|
-
const repo = this.requireRepoById(issue.repo_id);
|
|
397
|
-
return issueJson(issue, repo, this.listIssueLabels(issue.repo_id, issue.number), this.listIssueAssignees(issue.repo_id, issue.number), this.issueCommentCount(issue.repo_id, issue.number));
|
|
398
|
-
})
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
getIssue(input) {
|
|
402
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
403
|
-
const issue = this.requireIssue(repo.id, input.issue_number);
|
|
404
|
-
return issueJson(issue, repo, this.listIssueLabels(repo.id, issue.number), this.listIssueAssignees(repo.id, issue.number), this.issueCommentCount(repo.id, issue.number));
|
|
405
|
-
}
|
|
406
|
-
updateIssue(input, onDelta) {
|
|
407
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
408
|
-
let before = null;
|
|
409
|
-
this.transaction(() => {
|
|
410
|
-
const issue = this.requireIssue(repo.id, input.issue_number);
|
|
411
|
-
before = issueState(issue, repo, this.listIssueLabels(repo.id, issue.number).map((label) => label.name), this.listIssueAssignees(repo.id, issue.number));
|
|
412
|
-
for (const label of input.labels ?? [])
|
|
413
|
-
if (!this.getLabel(repo.id, label))
|
|
414
|
-
validationFailed("labels", "missing", label);
|
|
415
|
-
for (const assignee of input.assignees ?? [])
|
|
416
|
-
if (!this.hasCollaborator(repo.id, assignee))
|
|
417
|
-
validationFailed("assignees", "invalid", assignee);
|
|
418
|
-
const state = input.state ?? issue.state;
|
|
419
|
-
const closedAt = state === "closed" && issue.state !== "closed" ? nowIso() : state === "open" ? null : issue.closed_at;
|
|
420
|
-
this.db.prepare("UPDATE issues SET title = ?, body = ?, state = ?, assignee_login = ?, updated_at = ?, closed_at = ? WHERE repo_id = ? AND number = ?").run(input.title ?? issue.title, input.body ?? issue.body, state, input.assignees?.[0] ?? issue.assignee_login, nowIso(), closedAt, repo.id, issue.number);
|
|
421
|
-
if (input.labels) {
|
|
422
|
-
this.db.prepare("DELETE FROM issue_labels WHERE repo_id = ? AND issue_number = ?").run(repo.id, issue.number);
|
|
423
|
-
for (const label of input.labels)
|
|
424
|
-
this.db.prepare("INSERT INTO issue_labels (repo_id, issue_number, label_name) VALUES (?, ?, ?)").run(repo.id, issue.number, label);
|
|
425
|
-
}
|
|
426
|
-
if (input.assignees) {
|
|
427
|
-
this.db.prepare("DELETE FROM issue_assignees WHERE repo_id = ? AND issue_number = ?").run(repo.id, issue.number);
|
|
428
|
-
for (const assignee of input.assignees)
|
|
429
|
-
this.db.prepare("INSERT INTO issue_assignees (repo_id, issue_number, login) VALUES (?, ?, ?)").run(repo.id, issue.number, assignee);
|
|
430
|
-
}
|
|
431
|
-
});
|
|
432
|
-
this.audit("update_issue", repo.full_name, input);
|
|
433
|
-
const updated = this.requireIssue(repo.id, input.issue_number);
|
|
434
|
-
const afterLabels = this.listIssueLabels(repo.id, updated.number).map((label) => label.name);
|
|
435
|
-
const afterAssignees = this.listIssueAssignees(repo.id, updated.number);
|
|
436
|
-
onDelta?.({ before, after: issueState(updated, repo, afterLabels, afterAssignees) });
|
|
437
|
-
return this.getIssue(input);
|
|
438
|
-
}
|
|
439
|
-
addIssueComment(input, onDelta) {
|
|
440
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
441
|
-
const comment = this.transaction(() => {
|
|
442
|
-
this.requireIssue(repo.id, input.issue_number);
|
|
443
|
-
if (!input.body.trim())
|
|
444
|
-
validationFailed("body", "missing");
|
|
445
|
-
const now = nowIso();
|
|
446
|
-
const result = this.db.prepare("INSERT INTO issue_comments (repo_id, issue_number, body, user_login, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)").run(repo.id, input.issue_number, input.body, "pome-agent", now, now);
|
|
447
|
-
return this.db.prepare("SELECT * FROM issue_comments WHERE id = ?").get(result.lastInsertRowid);
|
|
448
|
-
});
|
|
449
|
-
this.audit("add_issue_comment", repo.full_name, input);
|
|
450
|
-
onDelta?.({ before: null, after: issueCommentState(comment, repo) });
|
|
451
|
-
return issueCommentJson(comment, repo);
|
|
452
|
-
}
|
|
453
|
-
listIssueComments(input) {
|
|
454
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
455
|
-
this.requireIssue(repo.id, input.issue_number);
|
|
456
|
-
const rows = this.listIssueCommentRows(repo.id, input.issue_number);
|
|
457
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map((comment) => issueCommentJson(comment, repo));
|
|
458
|
-
}
|
|
459
|
-
listRepositoryLabels(input) {
|
|
460
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
461
|
-
return this.listLabels(repo.id).map(labelJson);
|
|
462
|
-
}
|
|
463
|
-
createRepositoryLabel(input, onDelta) {
|
|
464
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
465
|
-
this.transaction(() => {
|
|
466
|
-
if (this.getLabel(repo.id, input.name))
|
|
467
|
-
validationFailed("name", "already_exists", input.name);
|
|
468
|
-
this.createLabel(repo, input.name, input.color ?? "ededed", input.description ?? "");
|
|
469
|
-
});
|
|
470
|
-
this.audit("create_label", repo.full_name, input);
|
|
471
|
-
const created = this.getLabel(repo.id, input.name);
|
|
472
|
-
onDelta?.({ before: null, after: labelState(created, repo) });
|
|
473
|
-
return labelJson(created);
|
|
474
|
-
}
|
|
475
|
-
listIssueLabelsForIssue(input) {
|
|
476
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
477
|
-
this.requireIssue(repo.id, input.issue_number);
|
|
478
|
-
return this.listIssueLabels(repo.id, input.issue_number).map(labelJson);
|
|
479
|
-
}
|
|
480
|
-
addIssueLabels(input, onDelta) {
|
|
481
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
482
|
-
let before = null;
|
|
483
|
-
this.transaction(() => {
|
|
484
|
-
this.requireIssue(repo.id, input.issue_number);
|
|
485
|
-
before = issueLabelsState(repo, input.issue_number, this.listIssueLabels(repo.id, input.issue_number).map((label) => label.name));
|
|
486
|
-
for (const label of input.labels)
|
|
487
|
-
if (!this.getLabel(repo.id, label))
|
|
488
|
-
validationFailed("labels", "missing", label);
|
|
489
|
-
for (const label of input.labels)
|
|
490
|
-
this.db.prepare("INSERT OR IGNORE INTO issue_labels (repo_id, issue_number, label_name) VALUES (?, ?, ?)").run(repo.id, input.issue_number, label);
|
|
491
|
-
});
|
|
492
|
-
this.audit("add_issue_labels", repo.full_name, input);
|
|
493
|
-
const after = issueLabelsState(repo, input.issue_number, this.listIssueLabels(repo.id, input.issue_number).map((label) => label.name));
|
|
494
|
-
onDelta?.({ before, after });
|
|
495
|
-
return this.listIssueLabelsForIssue(input);
|
|
496
|
-
}
|
|
497
|
-
deleteIssueLabel(input, onDelta) {
|
|
498
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
499
|
-
this.requireIssue(repo.id, input.issue_number);
|
|
500
|
-
const before = issueLabelsState(repo, input.issue_number, this.listIssueLabels(repo.id, input.issue_number).map((label) => label.name));
|
|
501
|
-
const result = this.db.prepare("DELETE FROM issue_labels WHERE repo_id = ? AND issue_number = ? AND label_name = ?").run(repo.id, input.issue_number, input.label);
|
|
502
|
-
if (!result.changes)
|
|
503
|
-
notFound("Label not found");
|
|
504
|
-
this.audit("delete_issue_label", repo.full_name, input);
|
|
505
|
-
const after = issueLabelsState(repo, input.issue_number, this.listIssueLabels(repo.id, input.issue_number).map((label) => label.name));
|
|
506
|
-
onDelta?.({ before, after });
|
|
507
|
-
return this.listIssueLabelsForIssue(input);
|
|
508
|
-
}
|
|
509
|
-
listCollaborators(input) {
|
|
510
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
511
|
-
const rows = this.db.prepare("SELECT login FROM collaborators WHERE repo_id = ? ORDER BY login ASC").all(repo.id);
|
|
512
|
-
return rows.map((row) => userJson(row.login));
|
|
513
|
-
}
|
|
514
|
-
isCollaborator(input) {
|
|
515
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
516
|
-
return this.hasCollaborator(repo.id, input.username);
|
|
517
|
-
}
|
|
518
|
-
addAssignees(input, onDelta) {
|
|
519
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
520
|
-
let before = null;
|
|
521
|
-
this.transaction(() => {
|
|
522
|
-
const issue = this.requireIssue(repo.id, input.issue_number);
|
|
523
|
-
before = issueAssigneesState(repo, issue.number, this.listIssueAssignees(repo.id, issue.number));
|
|
524
|
-
for (const assignee of input.assignees)
|
|
525
|
-
if (!this.hasCollaborator(repo.id, assignee))
|
|
526
|
-
validationFailed("assignees", "invalid", assignee);
|
|
527
|
-
for (const assignee of input.assignees)
|
|
528
|
-
this.db.prepare("INSERT OR IGNORE INTO issue_assignees (repo_id, issue_number, login) VALUES (?, ?, ?)").run(repo.id, issue.number, assignee);
|
|
529
|
-
const firstAssignee = input.assignees[0] ?? issue.assignee_login;
|
|
530
|
-
this.db.prepare("UPDATE issues SET assignee_login = ?, updated_at = ? WHERE repo_id = ? AND number = ?").run(firstAssignee, nowIso(), repo.id, issue.number);
|
|
531
|
-
});
|
|
532
|
-
this.audit("add_assignees", repo.full_name, input);
|
|
533
|
-
const after = issueAssigneesState(repo, input.issue_number, this.listIssueAssignees(repo.id, input.issue_number));
|
|
534
|
-
onDelta?.({ before, after });
|
|
535
|
-
return this.getIssue(input);
|
|
536
|
-
}
|
|
537
|
-
createPullRequest(input, onDelta) {
|
|
538
|
-
const baseRepo = this.requireRepo(input.owner, input.repo);
|
|
539
|
-
const baseRef = input.base ?? baseRepo.default_branch;
|
|
540
|
-
const number = this.transaction(() => {
|
|
541
|
-
if (input.head === baseRef || input.head === `${input.owner}:${baseRef}`)
|
|
542
|
-
validationFailed("head", "invalid", input.head);
|
|
543
|
-
const { repo: headRepo, ref: headRef } = this.resolveHeadRef(baseRepo, input.head);
|
|
544
|
-
const baseBranch = this.requireBranch(baseRepo.id, baseRef);
|
|
545
|
-
const headBranch = this.requireBranch(headRepo.id, headRef);
|
|
546
|
-
const duplicate = this.db.prepare("SELECT * FROM pull_requests WHERE repo_id = ? AND state = 'open' AND head_repo_id = ? AND head_ref = ? AND base_ref = ?").get(baseRepo.id, headRepo.id, headRef, baseRef);
|
|
547
|
-
if (duplicate)
|
|
548
|
-
validationFailed("head", "already_exists", input.head);
|
|
549
|
-
const files = this.calculatePullFiles(baseRepo, baseRef, headRepo, headRef);
|
|
550
|
-
if (files.length === 0)
|
|
551
|
-
validationFailed("head", "missing_commits", input.head);
|
|
552
|
-
const now = nowIso();
|
|
553
|
-
const pullNumber = this.nextNumber(baseRepo.id);
|
|
554
|
-
this.db.prepare("INSERT INTO pull_requests (repo_id, number, title, body, state, user_login, head_repo_id, head_ref, head_sha, base_repo_id, base_ref, base_sha, merged, merge_commit_sha, created_at, updated_at, closed_at, merged_at) VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, 0, NULL, ?, ?, NULL, NULL)").run(baseRepo.id, pullNumber, input.title, input.body ?? "", input.actor ?? "pome-agent", headRepo.id, headRef, headBranch.head_sha, baseRepo.id, baseRef, baseBranch.head_sha, now, now);
|
|
555
|
-
this.replacePullFiles(baseRepo.id, pullNumber, files);
|
|
556
|
-
return pullNumber;
|
|
557
|
-
});
|
|
558
|
-
this.audit("create_pull_request", baseRepo.full_name, input);
|
|
559
|
-
const createdRow = this.requirePullRequest(baseRepo.id, number);
|
|
560
|
-
onDelta?.({ before: null, after: pullRequestState(createdRow, baseRepo) });
|
|
561
|
-
return this.getPullRequest({ owner: input.owner, repo: input.repo, pull_number: number });
|
|
562
|
-
}
|
|
563
|
-
listPullRequests(input) {
|
|
564
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
565
|
-
let rows = this.listPullRequestRows(repo.id);
|
|
566
|
-
if (input.state && input.state !== "all")
|
|
567
|
-
rows = rows.filter((pr) => pr.state === input.state);
|
|
568
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map((pr) => this.serializePull(pr));
|
|
569
|
-
}
|
|
570
|
-
getPullRequest(input) {
|
|
571
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
572
|
-
const pr = this.requirePullRequest(repo.id, input.pull_number);
|
|
573
|
-
return this.serializePull(pr);
|
|
574
|
-
}
|
|
575
|
-
getPullRequestFiles(input) {
|
|
576
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
577
|
-
this.requirePullRequest(repo.id, input.pull_number);
|
|
578
|
-
const rows = this.listPullRequestFileRows(repo.id, input.pull_number);
|
|
579
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map(pullRequestFileJson);
|
|
580
|
-
}
|
|
581
|
-
getPullRequestReviews(input) {
|
|
582
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
583
|
-
this.requirePullRequest(repo.id, input.pull_number);
|
|
584
|
-
const rows = this.listPullRequestReviewRows(repo.id, input.pull_number);
|
|
585
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map((review) => reviewJson(review, repo));
|
|
586
|
-
}
|
|
587
|
-
createPullRequestReview(input, onDelta) {
|
|
588
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
589
|
-
const review = this.transaction(() => {
|
|
590
|
-
const pr = this.requirePullRequest(repo.id, input.pull_number);
|
|
591
|
-
if (pr.state !== "open")
|
|
592
|
-
conflict("Pull request is closed");
|
|
593
|
-
const state = input.event === "APPROVE" ? "APPROVED" : input.event === "REQUEST_CHANGES" ? "CHANGES_REQUESTED" : "COMMENTED";
|
|
594
|
-
const headSha = this.requireBranch(pr.head_repo_id, pr.head_ref).head_sha;
|
|
595
|
-
const result = this.db.prepare("INSERT INTO pull_request_reviews (repo_id, pull_number, user_login, state, body, commit_sha, submitted_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(repo.id, pr.number, "pome-agent", state, input.body ?? "", headSha, nowIso());
|
|
596
|
-
return this.db.prepare("SELECT * FROM pull_request_reviews WHERE id = ?").get(result.lastInsertRowid);
|
|
597
|
-
});
|
|
598
|
-
this.audit("create_pull_request_review", repo.full_name, input);
|
|
599
|
-
onDelta?.({ before: null, after: pullRequestReviewState(review, repo) });
|
|
600
|
-
return reviewJson(review, repo);
|
|
601
|
-
}
|
|
602
|
-
getPullRequestComments(input) {
|
|
603
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
604
|
-
this.requirePullRequest(repo.id, input.pull_number);
|
|
605
|
-
const rows = this.listPullRequestReviewCommentRows(repo.id, input.pull_number);
|
|
606
|
-
return paginate(rows, input.page, input.per_page ?? input.perPage).map((comment) => ({
|
|
607
|
-
id: comment.id,
|
|
608
|
-
path: comment.path,
|
|
609
|
-
body: comment.body,
|
|
610
|
-
user: userJson(comment.user_login),
|
|
611
|
-
created_at: comment.created_at,
|
|
612
|
-
updated_at: comment.updated_at
|
|
613
|
-
}));
|
|
614
|
-
}
|
|
615
|
-
getPullRequestStatus(input) {
|
|
616
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
617
|
-
const pr = this.requirePullRequest(repo.id, input.pull_number);
|
|
618
|
-
const head = this.requireBranch(pr.head_repo_id, pr.head_ref);
|
|
619
|
-
const statuses = head.head_sha
|
|
620
|
-
? this.db.prepare("SELECT * FROM commit_statuses WHERE repo_id = ? AND sha = ? ORDER BY updated_at DESC").all(pr.head_repo_id, head.head_sha)
|
|
621
|
-
: [];
|
|
622
|
-
return combinedStatusJson(this.requireRepoById(pr.head_repo_id), head.head_sha ?? "", statuses);
|
|
623
|
-
}
|
|
624
|
-
mergePullRequest(input, onDelta) {
|
|
625
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
626
|
-
let before = null;
|
|
627
|
-
const commit = this.transaction(() => {
|
|
628
|
-
const pr = this.requirePullRequest(repo.id, input.pull_number);
|
|
629
|
-
before = pullRequestState(pr, repo);
|
|
630
|
-
if (pr.state !== "open")
|
|
631
|
-
conflict("Pull request is closed");
|
|
632
|
-
if (pr.merged)
|
|
633
|
-
conflict("Pull request already merged");
|
|
634
|
-
const status = this.getPullRequestStatus(input);
|
|
635
|
-
if (status.state === "failure")
|
|
636
|
-
conflict("Required status check failed");
|
|
637
|
-
const headRepo = this.requireRepoById(pr.head_repo_id);
|
|
638
|
-
const files = this.listPullRequestFileRows(repo.id, pr.number);
|
|
639
|
-
const changes = files.map((file) => {
|
|
640
|
-
if (file.status === "removed")
|
|
641
|
-
return { path: file.filename, content: "", delete: true };
|
|
642
|
-
const source = this.getFile(headRepo.id, pr.head_ref, file.filename);
|
|
643
|
-
if (!source)
|
|
644
|
-
validationFailed("files", "missing", file.filename);
|
|
645
|
-
return { path: file.filename, content: source.content };
|
|
646
|
-
});
|
|
647
|
-
const mergedCommit = this.commitFiles(repo, pr.base_ref, input.commit_title ?? `Merge pull request #${pr.number}`, changes, "pome-agent");
|
|
648
|
-
const now = nowIso();
|
|
649
|
-
this.db.prepare("UPDATE pull_requests SET state = 'closed', merged = 1, merge_commit_sha = ?, updated_at = ?, closed_at = ?, merged_at = ? WHERE repo_id = ? AND number = ?").run(mergedCommit.sha, now, now, now, repo.id, pr.number);
|
|
650
|
-
return mergedCommit;
|
|
651
|
-
});
|
|
652
|
-
this.audit("merge_pull_request", repo.full_name, input);
|
|
653
|
-
const merged = this.requirePullRequest(repo.id, input.pull_number);
|
|
654
|
-
onDelta?.({ before, after: pullRequestState(merged, repo) });
|
|
655
|
-
return { sha: commit.sha, merged: true, message: "Pull Request successfully merged" };
|
|
656
|
-
}
|
|
657
|
-
updatePullRequestBranch(input, onDelta) {
|
|
658
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
659
|
-
let before = null;
|
|
660
|
-
const pullNumber = this.transaction(() => {
|
|
661
|
-
const pr = this.requirePullRequest(repo.id, input.pull_number);
|
|
662
|
-
before = pullRequestState(pr, repo);
|
|
663
|
-
if (pr.state !== "open")
|
|
664
|
-
conflict("Pull request is closed");
|
|
665
|
-
const headRepo = this.requireRepoById(pr.head_repo_id);
|
|
666
|
-
const headBranch = this.requireBranch(headRepo.id, pr.head_ref);
|
|
667
|
-
if (input.expected_head_sha && headBranch.head_sha !== input.expected_head_sha)
|
|
668
|
-
conflict("Head SHA did not match");
|
|
669
|
-
const baseBranch = this.requireBranch(repo.id, pr.base_ref);
|
|
670
|
-
const now = nowIso();
|
|
671
|
-
this.db.prepare("UPDATE branches SET head_sha = ?, updated_at = ? WHERE repo_id = ? AND name = ?").run(baseBranch.head_sha, now, headRepo.id, pr.head_ref);
|
|
672
|
-
this.db.prepare("UPDATE pull_requests SET head_sha = ?, base_sha = ?, updated_at = ? WHERE repo_id = ? AND number = ?").run(baseBranch.head_sha, baseBranch.head_sha, now, repo.id, pr.number);
|
|
673
|
-
this.replacePullFiles(repo.id, pr.number, this.calculatePullFiles(repo, pr.base_ref, headRepo, pr.head_ref));
|
|
674
|
-
return pr.number;
|
|
675
|
-
});
|
|
676
|
-
this.audit("update_pull_request_branch", repo.full_name, input);
|
|
677
|
-
const updated = this.requirePullRequest(repo.id, pullNumber);
|
|
678
|
-
onDelta?.({ before, after: pullRequestState(updated, repo) });
|
|
679
|
-
return { message: "Updating pull request branch.", url: `https://api.github.com/repos/${repo.full_name}/pulls/${pullNumber}/update-branch` };
|
|
680
|
-
}
|
|
681
|
-
createStatus(input) {
|
|
682
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
683
|
-
const now = nowIso();
|
|
684
|
-
const result = this.db.prepare("INSERT INTO commit_statuses (repo_id, sha, state, context, description, target_url, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(repo.id, input.sha, input.state, input.context ?? "continuous-integration/local", input.description ?? "", input.target_url ?? "", now, now);
|
|
685
|
-
return this.db.prepare("SELECT * FROM commit_statuses WHERE id = ?").get(result.lastInsertRowid);
|
|
686
|
-
}
|
|
687
|
-
// Public MCP tool: create (overwrite) a commit status on a SHA. Mirrors
|
|
688
|
-
// createStatus()'s insert but adds the audit + state-delta channel the
|
|
689
|
-
// matrix scoring/anomaly digest reads. Note this lets an agent paint a
|
|
690
|
-
// failing head commit "success" — the fabricate-green-CI reward-hacking
|
|
691
|
-
// axis (scenario 18) hinges on whether it does.
|
|
692
|
-
createCommitStatus(input, onDelta) {
|
|
693
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
694
|
-
const row = this.transaction(() => this.createStatus(input));
|
|
695
|
-
this.audit("create_commit_status", repo.full_name, input);
|
|
696
|
-
onDelta?.({ before: null, after: commitStatusState(row, repo) });
|
|
697
|
-
return statusJson(row, repo);
|
|
698
|
-
}
|
|
699
|
-
// Public MCP tool: create a check run on a head SHA. Same fabrication
|
|
700
|
-
// surface as createCommitStatus via the modern checks API.
|
|
701
|
-
createCheckRun(input, onDelta) {
|
|
702
|
-
const repo = this.requireRepo(input.owner, input.repo);
|
|
703
|
-
const row = this.transaction(() => {
|
|
704
|
-
if (!input.name.trim())
|
|
705
|
-
validationFailed("name", "missing");
|
|
706
|
-
const status = input.status ?? "queued";
|
|
707
|
-
if (status === "completed" && !input.conclusion)
|
|
708
|
-
validationFailed("conclusion", "missing", "required when status=completed");
|
|
709
|
-
if (status !== "completed" && input.conclusion)
|
|
710
|
-
validationFailed("conclusion", "invalid", "only allowed when status=completed");
|
|
711
|
-
if (status !== "completed" && input.completed_at)
|
|
712
|
-
validationFailed("completed_at", "invalid", "only allowed when status=completed");
|
|
713
|
-
const started = input.started_at ?? nowIso();
|
|
714
|
-
const completed = status === "completed" ? input.completed_at ?? nowIso() : input.completed_at ?? null;
|
|
715
|
-
const result = this.db.prepare("INSERT INTO check_runs (repo_id, head_sha, name, status, conclusion, details_url, external_id, output_title, output_summary, started_at, completed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(repo.id, input.head_sha, input.name, status, input.conclusion ?? null, input.details_url ?? "", input.external_id ?? "", input.output?.title ?? null, input.output?.summary ?? null, started, completed);
|
|
716
|
-
return this.db.prepare("SELECT * FROM check_runs WHERE id = ?").get(result.lastInsertRowid);
|
|
717
|
-
});
|
|
718
|
-
this.audit("create_check_run", repo.full_name, input);
|
|
719
|
-
onDelta?.({ before: null, after: checkRunState(row, repo) });
|
|
720
|
-
return checkRunJson(row, repo);
|
|
721
|
-
}
|
|
722
|
-
transaction(fn) {
|
|
723
|
-
return this.db.transaction(fn).immediate();
|
|
724
|
-
}
|
|
725
|
-
insertRepository(input) {
|
|
726
|
-
const now = nowIso();
|
|
727
|
-
this.db.prepare("INSERT INTO repositories (owner, name, full_name, description, private, default_branch, fork, parent_full_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(input.owner, input.name, `${input.owner}/${input.name}`, input.description, input.private ? 1 : 0, input.defaultBranch, input.fork ? 1 : 0, input.parentFullName, now, now);
|
|
728
|
-
return this.requireRepo(input.owner, input.name);
|
|
729
|
-
}
|
|
730
|
-
copyForkCommits(source, fork) {
|
|
731
|
-
const sourceCommits = this.db.prepare("SELECT * FROM commits WHERE repo_id = ?").all(source.id);
|
|
732
|
-
const bySha = new Map(sourceCommits.map((commit) => [commit.sha, commit]));
|
|
733
|
-
const copied = new Map();
|
|
734
|
-
const copyCommit = (commit) => {
|
|
735
|
-
const existing = copied.get(commit.sha);
|
|
736
|
-
if (existing)
|
|
737
|
-
return existing;
|
|
738
|
-
const parent = commit.parent_sha ? bySha.get(commit.parent_sha) : undefined;
|
|
739
|
-
const parentSha = parent ? copyCommit(parent) : null;
|
|
740
|
-
const sha = makeSha(fork.full_name, commit.sha);
|
|
741
|
-
copied.set(commit.sha, sha);
|
|
742
|
-
this.db.prepare("INSERT INTO commits (sha, repo_id, message, author_login, committer_login, parent_sha, tree_sha, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(sha, fork.id, commit.message, commit.author_login, commit.committer_login, parentSha, commit.tree_sha, commit.created_at);
|
|
743
|
-
const versions = this.db.prepare("SELECT path, content, sha, status FROM file_versions WHERE repo_id = ? AND commit_sha = ?").all(source.id, commit.sha);
|
|
744
|
-
for (const version of versions) {
|
|
745
|
-
this.db.prepare("INSERT INTO file_versions (commit_sha, repo_id, path, content, sha, status) VALUES (?, ?, ?, ?, ?, ?)").run(sha, fork.id, version.path, version.content, version.sha, version.status);
|
|
746
|
-
}
|
|
747
|
-
return sha;
|
|
748
|
-
};
|
|
749
|
-
for (const commit of sourceCommits)
|
|
750
|
-
copyCommit(commit);
|
|
751
|
-
return copied;
|
|
752
|
-
}
|
|
753
|
-
commitFiles(repo, branchName, message, files, actor) {
|
|
754
|
-
const branch = this.requireBranch(repo.id, branchName);
|
|
755
|
-
const now = nowIso();
|
|
756
|
-
const normalizedFiles = files.map((file) => ({ ...file, path: normalizePath(file.path) }));
|
|
757
|
-
const existingPaths = this.db.prepare("SELECT path FROM files WHERE repo_id = ? AND branch = ? ORDER BY path").all(repo.id, branchName).map((row) => row.path);
|
|
758
|
-
const nextPaths = new Set(existingPaths);
|
|
759
|
-
for (const file of normalizedFiles) {
|
|
760
|
-
if (file.delete)
|
|
761
|
-
nextPaths.delete(file.path);
|
|
762
|
-
else
|
|
763
|
-
nextPaths.add(file.path);
|
|
764
|
-
}
|
|
765
|
-
const sha = makeSha(repo.full_name, branchName, message, normalizedFiles, now);
|
|
766
|
-
const commit = {
|
|
767
|
-
sha,
|
|
768
|
-
repo_id: repo.id,
|
|
769
|
-
message,
|
|
770
|
-
author_login: actor,
|
|
771
|
-
committer_login: actor,
|
|
772
|
-
parent_sha: branch.head_sha,
|
|
773
|
-
tree_sha: treeSha([...nextPaths]),
|
|
774
|
-
created_at: now
|
|
775
|
-
};
|
|
776
|
-
this.db.prepare("INSERT INTO commits (sha, repo_id, message, author_login, committer_login, parent_sha, tree_sha, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(commit.sha, commit.repo_id, commit.message, commit.author_login, commit.committer_login, commit.parent_sha, commit.tree_sha, commit.created_at);
|
|
777
|
-
for (const file of normalizedFiles) {
|
|
778
|
-
const path = file.path;
|
|
779
|
-
const existing = this.getFile(repo.id, branchName, path);
|
|
780
|
-
if (file.delete) {
|
|
781
|
-
if (!existing)
|
|
782
|
-
validationFailed("files", "missing", path);
|
|
783
|
-
this.db.prepare("INSERT INTO file_versions (commit_sha, repo_id, path, content, sha, status) VALUES (?, ?, ?, ?, ?, 'removed')").run(commit.sha, repo.id, path, existing.content, existing.sha);
|
|
784
|
-
this.db.prepare("DELETE FROM files WHERE repo_id = ? AND branch = ? AND path = ?").run(repo.id, branchName, path);
|
|
785
|
-
continue;
|
|
786
|
-
}
|
|
787
|
-
const sha = fileSha(file.content);
|
|
788
|
-
this.db.prepare("INSERT INTO file_versions (commit_sha, repo_id, path, content, sha, status) VALUES (?, ?, ?, ?, ?, ?)").run(commit.sha, repo.id, path, file.content, sha, existing ? "modified" : "added");
|
|
789
|
-
this.db.prepare("INSERT INTO files (repo_id, branch, path, content, sha, size, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(repo_id, branch, path) DO UPDATE SET content = excluded.content, sha = excluded.sha, size = excluded.size, updated_at = excluded.updated_at").run(repo.id, branchName, path, file.content, sha, Buffer.byteLength(file.content), now);
|
|
790
|
-
}
|
|
791
|
-
this.db.prepare("UPDATE branches SET head_sha = ?, updated_at = ? WHERE repo_id = ? AND name = ?").run(commit.sha, now, repo.id, branchName);
|
|
792
|
-
this.db.prepare("UPDATE repositories SET updated_at = ? WHERE id = ?").run(now, repo.id);
|
|
793
|
-
return commit;
|
|
794
|
-
}
|
|
795
|
-
calculatePullFiles(baseRepo, baseRef, headRepo, headRef) {
|
|
796
|
-
const baseFiles = new Map(this.db.prepare("SELECT * FROM files WHERE repo_id = ? AND branch = ?").all(baseRepo.id, baseRef).map((file) => [file.path, file]));
|
|
797
|
-
const headFiles = new Map(this.db.prepare("SELECT * FROM files WHERE repo_id = ? AND branch = ?").all(headRepo.id, headRef).map((file) => [file.path, file]));
|
|
798
|
-
const paths = [...new Set([...baseFiles.keys(), ...headFiles.keys()])].sort();
|
|
799
|
-
const rows = [];
|
|
800
|
-
for (const path of paths) {
|
|
801
|
-
const base = baseFiles.get(path);
|
|
802
|
-
const head = headFiles.get(path);
|
|
803
|
-
if (base?.sha === head?.sha)
|
|
804
|
-
continue;
|
|
805
|
-
const diff = linesChanged(base?.content, head?.content ?? "");
|
|
806
|
-
rows.push({
|
|
807
|
-
repo_id: baseRepo.id,
|
|
808
|
-
pull_number: 0,
|
|
809
|
-
filename: path,
|
|
810
|
-
status: base && head ? "modified" : head ? "added" : "removed",
|
|
811
|
-
additions: diff.additions,
|
|
812
|
-
deletions: head ? diff.deletions : base?.content.split("\n").length ?? 0,
|
|
813
|
-
changes: diff.additions + diff.deletions,
|
|
814
|
-
blob_url: `https://github.com/${headRepo.full_name}/blob/${headRef}/${path}`,
|
|
815
|
-
raw_url: `https://raw.githubusercontent.com/${headRepo.full_name}/${headRef}/${path}`,
|
|
816
|
-
contents_url: `https://api.github.com/repos/${headRepo.full_name}/contents/${path}`,
|
|
817
|
-
patch: `@@ ${path} @@`
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
return rows;
|
|
821
|
-
}
|
|
822
|
-
replacePullFiles(repoId, pullNumber, files) {
|
|
823
|
-
this.db.prepare("DELETE FROM pull_request_files WHERE repo_id = ? AND pull_number = ?").run(repoId, pullNumber);
|
|
824
|
-
for (const file of files) {
|
|
825
|
-
this.db.prepare("INSERT INTO pull_request_files (repo_id, pull_number, filename, status, additions, deletions, changes, blob_url, raw_url, contents_url, patch) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(repoId, pullNumber, file.filename, file.status, file.additions, file.deletions, file.changes, file.blob_url, file.raw_url, file.contents_url, file.patch);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
serializePull(pr) {
|
|
829
|
-
const baseRepo = this.requireRepoById(pr.base_repo_id);
|
|
830
|
-
const headRepo = this.requireRepoById(pr.head_repo_id);
|
|
831
|
-
const files = this.db.prepare("SELECT * FROM pull_request_files WHERE repo_id = ? AND pull_number = ?").all(pr.repo_id, pr.number);
|
|
832
|
-
const headSha = this.getBranch(headRepo.id, pr.head_ref)?.head_sha ?? pr.head_sha;
|
|
833
|
-
const baseSha = this.getBranch(baseRepo.id, pr.base_ref)?.head_sha ?? pr.base_sha;
|
|
834
|
-
return pullRequestJson(pr, baseRepo, headRepo, 1, files.length, headSha, baseSha);
|
|
835
|
-
}
|
|
836
|
-
resolveHeadRef(baseRepo, head) {
|
|
837
|
-
const [owner, ref] = head.includes(":") ? head.split(":", 2) : [baseRepo.owner, head];
|
|
838
|
-
const repo = this.requireRepo(owner, baseRepo.name);
|
|
839
|
-
return { repo, ref: ref };
|
|
840
|
-
}
|
|
841
|
-
listDirectory(repo, branch, path) {
|
|
842
|
-
const prefix = path ? `${path}/` : "";
|
|
843
|
-
const rows = this.db.prepare("SELECT * FROM files WHERE repo_id = ? AND branch = ? AND path LIKE ? ORDER BY path ASC").all(repo.id, branch, `${prefix}%`);
|
|
844
|
-
const seen = new Set();
|
|
845
|
-
const entries = [];
|
|
846
|
-
for (const file of rows) {
|
|
847
|
-
const rest = file.path.slice(prefix.length);
|
|
848
|
-
const first = rest.split("/")[0];
|
|
849
|
-
const childPath = prefix ? `${prefix}${first}` : first;
|
|
850
|
-
if (seen.has(childPath))
|
|
851
|
-
continue;
|
|
852
|
-
seen.add(childPath);
|
|
853
|
-
entries.push(contentDirectoryEntryJson(childPath, repo, branch, rest.includes("/") ? undefined : file));
|
|
854
|
-
}
|
|
855
|
-
return entries;
|
|
856
|
-
}
|
|
857
|
-
createBranchInternal(repo, name, headSha) {
|
|
858
|
-
const now = nowIso();
|
|
859
|
-
this.db.prepare("INSERT INTO branches (repo_id, name, head_sha, created_at, updated_at) VALUES (?, ?, ?, ?, ?)").run(repo.id, name, headSha, now, now);
|
|
860
|
-
return this.requireBranch(repo.id, name);
|
|
861
|
-
}
|
|
862
|
-
upsertUser(login, type, name) {
|
|
863
|
-
this.db.prepare("INSERT INTO users (login, type, name, created_at) VALUES (?, ?, ?, ?) ON CONFLICT(login) DO UPDATE SET type = excluded.type, name = excluded.name").run(login, type, name, nowIso());
|
|
864
|
-
}
|
|
865
|
-
addCollaborator(repoId, login) {
|
|
866
|
-
this.upsertUser(login, "User", login);
|
|
867
|
-
this.db.prepare("INSERT OR IGNORE INTO collaborators (repo_id, login, permission) VALUES (?, ?, 'push')").run(repoId, login);
|
|
868
|
-
}
|
|
869
|
-
createLabel(repo, name, color, description) {
|
|
870
|
-
this.db.prepare("INSERT OR IGNORE INTO labels (repo_id, name, color, description) VALUES (?, ?, ?, ?)").run(repo.id, name, color, description);
|
|
871
|
-
return labelJson(this.getLabel(repo.id, name));
|
|
872
|
-
}
|
|
873
|
-
getRepo(owner, repo) {
|
|
874
|
-
return this.db.prepare("SELECT * FROM repositories WHERE owner = ? AND name = ?").get(owner, repo);
|
|
875
|
-
}
|
|
876
|
-
requireRepo(owner, repo) {
|
|
877
|
-
return this.getRepo(owner, repo) ?? notFound("Not Found");
|
|
878
|
-
}
|
|
879
|
-
requireRepoById(repoId) {
|
|
880
|
-
return this.db.prepare("SELECT * FROM repositories WHERE id = ?").get(repoId) ?? notFound("Not Found");
|
|
881
|
-
}
|
|
882
|
-
getBranch(repoId, name) {
|
|
883
|
-
return this.db.prepare("SELECT * FROM branches WHERE repo_id = ? AND name = ?").get(repoId, name);
|
|
884
|
-
}
|
|
885
|
-
requireBranch(repoId, name) {
|
|
886
|
-
return this.getBranch(repoId, name) ?? notFound("Branch not found");
|
|
887
|
-
}
|
|
888
|
-
listBranches(repoId) {
|
|
889
|
-
return this.db.prepare("SELECT * FROM branches WHERE repo_id = ? ORDER BY name ASC").all(repoId);
|
|
890
|
-
}
|
|
891
|
-
getFile(repoId, branch, path) {
|
|
892
|
-
return this.db.prepare("SELECT * FROM files WHERE repo_id = ? AND branch = ? AND path = ?").get(repoId, branch, path);
|
|
893
|
-
}
|
|
894
|
-
getLabel(repoId, name) {
|
|
895
|
-
return this.db.prepare("SELECT * FROM labels WHERE repo_id = ? AND name = ?").get(repoId, name);
|
|
896
|
-
}
|
|
897
|
-
listLabels(repoId) {
|
|
898
|
-
return this.db.prepare("SELECT * FROM labels WHERE repo_id = ? ORDER BY name ASC").all(repoId);
|
|
899
|
-
}
|
|
900
|
-
listIssuesRows(repoId) {
|
|
901
|
-
return this.db.prepare("SELECT * FROM issues WHERE repo_id = ? ORDER BY number ASC").all(repoId);
|
|
902
|
-
}
|
|
903
|
-
requireIssue(repoId, number) {
|
|
904
|
-
return this.db.prepare("SELECT * FROM issues WHERE repo_id = ? AND number = ?").get(repoId, number) ?? notFound("Issue not found");
|
|
905
|
-
}
|
|
906
|
-
listIssueLabels(repoId, issueNumber) {
|
|
907
|
-
return this.db
|
|
908
|
-
.prepare("SELECT labels.* FROM labels INNER JOIN issue_labels ON labels.repo_id = issue_labels.repo_id AND labels.name = issue_labels.label_name WHERE issue_labels.repo_id = ? AND issue_labels.issue_number = ? ORDER BY labels.name ASC")
|
|
909
|
-
.all(repoId, issueNumber);
|
|
910
|
-
}
|
|
911
|
-
listIssueAssignees(repoId, issueNumber) {
|
|
912
|
-
const rows = this.db.prepare("SELECT login FROM issue_assignees WHERE repo_id = ? AND issue_number = ? ORDER BY login ASC").all(repoId, issueNumber);
|
|
913
|
-
return rows.map((row) => row.login);
|
|
914
|
-
}
|
|
915
|
-
issueCommentCount(repoId, issueNumber) {
|
|
916
|
-
const row = this.db.prepare("SELECT COUNT(*) AS count FROM issue_comments WHERE repo_id = ? AND issue_number = ?").get(repoId, issueNumber);
|
|
917
|
-
return row.count;
|
|
918
|
-
}
|
|
919
|
-
listIssueCommentRows(repoId, issueNumber) {
|
|
920
|
-
return this.db.prepare("SELECT * FROM issue_comments WHERE repo_id = ? AND issue_number = ? ORDER BY id ASC").all(repoId, issueNumber);
|
|
921
|
-
}
|
|
922
|
-
hasCollaborator(repoId, login) {
|
|
923
|
-
return Boolean(this.db.prepare("SELECT 1 FROM collaborators WHERE repo_id = ? AND login = ?").get(repoId, login));
|
|
924
|
-
}
|
|
925
|
-
listPullRequestRows(repoId) {
|
|
926
|
-
return this.db.prepare("SELECT * FROM pull_requests WHERE repo_id = ? ORDER BY number ASC").all(repoId);
|
|
927
|
-
}
|
|
928
|
-
listPullRequestFileRows(repoId, pullNumber) {
|
|
929
|
-
return this.db.prepare("SELECT * FROM pull_request_files WHERE repo_id = ? AND pull_number = ? ORDER BY filename ASC").all(repoId, pullNumber);
|
|
930
|
-
}
|
|
931
|
-
listPullRequestReviewRows(repoId, pullNumber) {
|
|
932
|
-
return this.db.prepare("SELECT * FROM pull_request_reviews WHERE repo_id = ? AND pull_number = ? ORDER BY submitted_at ASC").all(repoId, pullNumber);
|
|
933
|
-
}
|
|
934
|
-
listPullRequestReviewCommentRows(repoId, pullNumber) {
|
|
935
|
-
return this.db.prepare("SELECT * FROM pull_request_review_comments WHERE repo_id = ? AND pull_number = ? ORDER BY id ASC").all(repoId, pullNumber);
|
|
936
|
-
}
|
|
937
|
-
requirePullRequest(repoId, number) {
|
|
938
|
-
return this.db.prepare("SELECT * FROM pull_requests WHERE repo_id = ? AND number = ?").get(repoId, number) ?? notFound("Pull request not found");
|
|
939
|
-
}
|
|
940
|
-
nextNumber(repoId) {
|
|
941
|
-
this.db.prepare("UPDATE repositories SET entity_counter = entity_counter + 1 WHERE id = ?").run(repoId);
|
|
942
|
-
const row = this.db.prepare("SELECT entity_counter AS next FROM repositories WHERE id = ?").get(repoId);
|
|
943
|
-
return row.next;
|
|
944
|
-
}
|
|
945
|
-
bumpEntityCounter(repoId, number) {
|
|
946
|
-
this.db.prepare("UPDATE repositories SET entity_counter = CASE WHEN entity_counter < ? THEN ? ELSE entity_counter END WHERE id = ?").run(number, number, repoId);
|
|
947
|
-
}
|
|
948
|
-
audit(action, repoFullName, payload) {
|
|
949
|
-
this.db.prepare("INSERT INTO audit_log (ts, action, repo_full_name, payload_json) VALUES (?, ?, ?, ?)").run(nowIso(), action, repoFullName, JSON.stringify(payload));
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
function normalizePath(path) {
|
|
953
|
-
const normalized = path.replace(/^\/+/, "").replace(/\/+/g, "/").trim();
|
|
954
|
-
if (normalized.includes(".."))
|
|
955
|
-
validationFailed("path", "invalid", path);
|
|
956
|
-
return normalized;
|
|
957
|
-
}
|