@o2b/meta 1.0.0-dev.3 → 1.0.0-dev.5

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/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -28,7 +29,7 @@ var import_cac = __toESM(require("cac"));
28
29
  // package.json
29
30
  var package_default = {
30
31
  name: "@o2b/meta",
31
- version: "1.0.0-dev.1",
32
+ version: "1.0.0-dev.4",
32
33
  description: "filetree generator for o2b",
33
34
  main: "./dist/index.js",
34
35
  module: "./dist/index.mjs",
@@ -61,14 +62,17 @@ var package_default = {
61
62
  "@vitest/ui": "^4.0.16",
62
63
  tsup: "^8.5.1",
63
64
  typescript: "^5.9.3",
64
- vitest: "^4.0.16"
65
+ vitest: "^4.0.16",
66
+ zod: "^3.25.76"
65
67
  },
66
68
  dependencies: {
67
69
  cac: "^6.7.14",
68
70
  "gray-matter": "^4.0.3",
69
71
  ignore: "^7.0.5",
70
- lilconfig: "^3.1.3",
71
- zod: "^4.3.5"
72
+ lilconfig: "^3.1.3"
73
+ },
74
+ peerDependencies: {
75
+ zod: "^3.23.8"
72
76
  }
73
77
  };
74
78
 
@@ -113,12 +117,50 @@ var import_ignore = __toESM(require("ignore"));
113
117
  // src/utils/path.ts
114
118
  var import_node_fs2 = require("fs");
115
119
  var import_node_path2 = require("path");
120
+
121
+ // src/types/filetree.ts
122
+ var import_zod2 = __toESM(require("zod"));
123
+
124
+ // src/types/path.ts
125
+ var import_zod = __toESM(require("zod"));
126
+ var absPath = import_zod.default.string().brand();
127
+ var relPath = import_zod.default.string().brand();
128
+
129
+ // src/types/filetree.ts
130
+ var frontmatter = import_zod2.default.object({
131
+ title: import_zod2.default.string(),
132
+ description: import_zod2.default.string(),
133
+ last_modified: import_zod2.default.string()
134
+ });
135
+ function createFileTreeSchema(path) {
136
+ const baseNode = import_zod2.default.object({
137
+ path,
138
+ name: import_zod2.default.string()
139
+ });
140
+ const fileNode = baseNode.extend({
141
+ type: import_zod2.default.literal("file"),
142
+ frontmatter
143
+ });
144
+ const dirNode = baseNode.extend({
145
+ type: import_zod2.default.literal("dir"),
146
+ files: import_zod2.default.array(fileNode),
147
+ dirs: import_zod2.default.lazy(() => dirNode.array())
148
+ });
149
+ const fileTree2 = import_zod2.default.union([fileNode, dirNode]);
150
+ return { fileTree: fileTree2, dirNode, fileNode };
151
+ }
152
+ var defaultSchema = createFileTreeSchema(relPath);
153
+ var jsonSchema = createFileTreeSchema(import_zod2.default.string());
154
+ var fileTree = defaultSchema.fileTree;
155
+ var jsonFileTree = jsonSchema.fileTree;
156
+
157
+ // src/utils/path.ts
116
158
  function toAbsPath(path) {
117
159
  if (!(0, import_node_path2.isAbsolute)(path)) path = (0, import_node_path2.resolve)(path);
118
- return path;
160
+ return absPath.parse(path);
119
161
  }
120
162
  function toRelPath(from, to) {
121
- return (0, import_node_path2.relative)(from, to);
163
+ return relPath.parse((0, import_node_path2.relative)(from, to));
122
164
  }
123
165
  function isObsidianDirectory(path) {
124
166
  const stat = (0, import_node_fs2.lstatSync)(path);
@@ -146,8 +188,8 @@ var VaultIgnorer = class {
146
188
  if (path === this.rootPath) return false;
147
189
  if (!(0, import_node_fs3.existsSync)(path)) throw new Error("somethings wrong!");
148
190
  const stat = (0, import_node_fs3.lstatSync)(path);
149
- const relPath = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
150
- return this.ign.ignores(relPath);
191
+ const relPath2 = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
192
+ return this.ign.ignores(relPath2);
151
193
  }
152
194
  };
153
195
 
@@ -207,9 +249,9 @@ function runO2B(config) {
207
249
  if (!isObsidianDirectory(srcPath)) throw new Error("Not a obsidian vault");
208
250
  const ign = new VaultIgnorer(srcPath);
209
251
  if (ignore2) ign.load();
210
- const fileTree = scan(srcPath, ign);
211
- if (fileTree === null) throw new Error("No content in vault");
212
- mirror(fileTree, srcPath, destPath);
252
+ const fileTree2 = scan(srcPath, ign);
253
+ if (fileTree2 === null) throw new Error("No content in vault");
254
+ mirror(fileTree2, srcPath, destPath);
213
255
  }
214
256
 
