@tinacms/graphql 2.1.2 → 2.1.3
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.
|
@@ -3,6 +3,10 @@ import type { Bridge } from './index';
|
|
|
3
3
|
* This is the bridge from whatever datasource we need for I/O.
|
|
4
4
|
* The basic example here is for the filesystem, one is needed
|
|
5
5
|
* for GitHub has well.
|
|
6
|
+
*
|
|
7
|
+
* @security All public methods validate their `filepath` / `pattern`
|
|
8
|
+
* argument via `assertWithinBase` before performing any I/O. If you add a
|
|
9
|
+
* new method that accepts a path, you MUST validate it the same way.
|
|
6
10
|
*/
|
|
7
11
|
export declare class FilesystemBridge implements Bridge {
|
|
8
12
|
rootPath: string;
|
|
@@ -1,8 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* I/O abstraction layer for reading/writing content files.
|
|
3
|
+
*
|
|
4
|
+
* @security **Path traversal (CWE-22):** All `filepath` and `pattern`
|
|
5
|
+
* parameters may originate from user input (e.g. GraphQL mutations or media
|
|
6
|
+
* API requests). Implementations MUST validate that resolved paths stay
|
|
7
|
+
* within their root/output directory before performing any filesystem
|
|
8
|
+
* operation. See `FilesystemBridge.assertWithinBase` and
|
|
9
|
+
* `IsomorphicBridge.assertWithinBase` for reference implementations.
|
|
10
|
+
*
|
|
11
|
+
* The recommended validation pattern is:
|
|
12
|
+
* ```ts
|
|
13
|
+
* const resolved = path.resolve(path.join(baseDir, filepath));
|
|
14
|
+
* if (!resolved.startsWith(path.resolve(baseDir) + path.sep)) {
|
|
15
|
+
* throw new Error('Path traversal detected');
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* If you are adding a new Bridge implementation, add path traversal
|
|
20
|
+
* validation to every method that accepts a filepath from the caller.
|
|
21
|
+
*/
|
|
1
22
|
export interface Bridge {
|
|
2
23
|
rootPath: string;
|
|
24
|
+
/**
|
|
25
|
+
* @param pattern - Glob pattern prefix (untrusted — validate before use).
|
|
26
|
+
* @param extension - File extension to match.
|
|
27
|
+
*/
|
|
3
28
|
glob(pattern: string, extension: string): Promise<string[]>;
|
|
29
|
+
/** @param filepath - Relative path to delete (untrusted — validate before use). */
|
|
4
30
|
delete(filepath: string): Promise<void>;
|
|
31
|
+
/** @param filepath - Relative path to read (untrusted — validate before use). */
|
|
5
32
|
get(filepath: string): Promise<string>;
|
|
33
|
+
/** @param filepath - Relative path to write (untrusted — validate before use). */
|
|
6
34
|
put(filepath: string, data: string): Promise<void>;
|
|
7
35
|
/**
|
|
8
36
|
* Optionally, the bridge can perform
|
|
@@ -18,6 +18,11 @@ export type IsomorphicGitBridgeOptions = {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Bridge backed by isomorphic-git
|
|
21
|
+
*
|
|
22
|
+
* @security All public methods (glob, get, put, delete) validate their
|
|
23
|
+
* `filepath` / `pattern` argument via `assertWithinBase` before performing
|
|
24
|
+
* any git operations. If you add a new method that accepts a path, you
|
|
25
|
+
* MUST validate it the same way.
|
|
21
26
|
*/
|
|
22
27
|
export declare class IsomorphicBridge implements Bridge {
|
|
23
28
|
rootPath: string;
|
package/dist/index.js
CHANGED
|
@@ -45,8 +45,8 @@ var btoa = (string2) => {
|
|
|
45
45
|
var lastItem = (arr) => {
|
|
46
46
|
return arr[arr.length - 1];
|
|
47
47
|
};
|
|
48
|
-
var get = (obj,
|
|
49
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
48
|
+
var get = (obj, path9, defaultValue = void 0) => {
|
|
49
|
+
const travel = (regexp) => String.prototype.split.call(path9, regexp).filter(Boolean).reduce(
|
|
50
50
|
(res, key) => res !== null && res !== void 0 ? res[key] : res,
|
|
51
51
|
obj
|
|
52
52
|
);
|
|
@@ -3026,7 +3026,7 @@ var validateField = async (field) => {
|
|
|
3026
3026
|
var package_default = {
|
|
3027
3027
|
name: "@tinacms/graphql",
|
|
3028
3028
|
type: "module",
|
|
3029
|
-
version: "2.1.
|
|
3029
|
+
version: "2.1.3",
|
|
3030
3030
|
main: "dist/index.js",
|
|
3031
3031
|
module: "./dist/index.js",
|
|
3032
3032
|
files: [
|
|
@@ -3662,17 +3662,17 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
|
|
|
3662
3662
|
const documentPaths = await bridge.glob(normalPath, format);
|
|
3663
3663
|
const matches = tinaSchema.getMatches({ collection });
|
|
3664
3664
|
const filteredPaths = matches.length > 0 ? micromatch(documentPaths, matches) : documentPaths;
|
|
3665
|
-
filteredPaths.forEach((
|
|
3666
|
-
if (filesSeen.has(
|
|
3667
|
-
filesSeen.get(
|
|
3668
|
-
duplicateFiles.add(
|
|
3665
|
+
filteredPaths.forEach((path9) => {
|
|
3666
|
+
if (filesSeen.has(path9)) {
|
|
3667
|
+
filesSeen.get(path9).push(collection.name);
|
|
3668
|
+
duplicateFiles.add(path9);
|
|
3669
3669
|
} else {
|
|
3670
|
-
filesSeen.set(
|
|
3670
|
+
filesSeen.set(path9, [collection.name]);
|
|
3671
3671
|
}
|
|
3672
3672
|
});
|
|
3673
|
-
duplicateFiles.forEach((
|
|
3673
|
+
duplicateFiles.forEach((path9) => {
|
|
3674
3674
|
warnings.push(
|
|
3675
|
-
`"${
|
|
3675
|
+
`"${path9}" Found in multiple collections: ${filesSeen.get(path9).map((collection2) => `"${collection2}"`).join(
|
|
3676
3676
|
", "
|
|
3677
3677
|
)}. This can cause unexpected behavior. We recommend updating the \`match\` property of those collections so that each file is in only one collection.
|
|
3678
3678
|
This will be an error in the future. See https://tina.io/docs/errors/file-in-mutpliple-collections/
|
|
@@ -4235,9 +4235,9 @@ var makeFilterSuffixes = (filterChain, index) => {
|
|
|
4235
4235
|
}
|
|
4236
4236
|
};
|
|
4237
4237
|
var FOLDER_ROOT = "~";
|
|
4238
|
-
var stripCollectionFromPath = (collectionPath,
|
|
4238
|
+
var stripCollectionFromPath = (collectionPath, path9) => {
|
|
4239
4239
|
const collectionPathParts = collectionPath.split("/");
|
|
4240
|
-
const pathParts =
|
|
4240
|
+
const pathParts = path9.split("/");
|
|
4241
4241
|
const strippedPathParts = pathParts.slice(collectionPathParts.length);
|
|
4242
4242
|
return strippedPathParts.join("/");
|
|
4243
4243
|
};
|
|
@@ -4293,13 +4293,13 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
|
|
|
4293
4293
|
SUBLEVEL_OPTIONS
|
|
4294
4294
|
);
|
|
4295
4295
|
let folderSortingIdx = 0;
|
|
4296
|
-
for (const
|
|
4296
|
+
for (const path9 of Array.from(folder).sort()) {
|
|
4297
4297
|
for (const [sort] of Object.entries(indexDefinitions)) {
|
|
4298
4298
|
const indexSublevel = folderCollectionSublevel.sublevel(
|
|
4299
4299
|
sort,
|
|
4300
4300
|
SUBLEVEL_OPTIONS
|
|
4301
4301
|
);
|
|
4302
|
-
const subFolderKey = sha.hex(
|
|
4302
|
+
const subFolderKey = sha.hex(path9);
|
|
4303
4303
|
if (sort === DEFAULT_COLLECTION_SORT_KEY) {
|
|
4304
4304
|
result.push({
|
|
4305
4305
|
type: opType,
|
|
@@ -4381,8 +4381,8 @@ var makeRefOpsForDocument = (filepath, collection, references, data, opType, lev
|
|
|
4381
4381
|
SUBLEVEL_OPTIONS
|
|
4382
4382
|
);
|
|
4383
4383
|
const references2 = {};
|
|
4384
|
-
for (const
|
|
4385
|
-
const ref = JSONPath({ path:
|
|
4384
|
+
for (const path9 of referencePaths) {
|
|
4385
|
+
const ref = JSONPath({ path: path9, json: data });
|
|
4386
4386
|
if (!ref) {
|
|
4387
4387
|
continue;
|
|
4388
4388
|
}
|
|
@@ -4392,24 +4392,24 @@ var makeRefOpsForDocument = (filepath, collection, references, data, opType, lev
|
|
|
4392
4392
|
continue;
|
|
4393
4393
|
}
|
|
4394
4394
|
if (references2[r]) {
|
|
4395
|
-
references2[r].push(
|
|
4395
|
+
references2[r].push(path9);
|
|
4396
4396
|
} else {
|
|
4397
|
-
references2[r] = [
|
|
4397
|
+
references2[r] = [path9];
|
|
4398
4398
|
}
|
|
4399
4399
|
}
|
|
4400
4400
|
} else {
|
|
4401
4401
|
if (references2[ref]) {
|
|
4402
|
-
references2[ref].push(
|
|
4402
|
+
references2[ref].push(path9);
|
|
4403
4403
|
} else {
|
|
4404
|
-
references2[ref] = [
|
|
4404
|
+
references2[ref] = [path9];
|
|
4405
4405
|
}
|
|
4406
4406
|
}
|
|
4407
4407
|
}
|
|
4408
4408
|
for (const ref of Object.keys(references2)) {
|
|
4409
|
-
for (const
|
|
4409
|
+
for (const path9 of references2[ref]) {
|
|
4410
4410
|
result.push({
|
|
4411
4411
|
type: opType,
|
|
4412
|
-
key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${
|
|
4412
|
+
key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path9}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
|
|
4413
4413
|
sublevel: refSublevel,
|
|
4414
4414
|
value: opType === "put" ? {} : void 0
|
|
4415
4415
|
});
|
|
@@ -4676,9 +4676,9 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
|
|
|
4676
4676
|
return value;
|
|
4677
4677
|
}
|
|
4678
4678
|
};
|
|
4679
|
-
var cleanUpSlashes = (
|
|
4680
|
-
if (
|
|
4681
|
-
return `/${
|
|
4679
|
+
var cleanUpSlashes = (path9) => {
|
|
4680
|
+
if (path9) {
|
|
4681
|
+
return `/${path9.replace(/^\/+|\/+$/gm, "")}`;
|
|
4682
4682
|
}
|
|
4683
4683
|
return "";
|
|
4684
4684
|
};
|
|
@@ -4888,17 +4888,17 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
|
|
|
4888
4888
|
throw e;
|
|
4889
4889
|
}
|
|
4890
4890
|
};
|
|
4891
|
-
var updateObjectWithJsonPath = (obj,
|
|
4891
|
+
var updateObjectWithJsonPath = (obj, path9, oldValue, newValue) => {
|
|
4892
4892
|
let updated = false;
|
|
4893
|
-
if (!
|
|
4894
|
-
if (
|
|
4895
|
-
obj[
|
|
4893
|
+
if (!path9.includes(".") && !path9.includes("[")) {
|
|
4894
|
+
if (path9 in obj && obj[path9] === oldValue) {
|
|
4895
|
+
obj[path9] = newValue;
|
|
4896
4896
|
updated = true;
|
|
4897
4897
|
}
|
|
4898
4898
|
return { object: obj, updated };
|
|
4899
4899
|
}
|
|
4900
|
-
const parentPath =
|
|
4901
|
-
const keyToUpdate =
|
|
4900
|
+
const parentPath = path9.replace(/\.[^.\[\]]+$/, "");
|
|
4901
|
+
const keyToUpdate = path9.match(/[^.\[\]]+$/)[0];
|
|
4902
4902
|
const parents = JSONPath2({
|
|
4903
4903
|
path: parentPath,
|
|
4904
4904
|
json: obj,
|
|
@@ -5322,10 +5322,10 @@ var Resolver = class {
|
|
|
5322
5322
|
)) {
|
|
5323
5323
|
let docWithRef = await this.getRaw(pathToDocWithRef);
|
|
5324
5324
|
let hasUpdate = false;
|
|
5325
|
-
for (const
|
|
5325
|
+
for (const path9 of referencePaths) {
|
|
5326
5326
|
const { object: object2, updated } = updateObjectWithJsonPath(
|
|
5327
5327
|
docWithRef,
|
|
5328
|
-
|
|
5328
|
+
path9,
|
|
5329
5329
|
realPath,
|
|
5330
5330
|
newRealPath
|
|
5331
5331
|
);
|
|
@@ -5390,10 +5390,10 @@ var Resolver = class {
|
|
|
5390
5390
|
)) {
|
|
5391
5391
|
let refDoc = await this.getRaw(pathToDocWithRef);
|
|
5392
5392
|
let hasUpdate = false;
|
|
5393
|
-
for (const
|
|
5393
|
+
for (const path9 of referencePaths) {
|
|
5394
5394
|
const { object: object2, updated } = updateObjectWithJsonPath(
|
|
5395
5395
|
refDoc,
|
|
5396
|
-
|
|
5396
|
+
path9,
|
|
5397
5397
|
realPath,
|
|
5398
5398
|
null
|
|
5399
5399
|
);
|
|
@@ -5660,7 +5660,7 @@ var Resolver = class {
|
|
|
5660
5660
|
first: -1
|
|
5661
5661
|
},
|
|
5662
5662
|
collection: referencedCollection,
|
|
5663
|
-
hydrator: (
|
|
5663
|
+
hydrator: (path9) => path9
|
|
5664
5664
|
// just return the path
|
|
5665
5665
|
}
|
|
5666
5666
|
);
|
|
@@ -6101,8 +6101,8 @@ async function handleUpdatePassword({
|
|
|
6101
6101
|
// src/error.ts
|
|
6102
6102
|
import { GraphQLError as GraphQLError3 } from "graphql";
|
|
6103
6103
|
var NotFoundError = class extends GraphQLError3 {
|
|
6104
|
-
constructor(message, nodes, source, positions,
|
|
6105
|
-
super(message, nodes, source, positions,
|
|
6104
|
+
constructor(message, nodes, source, positions, path9, originalError, extensions) {
|
|
6105
|
+
super(message, nodes, source, positions, path9, originalError, extensions);
|
|
6106
6106
|
this.name = "NotFoundError";
|
|
6107
6107
|
}
|
|
6108
6108
|
};
|
|
@@ -7364,21 +7364,21 @@ var Database = class {
|
|
|
7364
7364
|
edges,
|
|
7365
7365
|
async ({
|
|
7366
7366
|
cursor,
|
|
7367
|
-
path:
|
|
7367
|
+
path: path9,
|
|
7368
7368
|
value
|
|
7369
7369
|
}) => {
|
|
7370
7370
|
try {
|
|
7371
|
-
const node = await hydrator(
|
|
7371
|
+
const node = await hydrator(path9, value);
|
|
7372
7372
|
return {
|
|
7373
7373
|
node,
|
|
7374
7374
|
cursor: btoa(cursor)
|
|
7375
7375
|
};
|
|
7376
7376
|
} catch (error) {
|
|
7377
7377
|
console.log(error);
|
|
7378
|
-
if (error instanceof Error && (!
|
|
7378
|
+
if (error instanceof Error && (!path9.includes(".tina/__generated__/_graphql.json") || !path9.includes("tina/__generated__/_graphql.json"))) {
|
|
7379
7379
|
throw new TinaQueryError({
|
|
7380
7380
|
originalError: error,
|
|
7381
|
-
file:
|
|
7381
|
+
file: path9,
|
|
7382
7382
|
collection: collection.name
|
|
7383
7383
|
});
|
|
7384
7384
|
}
|
|
@@ -7666,8 +7666,8 @@ var Database = class {
|
|
|
7666
7666
|
return { warnings };
|
|
7667
7667
|
};
|
|
7668
7668
|
};
|
|
7669
|
-
var hashPasswordVisitor = async (node,
|
|
7670
|
-
const passwordValuePath = [...
|
|
7669
|
+
var hashPasswordVisitor = async (node, path9) => {
|
|
7670
|
+
const passwordValuePath = [...path9, "value"];
|
|
7671
7671
|
const plaintextPassword = get(node, passwordValuePath);
|
|
7672
7672
|
if (plaintextPassword) {
|
|
7673
7673
|
set2(
|
|
@@ -7677,10 +7677,10 @@ var hashPasswordVisitor = async (node, path8) => {
|
|
|
7677
7677
|
);
|
|
7678
7678
|
}
|
|
7679
7679
|
};
|
|
7680
|
-
var visitNodes = async (node,
|
|
7681
|
-
const [currentLevel, ...remainingLevels] =
|
|
7680
|
+
var visitNodes = async (node, path9, callback) => {
|
|
7681
|
+
const [currentLevel, ...remainingLevels] = path9;
|
|
7682
7682
|
if (!remainingLevels?.length) {
|
|
7683
|
-
return callback(node,
|
|
7683
|
+
return callback(node, path9);
|
|
7684
7684
|
}
|
|
7685
7685
|
if (Array.isArray(node[currentLevel])) {
|
|
7686
7686
|
for (const item of node[currentLevel]) {
|
|
@@ -8009,10 +8009,20 @@ var shaExists = async ({
|
|
|
8009
8009
|
}) => git.readCommit({ fs: fs4, dir, oid: sha3 }).then(() => true).catch(() => false);
|
|
8010
8010
|
|
|
8011
8011
|
// src/database/bridge/filesystem.ts
|
|
8012
|
-
import fs2 from "fs-extra";
|
|
8013
|
-
import fg from "fast-glob";
|
|
8014
8012
|
import path7 from "path";
|
|
8013
|
+
import fg from "fast-glob";
|
|
8014
|
+
import fs2 from "fs-extra";
|
|
8015
8015
|
import normalize from "normalize-path";
|
|
8016
|
+
function assertWithinBase(filepath, baseDir) {
|
|
8017
|
+
const resolvedBase = path7.resolve(baseDir);
|
|
8018
|
+
const resolved = path7.resolve(path7.join(baseDir, filepath));
|
|
8019
|
+
if (resolved !== resolvedBase && !resolved.startsWith(resolvedBase + path7.sep)) {
|
|
8020
|
+
throw new Error(
|
|
8021
|
+
`Path traversal detected: "${filepath}" escapes the base directory`
|
|
8022
|
+
);
|
|
8023
|
+
}
|
|
8024
|
+
return resolved;
|
|
8025
|
+
}
|
|
8016
8026
|
var FilesystemBridge = class {
|
|
8017
8027
|
rootPath;
|
|
8018
8028
|
outputPath;
|
|
@@ -8021,7 +8031,7 @@ var FilesystemBridge = class {
|
|
|
8021
8031
|
this.outputPath = outputPath ? path7.resolve(outputPath) : this.rootPath;
|
|
8022
8032
|
}
|
|
8023
8033
|
async glob(pattern, extension) {
|
|
8024
|
-
const basePath =
|
|
8034
|
+
const basePath = assertWithinBase(pattern, this.outputPath);
|
|
8025
8035
|
const items = await fg(
|
|
8026
8036
|
path7.join(basePath, "**", `/*.${extension}`).replace(/\\/g, "/"),
|
|
8027
8037
|
{
|
|
@@ -8035,14 +8045,17 @@ var FilesystemBridge = class {
|
|
|
8035
8045
|
);
|
|
8036
8046
|
}
|
|
8037
8047
|
async delete(filepath) {
|
|
8038
|
-
|
|
8048
|
+
const resolved = assertWithinBase(filepath, this.outputPath);
|
|
8049
|
+
await fs2.remove(resolved);
|
|
8039
8050
|
}
|
|
8040
8051
|
async get(filepath) {
|
|
8041
|
-
|
|
8052
|
+
const resolved = assertWithinBase(filepath, this.outputPath);
|
|
8053
|
+
return (await fs2.readFile(resolved)).toString();
|
|
8042
8054
|
}
|
|
8043
8055
|
async put(filepath, data, basePathOverride) {
|
|
8044
8056
|
const basePath = basePathOverride || this.outputPath;
|
|
8045
|
-
|
|
8057
|
+
const resolved = assertWithinBase(filepath, basePath);
|
|
8058
|
+
await fs2.outputFile(resolved, data);
|
|
8046
8059
|
}
|
|
8047
8060
|
};
|
|
8048
8061
|
var AuditFileSystemBridge = class extends FilesystemBridge {
|
|
@@ -8062,12 +8075,21 @@ var AuditFileSystemBridge = class extends FilesystemBridge {
|
|
|
8062
8075
|
};
|
|
8063
8076
|
|
|
8064
8077
|
// src/database/bridge/isomorphic.ts
|
|
8065
|
-
import
|
|
8078
|
+
import path8, { dirname } from "path";
|
|
8066
8079
|
import fs3 from "fs-extra";
|
|
8067
8080
|
import globParent from "glob-parent";
|
|
8068
|
-
import normalize2 from "normalize-path";
|
|
8069
8081
|
import { GraphQLError as GraphQLError6 } from "graphql";
|
|
8070
|
-
import
|
|
8082
|
+
import git2 from "isomorphic-git";
|
|
8083
|
+
import normalize2 from "normalize-path";
|
|
8084
|
+
function assertWithinBase2(filepath, relativePath) {
|
|
8085
|
+
const qualified = relativePath ? `${relativePath}/${filepath}` : filepath;
|
|
8086
|
+
const normalized = path8.normalize(qualified);
|
|
8087
|
+
if (normalized.startsWith("..") || normalized.startsWith("/") || path8.isAbsolute(normalized) || relativePath && normalized !== relativePath && !normalized.startsWith(relativePath + "/")) {
|
|
8088
|
+
throw new Error(
|
|
8089
|
+
`Path traversal detected: "${filepath}" escapes the content root`
|
|
8090
|
+
);
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8071
8093
|
var flat = typeof Array.prototype.flat === "undefined" ? (entries) => entries.reduce((acc, x) => acc.concat(x), []) : (entries) => entries.flat();
|
|
8072
8094
|
var toUint8Array = (buf) => {
|
|
8073
8095
|
const ab = new ArrayBuffer(buf.length);
|
|
@@ -8146,7 +8168,7 @@ var IsomorphicBridge = class {
|
|
|
8146
8168
|
async listEntries({
|
|
8147
8169
|
pattern,
|
|
8148
8170
|
entry,
|
|
8149
|
-
path:
|
|
8171
|
+
path: path9,
|
|
8150
8172
|
results
|
|
8151
8173
|
}) {
|
|
8152
8174
|
const treeResult = await git2.readTree({
|
|
@@ -8156,7 +8178,7 @@ var IsomorphicBridge = class {
|
|
|
8156
8178
|
});
|
|
8157
8179
|
const children = [];
|
|
8158
8180
|
for (const childEntry of treeResult.tree) {
|
|
8159
|
-
const childPath =
|
|
8181
|
+
const childPath = path9 ? `${path9}/${childEntry.path}` : childEntry.path;
|
|
8160
8182
|
if (childEntry.type === "tree") {
|
|
8161
8183
|
children.push(childEntry);
|
|
8162
8184
|
} else {
|
|
@@ -8166,7 +8188,7 @@ var IsomorphicBridge = class {
|
|
|
8166
8188
|
}
|
|
8167
8189
|
}
|
|
8168
8190
|
for (const childEntry of children) {
|
|
8169
|
-
const childPath =
|
|
8191
|
+
const childPath = path9 ? `${path9}/${childEntry.path}` : childEntry.path;
|
|
8170
8192
|
await this.listEntries({
|
|
8171
8193
|
pattern,
|
|
8172
8194
|
entry: childEntry,
|
|
@@ -8184,17 +8206,17 @@ var IsomorphicBridge = class {
|
|
|
8184
8206
|
* @param ref - ref to resolve path entries for
|
|
8185
8207
|
* @private
|
|
8186
8208
|
*/
|
|
8187
|
-
async resolvePathEntries(
|
|
8188
|
-
let pathParts =
|
|
8209
|
+
async resolvePathEntries(path9, ref) {
|
|
8210
|
+
let pathParts = path9.split("/");
|
|
8189
8211
|
const result = await git2.walk({
|
|
8190
8212
|
...this.isomorphicConfig,
|
|
8191
8213
|
map: async (filepath, [head]) => {
|
|
8192
8214
|
if (head._fullpath === ".") {
|
|
8193
8215
|
return head;
|
|
8194
8216
|
}
|
|
8195
|
-
if (
|
|
8196
|
-
if (dirname(
|
|
8197
|
-
if (
|
|
8217
|
+
if (path9.startsWith(filepath)) {
|
|
8218
|
+
if (dirname(path9) === dirname(filepath)) {
|
|
8219
|
+
if (path9 === filepath) {
|
|
8198
8220
|
return head;
|
|
8199
8221
|
}
|
|
8200
8222
|
} else {
|
|
@@ -8225,7 +8247,7 @@ var IsomorphicBridge = class {
|
|
|
8225
8247
|
* @param pathParts - parent path parts
|
|
8226
8248
|
* @private
|
|
8227
8249
|
*/
|
|
8228
|
-
async updateTreeHierarchy(existingOid, updatedOid,
|
|
8250
|
+
async updateTreeHierarchy(existingOid, updatedOid, path9, type, pathEntries, pathParts) {
|
|
8229
8251
|
const lastIdx = pathEntries.length - 1;
|
|
8230
8252
|
const parentEntry = pathEntries[lastIdx];
|
|
8231
8253
|
const parentPath = pathParts[lastIdx];
|
|
@@ -8240,7 +8262,7 @@ var IsomorphicBridge = class {
|
|
|
8240
8262
|
cache: this.cache
|
|
8241
8263
|
});
|
|
8242
8264
|
tree = existingOid ? treeResult.tree.map((entry) => {
|
|
8243
|
-
if (entry.path ===
|
|
8265
|
+
if (entry.path === path9) {
|
|
8244
8266
|
entry.oid = updatedOid;
|
|
8245
8267
|
}
|
|
8246
8268
|
return entry;
|
|
@@ -8249,7 +8271,7 @@ var IsomorphicBridge = class {
|
|
|
8249
8271
|
{
|
|
8250
8272
|
oid: updatedOid,
|
|
8251
8273
|
type,
|
|
8252
|
-
path:
|
|
8274
|
+
path: path9,
|
|
8253
8275
|
mode
|
|
8254
8276
|
}
|
|
8255
8277
|
];
|
|
@@ -8258,7 +8280,7 @@ var IsomorphicBridge = class {
|
|
|
8258
8280
|
{
|
|
8259
8281
|
oid: updatedOid,
|
|
8260
8282
|
type,
|
|
8261
|
-
path:
|
|
8283
|
+
path: path9,
|
|
8262
8284
|
mode
|
|
8263
8285
|
}
|
|
8264
8286
|
];
|
|
@@ -8334,6 +8356,7 @@ var IsomorphicBridge = class {
|
|
|
8334
8356
|
return ref;
|
|
8335
8357
|
}
|
|
8336
8358
|
async glob(pattern, extension) {
|
|
8359
|
+
assertWithinBase2(pattern, this.relativePath);
|
|
8337
8360
|
const ref = await this.getRef();
|
|
8338
8361
|
const parent = globParent(this.qualifyPath(pattern));
|
|
8339
8362
|
const { pathParts, pathEntries } = await this.resolvePathEntries(
|
|
@@ -8367,9 +8390,10 @@ var IsomorphicBridge = class {
|
|
|
8367
8390
|
path: parentPath,
|
|
8368
8391
|
results
|
|
8369
8392
|
});
|
|
8370
|
-
return results.map((
|
|
8393
|
+
return results.map((path9) => this.unqualifyPath(path9)).filter((path9) => path9.endsWith(extension));
|
|
8371
8394
|
}
|
|
8372
8395
|
async delete(filepath) {
|
|
8396
|
+
assertWithinBase2(filepath, this.relativePath);
|
|
8373
8397
|
const ref = await this.getRef();
|
|
8374
8398
|
const { pathParts, pathEntries } = await this.resolvePathEntries(
|
|
8375
8399
|
this.qualifyPath(filepath),
|
|
@@ -8441,6 +8465,7 @@ var IsomorphicBridge = class {
|
|
|
8441
8465
|
return this.relativePath ? filepath.slice(this.relativePath.length + 1) : filepath;
|
|
8442
8466
|
}
|
|
8443
8467
|
async get(filepath) {
|
|
8468
|
+
assertWithinBase2(filepath, this.relativePath);
|
|
8444
8469
|
const ref = await this.getRef();
|
|
8445
8470
|
const oid = await git2.resolveRef({
|
|
8446
8471
|
...this.isomorphicConfig,
|
|
@@ -8455,6 +8480,7 @@ var IsomorphicBridge = class {
|
|
|
8455
8480
|
return Buffer.from(blob).toString("utf8");
|
|
8456
8481
|
}
|
|
8457
8482
|
async put(filepath, data) {
|
|
8483
|
+
assertWithinBase2(filepath, this.relativePath);
|
|
8458
8484
|
const ref = await this.getRef();
|
|
8459
8485
|
const { pathParts, pathEntries } = await this.resolvePathEntries(
|
|
8460
8486
|
this.qualifyPath(filepath),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinacms/graphql",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.3",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"files": [
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"normalize-path": "^3.0.0",
|
|
44
44
|
"readable-stream": "^4.7.0",
|
|
45
45
|
"yup": "^1.6.1",
|
|
46
|
-
"@tinacms/
|
|
47
|
-
"@tinacms/
|
|
46
|
+
"@tinacms/mdx": "2.0.6",
|
|
47
|
+
"@tinacms/schema-tools": "2.6.0"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"registry": "https://registry.npmjs.org"
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
"vite": "^4.5.9",
|
|
72
72
|
"vitest": "^0.32.4",
|
|
73
73
|
"zod": "^3.24.2",
|
|
74
|
-
"@tinacms/
|
|
75
|
-
"@tinacms/
|
|
74
|
+
"@tinacms/scripts": "1.5.0",
|
|
75
|
+
"@tinacms/schema-tools": "2.6.0"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"types": "pnpm tsc",
|