Skip to content

Commit 1479c0d

Browse files
author
Serhii Khoma
committed
WIP
1 parent 1058941 commit 1479c0d

File tree

4 files changed

+174
-2
lines changed

4 files changed

+174
-2
lines changed

generate-v2.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// import fg from 'fast-glob';
2+
// import { pascalCase } from 'change-case';
3+
// import { promises as fs } from 'fs';
4+
// import path from 'path';
5+
6+
var { default: fg } = await import("fast-glob");
7+
var { pascalCase } = await import("change-case");
8+
var { promises: fs } = await import("fs");
9+
var { default: path } = await import("path");
10+
11+
var inputDir = '/home/srghma/projects/faker/src/locales';
12+
var outputDir = '/home/srghma/projects/purescript-fakerjs/src/Fakerjs2/Locales';
13+
14+
// Find all .ts files except index.ts and metadata.ts
15+
var entries = await fg('**/*.ts', {
16+
cwd: inputDir,
17+
ignore: ['**/index.ts', '**/metadata.ts'],
18+
});
19+
20+
// Step 1: Build a naive tree (pure objects with `true`)
21+
const tree = {};
22+
for (const filepath of entries) {
23+
const parts = filepath.split(path.sep);
24+
const filename = path.basename(parts.pop(), '.ts');
25+
const pathParts = parts;
26+
setDeep(tree, [...pathParts, filename], true);
27+
}
28+
29+
function setDeep(obj, parts, value) {
30+
const last = parts.pop();
31+
let curr = obj;
32+
for (const part of parts) {
33+
curr[part] = curr[part] || {};
34+
curr = curr[part];
35+
}
36+
curr[last] = value;
37+
}
38+
39+
// Step 2: Postprocess tree into "smart" format (arrays for leaves)
40+
function postprocess(node) {
41+
if (typeof node !== 'object' || node === null) {
42+
return node;
43+
}
44+
45+
const entries = Object.entries(node);
46+
const onlyFiles = entries.every(([, value]) => value === true);
47+
48+
if (onlyFiles) {
49+
return entries.map(([name]) => name); // convert into array
50+
}
51+
52+
const result = {};
53+
for (const [key, value] of entries) {
54+
result[key] = postprocess(value);
55+
}
56+
return result;
57+
}
58+
59+
const smartTree = postprocess(tree);
60+
61+
// Done! Now smartTree looks like you want:
62+
// folders -> { folders or arrays of files }
63+
64+
console.dir(smartTree, { depth: null });
65+
66+
await walkAndGenerate(tree, []);
67+
68+
await Promise.all(
69+
Object.entries(filesByDir).map(async ([dir, files]) => {
70+
var moduleName = dir.split(path.sep).map(pascalCase).join('.');
71+
var targetDir = path.join(outputDir, dir);
72+
var baseName = pascalCase(path.basename(dir));
73+
74+
var pursFilePath = path.join(outputDir, `${dir}.purs`);
75+
var jsFilePath = path.join(outputDir, `${dir}.js`);
76+
77+
// Prepare contents
78+
var pursLines = [
79+
`module Fakerjs2.Locales.${moduleName} where`,
80+
'',
81+
'-- This file was generated by a script',
82+
'import Prelude',
83+
'import Fakerjs2.Types',
84+
'',
85+
...files.map(file => `foreign import ${file} :: ${pascalCase(file.replace(/_/g, ' ')).replace(/\s+/g, '')}`),
86+
];
87+
88+
var jsLines = files.map(file =>
89+
`export { default as ${file} } from '...'`
90+
);
91+
92+
// Ensure directory exists
93+
await fs.mkdir(path.dirname(pursFilePath), { recursive: true });
94+
await fs.mkdir(path.dirname(jsFilePath), { recursive: true });
95+
96+
// Write files
97+
await Promise.all([
98+
fs.writeFile(pursFilePath, pursLines.join('\n') + '\n'),
99+
fs.writeFile(jsFilePath, jsLines.join('\n') + '\n'),
100+
]);
101+
})
102+
);

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"author": "Serhii Khoma <[email protected]>",
77
"license": "MIT",
88
"dependencies": {
9-
"@faker-js/faker": "^9.7.0"
9+
"@faker-js/faker": "^9.7.0",
10+
"change-case": "^5.4.4",
11+
"fast-glob": "^3.3.3"
1012
}
1113
}

spago.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ package:
1515
- nullable: ">=6.0.0 <7.0.0"
1616
- prelude: ">=6.0.2 <7.0.0"
1717
- unsafe-coerce: ">=6.0.0 <7.0.0"
18+
- node-glob
19+
- node-path
20+
- node-fs
1821
# - undefinable
1922
test:
2023
main: Test.Main
@@ -25,7 +28,9 @@ workspace:
2528
packageSet:
2629
registry: 64.4.0
2730
extraPackages:
28-
{}
31+
node-fs:
32+
git: https://github.com/srghma/purescript-node-fs
33+
ref: master
2934
# undefinable:
3035
# git: https://github.com/srghma/purescript-undefinable/
3136
# ref: master

src/Fakerjs2Generate.purs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
module Fakerjs2Generate where
2+
3+
import Prelude
4+
5+
import Control.Monad.Aff (Aff)
6+
import Data.Array (catMaybes, filter, head, mapMaybe, snoc)
7+
import Data.Either (Either(..))
8+
import Data.Maybe (Maybe(..))
9+
import Effect (Effect)
10+
import Effect.Class (liftEffect)
11+
import Effect.Console (logShow)
12+
import Node.FS.Aff as FS
13+
import Node.Glob (glob)
14+
import Node.Path as Path
15+
import Node.Path as NP
16+
import Data.String (Pattern(..), split)
17+
18+
type Tree = TreeNode (Array (Either String Tree))
19+
20+
inputDir :: String
21+
inputDir = "/home/srghma/projects/faker/src/locales"
22+
23+
outputDir :: String
24+
outputDir = "/home/srghma/projects/purescript-fakerjs/src/Fakerjs2/Locales"
25+
26+
-- Build a tree where leaves are arrays of filenames
27+
buildTree :: Array String -> Tree
28+
buildTree files =
29+
let
30+
go :: Array (Array String) -> Tree
31+
go paths =
32+
let
33+
grouped = groupByHead paths
34+
in
35+
TreeNode
36+
( map
37+
( \(Tuple headPart subPaths) ->
38+
case map tail subPaths of
39+
[ [] ] -> Left headPart
40+
more -> Right (go more)
41+
)
42+
grouped
43+
)
44+
45+
-- Group list of path parts by their head
46+
groupByHead :: Array (Array String) -> Array (Tuple String (Array (Array String)))
47+
groupByHead paths =
48+
let
49+
heads = mapMaybe head paths
50+
uniqueHeads = nub heads
51+
in
52+
map (\h -> Tuple h (filter (\arr -> head arr == Just h) paths)) uniqueHeads
53+
54+
in
55+
go (map (split (Pattern Path.sep)) files)
56+
57+
main :: Effect Unit
58+
main = do
59+
files <- glob "**/*.ts" { cwd: inputDir }
60+
let filteredFiles = filter (\file -> not (file == "index.ts" || file == "metadata.ts")) files
61+
liftEffect $ logShow filteredFiles
62+
let tree = buildTree filteredFiles
63+
logShow tree

0 commit comments

Comments
 (0)