215
257
  // src/cli.ts
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../package.json","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/runO2B.ts"],"sourcesContent":["import cac from \"cac\";\nimport pkg from \"../package.json\";\nimport runO2B from \"./runO2B\";\nimport { toAbsPath } from \"./utils\";\n\nconst cli = cac(\"o2b-meta\");\n\ncli\n .command(\"<srcPath>\", \"target vault file\")\n .option(\"--destPath [destPath]\", \"dist\", {\n default: \"./o2b\",\n })\n .option(\"--ignore\", \"read the .o2bIgnore if exists\", {\n default: true,\n })\n .option(\"--sync\", \"synchro\", {\n default: true,\n })\n .action((srcPath, option) => {\n const { destPath, ignore, sync } = option;\n\n const startTime = performance.now();\n\n if (sync) {\n runO2B({\n srcPath: toAbsPath(srcPath),\n destPath: toAbsPath(destPath),\n ignore,\n });\n }\n\n const endTime = performance.now();\n const duration = (endTime - startTime).toFixed(2); // 소수점 2자리까지\n\n console.log(`\\n✅ Build Success!`);\n console.log(` Time: ${duration}ms`);\n // console.log(` Dest: ${config.destPath}\\n`);\n });\n\ncli.help();\ncli.version(pkg.version);\n\n// production에 대한 에러처리\ncli.parse();\n","{\n \"name\": \"@o2b/meta\",\n \"version\": \"1.0.0-dev.1\",\n \"description\": \"filetree generator for o2b\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"o2b-meta\": \"./dist/cli.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\"\n },\n \"keywords\": [],\n \"author\": \"goonco\",\n \"license\": \"ISC\",\n \"type\": \"commonjs\",\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.3.10\",\n \"@types/node\": \"^25.0.3\",\n \"@vitest/ui\": \"^4.0.16\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.16\"\n },\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"gray-matter\": \"^4.0.3\",\n \"ignore\": \"^7.0.5\",\n \"lilconfig\": \"^3.1.3\",\n \"zod\": \"^4.3.5\"\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { AbsPath, RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n if (!isAbsolute(path)) path = resolve(path);\n return path as AbsPath;\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n return relative(from, to) as RelPath;\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n const stat = lstatSync(path);\n\n if (!stat.isDirectory()) return false;\n\n const obsMetaDir = readdirSync(path, { withFileTypes: true })\n .filter((node) => node.isDirectory())\n .filter((node) => node.name === \".obsidian\");\n\n if (obsMetaDir.length !== 1) return false;\n\n return true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function runO2B(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":"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","names":["filetree","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","ignore","matter","ignore","cac","ignore"]}
1
+ {"version":3,"sources":["../src/cli.ts","../package.json","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/types/filetree.ts","../src/types/path.ts","../src/runO2B.ts"],"sourcesContent":["import cac from \"cac\";\nimport pkg from \"../package.json\";\nimport runO2B from \"./runO2B\";\nimport { toAbsPath } from \"./utils\";\n\nconst cli = cac(\"o2b-meta\");\n\ncli\n .command(\"<srcPath>\", \"target vault file\")\n .option(\"--destPath [destPath]\", \"dist\", {\n default: \"./o2b\",\n })\n .option(\"--ignore\", \"read the .o2bIgnore if exists\", {\n default: true,\n })\n .option(\"--sync\", \"synchro\", {\n default: true,\n })\n .action((srcPath, option) => {\n const { destPath, ignore, sync } = option;\n\n const startTime = performance.now();\n\n if (sync) {\n runO2B({\n srcPath: toAbsPath(srcPath),\n destPath: toAbsPath(destPath),\n ignore,\n });\n }\n\n const endTime = performance.now();\n const duration = (endTime - startTime).toFixed(2); // 소수점 2자리까지\n\n console.log(`\\n✅ Build Success!`);\n console.log(` Time: ${duration}ms`);\n // console.log(` Dest: ${config.destPath}\\n`);\n });\n\ncli.help();\ncli.version(pkg.version);\n\n// production에 대한 에러처리\ncli.parse();\n","{\n \"name\": \"@o2b/meta\",\n \"version\": \"1.0.0-dev.4\",\n \"description\": \"filetree generator for o2b\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"o2b-meta\": \"./dist/cli.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\"\n },\n \"keywords\": [],\n \"author\": \"goonco\",\n \"license\": \"ISC\",\n \"type\": \"commonjs\",\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.3.10\",\n \"@types/node\": \"^25.0.3\",\n \"@vitest/ui\": \"^4.0.16\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.16\",\n \"zod\": \"^3.25.76\"\n },\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"gray-matter\": \"^4.0.3\",\n \"ignore\": \"^7.0.5\",\n \"lilconfig\": \"^3.1.3\"\n },\n \"peerDependencies\": {\n \"zod\": \"^3.23.8\"\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport { absPath, relPath, type AbsPath, type RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n if (!isAbsolute(path)) path = resolve(path);\n return absPath.parse(path);\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n return relPath.parse(relative(from, to));\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n const stat = lstatSync(path);\n\n if (!stat.isDirectory()) return false;\n\n const obsMetaDir = readdirSync(path, { withFileTypes: true })\n .filter((node) => node.isDirectory())\n .filter((node) => node.name === \".obsidian\");\n\n if (obsMetaDir.length !== 1) return false;\n\n return true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import z from \"zod\";\nimport { relPath, type RelPath } from \"./path\";\n\nconst frontmatter = z.object({\n title: z.string(),\n description: z.string(),\n last_modified: z.string(),\n});\n\nfunction createFileTreeSchema<P extends typeof relPath | z.ZodString>(path: P) {\n type BaseNode = z.infer<typeof baseNode>;\n const baseNode = z.object({\n path,\n name: z.string(),\n });\n\n type FileNodeOutput = z.infer<typeof fileNode>;\n type FileNodeInput = z.input<typeof fileNode>;\n const fileNode = baseNode.extend({\n type: z.literal(\"file\"),\n frontmatter: frontmatter,\n });\n\n // https://v3.zod.dev/?id=recursive-types\n type DirNodeOutput = BaseNode & {\n type: \"dir\";\n files: FileNodeOutput[];\n dirs: DirNodeOutput[];\n };\n type DirNodeInput = z.input<typeof baseNode> & {\n type: \"dir\";\n files: FileNodeInput[];\n dirs: DirNodeInput[];\n };\n\n const dirNode: z.ZodType<DirNodeOutput, z.ZodTypeDef, DirNodeInput> =\n baseNode.extend({\n type: z.literal(\"dir\"),\n files: z.array(fileNode),\n dirs: z.lazy(() => dirNode.array()),\n });\n\n const fileTree = z.union([fileNode, dirNode]);\n\n return { fileTree, dirNode, fileNode };\n}\n\nconst defaultSchema = createFileTreeSchema(relPath);\nconst jsonSchema = createFileTreeSchema(z.string());\n\nexport const fileTree = defaultSchema.fileTree;\nexport const jsonFileTree = jsonSchema.fileTree;\n\nexport type FileTree = z.infer<typeof defaultSchema.fileTree>;\nexport type FileNode = z.infer<typeof defaultSchema.fileNode>;\nexport type DirNode = z.infer<typeof defaultSchema.dirNode>;\nexport type Frontmatter = z.infer<typeof frontmatter>;\n","import z from \"zod\";\n\ntype AbsPath = z.infer<typeof absPath>;\nconst absPath = z.string().brand<\"absPath\">();\n\ntype RelPath = z.infer<typeof relPath>;\nconst relPath = z.string().brand<\"relpath\">();\n\nexport { type AbsPath, type RelPath, absPath, relPath };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function runO2B(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAAgB;;;ACAhB;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,OAAS;AAAA,EACT,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,KAAO;AAAA,IACL,YAAY;AAAA,EACd;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,YAAY;AAAA,EACd;AAAA,EACA,UAAY,CAAC;AAAA,EACb,QAAU;AAAA,EACV,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,iBAAmB;AAAA,IACjB,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,QAAU;AAAA,IACV,KAAO;AAAA,EACT;AAAA,EACA,cAAgB;AAAA,IACd,KAAO;AAAA,IACP,eAAe;AAAA,IACf,QAAU;AAAA,IACV,WAAa;AAAA,EACf;AAAA,EACA,kBAAoB;AAAA,IAClB,KAAO;AAAA,EACT;AACF;;;AC/CA,qBAAmE;AACnE,uBAAqB;AAGd,SAAS,OACf,UACA,SACA,UACC;AACD,WAAS,IAAIA,WAAoB;AAChC,UAAM,WAAO,uBAAK,SAASA,UAAS,IAAI;AACxC,UAAM,SAAK,uBAAK,UAAUA,UAAS,IAAI;AAEvC,QAAIA,UAAS,SAAS,OAAO;AAC5B,UAAI,KAAC,2BAAW,EAAE,EAAG,+BAAU,IAAI,EAAE,WAAW,KAAK,CAAC;AAEtD,MAAAA,UAAS,MAAM,QAAQ,CAAC,SAAS;AAChC,YAAI,IAAI;AAAA,MACT,CAAC;AAED,MAAAA,UAAS,KAAK,QAAQ,CAAC,QAAQ;AAC9B,YAAI,GAAG;AAAA,MACR,CAAC;AAAA,IACF;AAEA,QAAIA,UAAS,SAAS,QAAQ;AAC7B,uCAAa,MAAM,EAAE;AAAA,IACtB;AAAA,EACD;AAEA,MAAI,QAAQ;AACZ,mBAAiB,UAAU,QAAQ;AACpC;AAEA,SAAS,iBAAiB,UAAoB,UAAmB;AAChE,QAAM,mBAAe,uBAAK,UAAU,kBAAkB;AACtD,oCAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AACvE;;;ACrCA,IAAAC,kBAAqD;AACrD,IAAAC,oBAA+B;AAC/B,yBAAmB;;;ACFnB,IAAAC,kBAAoD;AACpD,IAAAC,oBAAqB;AACrB,oBAAoC;;;ACFpC,IAAAC,kBAAuC;AACvC,IAAAC,oBAA8C;;;ACD9C,IAAAC,cAAc;;;ACAd,iBAAc;AAGd,IAAM,UAAU,WAAAC,QAAE,OAAO,EAAE,MAAiB;AAG5C,IAAM,UAAU,WAAAA,QAAE,OAAO,EAAE,MAAiB;;;ADH5C,IAAM,cAAc,YAAAC,QAAE,OAAO;AAAA,EAC3B,OAAO,YAAAA,QAAE,OAAO;AAAA,EAChB,aAAa,YAAAA,QAAE,OAAO;AAAA,EACtB,eAAe,YAAAA,QAAE,OAAO;AAC1B,CAAC;AAED,SAAS,qBAA6D,MAAS;AAE7E,QAAM,WAAW,YAAAA,QAAE,OAAO;AAAA,IACxB;AAAA,IACA,MAAM,YAAAA,QAAE,OAAO;AAAA,EACjB,CAAC;AAID,QAAM,WAAW,SAAS,OAAO;AAAA,IAC/B,MAAM,YAAAA,QAAE,QAAQ,MAAM;AAAA,IACtB;AAAA,EACF,CAAC;AAcD,QAAM,UACJ,SAAS,OAAO;AAAA,IACd,MAAM,YAAAA,QAAE,QAAQ,KAAK;AAAA,IACrB,OAAO,YAAAA,QAAE,MAAM,QAAQ;AAAA,IACvB,MAAM,YAAAA,QAAE,KAAK,MAAM,QAAQ,MAAM,CAAC;AAAA,EACpC,CAAC;AAEH,QAAMC,YAAW,YAAAD,QAAE,MAAM,CAAC,UAAU,OAAO,CAAC;AAE5C,SAAO,EAAE,UAAAC,WAAU,SAAS,SAAS;AACvC;AAEA,IAAM,gBAAgB,qBAAqB,OAAO;AAClD,IAAM,aAAa,qBAAqB,YAAAD,QAAE,OAAO,CAAC;AAE3C,IAAM,WAAW,cAAc;AAC/B,IAAM,eAAe,WAAW;;;AD/CvC,SAAS,UAAU,MAAuB;AACxC,MAAI,KAAC,8BAAW,IAAI,EAAG,YAAO,2BAAQ,IAAI;AAC1C,SAAO,QAAQ,MAAM,IAAI;AAC3B;AAEA,SAAS,UAAU,MAAe,IAAsB;AACtD,SAAO,QAAQ,UAAM,4BAAS,MAAM,EAAE,CAAC;AACzC;AAEA,SAAS,oBAAoB,MAAe;AAC1C,QAAM,WAAO,2BAAU,IAAI;AAE3B,MAAI,CAAC,KAAK,YAAY,EAAG,QAAO;AAEhC,QAAM,iBAAa,6BAAY,MAAM,EAAE,eAAe,KAAK,CAAC,EACzD,OAAO,CAAC,SAAS,KAAK,YAAY,CAAC,EACnC,OAAO,CAAC,SAAS,KAAK,SAAS,WAAW;AAE7C,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,SAAO;AACT;;;ADnBO,IAAM,eAAN,MAAmB;AAAA,EACjB;AAAA,EACA;AAAA,EAER,YAAY,UAAmB;AAC9B,SAAK,WAAW;AAChB,SAAK,UAAM,cAAAE,SAAO;AAElB,SAAK,IAAI,IAAI,CAAC,IAAI,CAAC;AAAA,EACpB;AAAA,EAEO,OAAO;AACb,UAAM,iBAAa,wBAAK,KAAK,UAAU,YAAY;AACnD,YAAI,4BAAW,UAAU;AACxB,WAAK,IAAI,QAAI,8BAAa,UAAU,EAAE,SAAS,CAAC;AAAA,EAClD;AAAA,EAEO,OAAO,MAAwB;AACrC,QAAI,SAAS,KAAK,SAAU,QAAO;AAEnC,QAAI,KAAC,4BAAW,IAAI,EAAG,OAAM,IAAI,MAAM,mBAAmB;AAE1D,UAAM,WAAO,2BAAU,IAAI;AAE3B,UAAMC,WACL,UAAU,KAAK,UAAU,IAAI,KAAK,KAAK,YAAY,IAAI,MAAM;AAE9D,WAAO,KAAK,IAAI,QAAQA,QAAO;AAAA,EAChC;AACD;;;ADvBO,SAAS,KAAK,UAAmB,KAAoC;AAC3E,WAAS,IAAI,MAAgC;AAC5C,QAAI,2BAAK,OAAO,MAAO,QAAO;AAE9B,UAAM,WAAO,2BAAU,IAAI;AAC3B,UAAM,WAAO,4BAAS,IAAI;AAE1B,QAAI,KAAK,YAAY,GAAG;AACvB,YAAM,EAAE,MAAM,MAAM,QAAI,6BAAY,IAAI,EAAE;AAAA,QACzC,CAAC,KAAK,UAAU;AACf,gBAAM,OAAO,IAAI,cAAU,wBAAK,MAAM,KAAK,CAAC,CAAC;AAE7C,eAAI,6BAAM,UAAS,MAAO,KAAI,KAAK,KAAK,IAAI;AAC5C,eAAI,6BAAM,UAAS,OAAQ,KAAI,MAAM,KAAK,IAAI;AAE9C,iBAAO;AAAA,QACR;AAAA,QACA;AAAA,UACC,MAAM,CAAC;AAAA,UACP,OAAO,CAAC;AAAA,QACT;AAAA,MACD;AAEA,aAAO;AAAA,QACN,MAAM,UAAU,UAAU,IAAI;AAAA,QAC9B;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,GAAG;AAC1C,aAAO;AAAA,QACN,MAAM,UAAU,UAAU,IAAI;AAAA,QAC9B;AAAA,QACA,MAAM;AAAA,QACN,aAAa,eAAe,IAAI;AAAA,MACjC;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,QAAQ;AACpB;AAEA,SAAS,eAAe,MAA4B;AACnD,QAAM,EAAE,MAAM,eAAe,QAAI,mBAAAC,aAAO,8BAAa,MAAM,OAAO,CAAC;AACnE,SAAO;AAAA,IACN,WAAO,4BAAS,IAAI,EAAE,QAAQ,SAAS,EAAE;AAAA,IACzC,aAAa;AAAA,IACb,mBAAe,2BAAU,IAAI,EAAE,MAAM,mBAAmB,OAAO;AAAA;AAAA,IAC/D,GAAG;AAAA,EACJ;AACD;;;AK/De,SAAR,OAAwB,QAAgB;AAC7C,QAAM,EAAE,SAAS,UAAU,QAAAC,QAAO,IAAI;AACtC,MAAI,CAAC,oBAAoB,OAAO,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAEzE,QAAM,MAAM,IAAI,aAAa,OAAO;AACpC,MAAIA,QAAQ,KAAI,KAAK;AAErB,QAAMC,YAAW,KAAK,SAAS,GAAG;AAClC,MAAIA,cAAa,KAAM,OAAM,IAAI,MAAM,qBAAqB;AAE5D,SAAOA,WAAU,SAAS,QAAQ;AACpC;;;ARVA,IAAM,UAAM,WAAAC,SAAI,UAAU;AAE1B,IACG,QAAQ,aAAa,mBAAmB,EACxC,OAAO,yBAAyB,QAAQ;AAAA,EACvC,SAAS;AACX,CAAC,EACA,OAAO,YAAY,iCAAiC;AAAA,EACnD,SAAS;AACX,CAAC,EACA,OAAO,UAAU,WAAW;AAAA,EAC3B,SAAS;AACX,CAAC,EACA,OAAO,CAAC,SAAS,WAAW;AAC3B,QAAM,EAAE,UAAU,QAAAC,SAAQ,KAAK,IAAI;AAEnC,QAAM,YAAY,YAAY,IAAI;AAElC,MAAI,MAAM;AACR,WAAO;AAAA,MACL,SAAS,UAAU,OAAO;AAAA,MAC1B,UAAU,UAAU,QAAQ;AAAA,MAC5B,QAAAA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,YAAY,IAAI;AAChC,QAAM,YAAY,UAAU,WAAW,QAAQ,CAAC;AAEhD,UAAQ,IAAI;AAAA,sBAAoB;AAChC,UAAQ,IAAI,YAAY,QAAQ,IAAI;AAEtC,CAAC;AAEH,IAAI,KAAK;AACT,IAAI,QAAQ,gBAAI,OAAO;AAGvB,IAAI,MAAM;","names":["filetree","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","import_zod","z","z","fileTree","ignore","relPath","matter","ignore","fileTree","cac","ignore"]}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import z from 'zod';
2
2
 
3
- type AbsPath = z.infer<typeof AbsPathSchema>;
4
- declare const AbsPathSchema: z.core.$ZodBranded<z.ZodString, "absPath", "out">;
3
+ type AbsPath = z.infer<typeof absPath>;
4
+ declare const absPath: z.ZodBranded<z.ZodString, "absPath">;
5
5
 
6
6
  type Config = {
7
7
  srcPath: AbsPath;
@@ -9,38 +9,157 @@ type Config = {
9
9
  ignore: boolean;
10
10
  };
11
11
 
12
- declare const FileTreeSchema: z.ZodUnion<readonly [z.ZodIntersection<z.ZodObject<{
13
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
12
+ declare const fileTree: z.ZodUnion<[z.ZodObject<{
13
+ path: z.ZodBranded<z.ZodString, "relpath">;
14
14
  name: z.ZodString;
15
- }, z.core.$strip>, z.ZodObject<{
15
+ } & {
16
16
  type: z.ZodLiteral<"file">;
17
17
  frontmatter: z.ZodObject<{
18
18
  title: z.ZodString;
19
- descriptionL: z.ZodString;
19
+ description: z.ZodString;
20
20
  last_modified: z.ZodString;
21
- }, z.core.$strip>;
22
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
23
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
21
+ }, "strip", z.ZodTypeAny, {
22
+ title: string;
23
+ description: string;
24
+ last_modified: string;
25
+ }, {
26
+ title: string;
27
+ description: string;
28
+ last_modified: string;
29
+ }>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ path: string & z.BRAND<"relpath">;
32
+ type: "file";
33
+ name: string;
34
+ frontmatter: {
35
+ title: string;
36
+ description: string;
37
+ last_modified: string;
38
+ };
39
+ }, {
40
+ path: string;
41
+ type: "file";
42
+ name: string;
43
+ frontmatter: {
44
+ title: string;
45
+ description: string;
46
+ last_modified: string;
47
+ };
48
+ }>, z.ZodType<{
49
+ path: string & z.BRAND<"relpath">;
50
+ name: string;
51
+ } & {
52
+ type: "dir";
53
+ files: {
54
+ path: string & z.BRAND<"relpath">;
55
+ type: "file";
56
+ name: string;
57
+ frontmatter: {
58
+ title: string;
59
+ description: string;
60
+ last_modified: string;
61
+ };
62
+ }[];
63
+ dirs: ({
64
+ path: string & z.BRAND<"relpath">;
65
+ name: string;
66
+ } & /*elided*/ any)[];
67
+ }, z.ZodTypeDef, {
68
+ path: string;
69
+ name: string;
70
+ } & {
71
+ type: "dir";
72
+ files: {
73
+ path: string;
74
+ type: "file";
75
+ name: string;
76
+ frontmatter: {
77
+ title: string;
78
+ description: string;
79
+ last_modified: string;
80
+ };
81
+ }[];
82
+ dirs: ({
83
+ path: string;
84
+ name: string;
85
+ } & /*elided*/ any)[];
86
+ }>]>;
87
+ declare const jsonFileTree: z.ZodUnion<[z.ZodObject<{
88
+ path: z.ZodString;
24
89
  name: z.ZodString;
25
- }, z.core.$strip>, z.ZodObject<{
26
- type: z.ZodLiteral<"dir">;
27
- dirs: z.ZodArray<z.ZodIntersection<z.ZodObject<{
28
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
29
- name: z.ZodString;
30
- }, z.core.$strip>, z.ZodObject</*elided*/ any, z.core.$strip>>>;
31
- files: z.ZodArray<z.ZodIntersection<z.ZodObject<{
32
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
33
- name: z.ZodString;
34
- }, z.core.$strip>, z.ZodObject<{
35
- type: z.ZodLiteral<"file">;
36
- frontmatter: z.ZodObject<{
37
- title: z.ZodString;
38
- descriptionL: z.ZodString;
39
- last_modified: z.ZodString;
40
- }, z.core.$strip>;
41
- }, z.core.$strip>>>;
42
- }, z.core.$strip>>]>;
90
+ } & {
91
+ type: z.ZodLiteral<"file">;
92
+ frontmatter: z.ZodObject<{
93
+ title: z.ZodString;
94
+ description: z.ZodString;
95
+ last_modified: z.ZodString;
96
+ }, "strip", z.ZodTypeAny, {
97
+ title: string;
98
+ description: string;
99
+ last_modified: string;
100
+ }, {
101
+ title: string;
102
+ description: string;
103
+ last_modified: string;
104
+ }>;
105
+ }, "strip", z.ZodTypeAny, {
106
+ path: string;
107
+ type: "file";
108
+ name: string;
109
+ frontmatter: {
110
+ title: string;
111
+ description: string;
112
+ last_modified: string;
113
+ };
114
+ }, {
115
+ path: string;
116
+ type: "file";
117
+ name: string;
118
+ frontmatter: {
119
+ title: string;
120
+ description: string;
121
+ last_modified: string;
122
+ };
123
+ }>, z.ZodType<{
124
+ path: string;
125
+ name: string;
126
+ } & {
127
+ type: "dir";
128
+ files: {
129
+ path: string;
130
+ type: "file";
131
+ name: string;
132
+ frontmatter: {
133
+ title: string;
134
+ description: string;
135
+ last_modified: string;
136
+ };
137
+ }[];
138
+ dirs: ({
139
+ path: string;
140
+ name: string;
141
+ } & /*elided*/ any)[];
142
+ }, z.ZodTypeDef, {
143
+ path: string;
144
+ name: string;
145
+ } & {
146
+ type: "dir";
147
+ files: {
148
+ path: string;
149
+ type: "file";
150
+ name: string;
151
+ frontmatter: {
152
+ title: string;
153
+ description: string;
154
+ last_modified: string;
155
+ };
156
+ }[];
157
+ dirs: ({
158
+ path: string;
159
+ name: string;
160
+ } & /*elided*/ any)[];
161
+ }>]>;
43
162
 
44
163
  declare function runO2B(config: Config): void;
45
164
 
46
- export { FileTreeSchema, runO2B as default };
165
+ export { runO2B as default, fileTree, jsonFileTree };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import z from 'zod';
2
2
 
3
- type AbsPath = z.infer<typeof AbsPathSchema>;
4
- declare const AbsPathSchema: z.core.$ZodBranded<z.ZodString, "absPath", "out">;
3
+ type AbsPath = z.infer<typeof absPath>;
4
+ declare const absPath: z.ZodBranded<z.ZodString, "absPath">;
5
5
 
6
6
  type Config = {
7
7
  srcPath: AbsPath;
@@ -9,38 +9,157 @@ type Config = {
9
9
  ignore: boolean;
10
10
  };
11
11
 
12
- declare const FileTreeSchema: z.ZodUnion<readonly [z.ZodIntersection<z.ZodObject<{
13
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
12
+ declare const fileTree: z.ZodUnion<[z.ZodObject<{
13
+ path: z.ZodBranded<z.ZodString, "relpath">;
14
14
  name: z.ZodString;
15
- }, z.core.$strip>, z.ZodObject<{
15
+ } & {
16
16
  type: z.ZodLiteral<"file">;
17
17
  frontmatter: z.ZodObject<{
18
18
  title: z.ZodString;
19
- descriptionL: z.ZodString;
19
+ description: z.ZodString;
20
20
  last_modified: z.ZodString;
21
- }, z.core.$strip>;
22
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
23
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
21
+ }, "strip", z.ZodTypeAny, {
22
+ title: string;
23
+ description: string;
24
+ last_modified: string;
25
+ }, {
26
+ title: string;
27
+ description: string;
28
+ last_modified: string;
29
+ }>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ path: string & z.BRAND<"relpath">;
32
+ type: "file";
33
+ name: string;
34
+ frontmatter: {
35
+ title: string;
36
+ description: string;
37
+ last_modified: string;
38
+ };
39
+ }, {
40
+ path: string;
41
+ type: "file";
42
+ name: string;
43
+ frontmatter: {
44
+ title: string;
45
+ description: string;
46
+ last_modified: string;
47
+ };
48
+ }>, z.ZodType<{
49
+ path: string & z.BRAND<"relpath">;
50
+ name: string;
51
+ } & {
52
+ type: "dir";
53
+ files: {
54
+ path: string & z.BRAND<"relpath">;
55
+ type: "file";
56
+ name: string;
57
+ frontmatter: {
58
+ title: string;
59
+ description: string;
60
+ last_modified: string;
61
+ };
62
+ }[];
63
+ dirs: ({
64
+ path: string & z.BRAND<"relpath">;
65
+ name: string;
66
+ } & /*elided*/ any)[];
67
+ }, z.ZodTypeDef, {
68
+ path: string;
69
+ name: string;
70
+ } & {
71
+ type: "dir";
72
+ files: {
73
+ path: string;
74
+ type: "file";
75
+ name: string;
76
+ frontmatter: {
77
+ title: string;
78
+ description: string;
79
+ last_modified: string;
80
+ };
81
+ }[];
82
+ dirs: ({
83
+ path: string;
84
+ name: string;
85
+ } & /*elided*/ any)[];
86
+ }>]>;
87
+ declare const jsonFileTree: z.ZodUnion<[z.ZodObject<{
88
+ path: z.ZodString;
24
89
  name: z.ZodString;
25
- }, z.core.$strip>, z.ZodObject<{
26
- type: z.ZodLiteral<"dir">;
27
- dirs: z.ZodArray<z.ZodIntersection<z.ZodObject<{
28
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
29
- name: z.ZodString;
30
- }, z.core.$strip>, z.ZodObject</*elided*/ any, z.core.$strip>>>;
31
- files: z.ZodArray<z.ZodIntersection<z.ZodObject<{
32
- path: z.core.$ZodBranded<z.ZodString, "relpath", "out">;
33
- name: z.ZodString;
34
- }, z.core.$strip>, z.ZodObject<{
35
- type: z.ZodLiteral<"file">;
36
- frontmatter: z.ZodObject<{
37
- title: z.ZodString;
38
- descriptionL: z.ZodString;
39
- last_modified: z.ZodString;
40
- }, z.core.$strip>;
41
- }, z.core.$strip>>>;
42
- }, z.core.$strip>>]>;
90
+ } & {
91
+ type: z.ZodLiteral<"file">;
92
+ frontmatter: z.ZodObject<{
93
+ title: z.ZodString;
94
+ description: z.ZodString;
95
+ last_modified: z.ZodString;
96
+ }, "strip", z.ZodTypeAny, {
97
+ title: string;
98
+ description: string;
99
+ last_modified: string;
100
+ }, {
101
+ title: string;
102
+ description: string;
103
+ last_modified: string;
104
+ }>;
105
+ }, "strip", z.ZodTypeAny, {
106
+ path: string;
107
+ type: "file";
108
+ name: string;
109
+ frontmatter: {
110
+ title: string;
111
+ description: string;
112
+ last_modified: string;
113
+ };
114
+ }, {
115
+ path: string;
116
+ type: "file";
117
+ name: string;
118
+ frontmatter: {
119
+ title: string;
120
+ description: string;
121
+ last_modified: string;
122
+ };
123
+ }>, z.ZodType<{
124
+ path: string;
125
+ name: string;
126
+ } & {
127
+ type: "dir";
128
+ files: {
129
+ path: string;
130
+ type: "file";
131
+ name: string;
132
+ frontmatter: {
133
+ title: string;
134
+ description: string;
135
+ last_modified: string;
136
+ };
137
+ }[];
138
+ dirs: ({
139
+ path: string;
140
+ name: string;
141
+ } & /*elided*/ any)[];
142
+ }, z.ZodTypeDef, {
143
+ path: string;
144
+ name: string;
145
+ } & {
146
+ type: "dir";
147
+ files: {
148
+ path: string;
149
+ type: "file";
150
+ name: string;
151
+ frontmatter: {
152
+ title: string;
153
+ description: string;
154
+ last_modified: string;
155
+ };
156
+ }[];
157
+ dirs: ({
158
+ path: string;
159
+ name: string;
160
+ } & /*elided*/ any)[];
161
+ }>]>;
43
162
 
44
163
  declare function runO2B(config: Config): void;
45
164
 
46
- export { FileTreeSchema, runO2B as default };
165
+ export { runO2B as default, fileTree, jsonFileTree };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -29,8 +30,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
30
  // src/index.ts
30
31
  var index_exports = {};
31
32
  __export(index_exports, {
32
- FileTreeSchema: () => FileTreeSchema,
33
- default: () => runO2B
33
+ default: () => runO2B,
34
+ fileTree: () => fileTree,
35
+ jsonFileTree: () => jsonFileTree
34
36
  });
35
37
  module.exports = __toCommonJS(index_exports);
36
38
 
@@ -39,38 +41,36 @@ var import_zod2 = __toESM(require("zod"));
39
41
 
40
42
  // src/types/path.ts
41
43
  var import_zod = __toESM(require("zod"));
42
- var AbsPathSchema = import_zod.default.string().brand();
43
- var RelPathSchema = import_zod.default.string().brand();
44
+ var absPath = import_zod.default.string().brand();
45
+ var relPath = import_zod.default.string().brand();
44
46
 
45
47
  // src/types/filetree.ts
46
- var FileTreeNodeSchema = import_zod2.default.object({
47
- path: RelPathSchema,
48
- name: import_zod2.default.string()
49
- });
50
- var FrontmatterSchema = import_zod2.default.object({
48
+ var frontmatter = import_zod2.default.object({
51
49
  title: import_zod2.default.string(),
52
- descriptionL: import_zod2.default.string(),
50
+ description: import_zod2.default.string(),
53
51
  last_modified: import_zod2.default.string()
54
52
  });
55
- var FileNodeSchema = import_zod2.default.intersection(
56
- FileTreeNodeSchema,
57
- import_zod2.default.object({
53
+ function createFileTreeSchema(path) {
54
+ const baseNode = import_zod2.default.object({
55
+ path,
56
+ name: import_zod2.default.string()
57
+ });
58
+ const fileNode = baseNode.extend({
58
59
  type: import_zod2.default.literal("file"),
59
- frontmatter: FrontmatterSchema
60
- })
61
- );
62
- var DirNodeScehma = import_zod2.default.intersection(
63
- FileTreeNodeSchema,
64
- import_zod2.default.object({
60
+ frontmatter
61
+ });
62
+ const dirNode = baseNode.extend({
65
63
  type: import_zod2.default.literal("dir"),
66
- // https://zod.dev/api?id=recursive-objects
67
- get dirs() {
68
- return import_zod2.default.array(DirNodeScehma);
69
- },
70
- files: import_zod2.default.array(FileNodeSchema)
71
- })
72
- );
73
- var FileTreeSchema = import_zod2.default.union([FileNodeSchema, DirNodeScehma]);
64
+ files: import_zod2.default.array(fileNode),
65
+ dirs: import_zod2.default.lazy(() => dirNode.array())
66
+ });
67
+ const fileTree2 = import_zod2.default.union([fileNode, dirNode]);
68
+ return { fileTree: fileTree2, dirNode, fileNode };
69
+ }
70
+ var defaultSchema = createFileTreeSchema(relPath);
71
+ var jsonSchema = createFileTreeSchema(import_zod2.default.string());
72
+ var fileTree = defaultSchema.fileTree;
73
+ var jsonFileTree = jsonSchema.fileTree;
74
74
 
75
75
  // src/core/sync/mirror.ts
76
76
  var import_node_fs = require("fs");
@@ -115,10 +115,10 @@ var import_node_fs2 = require("fs");
115
115
  var import_node_path2 = require("path");
116
116
  function toAbsPath(path) {
117
117
  if (!(0, import_node_path2.isAbsolute)(path)) path = (0, import_node_path2.resolve)(path);
118
- return path;
118
+ return absPath.parse(path);
119
119
  }
120
120
  function toRelPath(from, to) {
121
- return (0, import_node_path2.relative)(from, to);
121
+ return relPath.parse((0, import_node_path2.relative)(from, to));
122
122
  }
123
123
  function isObsidianDirectory(path) {
124
124
  const stat = (0, import_node_fs2.lstatSync)(path);
@@ -146,8 +146,8 @@ var VaultIgnorer = class {
146
146
  if (path === this.rootPath) return false;
147
147
  if (!(0, import_node_fs3.existsSync)(path)) throw new Error("somethings wrong!");
148
148
  const stat = (0, import_node_fs3.lstatSync)(path);
149
- const relPath = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
150
- return this.ign.ignores(relPath);
149
+ const relPath2 = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
150
+ return this.ign.ignores(relPath2);
151
151
  }
152
152
  };
153
153
 
@@ -207,12 +207,13 @@ function runO2B(config) {
207
207
  if (!isObsidianDirectory(srcPath)) throw new Error("Not a obsidian vault");
208
208
  const ign = new VaultIgnorer(srcPath);
209
209
  if (ignore2) ign.load();
210
- const fileTree = scan(srcPath, ign);
211
- if (fileTree === null) throw new Error("No content in vault");
212
- mirror(fileTree, srcPath, destPath);
210
+ const fileTree2 = scan(srcPath, ign);
211
+ if (fileTree2 === null) throw new Error("No content in vault");
212
+ mirror(fileTree2, srcPath, destPath);
213
213
  }
214
214
  // Annotate the CommonJS export names for ESM import in node:
215
215
  0 && (module.exports = {
216
- FileTreeSchema
216
+ fileTree,
217
+ jsonFileTree
217
218
  });
218
219
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/filetree.ts","../src/types/path.ts","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/runO2B.ts"],"sourcesContent":["export { FileTreeSchema } from \"./types\";\nexport { default } from \"./runO2B\";\n","import z from \"zod\";\nimport { RelPathSchema } from \"./path\";\n\ntype FileTreeNode = z.infer<typeof FileTreeNodeSchema>;\nconst FileTreeNodeSchema = z.object({\n path: RelPathSchema,\n name: z.string(),\n});\n\ntype Frontmatter = z.infer<typeof FrontmatterSchema>;\nconst FrontmatterSchema = z.object({\n title: z.string(),\n descriptionL: z.string(),\n last_modified: z.string(),\n});\n\ntype FileNode = z.infer<typeof FileNodeSchema>;\nconst FileNodeSchema = z.intersection(\n FileTreeNodeSchema,\n z.object({\n type: z.literal(\"file\"),\n frontmatter: FrontmatterSchema,\n })\n);\n\ntype DirNode = z.infer<typeof DirNodeScehma>;\nconst DirNodeScehma = z.intersection(\n FileTreeNodeSchema,\n z.object({\n type: z.literal(\"dir\"),\n // https://zod.dev/api?id=recursive-objects\n get dirs() {\n return z.array(DirNodeScehma);\n },\n files: z.array(FileNodeSchema),\n })\n);\n\ntype FileTree = z.infer<typeof FileTreeSchema>;\nconst FileTreeSchema = z.union([FileNodeSchema, DirNodeScehma]);\n\nexport { FileTree, FileNode, DirNode, Frontmatter, FileTreeSchema };\n","import z from \"zod\";\n\ntype AbsPath = z.infer<typeof AbsPathSchema>;\nconst AbsPathSchema = z.string().brand<\"absPath\">();\n\ntype RelPath = z.infer<typeof RelPathSchema>;\nconst RelPathSchema = z.string().brand<\"relpath\">();\n\nexport { type AbsPath, type RelPath, AbsPathSchema, RelPathSchema };\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { AbsPath, RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n if (!isAbsolute(path)) path = resolve(path);\n return path as AbsPath;\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n return relative(from, to) as RelPath;\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n const stat = lstatSync(path);\n\n if (!stat.isDirectory()) return false;\n\n const obsMetaDir = readdirSync(path, { withFileTypes: true })\n .filter((node) => node.isDirectory())\n .filter((node) => node.name === \".obsidian\");\n\n if (obsMetaDir.length !== 1) return false;\n\n return true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function runO2B(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":"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","names":["import_zod","z","z","filetree","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","ignore","matter","ignore"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/filetree.ts","../src/types/path.ts","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/runO2B.ts"],"sourcesContent":["export { fileTree, jsonFileTree } from \"./types\";\nexport { default } from \"./runO2B\";\n","import z from \"zod\";\nimport { relPath, type RelPath } from \"./path\";\n\nconst frontmatter = z.object({\n title: z.string(),\n description: z.string(),\n last_modified: z.string(),\n});\n\nfunction createFileTreeSchema<P extends typeof relPath | z.ZodString>(path: P) {\n type BaseNode = z.infer<typeof baseNode>;\n const baseNode = z.object({\n path,\n name: z.string(),\n });\n\n type FileNodeOutput = z.infer<typeof fileNode>;\n type FileNodeInput = z.input<typeof fileNode>;\n const fileNode = baseNode.extend({\n type: z.literal(\"file\"),\n frontmatter: frontmatter,\n });\n\n // https://v3.zod.dev/?id=recursive-types\n type DirNodeOutput = BaseNode & {\n type: \"dir\";\n files: FileNodeOutput[];\n dirs: DirNodeOutput[];\n };\n type DirNodeInput = z.input<typeof baseNode> & {\n type: \"dir\";\n files: FileNodeInput[];\n dirs: DirNodeInput[];\n };\n\n const dirNode: z.ZodType<DirNodeOutput, z.ZodTypeDef, DirNodeInput> =\n baseNode.extend({\n type: z.literal(\"dir\"),\n files: z.array(fileNode),\n dirs: z.lazy(() => dirNode.array()),\n });\n\n const fileTree = z.union([fileNode, dirNode]);\n\n return { fileTree, dirNode, fileNode };\n}\n\nconst defaultSchema = createFileTreeSchema(relPath);\nconst jsonSchema = createFileTreeSchema(z.string());\n\nexport const fileTree = defaultSchema.fileTree;\nexport const jsonFileTree = jsonSchema.fileTree;\n\nexport type FileTree = z.infer<typeof defaultSchema.fileTree>;\nexport type FileNode = z.infer<typeof defaultSchema.fileNode>;\nexport type DirNode = z.infer<typeof defaultSchema.dirNode>;\nexport type Frontmatter = z.infer<typeof frontmatter>;\n","import z from \"zod\";\n\ntype AbsPath = z.infer<typeof absPath>;\nconst absPath = z.string().brand<\"absPath\">();\n\ntype RelPath = z.infer<typeof relPath>;\nconst relPath = z.string().brand<\"relpath\">();\n\nexport { type AbsPath, type RelPath, absPath, relPath };\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport { absPath, relPath, type AbsPath, type RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n if (!isAbsolute(path)) path = resolve(path);\n return absPath.parse(path);\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n return relPath.parse(relative(from, to));\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n const stat = lstatSync(path);\n\n if (!stat.isDirectory()) return false;\n\n const obsMetaDir = readdirSync(path, { withFileTypes: true })\n .filter((node) => node.isDirectory())\n .filter((node) => node.name === \".obsidian\");\n\n if (obsMetaDir.length !== 1) return false;\n\n return true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function runO2B(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,cAAc;;;ACAd,iBAAc;AAGd,IAAM,UAAU,WAAAC,QAAE,OAAO,EAAE,MAAiB;AAG5C,IAAM,UAAU,WAAAA,QAAE,OAAO,EAAE,MAAiB;;;ADH5C,IAAM,cAAc,YAAAC,QAAE,OAAO;AAAA,EAC3B,OAAO,YAAAA,QAAE,OAAO;AAAA,EAChB,aAAa,YAAAA,QAAE,OAAO;AAAA,EACtB,eAAe,YAAAA,QAAE,OAAO;AAC1B,CAAC;AAED,SAAS,qBAA6D,MAAS;AAE7E,QAAM,WAAW,YAAAA,QAAE,OAAO;AAAA,IACxB;AAAA,IACA,MAAM,YAAAA,QAAE,OAAO;AAAA,EACjB,CAAC;AAID,QAAM,WAAW,SAAS,OAAO;AAAA,IAC/B,MAAM,YAAAA,QAAE,QAAQ,MAAM;AAAA,IACtB;AAAA,EACF,CAAC;AAcD,QAAM,UACJ,SAAS,OAAO;AAAA,IACd,MAAM,YAAAA,QAAE,QAAQ,KAAK;AAAA,IACrB,OAAO,YAAAA,QAAE,MAAM,QAAQ;AAAA,IACvB,MAAM,YAAAA,QAAE,KAAK,MAAM,QAAQ,MAAM,CAAC;AAAA,EACpC,CAAC;AAEH,QAAMC,YAAW,YAAAD,QAAE,MAAM,CAAC,UAAU,OAAO,CAAC;AAE5C,SAAO,EAAE,UAAAC,WAAU,SAAS,SAAS;AACvC;AAEA,IAAM,gBAAgB,qBAAqB,OAAO;AAClD,IAAM,aAAa,qBAAqB,YAAAD,QAAE,OAAO,CAAC;AAE3C,IAAM,WAAW,cAAc;AAC/B,IAAM,eAAe,WAAW;;;AEnDvC,qBAAmE;AACnE,uBAAqB;AAGd,SAAS,OACf,UACA,SACA,UACC;AACD,WAAS,IAAIE,WAAoB;AAChC,UAAM,WAAO,uBAAK,SAASA,UAAS,IAAI;AACxC,UAAM,SAAK,uBAAK,UAAUA,UAAS,IAAI;AAEvC,QAAIA,UAAS,SAAS,OAAO;AAC5B,UAAI,KAAC,2BAAW,EAAE,EAAG,+BAAU,IAAI,EAAE,WAAW,KAAK,CAAC;AAEtD,MAAAA,UAAS,MAAM,QAAQ,CAAC,SAAS;AAChC,YAAI,IAAI;AAAA,MACT,CAAC;AAED,MAAAA,UAAS,KAAK,QAAQ,CAAC,QAAQ;AAC9B,YAAI,GAAG;AAAA,MACR,CAAC;AAAA,IACF;AAEA,QAAIA,UAAS,SAAS,QAAQ;AAC7B,uCAAa,MAAM,EAAE;AAAA,IACtB;AAAA,EACD;AAEA,MAAI,QAAQ;AACZ,mBAAiB,UAAU,QAAQ;AACpC;AAEA,SAAS,iBAAiB,UAAoB,UAAmB;AAChE,QAAM,mBAAe,uBAAK,UAAU,kBAAkB;AACtD,oCAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AACvE;;;ACrCA,IAAAC,kBAAqD;AACrD,IAAAC,oBAA+B;AAC/B,yBAAmB;;;ACFnB,IAAAC,kBAAoD;AACpD,IAAAC,oBAAqB;AACrB,oBAAoC;;;ACFpC,IAAAC,kBAAuC;AACvC,IAAAC,oBAA8C;AAG9C,SAAS,UAAU,MAAuB;AACxC,MAAI,KAAC,8BAAW,IAAI,EAAG,YAAO,2BAAQ,IAAI;AAC1C,SAAO,QAAQ,MAAM,IAAI;AAC3B;AAEA,SAAS,UAAU,MAAe,IAAsB;AACtD,SAAO,QAAQ,UAAM,4BAAS,MAAM,EAAE,CAAC;AACzC;AAEA,SAAS,oBAAoB,MAAe;AAC1C,QAAM,WAAO,2BAAU,IAAI;AAE3B,MAAI,CAAC,KAAK,YAAY,EAAG,QAAO;AAEhC,QAAM,iBAAa,6BAAY,MAAM,EAAE,eAAe,KAAK,CAAC,EACzD,OAAO,CAAC,SAAS,KAAK,YAAY,CAAC,EACnC,OAAO,CAAC,SAAS,KAAK,SAAS,WAAW;AAE7C,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,SAAO;AACT;;;ADnBO,IAAM,eAAN,MAAmB;AAAA,EACjB;AAAA,EACA;AAAA,EAER,YAAY,UAAmB;AAC9B,SAAK,WAAW;AAChB,SAAK,UAAM,cAAAC,SAAO;AAElB,SAAK,IAAI,IAAI,CAAC,IAAI,CAAC;AAAA,EACpB;AAAA,EAEO,OAAO;AACb,UAAM,iBAAa,wBAAK,KAAK,UAAU,YAAY;AACnD,YAAI,4BAAW,UAAU;AACxB,WAAK,IAAI,QAAI,8BAAa,UAAU,EAAE,SAAS,CAAC;AAAA,EAClD;AAAA,EAEO,OAAO,MAAwB;AACrC,QAAI,SAAS,KAAK,SAAU,QAAO;AAEnC,QAAI,KAAC,4BAAW,IAAI,EAAG,OAAM,IAAI,MAAM,mBAAmB;AAE1D,UAAM,WAAO,2BAAU,IAAI;AAE3B,UAAMC,WACL,UAAU,KAAK,UAAU,IAAI,KAAK,KAAK,YAAY,IAAI,MAAM;AAE9D,WAAO,KAAK,IAAI,QAAQA,QAAO;AAAA,EAChC;AACD;;;ADvBO,SAAS,KAAK,UAAmB,KAAoC;AAC3E,WAAS,IAAI,MAAgC;AAC5C,QAAI,2BAAK,OAAO,MAAO,QAAO;AAE9B,UAAM,WAAO,2BAAU,IAAI;AAC3B,UAAM,WAAO,4BAAS,IAAI;AAE1B,QAAI,KAAK,YAAY,GAAG;AACvB,YAAM,EAAE,MAAM,MAAM,QAAI,6BAAY,IAAI,EAAE;AAAA,QACzC,CAAC,KAAK,UAAU;AACf,gBAAM,OAAO,IAAI,cAAU,wBAAK,MAAM,KAAK,CAAC,CAAC;AAE7C,eAAI,6BAAM,UAAS,MAAO,KAAI,KAAK,KAAK,IAAI;AAC5C,eAAI,6BAAM,UAAS,OAAQ,KAAI,MAAM,KAAK,IAAI;AAE9C,iBAAO;AAAA,QACR;AAAA,QACA;AAAA,UACC,MAAM,CAAC;AAAA,UACP,OAAO,CAAC;AAAA,QACT;AAAA,MACD;AAEA,aAAO;AAAA,QACN,MAAM,UAAU,UAAU,IAAI;AAAA,QAC9B;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,GAAG;AAC1C,aAAO;AAAA,QACN,MAAM,UAAU,UAAU,IAAI;AAAA,QAC9B;AAAA,QACA,MAAM;AAAA,QACN,aAAa,eAAe,IAAI;AAAA,MACjC;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,QAAQ;AACpB;AAEA,SAAS,eAAe,MAA4B;AACnD,QAAM,EAAE,MAAM,eAAe,QAAI,mBAAAC,aAAO,8BAAa,MAAM,OAAO,CAAC;AACnE,SAAO;AAAA,IACN,WAAO,4BAAS,IAAI,EAAE,QAAQ,SAAS,EAAE;AAAA,IACzC,aAAa;AAAA,IACb,mBAAe,2BAAU,IAAI,EAAE,MAAM,mBAAmB,OAAO;AAAA;AAAA,IAC/D,GAAG;AAAA,EACJ;AACD;;;AG/De,SAAR,OAAwB,QAAgB;AAC7C,QAAM,EAAE,SAAS,UAAU,QAAAC,QAAO,IAAI;AACtC,MAAI,CAAC,oBAAoB,OAAO,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAEzE,QAAM,MAAM,IAAI,aAAa,OAAO;AACpC,MAAIA,QAAQ,KAAI,KAAK;AAErB,QAAMC,YAAW,KAAK,SAAS,GAAG;AAClC,MAAIA,cAAa,KAAM,OAAM,IAAI,MAAM,qBAAqB;AAE5D,SAAOA,WAAU,SAAS,QAAQ;AACpC;","names":["import_zod","z","z","fileTree","filetree","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","ignore","relPath","matter","ignore","fileTree"]}
package/dist/index.mjs CHANGED
@@ -3,38 +3,36 @@ import z2 from "zod";
3
3
 
4
4
  // src/types/path.ts
5
5
  import z from "zod";
6
- var AbsPathSchema = z.string().brand();
7
- var RelPathSchema = z.string().brand();
6
+ var absPath = z.string().brand();
7
+ var relPath = z.string().brand();
8
8
 
9
9
  // src/types/filetree.ts
10
- var FileTreeNodeSchema = z2.object({
11
- path: RelPathSchema,
12
- name: z2.string()
13
- });
14
- var FrontmatterSchema = z2.object({
10
+ var frontmatter = z2.object({
15
11
  title: z2.string(),
16
- descriptionL: z2.string(),
12
+ description: z2.string(),
17
13
  last_modified: z2.string()
18
14
  });
19
- var FileNodeSchema = z2.intersection(
20
- FileTreeNodeSchema,
21
- z2.object({
15
+ function createFileTreeSchema(path) {
16
+ const baseNode = z2.object({
17
+ path,
18
+ name: z2.string()
19
+ });
20
+ const fileNode = baseNode.extend({
22
21
  type: z2.literal("file"),
23
- frontmatter: FrontmatterSchema
24
- })
25
- );
26
- var DirNodeScehma = z2.intersection(
27
- FileTreeNodeSchema,
28
- z2.object({
22
+ frontmatter
23
+ });
24
+ const dirNode = baseNode.extend({
29
25
  type: z2.literal("dir"),
30
- // https://zod.dev/api?id=recursive-objects
31
- get dirs() {
32
- return z2.array(DirNodeScehma);
33
- },
34
- files: z2.array(FileNodeSchema)
35
- })
36
- );
37
- var FileTreeSchema = z2.union([FileNodeSchema, DirNodeScehma]);
26
+ files: z2.array(fileNode),
27
+ dirs: z2.lazy(() => dirNode.array())
28
+ });
29
+ const fileTree2 = z2.union([fileNode, dirNode]);
30
+ return { fileTree: fileTree2, dirNode, fileNode };
31
+ }
32
+ var defaultSchema = createFileTreeSchema(relPath);
33
+ var jsonSchema = createFileTreeSchema(z2.string());
34
+ var fileTree = defaultSchema.fileTree;
35
+ var jsonFileTree = jsonSchema.fileTree;
38
36
 
39
37
  // src/core/sync/mirror.ts
40
38
  import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
@@ -79,10 +77,10 @@ import { lstatSync, readdirSync } from "fs";
79
77
  import { isAbsolute, relative, resolve } from "path";
80
78
  function toAbsPath(path) {
81
79
  if (!isAbsolute(path)) path = resolve(path);
82
- return path;
80
+ return absPath.parse(path);
83
81
  }
84
82
  function toRelPath(from, to) {
85
- return relative(from, to);
83
+ return relPath.parse(relative(from, to));
86
84
  }
87
85
  function isObsidianDirectory(path) {
88
86
  const stat = lstatSync(path);
@@ -110,8 +108,8 @@ var VaultIgnorer = class {
110
108
  if (path === this.rootPath) return false;
111
109
  if (!existsSync2(path)) throw new Error("somethings wrong!");
112
110
  const stat = lstatSync2(path);
113
- const relPath = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
114
- return this.ign.ignores(relPath);
111
+ const relPath2 = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
112
+ return this.ign.ignores(relPath2);
115
113
  }
116
114
  };
117
115
 
@@ -171,12 +169,13 @@ function runO2B(config) {
171
169
  if (!isObsidianDirectory(srcPath)) throw new Error("Not a obsidian vault");
172
170
  const ign = new VaultIgnorer(srcPath);
173
171
  if (ignore2) ign.load();
174
- const fileTree = scan(srcPath, ign);
175
- if (fileTree === null) throw new Error("No content in vault");
176
- mirror(fileTree, srcPath, destPath);
172
+ const fileTree2 = scan(srcPath, ign);
173
+ if (fileTree2 === null) throw new Error("No content in vault");
174
+ mirror(fileTree2, srcPath, destPath);
177
175
  }
178
176
  export {
179
- FileTreeSchema,
180
- runO2B as default
177
+ runO2B as default,
178
+ fileTree,
179
+ jsonFileTree
181
180
  };
182
181
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/filetree.ts","../src/types/path.ts","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/runO2B.ts"],"sourcesContent":["import z from \"zod\";\nimport { RelPathSchema } from \"./path\";\n\ntype FileTreeNode = z.infer<typeof FileTreeNodeSchema>;\nconst FileTreeNodeSchema = z.object({\n path: RelPathSchema,\n name: z.string(),\n});\n\ntype Frontmatter = z.infer<typeof FrontmatterSchema>;\nconst FrontmatterSchema = z.object({\n title: z.string(),\n descriptionL: z.string(),\n last_modified: z.string(),\n});\n\ntype FileNode = z.infer<typeof FileNodeSchema>;\nconst FileNodeSchema = z.intersection(\n FileTreeNodeSchema,\n z.object({\n type: z.literal(\"file\"),\n frontmatter: FrontmatterSchema,\n })\n);\n\ntype DirNode = z.infer<typeof DirNodeScehma>;\nconst DirNodeScehma = z.intersection(\n FileTreeNodeSchema,\n z.object({\n type: z.literal(\"dir\"),\n // https://zod.dev/api?id=recursive-objects\n get dirs() {\n return z.array(DirNodeScehma);\n },\n files: z.array(FileNodeSchema),\n })\n);\n\ntype FileTree = z.infer<typeof FileTreeSchema>;\nconst FileTreeSchema = z.union([FileNodeSchema, DirNodeScehma]);\n\nexport { FileTree, FileNode, DirNode, Frontmatter, FileTreeSchema };\n","import z from \"zod\";\n\ntype AbsPath = z.infer<typeof AbsPathSchema>;\nconst AbsPathSchema = z.string().brand<\"absPath\">();\n\ntype RelPath = z.infer<typeof RelPathSchema>;\nconst RelPathSchema = z.string().brand<\"relpath\">();\n\nexport { type AbsPath, type RelPath, AbsPathSchema, RelPathSchema };\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { AbsPath, RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n if (!isAbsolute(path)) path = resolve(path);\n return path as AbsPath;\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n return relative(from, to) as RelPath;\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n const stat = lstatSync(path);\n\n if (!stat.isDirectory()) return false;\n\n const obsMetaDir = readdirSync(path, { withFileTypes: true })\n .filter((node) => node.isDirectory())\n .filter((node) => node.name === \".obsidian\");\n\n if (obsMetaDir.length !== 1) return false;\n\n return true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function runO2B(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":"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","names":["z","z","filetree","lstatSync","readdirSync","readFileSync","join","existsSync","lstatSync","join","join","existsSync","lstatSync","lstatSync","readdirSync","join","readFileSync","ignore"]}
1
+ {"version":3,"sources":["../src/types/filetree.ts","../src/types/path.ts","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/runO2B.ts"],"sourcesContent":["import z from \"zod\";\nimport { relPath, type RelPath } from \"./path\";\n\nconst frontmatter = z.object({\n title: z.string(),\n description: z.string(),\n last_modified: z.string(),\n});\n\nfunction createFileTreeSchema<P extends typeof relPath | z.ZodString>(path: P) {\n type BaseNode = z.infer<typeof baseNode>;\n const baseNode = z.object({\n path,\n name: z.string(),\n });\n\n type FileNodeOutput = z.infer<typeof fileNode>;\n type FileNodeInput = z.input<typeof fileNode>;\n const fileNode = baseNode.extend({\n type: z.literal(\"file\"),\n frontmatter: frontmatter,\n });\n\n // https://v3.zod.dev/?id=recursive-types\n type DirNodeOutput = BaseNode & {\n type: \"dir\";\n files: FileNodeOutput[];\n dirs: DirNodeOutput[];\n };\n type DirNodeInput = z.input<typeof baseNode> & {\n type: \"dir\";\n files: FileNodeInput[];\n dirs: DirNodeInput[];\n };\n\n const dirNode: z.ZodType<DirNodeOutput, z.ZodTypeDef, DirNodeInput> =\n baseNode.extend({\n type: z.literal(\"dir\"),\n files: z.array(fileNode),\n dirs: z.lazy(() => dirNode.array()),\n });\n\n const fileTree = z.union([fileNode, dirNode]);\n\n return { fileTree, dirNode, fileNode };\n}\n\nconst defaultSchema = createFileTreeSchema(relPath);\nconst jsonSchema = createFileTreeSchema(z.string());\n\nexport const fileTree = defaultSchema.fileTree;\nexport const jsonFileTree = jsonSchema.fileTree;\n\nexport type FileTree = z.infer<typeof defaultSchema.fileTree>;\nexport type FileNode = z.infer<typeof defaultSchema.fileNode>;\nexport type DirNode = z.infer<typeof defaultSchema.dirNode>;\nexport type Frontmatter = z.infer<typeof frontmatter>;\n","import z from \"zod\";\n\ntype AbsPath = z.infer<typeof absPath>;\nconst absPath = z.string().brand<\"absPath\">();\n\ntype RelPath = z.infer<typeof relPath>;\nconst relPath = z.string().brand<\"relpath\">();\n\nexport { type AbsPath, type RelPath, absPath, relPath };\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport { absPath, relPath, type AbsPath, type RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n if (!isAbsolute(path)) path = resolve(path);\n return absPath.parse(path);\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n return relPath.parse(relative(from, to));\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n const stat = lstatSync(path);\n\n if (!stat.isDirectory()) return false;\n\n const obsMetaDir = readdirSync(path, { withFileTypes: true })\n .filter((node) => node.isDirectory())\n .filter((node) => node.name === \".obsidian\");\n\n if (obsMetaDir.length !== 1) return false;\n\n return true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function runO2B(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":"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","names":["z","z","fileTree","filetree","lstatSync","readdirSync","readFileSync","join","existsSync","lstatSync","join","join","existsSync","lstatSync","relPath","lstatSync","readdirSync","join","readFileSync","ignore","fileTree"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o2b/meta",
3
- "version": "1.0.0-dev.3",
3
+ "version": "1.0.0-dev.5",
4
4
  "description": "filetree generator for o2b",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",