tsondb 0.17.7 → 0.18.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/src/bin/tsondb.js +46 -33
- package/dist/src/node/config.d.ts +2 -1
- package/dist/src/node/config.js +5 -0
- package/dist/src/node/git.d.ts +130 -0
- package/dist/src/node/git.js +233 -0
- package/dist/src/node/index.d.ts +217 -17
- package/dist/src/node/index.js +441 -105
- package/dist/src/node/renderers/jsonschema/index.js +4 -4
- package/dist/src/node/renderers/jsonschema/render.js +1 -1
- package/dist/src/node/renderers/ts/index.js +1 -1
- package/dist/src/node/renderers/ts/render.js +3 -3
- package/dist/src/node/schema/Node.js +1 -1
- package/dist/src/node/schema/Schema.d.ts +13 -5
- package/dist/src/node/schema/Schema.js +78 -36
- package/dist/src/node/schema/declarations/Declaration.js +1 -1
- package/dist/src/node/schema/declarations/EntityDecl.d.ts +1 -1
- package/dist/src/node/schema/declarations/EntityDecl.js +1 -1
- package/dist/src/node/schema/declarations/EnumDecl.d.ts +46 -9
- package/dist/src/node/schema/declarations/EnumDecl.js +9 -17
- package/dist/src/node/schema/declarations/TypeAliasDecl.d.ts +45 -10
- package/dist/src/node/schema/declarations/TypeAliasDecl.js +10 -17
- package/dist/src/node/schema/helpers.d.ts +50 -9
- package/dist/src/node/schema/helpers.js +9 -0
- package/dist/src/node/schema/types/Type.js +2 -2
- package/dist/src/node/schema/types/generic/ObjectType.js +2 -2
- package/dist/src/node/schema/types/generic/TranslationObjectType.js +2 -2
- package/dist/src/node/schema/types/references/NestedEntityMapType.d.ts +1 -1
- package/dist/src/node/schema/types/references/NestedEntityMapType.js +3 -3
- package/dist/src/node/server/api/declarations.js +41 -64
- package/dist/src/node/server/api/git.js +44 -75
- package/dist/src/node/server/api/index.js +1 -1
- package/dist/src/node/server/api/instances.js +1 -2
- package/dist/src/node/server/api/search.js +1 -38
- package/dist/src/node/server/index.d.ts +3 -20
- package/dist/src/node/server/index.js +25 -7
- package/dist/src/node/server/utils/instanceOperations.d.ts +4 -5
- package/dist/src/node/server/utils/instanceOperations.js +27 -48
- package/dist/src/node/transaction.d.ts +44 -0
- package/dist/src/node/transaction.js +125 -0
- package/dist/src/node/utils/childInstances.d.ts +4 -6
- package/dist/src/node/utils/childInstances.js +58 -46
- package/dist/src/node/utils/customConstraints.d.ts +20 -21
- package/dist/src/node/utils/customConstraints.js +13 -37
- package/dist/src/node/utils/databaseInMemory.d.ts +17 -20
- package/dist/src/node/utils/databaseInMemory.js +28 -44
- package/dist/src/node/utils/databaseOnDisk.d.ts +2 -2
- package/dist/src/node/utils/databaseOnDisk.js +8 -10
- package/dist/src/node/utils/displayName.d.ts +15 -12
- package/dist/src/node/utils/displayName.js +49 -31
- package/dist/src/node/utils/error.d.ts +2 -0
- package/dist/src/node/utils/error.js +12 -0
- package/dist/src/node/utils/git.d.ts +2 -1
- package/dist/src/node/utils/git.js +1 -2
- package/dist/src/node/utils/references.d.ts +3 -2
- package/dist/src/node/utils/references.js +21 -13
- package/dist/src/node/utils/render.js +1 -1
- package/dist/src/node/utils/unique.d.ts +2 -2
- package/dist/src/node/utils/unique.js +5 -4
- package/dist/src/node/utils/workers.d.ts +1 -1
- package/dist/src/node/utils/workers.js +1 -1
- package/dist/src/shared/output.d.ts +2 -1
- package/dist/src/shared/schema/Node.js +1 -1
- package/dist/src/shared/schema/types/Type.js +1 -1
- package/dist/src/shared/schema/utils/keyPath.d.ts +1 -1
- package/dist/src/shared/schema/utils/keyPath.js +3 -3
- package/dist/src/shared/utils/instances.d.ts +5 -6
- package/dist/src/shared/utils/instances.js +3 -3
- package/dist/src/shared/utils/markdown.js +3 -3
- package/dist/src/shared/utils/object.d.ts +0 -7
- package/dist/src/shared/utils/object.js +1 -14
- package/dist/src/shared/utils/translation.js +1 -1
- package/dist/src/shared/utils/validation.js +1 -1
- package/dist/src/shared/validation/number.js +1 -1
- package/dist/src/web/components/InstanceRouteSkeleton.js +2 -2
- package/dist/src/web/components/Settings.js +1 -1
- package/dist/src/web/components/typeInputs/ArrayTypeInput.js +1 -1
- package/dist/src/web/components/typeInputs/ChildEntitiesTypeInput.js +1 -1
- package/dist/src/web/components/typeInputs/EnumTypeInput.js +2 -2
- package/dist/src/web/components/typeInputs/NestedEntityMapTypeInput.js +4 -4
- package/dist/src/web/components/typeInputs/ObjectTypeInput.js +4 -4
- package/dist/src/web/components/typeInputs/TranslationObjectTypeInput.js +3 -3
- package/dist/src/web/components/typeInputs/TypeInput.js +1 -1
- package/dist/src/web/routes/CreateInstance.js +1 -1
- package/dist/src/web/routes/Entity.js +1 -1
- package/dist/src/web/routes/Home.js +1 -1
- package/dist/src/web/routes/Instance.js +1 -1
- package/dist/src/web/routes/Search.js +1 -1
- package/dist/src/web/utils/BlockMarkdown.js +1 -1
- package/dist/src/web/utils/InlineMarkdown.js +1 -1
- package/dist/src/web/utils/typeSkeleton.js +1 -1
- package/package.json +8 -7
- package/dist/src/node/server/init.d.ts +0 -7
- package/dist/src/node/server/init.js +0 -65
- package/dist/src/node/server/utils/childInstances.d.ts +0 -4
- package/dist/src/node/server/utils/childInstances.js +0 -12
- package/dist/src/node/utils/databaseTransactions.d.ts +0 -46
- package/dist/src/node/utils/databaseTransactions.js +0 -117
- package/dist/src/node/utils/instanceTransactionSteps.d.ts +0 -10
- package/dist/src/node/utils/instanceTransactionSteps.js +0 -40
- package/dist/src/shared/utils/array.d.ts +0 -61
- package/dist/src/shared/utils/array.js +0 -117
- package/dist/src/shared/utils/async.d.ts +0 -8
- package/dist/src/shared/utils/async.js +0 -35
- package/dist/src/shared/utils/compare.d.ts +0 -13
- package/dist/src/shared/utils/compare.js +0 -29
- package/dist/src/shared/utils/dictionary.d.ts +0 -18
- package/dist/src/shared/utils/dictionary.js +0 -77
- package/dist/src/shared/utils/lazy.d.ts +0 -16
- package/dist/src/shared/utils/lazy.js +0 -32
- package/dist/src/shared/utils/result.d.ts +0 -73
- package/dist/src/shared/utils/result.js +0 -52
- package/dist/src/shared/utils/string.d.ts +0 -7
- package/dist/src/shared/utils/string.js +0 -64
- package/dist/src/shared/utils/typeSafety.d.ts +0 -5
- package/dist/src/shared/utils/typeSafety.js +0 -11
package/dist/src/bin/tsondb.js
CHANGED
|
@@ -7,15 +7,16 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
7
7
|
}
|
|
8
8
|
return path;
|
|
9
9
|
};
|
|
10
|
+
import { omitUndefinedKeys } from "@elyukai/utils/object";
|
|
10
11
|
import Debug from "debug";
|
|
11
12
|
import { access, constants } from "node:fs/promises";
|
|
12
13
|
import { join } from "node:path";
|
|
13
14
|
import { cwd } from "node:process";
|
|
14
15
|
import { pathToFileURL } from "node:url";
|
|
15
16
|
import { parseArguments } from "simple-cli-args";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { validateConfigForData, validateConfigForGeneration, validateConfigForServer, validateConfigForTesting, } from "../node/config.js";
|
|
18
|
+
import { TSONDB } from "../node/index.js";
|
|
19
|
+
import { createServer } from "../node/server/index.js";
|
|
19
20
|
const debug = Debug("tsondb:cli");
|
|
20
21
|
const passedArguments = parseArguments({
|
|
21
22
|
commands: {
|
|
@@ -83,35 +84,47 @@ if (config === undefined) {
|
|
|
83
84
|
if (passedArguments.command === undefined) {
|
|
84
85
|
throw new Error("No command has been specified. Possible commands are: generate, serve, validate.");
|
|
85
86
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
87
|
+
if (passedArguments.command.name === "generate") {
|
|
88
|
+
debug(`running command: generate`);
|
|
89
|
+
validateConfigForGeneration(config);
|
|
90
|
+
await TSONDB.generateOutputs(config);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
validateConfigForData(config);
|
|
94
|
+
const db = await TSONDB.create({
|
|
95
|
+
...config,
|
|
96
|
+
validationOptions: passedArguments.command.name === "validate"
|
|
97
|
+
? {
|
|
98
|
+
...config.validationOptions,
|
|
99
|
+
...omitUndefinedKeys(passedArguments.command.options ?? {}),
|
|
100
|
+
}
|
|
101
|
+
: config.validationOptions,
|
|
102
|
+
});
|
|
103
|
+
switch (passedArguments.command.name) {
|
|
104
|
+
case "serve":
|
|
105
|
+
debug(`running command: serve`);
|
|
106
|
+
validateConfigForServer(config);
|
|
107
|
+
await createServer(db, config.homeLayoutSections, config.serverOptions, config.validationOptions, config.customStylesheetPath);
|
|
108
|
+
break;
|
|
109
|
+
case "validate": {
|
|
110
|
+
debug(`running command: validate`);
|
|
111
|
+
validateConfigForTesting(config);
|
|
112
|
+
if (passedArguments.command.options?.checkReferentialIntegrity !== undefined) {
|
|
113
|
+
debug(`check referential integrity: ${passedArguments.command.options.checkReferentialIntegrity ? "yes" : "no"}`);
|
|
114
|
+
}
|
|
115
|
+
if (passedArguments.command.options?.checkOnlyEntities !== undefined) {
|
|
116
|
+
const entities = passedArguments.command.options.checkOnlyEntities;
|
|
117
|
+
debug(`only check the following entities: ${entities.join(", ")}`);
|
|
118
|
+
}
|
|
119
|
+
const result = db.validate();
|
|
120
|
+
if (!result) {
|
|
121
|
+
process.exitCode = 1;
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
106
124
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
case "format":
|
|
113
|
-
debug(`running command: format`);
|
|
114
|
-
validateConfigForFormatting(config);
|
|
115
|
-
await format(config.schema, config.dataRootPath);
|
|
116
|
-
break;
|
|
125
|
+
case "format":
|
|
126
|
+
debug(`running command: format`);
|
|
127
|
+
await db.format();
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
117
130
|
}
|
|
@@ -37,10 +37,11 @@ export declare const validateConfigForGeneration: (config: Config) => asserts co
|
|
|
37
37
|
/**
|
|
38
38
|
* The configuration type required for any commands that need to read data stored in the database.
|
|
39
39
|
*/
|
|
40
|
-
export type DataConfig = {
|
|
40
|
+
export type DataConfig = Config & {
|
|
41
41
|
schema: Schema;
|
|
42
42
|
dataRootPath: string;
|
|
43
43
|
};
|
|
44
|
+
export declare const validateConfigForData: (config: Config) => asserts config is DataConfig;
|
|
44
45
|
/**
|
|
45
46
|
* The configuration type required for running the server for the editor.
|
|
46
47
|
*/
|
package/dist/src/node/config.js
CHANGED
|
@@ -3,6 +3,11 @@ export const validateConfigForGeneration = config => {
|
|
|
3
3
|
throw new Error("At least one output must be specified in the config.");
|
|
4
4
|
}
|
|
5
5
|
};
|
|
6
|
+
export const validateConfigForData = config => {
|
|
7
|
+
if (config.dataRootPath === undefined) {
|
|
8
|
+
throw new Error("A data root path must be specified in the config.");
|
|
9
|
+
}
|
|
10
|
+
};
|
|
6
11
|
export const validateConfigForServer = config => {
|
|
7
12
|
if ((config.locales?.length ?? 0) === 0) {
|
|
8
13
|
throw new Error("At least one locale must be specified in the config.");
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { SimpleGit } from "simple-git";
|
|
2
|
+
import type { InstanceContainerOverview } from "../shared/utils/instances.ts";
|
|
3
|
+
import type { DefaultTSONDBTypes, EntityName, TSONDB } from "./index.ts";
|
|
4
|
+
import type { DatabaseInMemory } from "./utils/databaseInMemory.ts";
|
|
5
|
+
export declare class Git<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(db: TSONDB<T>, git: SimpleGit, gitRoot: string, dataRoot: string, getData: () => DatabaseInMemory<T["entityMap"]>, setData: (data: DatabaseInMemory<T["entityMap"]>) => void);
|
|
8
|
+
/**
|
|
9
|
+
* Runs a `git status` operation and updates the in-memory database with the latest statuses.
|
|
10
|
+
*
|
|
11
|
+
* @throws {HTTPError} when no git repository is found
|
|
12
|
+
*/
|
|
13
|
+
status(): Promise<{
|
|
14
|
+
currentBranch: string | null;
|
|
15
|
+
trackingBranch: string | null;
|
|
16
|
+
commitsAhead: number;
|
|
17
|
+
commitsBehind: number;
|
|
18
|
+
latestCommit: string;
|
|
19
|
+
instances: Record<string, InstanceContainerOverview[]>;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Fetches updates from remote git repositories.
|
|
23
|
+
*
|
|
24
|
+
* @throws {HTTPError} when no git repository is found
|
|
25
|
+
*/
|
|
26
|
+
fetch(options: Partial<{
|
|
27
|
+
all: boolean;
|
|
28
|
+
prune: boolean;
|
|
29
|
+
}>): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Adds files to the git staging area.
|
|
32
|
+
*
|
|
33
|
+
* - If the function is called without parameters, all changes to all instances are added.
|
|
34
|
+
* - If the function is called with only the `entity` parameter, all changes to instances of that entity are added.
|
|
35
|
+
* - If both `entity` and `id` parameters are provided, only the changes to that specific instance are added.
|
|
36
|
+
*
|
|
37
|
+
* @throws {HTTPError} when no git repository is found
|
|
38
|
+
*/
|
|
39
|
+
stage(entity?: EntityName<T>, id?: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Removes files from the git staging area.
|
|
42
|
+
*
|
|
43
|
+
* - If the function is called without parameters, all changes to all instances are removed.
|
|
44
|
+
* - If the function is called with only the `entity` parameter, all changes to instances of that entity are removed.
|
|
45
|
+
* - If both `entity` and `id` parameters are provided, only the changes to that specific instance are removed.
|
|
46
|
+
*
|
|
47
|
+
* @throws {HTTPError} when no git repository is found
|
|
48
|
+
*/
|
|
49
|
+
unstage(entity?: EntityName<T>, id?: string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Restores files in the git repository to their last committed state.
|
|
52
|
+
*
|
|
53
|
+
* - If the function is called without parameters, all changes to all instances are restored.
|
|
54
|
+
* - If the function is called with only the `entity` parameter, all changes to instances of that entity are restored.
|
|
55
|
+
* - If both `entity` and `id` parameters are provided, only the changes to that specific instance are restored.
|
|
56
|
+
*
|
|
57
|
+
* @throws {HTTPError} when no git repository is found
|
|
58
|
+
*/
|
|
59
|
+
restore(entity?: EntityName<T>, id?: string): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Commits staged changes to the git repository with the provided commit message.
|
|
62
|
+
*
|
|
63
|
+
* @throws {HTTPError} when no git repository is found
|
|
64
|
+
* @throws {HTTPError} when the commit message is empty
|
|
65
|
+
*/
|
|
66
|
+
commit(message: string): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Pushes committed changes to the remote git repository.
|
|
69
|
+
*
|
|
70
|
+
* @throws {HTTPError} when no git repository is found
|
|
71
|
+
*/
|
|
72
|
+
push(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Pulls changes from the remote git repository.
|
|
75
|
+
*
|
|
76
|
+
* @throws {HTTPError} when no git repository is found
|
|
77
|
+
*/
|
|
78
|
+
pull(): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves information about the branches in the git repository.
|
|
81
|
+
*/
|
|
82
|
+
branch(): Promise<{
|
|
83
|
+
isDetached: boolean;
|
|
84
|
+
currentBranch: string;
|
|
85
|
+
allBranches: string[];
|
|
86
|
+
branches: {
|
|
87
|
+
[key: string]: {
|
|
88
|
+
current: boolean;
|
|
89
|
+
name: string;
|
|
90
|
+
commit: string;
|
|
91
|
+
label: string;
|
|
92
|
+
linkedWorkTree: boolean;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
}>;
|
|
96
|
+
/**
|
|
97
|
+
* Creates a new branch in the git repository and checks it out.
|
|
98
|
+
*
|
|
99
|
+
* @param branchName The name of the branch to create.
|
|
100
|
+
* @throws {HTTPError} when no git repository is found
|
|
101
|
+
*/
|
|
102
|
+
createBranch(branchName: string): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Switches to an existing branch in the git repository.
|
|
105
|
+
*
|
|
106
|
+
* @param branchName The name of the branch to switch to.
|
|
107
|
+
* @throws {HTTPError} when no git repository is found
|
|
108
|
+
*/
|
|
109
|
+
switchBranch(branchName: string): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Deletes a branch in the git repository.
|
|
112
|
+
*
|
|
113
|
+
* @param branchName The name of the branch to delete.
|
|
114
|
+
* @param options Options for deleting the branch.
|
|
115
|
+
* @throws {HTTPError} when no git repository is found
|
|
116
|
+
* @throws {HTTPError} when trying to delete the currently checked out branch
|
|
117
|
+
*/
|
|
118
|
+
deleteBranch(branchName: string, options: {
|
|
119
|
+
force?: boolean;
|
|
120
|
+
}): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Run a custom git operation.
|
|
123
|
+
*
|
|
124
|
+
* @param commands The git commands to run as an array of strings.
|
|
125
|
+
* @param commandMayChangeDataOnDisk Whether the command may change data on disk and thus requires a sync afterwards.
|
|
126
|
+
* @returns The raw output of the git command.
|
|
127
|
+
* @throws {HTTPError} when no git repository is found
|
|
128
|
+
*/
|
|
129
|
+
raw(commands: string[], commandMayChangeDataOnDisk: boolean): Promise<string>;
|
|
130
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import Debug from "debug";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { getAllInstanceOverviewsByEntityName } from "./utils/displayName.js";
|
|
4
|
+
import { HTTPError } from "./utils/error.js";
|
|
5
|
+
import { getFileNameForId } from "./utils/files.js";
|
|
6
|
+
import { attachGitStatusToDatabaseInMemory } from "./utils/git.js";
|
|
7
|
+
const debug = Debug("tsondb:git");
|
|
8
|
+
export class Git {
|
|
9
|
+
#db;
|
|
10
|
+
#git;
|
|
11
|
+
#gitRoot;
|
|
12
|
+
#dataRoot;
|
|
13
|
+
#getData;
|
|
14
|
+
#setData;
|
|
15
|
+
constructor(db, git, gitRoot, dataRoot, getData, setData) {
|
|
16
|
+
this.#db = db;
|
|
17
|
+
this.#git = git;
|
|
18
|
+
this.#gitRoot = gitRoot;
|
|
19
|
+
this.#dataRoot = dataRoot;
|
|
20
|
+
this.#getData = getData;
|
|
21
|
+
this.#setData = setData;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Runs a `git status` operation and updates the in-memory database with the latest statuses.
|
|
25
|
+
*
|
|
26
|
+
* @throws {HTTPError} when no git repository is found
|
|
27
|
+
*/
|
|
28
|
+
async status() {
|
|
29
|
+
debug("status");
|
|
30
|
+
const status = await this.#git.status();
|
|
31
|
+
const data = attachGitStatusToDatabaseInMemory(this.#getData(), this.#dataRoot, this.#gitRoot, status);
|
|
32
|
+
this.#setData(data);
|
|
33
|
+
return {
|
|
34
|
+
currentBranch: status.current,
|
|
35
|
+
trackingBranch: status.tracking,
|
|
36
|
+
commitsAhead: status.ahead,
|
|
37
|
+
commitsBehind: status.behind,
|
|
38
|
+
instances: getAllInstanceOverviewsByEntityName(this.#db.getInstanceContainerOfEntityById.bind(this.#db), this.#db.getAllChildInstanceContainersForParent.bind(this.#db), this.#db.schema.getEntity.bind(this.#db.schema), data, this.#db.locales),
|
|
39
|
+
latestCommit: await this.#git.revparse(["HEAD"]),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Fetches updates from remote git repositories.
|
|
44
|
+
*
|
|
45
|
+
* @throws {HTTPError} when no git repository is found
|
|
46
|
+
*/
|
|
47
|
+
async fetch(options) {
|
|
48
|
+
debug("fetch");
|
|
49
|
+
const args = {
|
|
50
|
+
all: options.all ? "--all" : undefined,
|
|
51
|
+
prune: options.prune ? "-p" : undefined,
|
|
52
|
+
};
|
|
53
|
+
await this.#git.fetch(Object.values(args));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Adds files to the git staging area.
|
|
57
|
+
*
|
|
58
|
+
* - If the function is called without parameters, all changes to all instances are added.
|
|
59
|
+
* - If the function is called with only the `entity` parameter, all changes to instances of that entity are added.
|
|
60
|
+
* - If both `entity` and `id` parameters are provided, only the changes to that specific instance are added.
|
|
61
|
+
*
|
|
62
|
+
* @throws {HTTPError} when no git repository is found
|
|
63
|
+
*/
|
|
64
|
+
async stage(entity, id) {
|
|
65
|
+
if (entity) {
|
|
66
|
+
if (id) {
|
|
67
|
+
debug("add instance %s of entity %s", id, entity);
|
|
68
|
+
await this.#git.add(join(this.#dataRoot, entity, getFileNameForId(id)));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
debug("add all instances of entity %s", entity);
|
|
72
|
+
await this.#git.add(join(this.#dataRoot, entity));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
debug("add all instances");
|
|
77
|
+
await this.#git.add(this.#dataRoot);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Removes files from the git staging area.
|
|
82
|
+
*
|
|
83
|
+
* - If the function is called without parameters, all changes to all instances are removed.
|
|
84
|
+
* - If the function is called with only the `entity` parameter, all changes to instances of that entity are removed.
|
|
85
|
+
* - If both `entity` and `id` parameters are provided, only the changes to that specific instance are removed.
|
|
86
|
+
*
|
|
87
|
+
* @throws {HTTPError} when no git repository is found
|
|
88
|
+
*/
|
|
89
|
+
async unstage(entity, id) {
|
|
90
|
+
if (entity) {
|
|
91
|
+
if (id) {
|
|
92
|
+
debug("reset HEAD instance %s of entity %s", id, entity);
|
|
93
|
+
await this.#git.reset(["HEAD", "--", join(this.#dataRoot, entity, getFileNameForId(id))]);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
debug("reset HEAD all instances of entity %s", entity);
|
|
97
|
+
await this.#git.reset(["HEAD", "--", join(this.#dataRoot, entity)]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
debug("reset HEAD all instances");
|
|
102
|
+
await this.#git.reset(["HEAD", "--", this.#dataRoot]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Restores files in the git repository to their last committed state.
|
|
107
|
+
*
|
|
108
|
+
* - If the function is called without parameters, all changes to all instances are restored.
|
|
109
|
+
* - If the function is called with only the `entity` parameter, all changes to instances of that entity are restored.
|
|
110
|
+
* - If both `entity` and `id` parameters are provided, only the changes to that specific instance are restored.
|
|
111
|
+
*
|
|
112
|
+
* @throws {HTTPError} when no git repository is found
|
|
113
|
+
*/
|
|
114
|
+
async restore(entity, id) {
|
|
115
|
+
if (entity) {
|
|
116
|
+
if (id) {
|
|
117
|
+
debug("restore instance %s of entity %s", id, entity);
|
|
118
|
+
await this.#git.raw(["restore", "--", join(this.#dataRoot, entity, getFileNameForId(id))]);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
debug("restore all instances of entity %s", entity);
|
|
122
|
+
await this.#git.raw(["restore", "--", join(this.#dataRoot, entity)]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
debug("restore all instances");
|
|
127
|
+
await this.#git.raw(["restore", "--", this.#dataRoot]);
|
|
128
|
+
}
|
|
129
|
+
await this.#db.sync();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Commits staged changes to the git repository with the provided commit message.
|
|
133
|
+
*
|
|
134
|
+
* @throws {HTTPError} when no git repository is found
|
|
135
|
+
* @throws {HTTPError} when the commit message is empty
|
|
136
|
+
*/
|
|
137
|
+
async commit(message) {
|
|
138
|
+
debug("commit");
|
|
139
|
+
if (message.trim().length === 0) {
|
|
140
|
+
throw new HTTPError(400, "Commit message cannot be empty.");
|
|
141
|
+
}
|
|
142
|
+
await this.#git.commit(message);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Pushes committed changes to the remote git repository.
|
|
146
|
+
*
|
|
147
|
+
* @throws {HTTPError} when no git repository is found
|
|
148
|
+
*/
|
|
149
|
+
async push() {
|
|
150
|
+
debug("push");
|
|
151
|
+
const status = await this.#git.status();
|
|
152
|
+
const remotes = await this.#git.getRemotes();
|
|
153
|
+
await this.#git.push(remotes[0]?.name, status.current ?? undefined);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Pulls changes from the remote git repository.
|
|
157
|
+
*
|
|
158
|
+
* @throws {HTTPError} when no git repository is found
|
|
159
|
+
*/
|
|
160
|
+
async pull() {
|
|
161
|
+
debug("pull");
|
|
162
|
+
const status = await this.#git.status();
|
|
163
|
+
const remotes = await this.#git.getRemotes();
|
|
164
|
+
await this.#git.pull(remotes[0]?.name, status.current ?? undefined);
|
|
165
|
+
await this.#db.sync();
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Retrieves information about the branches in the git repository.
|
|
169
|
+
*/
|
|
170
|
+
async branch() {
|
|
171
|
+
debug("branch");
|
|
172
|
+
const branchSummary = await this.#git.branch();
|
|
173
|
+
return {
|
|
174
|
+
allBranches: branchSummary.all,
|
|
175
|
+
currentBranch: branchSummary.current,
|
|
176
|
+
isDetached: branchSummary.detached,
|
|
177
|
+
branches: branchSummary.branches,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Creates a new branch in the git repository and checks it out.
|
|
182
|
+
*
|
|
183
|
+
* @param branchName The name of the branch to create.
|
|
184
|
+
* @throws {HTTPError} when no git repository is found
|
|
185
|
+
*/
|
|
186
|
+
async createBranch(branchName) {
|
|
187
|
+
debug("create branch %s", branchName);
|
|
188
|
+
await this.#git.checkoutLocalBranch(branchName);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Switches to an existing branch in the git repository.
|
|
192
|
+
*
|
|
193
|
+
* @param branchName The name of the branch to switch to.
|
|
194
|
+
* @throws {HTTPError} when no git repository is found
|
|
195
|
+
*/
|
|
196
|
+
async switchBranch(branchName) {
|
|
197
|
+
debug("switch branch %s", branchName);
|
|
198
|
+
await this.#git.raw("switch", branchName);
|
|
199
|
+
await this.#db.sync();
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Deletes a branch in the git repository.
|
|
203
|
+
*
|
|
204
|
+
* @param branchName The name of the branch to delete.
|
|
205
|
+
* @param options Options for deleting the branch.
|
|
206
|
+
* @throws {HTTPError} when no git repository is found
|
|
207
|
+
* @throws {HTTPError} when trying to delete the currently checked out branch
|
|
208
|
+
*/
|
|
209
|
+
async deleteBranch(branchName, options) {
|
|
210
|
+
debug("delete branch %s", branchName);
|
|
211
|
+
const branchSummary = await this.#git.branchLocal();
|
|
212
|
+
if (branchSummary.current === branchName) {
|
|
213
|
+
throw new HTTPError(400, "Cannot delete the branch currently checked out.");
|
|
214
|
+
}
|
|
215
|
+
await this.#git.deleteLocalBranch(branchName, options.force ?? false);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Run a custom git operation.
|
|
219
|
+
*
|
|
220
|
+
* @param commands The git commands to run as an array of strings.
|
|
221
|
+
* @param commandMayChangeDataOnDisk Whether the command may change data on disk and thus requires a sync afterwards.
|
|
222
|
+
* @returns The raw output of the git command.
|
|
223
|
+
* @throws {HTTPError} when no git repository is found
|
|
224
|
+
*/
|
|
225
|
+
async raw(commands, commandMayChangeDataOnDisk) {
|
|
226
|
+
debug("raw %O", commands);
|
|
227
|
+
const result = await this.#git.raw(...commands);
|
|
228
|
+
if (commandMayChangeDataOnDisk) {
|
|
229
|
+
await this.#db.sync();
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
}
|