@manta-eu/cli 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -2
- package/dist/app-file.d.ts +18 -1
- package/dist/app-file.d.ts.map +1 -1
- package/dist/app-file.js +27 -10
- package/dist/app-file.js.map +1 -1
- package/dist/cli.js +23 -16
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/app-file.ts +49 -9
- package/src/cli.ts +47 -16
- package/src/index.ts +3 -0
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# @manta-eu/cli
|
|
2
2
|
|
|
3
3
|
The `manta` CLI keeps what a Manta datastore holds in line with files you track in git. It covers your app's
|
|
4
|
-
vocabulary (the classes and properties your app adds to the knowledge graph)
|
|
4
|
+
vocabulary (the classes and properties your app adds to the knowledge graph), the SHACL shapes for those classes, and
|
|
5
|
+
the Datalog rules that derive new facts from them.
|
|
5
6
|
|
|
6
7
|
Documentation: [developers.manta.eu](https://developers.manta.eu)
|
|
7
8
|
|
|
@@ -81,12 +82,35 @@ shapes pushed under the same `--name` are still in the datastore.
|
|
|
81
82
|
The vocabulary push keeps the prefixes your file declares for your own namespace, so `manta-codegen` names your schemas
|
|
82
83
|
after them (`todo.ts`). Declare your namespace with its prefix in the vocabulary before you push shapes for it.
|
|
83
84
|
|
|
85
|
+
## Push your rules
|
|
86
|
+
|
|
87
|
+
Keep your Datalog rules in a `.dlog` file, each one named by a `# s:` line in your own namespace. Use only the
|
|
88
|
+
prefixes the realm's rules declare, and spell your own IRIs out in full: a realm deploy recommits your rules under the
|
|
89
|
+
realm's prefixes, so a prefix of your own would stop them.
|
|
90
|
+
|
|
91
|
+
```datalog
|
|
92
|
+
# s: <https://todomvc.example/vocab#Rule_Done>
|
|
93
|
+
<https://todomvc.example/vocab#isDone>[?todo, true] :-
|
|
94
|
+
<https://todomvc.example/vocab#Todo>[?todo], <https://todomvc.example/vocab#completed>[?todo, true] .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```shell
|
|
98
|
+
pnpm manta rules push manta/rules.dlog --datastore your-datastore --name todomvc
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
- **Committed, not only staged.** The push makes the file your app's whole live rule set in one transaction: new rules
|
|
102
|
+
are added, changed ones replaced, and the ones the file no longer holds removed. The datastore starts deriving at once.
|
|
103
|
+
- **Survives a deploy.** Your rules are owned by your app, and a realm deploy only replaces the realm's own.
|
|
104
|
+
- **Dry run.** `--dry-run` reports how many rules would be added, changed and removed, and commits nothing.
|
|
105
|
+
|
|
106
|
+
`manta rules delete` withdraws all of your app's rules.
|
|
107
|
+
|
|
84
108
|
The command targets hiremanta.com production unless `--api-url`, `--keycloak-url` and `--keycloak-realm` name another
|
|
85
109
|
deployment, as for `manta-codegen`.
|
|
86
110
|
|
|
87
111
|
## What the API checks
|
|
88
112
|
|
|
89
|
-
The whole push is refused, and nothing is written, when
|
|
113
|
+
The whole push is refused, and nothing is written, when a Turtle file:
|
|
90
114
|
|
|
91
115
|
- is not valid Turtle, declares nothing, or is larger than 1 MiB;
|
|
92
116
|
- declares a term outside `--namespace`, or names a namespace that overlaps one another app's vocabulary already
|
|
@@ -98,6 +122,11 @@ The whole push is refused, and nothing is written, when the file:
|
|
|
98
122
|
A shapes file is also refused when it declares no `sh:NodeShape`, uses `sh:targetNode`, `sh:targetSubjectsOf` or
|
|
99
123
|
`sh:targetObjectsOf`, or targets a class the realm's own shapes already cover.
|
|
100
124
|
|
|
125
|
+
A rules file is refused when a rule has no `# s:` name or shares one, uses a prefix the file does not declare, declares
|
|
126
|
+
a prefix the realm's rules do not, binds a prefix differently from the datastore's rules, is not valid Datalog, derives a predicate the platform protects or a
|
|
127
|
+
variable predicate, names an action the datastore cannot run, or takes a name in a namespace Manta owns or one
|
|
128
|
+
another owner already holds.
|
|
129
|
+
|
|
101
130
|
`--name` is 1 to 64 lowercase letters, digits and dashes, and may not end in `ontology`, which marks the realm
|
|
102
131
|
ontology. `--namespace` is an http(s) IRI ending in `#` or `/`, and may not overlap a namespace Manta already owns: the
|
|
103
132
|
realm's own vocabulary, an integration's (such as `meta:` or `shopify:`), or RDF, RDFS, OWL, XSD, SHACL and the other
|
package/dist/app-file.d.ts
CHANGED
|
@@ -14,7 +14,19 @@ export type AppFileDeletion = {
|
|
|
14
14
|
graphIri: string;
|
|
15
15
|
deleted: boolean;
|
|
16
16
|
};
|
|
17
|
-
export type
|
|
17
|
+
export type RulesPush = {
|
|
18
|
+
name: string;
|
|
19
|
+
graphIri: string;
|
|
20
|
+
owner: string;
|
|
21
|
+
added: number;
|
|
22
|
+
changed: number;
|
|
23
|
+
removed: number;
|
|
24
|
+
unchanged: number;
|
|
25
|
+
prefixesRebound: boolean;
|
|
26
|
+
written: boolean;
|
|
27
|
+
dryRun: boolean;
|
|
28
|
+
};
|
|
29
|
+
export type AppFileCollection = "vocabularies" | "shapes" | "rules";
|
|
18
30
|
export type AppFileLocation = {
|
|
19
31
|
apiUrl: string;
|
|
20
32
|
datastore: string;
|
|
@@ -31,6 +43,11 @@ export declare function pushAppFile(target: AppFileTarget & {
|
|
|
31
43
|
turtle: string;
|
|
32
44
|
dryRun: boolean;
|
|
33
45
|
}): Promise<AppFilePush>;
|
|
46
|
+
export declare function pushRules(target: Omit<AppFileTarget, "collection"> & {
|
|
47
|
+
text: string;
|
|
48
|
+
dryRun: boolean;
|
|
49
|
+
}): Promise<RulesPush>;
|
|
34
50
|
export declare function deleteAppFile(target: AppFileTarget): Promise<AppFileDeletion>;
|
|
35
51
|
export declare function describePush(push: AppFilePush): string;
|
|
52
|
+
export declare function describeRulesPush(push: RulesPush): string;
|
|
36
53
|
//# sourceMappingURL=app-file.d.ts.map
|
package/dist/app-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-file.d.ts","sourceRoot":"","sources":["../src/app-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAGd,KAAK,WAAW,EAEjB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnF,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"app-file.d.ts","sourceRoot":"","sources":["../src/app-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAGd,KAAK,WAAW,EAEjB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjH,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5F,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,eAAe,GAAG,MAAM,CAEhG;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC9E,OAAO,CAAC,WAAW,CAAC,CAEtB;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC5E,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAE7E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAStD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAWzD"}
|
package/dist/app-file.js
CHANGED
|
@@ -3,16 +3,10 @@ export function appFileEndpoint({ apiUrl, datastore, collection, name }) {
|
|
|
3
3
|
return `${apiUrl.replace(/\/$/, "")}/d/${encodeURIComponent(datastore)}/${collection}/${encodeURIComponent(name)}`;
|
|
4
4
|
}
|
|
5
5
|
export function pushAppFile(target) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
endpoint.searchParams.set("dryRun", "true");
|
|
11
|
-
return send(target, endpoint.toString(), {
|
|
12
|
-
method: "PUT",
|
|
13
|
-
headers: { "content-type": "text/turtle" },
|
|
14
|
-
body: target.turtle,
|
|
15
|
-
});
|
|
6
|
+
return put(target, "text/turtle", target.turtle);
|
|
7
|
+
}
|
|
8
|
+
export function pushRules(target) {
|
|
9
|
+
return put({ ...target, collection: "rules" }, "application/x.datalog", target.text);
|
|
16
10
|
}
|
|
17
11
|
export function deleteAppFile(target) {
|
|
18
12
|
return send(target, appFileEndpoint(target), { method: "DELETE", headers: {} });
|
|
@@ -27,6 +21,29 @@ export function describePush(push) {
|
|
|
27
21
|
return `${push.name} would change: ${changes}${dryRun}`;
|
|
28
22
|
return `updated ${push.name} in <${push.graphIri}>: ${changes}`;
|
|
29
23
|
}
|
|
24
|
+
export function describeRulesPush(push) {
|
|
25
|
+
const dryRun = push.dryRun ? " (dry run, nothing committed)" : "";
|
|
26
|
+
const rebound = push.prefixesRebound ? ", prefixes rebound" : "";
|
|
27
|
+
const counts = `${push.added} added, ${push.changed} changed, ${push.removed} removed, ${push.unchanged} unchanged${rebound}`;
|
|
28
|
+
if (push.added + push.changed + push.removed === 0 && !push.prefixesRebound) {
|
|
29
|
+
return `${push.name}'s rules are already up to date${dryRun}`;
|
|
30
|
+
}
|
|
31
|
+
if (push.dryRun)
|
|
32
|
+
return `${push.name}'s rules would change: ${counts}${dryRun}`;
|
|
33
|
+
return `committed ${push.name}'s rules: ${counts}`;
|
|
34
|
+
}
|
|
35
|
+
function put(target, contentType, body) {
|
|
36
|
+
const endpoint = new URL(appFileEndpoint(target));
|
|
37
|
+
if (target.namespace !== undefined)
|
|
38
|
+
endpoint.searchParams.set("namespace", target.namespace);
|
|
39
|
+
if (target.dryRun)
|
|
40
|
+
endpoint.searchParams.set("dryRun", "true");
|
|
41
|
+
return send(target, endpoint.toString(), {
|
|
42
|
+
method: "PUT",
|
|
43
|
+
headers: { "content-type": contentType },
|
|
44
|
+
body,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
30
47
|
async function send({ token, fetchImpl = fetch }, endpoint, init) {
|
|
31
48
|
return withRenewal(token, async (accessToken) => {
|
|
32
49
|
let response;
|
package/dist/app-file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-file.js","sourceRoot":"","sources":["../src/app-file.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,QAAQ,EACR,mBAAmB,EAEnB,WAAW,GACZ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"app-file.js","sourceRoot":"","sources":["../src/app-file.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { clientIdHelp, cliTokenSource, defaultDeployment, describeError, registerAuthCommands, } from "@manta-eu/auth";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
|
-
import { deleteAppFile, describePush, pushAppFile } from "./app-file.js";
|
|
5
|
+
import { deleteAppFile, describePush, describeRulesPush, pushAppFile, pushRules, } from "./app-file.js";
|
|
6
6
|
const label = "manta";
|
|
7
7
|
function withTargetOptions(command) {
|
|
8
8
|
return command
|
|
@@ -36,24 +36,19 @@ async function run(action) {
|
|
|
36
36
|
const program = new Command()
|
|
37
37
|
.name(label)
|
|
38
38
|
.description("Keep what a Manta datastore holds in line with files you track in git.");
|
|
39
|
-
|
|
39
|
+
const pushTurtle = async (target, turtle, options) => describePush(await pushAppFile({ ...target, ...options, turtle }));
|
|
40
|
+
function registerAppFileCommands({ command, collection, description, noun, format, push, addPushOptions, }) {
|
|
40
41
|
const group = program.command(command).description(description);
|
|
41
|
-
const
|
|
42
|
+
const pushCommand = group
|
|
42
43
|
.command("push")
|
|
43
|
-
.description(`make the datastore hold exactly the ${noun} the
|
|
44
|
-
.argument("<file>",
|
|
44
|
+
.description(`make the datastore hold exactly the ${noun} the ${format} file declares`)
|
|
45
|
+
.argument("<file>", `${format} file with your app's ${noun}`)
|
|
45
46
|
.option("--dry-run", "report what would change without writing it");
|
|
46
|
-
addPushOptions?.(
|
|
47
|
-
withTargetOptions(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
namespace: options.namespace,
|
|
52
|
-
turtle,
|
|
53
|
-
dryRun: options.dryRun === true,
|
|
54
|
-
});
|
|
55
|
-
return describePush(pushed);
|
|
56
|
-
}));
|
|
47
|
+
addPushOptions?.(pushCommand);
|
|
48
|
+
withTargetOptions(pushCommand).action((file, options) => run(async () => push(targetFrom(collection, options), await readFile(file, "utf8"), {
|
|
49
|
+
namespace: options.namespace,
|
|
50
|
+
dryRun: options.dryRun === true,
|
|
51
|
+
})));
|
|
57
52
|
withTargetOptions(group.command("delete").description(`remove your app's ${noun} from the datastore`)).action((options) => run(async () => {
|
|
58
53
|
const deletion = await deleteAppFile(targetFrom(collection, options));
|
|
59
54
|
return deletion.deleted ? `deleted ${deletion.name}` : `${deletion.name} was not in the datastore`;
|
|
@@ -64,6 +59,8 @@ registerAppFileCommands({
|
|
|
64
59
|
collection: "vocabularies",
|
|
65
60
|
description: "your app's vocabulary: its classes and properties",
|
|
66
61
|
noun: "vocabulary",
|
|
62
|
+
format: "Turtle",
|
|
63
|
+
push: pushTurtle,
|
|
67
64
|
addPushOptions: (push) => push.requiredOption("--namespace <iri>", "your app's namespace, ending in # or /: every term the file declares is under it"),
|
|
68
65
|
});
|
|
69
66
|
registerAppFileCommands({
|
|
@@ -71,6 +68,16 @@ registerAppFileCommands({
|
|
|
71
68
|
collection: "shapes",
|
|
72
69
|
description: "your app's SHACL shapes",
|
|
73
70
|
noun: "shapes",
|
|
71
|
+
format: "Turtle",
|
|
72
|
+
push: pushTurtle,
|
|
73
|
+
});
|
|
74
|
+
registerAppFileCommands({
|
|
75
|
+
command: "rules",
|
|
76
|
+
collection: "rules",
|
|
77
|
+
description: "your app's Datalog rules, committed as one set",
|
|
78
|
+
noun: "rules",
|
|
79
|
+
format: "Datalog",
|
|
80
|
+
push: async (target, text, { dryRun }) => describeRulesPush(await pushRules({ ...target, text, dryRun })),
|
|
74
81
|
});
|
|
75
82
|
registerAuthCommands(program, { label });
|
|
76
83
|
await program.parseAsync();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAEL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { appFileEndpoint, deleteAppFile, describePush, pushAppFile, type AppFileCollection, type AppFileDeletion, type AppFileLocation, type AppFilePush, type AppFileTarget, } from "./app-file.js";
|
|
1
|
+
export { appFileEndpoint, deleteAppFile, describePush, describeRulesPush, pushAppFile, pushRules, type AppFileCollection, type AppFileDeletion, type AppFileLocation, type AppFilePush, type AppFileTarget, type RulesPush, } from "./app-file.js";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { appFileEndpoint, deleteAppFile, describePush, pushAppFile, } from "./app-file.js";
|
|
1
|
+
export { appFileEndpoint, deleteAppFile, describePush, describeRulesPush, pushAppFile, pushRules, } from "./app-file.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,WAAW,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,SAAS,GAOV,MAAM,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manta-eu/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CLI that keeps what a Manta datastore holds in line with files you track in git: your app's vocabulary and
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "CLI that keeps what a Manta datastore holds in line with files you track in git: your app's vocabulary, shapes and rules",
|
|
5
5
|
"homepage": "https://developers.manta.eu",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"manta",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"commander": "^15.0.0",
|
|
26
|
-
"@manta-eu/auth": "0.
|
|
26
|
+
"@manta-eu/auth": "0.6.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^24.13.3",
|
package/src/app-file.ts
CHANGED
|
@@ -20,7 +20,20 @@ export type AppFilePush = {
|
|
|
20
20
|
|
|
21
21
|
export type AppFileDeletion = { name: string; graphIri: string; deleted: boolean };
|
|
22
22
|
|
|
23
|
-
export type
|
|
23
|
+
export type RulesPush = {
|
|
24
|
+
name: string;
|
|
25
|
+
graphIri: string;
|
|
26
|
+
owner: string;
|
|
27
|
+
added: number;
|
|
28
|
+
changed: number;
|
|
29
|
+
removed: number;
|
|
30
|
+
unchanged: number;
|
|
31
|
+
prefixesRebound: boolean;
|
|
32
|
+
written: boolean;
|
|
33
|
+
dryRun: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type AppFileCollection = "vocabularies" | "shapes" | "rules";
|
|
24
37
|
|
|
25
38
|
export type AppFileLocation = { apiUrl: string; datastore: string; collection: AppFileCollection; name: string };
|
|
26
39
|
|
|
@@ -33,15 +46,13 @@ export function appFileEndpoint({ apiUrl, datastore, collection, name }: AppFile
|
|
|
33
46
|
export function pushAppFile(
|
|
34
47
|
target: AppFileTarget & { namespace?: string; turtle: string; dryRun: boolean },
|
|
35
48
|
): Promise<AppFilePush> {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (target.dryRun) endpoint.searchParams.set("dryRun", "true");
|
|
49
|
+
return put<AppFilePush>(target, "text/turtle", target.turtle);
|
|
50
|
+
}
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
52
|
+
export function pushRules(
|
|
53
|
+
target: Omit<AppFileTarget, "collection"> & { text: string; dryRun: boolean },
|
|
54
|
+
): Promise<RulesPush> {
|
|
55
|
+
return put<RulesPush>({ ...target, collection: "rules" }, "application/x.datalog", target.text);
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
export function deleteAppFile(target: AppFileTarget): Promise<AppFileDeletion> {
|
|
@@ -59,6 +70,35 @@ export function describePush(push: AppFilePush): string {
|
|
|
59
70
|
return `updated ${push.name} in <${push.graphIri}>: ${changes}`;
|
|
60
71
|
}
|
|
61
72
|
|
|
73
|
+
export function describeRulesPush(push: RulesPush): string {
|
|
74
|
+
const dryRun = push.dryRun ? " (dry run, nothing committed)" : "";
|
|
75
|
+
const rebound = push.prefixesRebound ? ", prefixes rebound" : "";
|
|
76
|
+
const counts = `${push.added} added, ${push.changed} changed, ${push.removed} removed, ${push.unchanged} unchanged${rebound}`;
|
|
77
|
+
|
|
78
|
+
if (push.added + push.changed + push.removed === 0 && !push.prefixesRebound) {
|
|
79
|
+
return `${push.name}'s rules are already up to date${dryRun}`;
|
|
80
|
+
}
|
|
81
|
+
if (push.dryRun) return `${push.name}'s rules would change: ${counts}${dryRun}`;
|
|
82
|
+
|
|
83
|
+
return `committed ${push.name}'s rules: ${counts}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function put<T>(
|
|
87
|
+
target: AppFileTarget & { namespace?: string; dryRun: boolean },
|
|
88
|
+
contentType: string,
|
|
89
|
+
body: string,
|
|
90
|
+
): Promise<T> {
|
|
91
|
+
const endpoint = new URL(appFileEndpoint(target));
|
|
92
|
+
if (target.namespace !== undefined) endpoint.searchParams.set("namespace", target.namespace);
|
|
93
|
+
if (target.dryRun) endpoint.searchParams.set("dryRun", "true");
|
|
94
|
+
|
|
95
|
+
return send<T>(target, endpoint.toString(), {
|
|
96
|
+
method: "PUT",
|
|
97
|
+
headers: { "content-type": contentType },
|
|
98
|
+
body,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
62
102
|
async function send<T>(
|
|
63
103
|
{ token, fetchImpl = fetch }: AppFileTarget,
|
|
64
104
|
endpoint: string,
|
package/src/cli.ts
CHANGED
|
@@ -9,7 +9,15 @@ import {
|
|
|
9
9
|
} from "@manta-eu/auth";
|
|
10
10
|
import { Command } from "commander";
|
|
11
11
|
import { readFile } from "node:fs/promises";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
type AppFileCollection,
|
|
14
|
+
type AppFileTarget,
|
|
15
|
+
deleteAppFile,
|
|
16
|
+
describePush,
|
|
17
|
+
describeRulesPush,
|
|
18
|
+
pushAppFile,
|
|
19
|
+
pushRules,
|
|
20
|
+
} from "./app-file.js";
|
|
13
21
|
|
|
14
22
|
const label = "manta";
|
|
15
23
|
|
|
@@ -50,35 +58,45 @@ const program = new Command()
|
|
|
50
58
|
.name(label)
|
|
51
59
|
.description("Keep what a Manta datastore holds in line with files you track in git.");
|
|
52
60
|
|
|
61
|
+
type AppFilePushOptions = { namespace?: string; dryRun: boolean };
|
|
62
|
+
|
|
53
63
|
type AppFileCommand = {
|
|
54
64
|
command: string;
|
|
55
65
|
collection: AppFileCollection;
|
|
56
66
|
description: string;
|
|
57
67
|
noun: string;
|
|
68
|
+
format: string;
|
|
69
|
+
push: (target: AppFileTarget, text: string, options: AppFilePushOptions) => Promise<string>;
|
|
58
70
|
addPushOptions?: (push: Command) => Command;
|
|
59
71
|
};
|
|
60
72
|
|
|
61
|
-
|
|
73
|
+
const pushTurtle: AppFileCommand["push"] = async (target, turtle, options) =>
|
|
74
|
+
describePush(await pushAppFile({ ...target, ...options, turtle }));
|
|
75
|
+
|
|
76
|
+
function registerAppFileCommands({
|
|
77
|
+
command,
|
|
78
|
+
collection,
|
|
79
|
+
description,
|
|
80
|
+
noun,
|
|
81
|
+
format,
|
|
82
|
+
push,
|
|
83
|
+
addPushOptions,
|
|
84
|
+
}: AppFileCommand): void {
|
|
62
85
|
const group = program.command(command).description(description);
|
|
63
|
-
const
|
|
86
|
+
const pushCommand = group
|
|
64
87
|
.command("push")
|
|
65
|
-
.description(`make the datastore hold exactly the ${noun} the
|
|
66
|
-
.argument("<file>",
|
|
88
|
+
.description(`make the datastore hold exactly the ${noun} the ${format} file declares`)
|
|
89
|
+
.argument("<file>", `${format} file with your app's ${noun}`)
|
|
67
90
|
.option("--dry-run", "report what would change without writing it");
|
|
68
|
-
addPushOptions?.(
|
|
91
|
+
addPushOptions?.(pushCommand);
|
|
69
92
|
|
|
70
|
-
withTargetOptions(
|
|
71
|
-
run(async () =>
|
|
72
|
-
|
|
73
|
-
const pushed = await pushAppFile({
|
|
74
|
-
...targetFrom(collection, options),
|
|
93
|
+
withTargetOptions(pushCommand).action((file: string, options: TargetOptions & AppFilePushOptions) =>
|
|
94
|
+
run(async () =>
|
|
95
|
+
push(targetFrom(collection, options), await readFile(file, "utf8"), {
|
|
75
96
|
namespace: options.namespace,
|
|
76
|
-
turtle,
|
|
77
97
|
dryRun: options.dryRun === true,
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
return describePush(pushed);
|
|
81
|
-
}),
|
|
98
|
+
}),
|
|
99
|
+
),
|
|
82
100
|
);
|
|
83
101
|
|
|
84
102
|
withTargetOptions(group.command("delete").description(`remove your app's ${noun} from the datastore`)).action(
|
|
@@ -96,6 +114,8 @@ registerAppFileCommands({
|
|
|
96
114
|
collection: "vocabularies",
|
|
97
115
|
description: "your app's vocabulary: its classes and properties",
|
|
98
116
|
noun: "vocabulary",
|
|
117
|
+
format: "Turtle",
|
|
118
|
+
push: pushTurtle,
|
|
99
119
|
addPushOptions: (push) =>
|
|
100
120
|
push.requiredOption(
|
|
101
121
|
"--namespace <iri>",
|
|
@@ -108,6 +128,17 @@ registerAppFileCommands({
|
|
|
108
128
|
collection: "shapes",
|
|
109
129
|
description: "your app's SHACL shapes",
|
|
110
130
|
noun: "shapes",
|
|
131
|
+
format: "Turtle",
|
|
132
|
+
push: pushTurtle,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
registerAppFileCommands({
|
|
136
|
+
command: "rules",
|
|
137
|
+
collection: "rules",
|
|
138
|
+
description: "your app's Datalog rules, committed as one set",
|
|
139
|
+
noun: "rules",
|
|
140
|
+
format: "Datalog",
|
|
141
|
+
push: async (target, text, { dryRun }) => describeRulesPush(await pushRules({ ...target, text, dryRun })),
|
|
111
142
|
});
|
|
112
143
|
|
|
113
144
|
registerAuthCommands(program, { label });
|
package/src/index.ts
CHANGED
|
@@ -2,10 +2,13 @@ export {
|
|
|
2
2
|
appFileEndpoint,
|
|
3
3
|
deleteAppFile,
|
|
4
4
|
describePush,
|
|
5
|
+
describeRulesPush,
|
|
5
6
|
pushAppFile,
|
|
7
|
+
pushRules,
|
|
6
8
|
type AppFileCollection,
|
|
7
9
|
type AppFileDeletion,
|
|
8
10
|
type AppFileLocation,
|
|
9
11
|
type AppFilePush,
|
|
10
12
|
type AppFileTarget,
|
|
13
|
+
type RulesPush,
|
|
11
14
|
} from "./app-file.js";
|