@regressionproof/snapshotter 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/.vscode/launch.json +58 -0
- package/.vscode/settings.json +67 -0
- package/.vscode/tasks.json +112 -0
- package/eslint.config.mjs +3 -0
- package/package.json +88 -0
- package/src/.spruce/settings.json +16 -0
- package/src/git.ts +48 -0
- package/src/index.ts +2 -0
- package/src/scripts/testManual.ts +55 -0
- package/src/snapshot.ts +27 -0
- package/src/snapshotter.types.ts +59 -0
- package/src/sync.ts +35 -0
- package/tsconfig.dist.json +26 -0
- package/tsconfig.json +27 -0
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lts/*
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"type": "node",
|
|
6
|
+
"request": "attach",
|
|
7
|
+
"name": "attach.tests",
|
|
8
|
+
"port": 5200,
|
|
9
|
+
"restart": true,
|
|
10
|
+
"timeout": 10000
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"type": "node",
|
|
14
|
+
"request": "launch",
|
|
15
|
+
"name": "test.file",
|
|
16
|
+
"runtimeExecutable": "node",
|
|
17
|
+
"runtimeArgs": [
|
|
18
|
+
"--inspect-brk",
|
|
19
|
+
"--trace-warnings",
|
|
20
|
+
"${workspaceFolder}/node_modules/.bin/jest",
|
|
21
|
+
"${fileBasenameNoExtension}",
|
|
22
|
+
"--detectOpenHandles"
|
|
23
|
+
],
|
|
24
|
+
"cwd": "${workspaceFolder}",
|
|
25
|
+
"console": "integratedTerminal",
|
|
26
|
+
"internalConsoleOptions": "neverOpen"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"type": "node",
|
|
30
|
+
"request": "launch",
|
|
31
|
+
"name": "test.all",
|
|
32
|
+
"runtimeExecutable": "node",
|
|
33
|
+
"runtimeArgs": [
|
|
34
|
+
"--inspect-brk",
|
|
35
|
+
"--trace-warnings",
|
|
36
|
+
"${workspaceFolder}/node_modules/.bin/jest"
|
|
37
|
+
],
|
|
38
|
+
"cwd": "${workspaceFolder}",
|
|
39
|
+
"console": "integratedTerminal",
|
|
40
|
+
"internalConsoleOptions": "neverOpen"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "node",
|
|
44
|
+
"request": "launch",
|
|
45
|
+
"name": "boot",
|
|
46
|
+
"runtimeExecutable": "yarn",
|
|
47
|
+
"runtimeArgs": [
|
|
48
|
+
"run",
|
|
49
|
+
"--inspect-brk",
|
|
50
|
+
"--trace-warnings",
|
|
51
|
+
"boot"
|
|
52
|
+
],
|
|
53
|
+
"cwd": "${workspaceFolder}",
|
|
54
|
+
"console": "integratedTerminal",
|
|
55
|
+
"internalConsoleOptions": "neverOpen"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"debug.node.autoAttach": "on",
|
|
3
|
+
"git.ignoreLimitWarning": true,
|
|
4
|
+
"javascript.validate.enable": false,
|
|
5
|
+
"files.watcherExclude": {
|
|
6
|
+
"**/.git/objects/**": true,
|
|
7
|
+
"**/.git/subtree-cache/**": true,
|
|
8
|
+
"**/build/**": true,
|
|
9
|
+
"**/node_modules/**": true,
|
|
10
|
+
},
|
|
11
|
+
"search.exclude": {
|
|
12
|
+
"**/build/**": true,
|
|
13
|
+
"**/node_modules/**": true,
|
|
14
|
+
"**/.next/**": true
|
|
15
|
+
},
|
|
16
|
+
"editor.maxTokenizationLineLength": 20000000,
|
|
17
|
+
"[javascript]": {
|
|
18
|
+
"editor.formatOnSave": false
|
|
19
|
+
},
|
|
20
|
+
"[javascriptreact]": {
|
|
21
|
+
"editor.formatOnSave": false
|
|
22
|
+
},
|
|
23
|
+
"[typescript]": {
|
|
24
|
+
"editor.formatOnSave": false
|
|
25
|
+
},
|
|
26
|
+
"[typescriptreact]": {
|
|
27
|
+
"editor.formatOnSave": false
|
|
28
|
+
},
|
|
29
|
+
"[handlebars]": {
|
|
30
|
+
"editor.formatOnSave": false
|
|
31
|
+
},
|
|
32
|
+
"typescript.tsdk": "node_modules/typescript/lib",
|
|
33
|
+
"cSpell.ignorePaths": [
|
|
34
|
+
"**/package-lock.json",
|
|
35
|
+
"**/node_modules/**",
|
|
36
|
+
"**/build/**",
|
|
37
|
+
"**/vscode-extension/**",
|
|
38
|
+
"**/.git/objects/**",
|
|
39
|
+
".vscode",
|
|
40
|
+
".spruce"
|
|
41
|
+
],
|
|
42
|
+
"cSpell.words": [
|
|
43
|
+
"arkit",
|
|
44
|
+
"autogenerated",
|
|
45
|
+
"scrollable",
|
|
46
|
+
"serializable"
|
|
47
|
+
],
|
|
48
|
+
"debug.javascript.unmapMissingSources": true,
|
|
49
|
+
"javascript.preferences.importModuleSpecifier": "relative",
|
|
50
|
+
"typescript.preferences.importModuleSpecifier": "relative",
|
|
51
|
+
"eslint.useFlatConfig": true,
|
|
52
|
+
"eslint.enable": true,
|
|
53
|
+
"eslint.validate": [
|
|
54
|
+
"javascript",
|
|
55
|
+
"javascriptreact",
|
|
56
|
+
"typescript",
|
|
57
|
+
"typescriptreact"
|
|
58
|
+
],
|
|
59
|
+
"eslint.workingDirectories": [
|
|
60
|
+
"./"
|
|
61
|
+
],
|
|
62
|
+
"typescript.validate.enable": true,
|
|
63
|
+
"editor.formatOnSave": false,
|
|
64
|
+
"editor.codeActionsOnSave": {
|
|
65
|
+
"source.fixAll.eslint": "always"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"type": "npm",
|
|
6
|
+
"script": "watch.build.dev",
|
|
7
|
+
"group": "build",
|
|
8
|
+
"label": "watch.build.dev & problem.watcher",
|
|
9
|
+
"isBackground": true,
|
|
10
|
+
"runOptions": {
|
|
11
|
+
"runOn": "folderOpen"
|
|
12
|
+
},
|
|
13
|
+
"promptOnClose": false,
|
|
14
|
+
"presentation": {
|
|
15
|
+
"focus": false,
|
|
16
|
+
"reveal": "never"
|
|
17
|
+
},
|
|
18
|
+
"problemMatcher": {
|
|
19
|
+
"base": "$tsc-watch",
|
|
20
|
+
"applyTo": "allDocuments"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"label": "test.file",
|
|
25
|
+
"command": "spruce",
|
|
26
|
+
"args": [
|
|
27
|
+
"test",
|
|
28
|
+
"--inspect",
|
|
29
|
+
"5200",
|
|
30
|
+
"--pattern",
|
|
31
|
+
"${fileBasenameNoExtension}",
|
|
32
|
+
"--watchMode",
|
|
33
|
+
"standard"
|
|
34
|
+
],
|
|
35
|
+
"promptOnClose": false,
|
|
36
|
+
"group": {
|
|
37
|
+
"kind": "test",
|
|
38
|
+
"isDefault": true
|
|
39
|
+
},
|
|
40
|
+
"presentation": {
|
|
41
|
+
"reveal": "always",
|
|
42
|
+
"panel": "dedicated",
|
|
43
|
+
},
|
|
44
|
+
"problemMatcher": []
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"label": "test.reporter",
|
|
48
|
+
"command": "spruce",
|
|
49
|
+
"args": [
|
|
50
|
+
"test",
|
|
51
|
+
"--shouldHoldAtStart",
|
|
52
|
+
"true",
|
|
53
|
+
"--watchMode",
|
|
54
|
+
"smart"
|
|
55
|
+
],
|
|
56
|
+
"promptOnClose": false,
|
|
57
|
+
"group": "test",
|
|
58
|
+
"runOptions": {
|
|
59
|
+
"runOn": "folderOpen"
|
|
60
|
+
},
|
|
61
|
+
"presentation": {
|
|
62
|
+
"panel": "shared",
|
|
63
|
+
"focus": true,
|
|
64
|
+
"reveal": "always"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"label": "spruce",
|
|
69
|
+
"type": "shell",
|
|
70
|
+
"command": "spruce ${input:spruceCommand}",
|
|
71
|
+
"problemMatcher": [],
|
|
72
|
+
"presentation": {
|
|
73
|
+
"reveal": "always",
|
|
74
|
+
"focus": true,
|
|
75
|
+
"panel": "new",
|
|
76
|
+
"clear": false
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"label": "shell",
|
|
81
|
+
"type": "shell",
|
|
82
|
+
"command": "${input:command} ${input:optionsCommand}",
|
|
83
|
+
"problemMatcher": [],
|
|
84
|
+
"presentation": {
|
|
85
|
+
"reveal": "always",
|
|
86
|
+
"focus": true,
|
|
87
|
+
"panel": "new",
|
|
88
|
+
"clear": false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"inputs": [
|
|
93
|
+
{
|
|
94
|
+
"id": "spruceCommand",
|
|
95
|
+
"description": "spruce command",
|
|
96
|
+
"default": "create.test",
|
|
97
|
+
"type": "promptString"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "command",
|
|
101
|
+
"description": "command",
|
|
102
|
+
"default": "yarn",
|
|
103
|
+
"type": "promptString"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "optionsCommand",
|
|
107
|
+
"description": "optionsCommand",
|
|
108
|
+
"default": "add",
|
|
109
|
+
"type": "promptString"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@regressionproof/snapshotter",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"main": "./build/index.js",
|
|
8
|
+
"types": "./build/index.d.ts",
|
|
9
|
+
"module": "./build/esm/index.js",
|
|
10
|
+
"sideEffects": false,
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./build/esm/index.d.ts",
|
|
15
|
+
"default": "./build/esm/index.js"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./build/index.d.ts",
|
|
19
|
+
"default": "./build/index.js"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build.ci": "yarn run build.tsc && yarn run build.resolve-paths && yarn run lint",
|
|
25
|
+
"build.dev": "yarn run build.tsc --sourceMap ; yarn run resolve-paths.lint",
|
|
26
|
+
"build.copy-files": "mkdir -p build && rsync -avzq --exclude='*.ts' ./src/ ./build/",
|
|
27
|
+
"build.resolve-paths": "resolve-path-aliases --target build --patterns '**/*.js,**/*.d.ts'",
|
|
28
|
+
"build.tsc": "yarn run build.copy-files && tsc",
|
|
29
|
+
"build.dist": "tsc --project tsconfig.dist.json && yarn build.resolve-paths && mv build esm && yarn build.esm-postbuild && yarn build.tsc && yarn build.resolve-paths && mv esm build/",
|
|
30
|
+
"build.esm-postbuild": "esm-postbuild --target esm --patterns '**/*.js'",
|
|
31
|
+
"clean": "yarn run clean.build",
|
|
32
|
+
"clean.all": "yarn run clean.dependencies && yarn run clean.build",
|
|
33
|
+
"clean.build": "rm -rf build/",
|
|
34
|
+
"clean.dependencies": "rm -rf node_modules/ package-lock.json yarn.lock",
|
|
35
|
+
"fix.lint": "eslint --fix --cache '**/*.ts'",
|
|
36
|
+
"lint": "eslint --cache '**/*.ts'",
|
|
37
|
+
"lint.tsc": "tsc -p . --noEmit",
|
|
38
|
+
"post.watch.build": "yarn run build.copy-files && yarn run build.resolve-paths",
|
|
39
|
+
"rebuild": "yarn run clean.all && yarn install && yarn run build.dev",
|
|
40
|
+
"update.dependencies": "yarn run clean.dependencies && yarn",
|
|
41
|
+
"resolve-paths.lint": "yarn run build.resolve-paths ; yarn run lint",
|
|
42
|
+
"test": "jest --passWithNoTests",
|
|
43
|
+
"test.manual": "node --env-file=.env build/scripts/testManual.js",
|
|
44
|
+
"watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn run post.watch.build'",
|
|
45
|
+
"watch.rebuild": "yarn run clean.all && yarn install && yarn run watch.build.dev",
|
|
46
|
+
"watch.tsc": "tsc -w"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@sprucelabs/esm-postbuild": "^9.0.13",
|
|
50
|
+
"@sprucelabs/jest-json-reporter": "^10.0.19",
|
|
51
|
+
"@sprucelabs/resolve-path-aliases": "^4.0.13",
|
|
52
|
+
"@sprucelabs/test": "^11.1.0",
|
|
53
|
+
"@sprucelabs/test-utils": "^7.2.3",
|
|
54
|
+
"@types/node": "^25.0.6",
|
|
55
|
+
"chokidar-cli": "^3.0.0",
|
|
56
|
+
"eslint": "^9.39.2",
|
|
57
|
+
"eslint-config-spruce": "^11.2.26",
|
|
58
|
+
"jest": "^30.2.0",
|
|
59
|
+
"jest-circus": "^30.2.0",
|
|
60
|
+
"prettier": "^3.7.4",
|
|
61
|
+
"ts-node": "^10.9.2",
|
|
62
|
+
"tsc-watch": "^7.2.0",
|
|
63
|
+
"typescript": "^5.9.3"
|
|
64
|
+
},
|
|
65
|
+
"description": "Take snapshots of your TDD project to be used for LLM training data",
|
|
66
|
+
"skill": {
|
|
67
|
+
"namespace": "regressionproof-snapshotter"
|
|
68
|
+
},
|
|
69
|
+
"jest": {
|
|
70
|
+
"testRunner": "jest-circus/runner",
|
|
71
|
+
"maxWorkers": 4,
|
|
72
|
+
"testTimeout": 120000,
|
|
73
|
+
"testEnvironment": "node",
|
|
74
|
+
"testPathIgnorePatterns": [
|
|
75
|
+
"<rootDir>/tmp/",
|
|
76
|
+
"<rootDir>/src/",
|
|
77
|
+
"<rootDir>/node_modules/",
|
|
78
|
+
"<rootDir>/build/__tests__/testDirsAndFiles/"
|
|
79
|
+
],
|
|
80
|
+
"testMatch": [
|
|
81
|
+
"**/__tests__/**/*.test.js?(x)"
|
|
82
|
+
],
|
|
83
|
+
"moduleNameMapper": {
|
|
84
|
+
"^#spruce/(.*)$": "<rootDir>/build/.spruce/$1"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"dependencies": {}
|
|
88
|
+
}
|
package/src/git.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { exec } from 'child_process'
|
|
2
|
+
import { existsSync } from 'fs'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { promisify } from 'util'
|
|
5
|
+
import { RemoteOptions } from './snapshotter.types.js'
|
|
6
|
+
|
|
7
|
+
const execAsync = promisify(exec)
|
|
8
|
+
|
|
9
|
+
export async function gitCommit(mirrorPath: string): Promise<boolean> {
|
|
10
|
+
const gitDir = path.join(mirrorPath, '.git')
|
|
11
|
+
|
|
12
|
+
if (!existsSync(gitDir)) {
|
|
13
|
+
await execAsync(`git -C "${mirrorPath}" init`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
await execAsync(`git -C "${mirrorPath}" add -A`)
|
|
17
|
+
|
|
18
|
+
const { stdout } = await execAsync(
|
|
19
|
+
`git -C "${mirrorPath}" status --porcelain`
|
|
20
|
+
)
|
|
21
|
+
if (!stdout.trim()) {
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const message = `Snapshot ${new Date().toISOString()}`
|
|
26
|
+
await execAsync(`git -C "${mirrorPath}" commit -m "${message}"`)
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function gitPush(
|
|
31
|
+
mirrorPath: string,
|
|
32
|
+
remote: RemoteOptions
|
|
33
|
+
): Promise<void> {
|
|
34
|
+
const authedUrl = remote.url.replace('://', `://${remote.token}@`)
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
await execAsync(`git -C "${mirrorPath}" remote get-url origin`)
|
|
38
|
+
await execAsync(
|
|
39
|
+
`git -C "${mirrorPath}" remote set-url origin "${authedUrl}"`
|
|
40
|
+
)
|
|
41
|
+
} catch {
|
|
42
|
+
await execAsync(
|
|
43
|
+
`git -C "${mirrorPath}" remote add origin "${authedUrl}"`
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await execAsync(`git -C "${mirrorPath}" push -u origin HEAD`)
|
|
48
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { snapshot } from '../index'
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const sourcePath = process.env.SOURCE_PATH
|
|
5
|
+
const mirrorPath = process.env.MIRROR_PATH
|
|
6
|
+
const remoteUrl = process.env.REMOTE_URL
|
|
7
|
+
const remoteToken = process.env.REMOTE_TOKEN
|
|
8
|
+
|
|
9
|
+
if (!sourcePath || !mirrorPath || !remoteUrl || !remoteToken) {
|
|
10
|
+
console.error('Missing required env vars. See .env.example')
|
|
11
|
+
process.exit(1)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
console.log('Running snapshot...')
|
|
15
|
+
console.log(' Source:', sourcePath)
|
|
16
|
+
console.log(' Mirror:', mirrorPath)
|
|
17
|
+
console.log(' Remote:', remoteUrl)
|
|
18
|
+
|
|
19
|
+
const result = await snapshot({
|
|
20
|
+
sourcePath,
|
|
21
|
+
mirrorPath,
|
|
22
|
+
testResults: {
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
summary: {
|
|
25
|
+
totalSuites: 1,
|
|
26
|
+
passedSuites: 1,
|
|
27
|
+
failedSuites: 0,
|
|
28
|
+
totalTests: 2,
|
|
29
|
+
passedTests: 2,
|
|
30
|
+
failedTests: 0,
|
|
31
|
+
},
|
|
32
|
+
suites: [
|
|
33
|
+
{
|
|
34
|
+
path: 'src/__tests__/Example.test.ts',
|
|
35
|
+
passed: true,
|
|
36
|
+
tests: [
|
|
37
|
+
{ name: 'should work', passed: true },
|
|
38
|
+
{ name: 'should also work', passed: true },
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
remote: {
|
|
44
|
+
url: remoteUrl,
|
|
45
|
+
token: remoteToken,
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
console.log('Snapshot created:', result)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
main().catch((err) => {
|
|
53
|
+
console.error('Error:', err.message)
|
|
54
|
+
process.exit(1)
|
|
55
|
+
})
|
package/src/snapshot.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { gitCommit, gitPush } from './git.js'
|
|
4
|
+
import { SnapshotOptions } from './snapshotter.types.js'
|
|
5
|
+
import { syncFiles } from './sync.js'
|
|
6
|
+
|
|
7
|
+
export async function snapshot(options: SnapshotOptions): Promise<boolean> {
|
|
8
|
+
const sourcePath = options.sourcePath ?? process.cwd()
|
|
9
|
+
const { mirrorPath, testResults, remote } = options
|
|
10
|
+
|
|
11
|
+
await syncFiles(sourcePath, mirrorPath)
|
|
12
|
+
|
|
13
|
+
const snapshotterDir = path.join(mirrorPath, '.snapshotter')
|
|
14
|
+
mkdirSync(snapshotterDir, { recursive: true })
|
|
15
|
+
writeFileSync(
|
|
16
|
+
path.join(snapshotterDir, 'testResults.json'),
|
|
17
|
+
JSON.stringify(testResults, null, 2)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const committed = await gitCommit(mirrorPath)
|
|
21
|
+
|
|
22
|
+
if (committed) {
|
|
23
|
+
await gitPush(mirrorPath, remote)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return committed
|
|
27
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface TestResult {
|
|
2
|
+
/** Name of the individual test */
|
|
3
|
+
name: string
|
|
4
|
+
/** Whether this test passed */
|
|
5
|
+
passed: boolean
|
|
6
|
+
/** Full error message + callstack (only present if failed) */
|
|
7
|
+
error?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SuiteResult {
|
|
11
|
+
/** Path to test file, relative to project root */
|
|
12
|
+
path: string
|
|
13
|
+
/** Whether all tests in suite passed */
|
|
14
|
+
passed: boolean
|
|
15
|
+
/** Array of test results */
|
|
16
|
+
tests: TestResult[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TestResultsSummary {
|
|
20
|
+
/** Total number of test suites (files) */
|
|
21
|
+
totalSuites: number
|
|
22
|
+
/** Number of suites with all tests passing */
|
|
23
|
+
passedSuites: number
|
|
24
|
+
/** Number of suites with at least one failure */
|
|
25
|
+
failedSuites: number
|
|
26
|
+
/** Total number of individual tests */
|
|
27
|
+
totalTests: number
|
|
28
|
+
/** Number of passing tests */
|
|
29
|
+
passedTests: number
|
|
30
|
+
/** Number of failing tests */
|
|
31
|
+
failedTests: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface TestResults {
|
|
35
|
+
/** ISO 8601 timestamp of when test run completed */
|
|
36
|
+
timestamp: string
|
|
37
|
+
/** Summary counts */
|
|
38
|
+
summary: TestResultsSummary
|
|
39
|
+
/** Array of suite results */
|
|
40
|
+
suites: SuiteResult[]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface RemoteOptions {
|
|
44
|
+
/** Gitea repo URL to push to */
|
|
45
|
+
url: string
|
|
46
|
+
/** Gitea access token for authentication */
|
|
47
|
+
token: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface SnapshotOptions {
|
|
51
|
+
/** Source project path to sync from. Defaults to process.cwd() */
|
|
52
|
+
sourcePath?: string
|
|
53
|
+
/** Mirror directory path where the isolated git repo lives */
|
|
54
|
+
mirrorPath: string
|
|
55
|
+
/** Test results from the completed test run */
|
|
56
|
+
testResults: TestResults
|
|
57
|
+
/** Remote Gitea repo to push to */
|
|
58
|
+
remote: RemoteOptions
|
|
59
|
+
}
|
package/src/sync.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { exec } from 'child_process'
|
|
2
|
+
import { existsSync } from 'fs'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { promisify } from 'util'
|
|
5
|
+
|
|
6
|
+
const execAsync = promisify(exec)
|
|
7
|
+
|
|
8
|
+
const DEFAULT_EXCLUDES = [
|
|
9
|
+
'node_modules',
|
|
10
|
+
'build',
|
|
11
|
+
'*.env*',
|
|
12
|
+
'*.pem',
|
|
13
|
+
'*.key',
|
|
14
|
+
'*.p12',
|
|
15
|
+
'*.pfx',
|
|
16
|
+
'*credentials*',
|
|
17
|
+
'*secret*',
|
|
18
|
+
'*.local',
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
export async function syncFiles(
|
|
22
|
+
sourcePath: string,
|
|
23
|
+
mirrorPath: string
|
|
24
|
+
): Promise<void> {
|
|
25
|
+
const hasGitIgnore = existsSync(path.join(sourcePath, '.gitignore'))
|
|
26
|
+
const excludes = DEFAULT_EXCLUDES.map((e) => `--exclude='${e}'`).join(' ')
|
|
27
|
+
|
|
28
|
+
if (hasGitIgnore) {
|
|
29
|
+
const cmd = `cd "${sourcePath}" && git ls-files --cached --others --exclude-standard -z | rsync -av --files-from=- --from0 ${excludes} . "${mirrorPath}/"`
|
|
30
|
+
await execAsync(cmd)
|
|
31
|
+
} else {
|
|
32
|
+
const cmd = `rsync -av --delete ${excludes} "${sourcePath}/" "${mirrorPath}/"`
|
|
33
|
+
await execAsync(cmd)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "ES2020",
|
|
4
|
+
"target": "ES6",
|
|
5
|
+
"lib": ["ES2020", "DOM"],
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"noImplicitAny": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"noImplicitReturns": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"noUnusedLocals": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"sourceMap": false,
|
|
17
|
+
"outDir": "./build",
|
|
18
|
+
"baseUrl": "src",
|
|
19
|
+
"experimentalDecorators": true,
|
|
20
|
+
"paths": {
|
|
21
|
+
"#spruce/*": [".spruce/*"]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"include": ["./src/*.ts", "./src/**/*.ts"],
|
|
25
|
+
"exclude": ["**/node_modules/*", "build/*", "esm/*"]
|
|
26
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"skipLibCheck": true,
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"esModuleInterop": true,
|
|
6
|
+
"target": "ES2020",
|
|
7
|
+
"lib": ["DOM", "ES2022"],
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"noImplicitAny": true,
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"noImplicitReturns": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"noUnusedLocals": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"moduleResolution": "node",
|
|
17
|
+
"sourceMap": false,
|
|
18
|
+
"outDir": "build",
|
|
19
|
+
"baseUrl": "src",
|
|
20
|
+
"experimentalDecorators": true,
|
|
21
|
+
"paths": {
|
|
22
|
+
"#spruce/*": [".spruce/*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": ["./src/*.ts", "./src/**/*.ts", "./src/.spruce/**/*"],
|
|
26
|
+
"exclude": ["build", "esm"]
|
|
27
|
+
}
|