@reventlessdev/reventless-spec 3.0.0-alpha.61
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/CHANGELOG.md +625 -0
- package/LICENSE +202 -0
- package/README.md +114 -0
- package/package.json +34 -0
- package/rescript.json +25 -0
- package/run-generator.mjs +2 -0
- package/src/AnsiStyle.res +40 -0
- package/src/AnsiStyle.res.mjs +54 -0
- package/src/LogPrefix.res +168 -0
- package/src/LogPrefix.res.mjs +148 -0
- package/src/PackageVersion.res +73 -0
- package/src/PackageVersion.res.mjs +81 -0
- package/src/components/Aggregate.res +64 -0
- package/src/components/Aggregate.res.mjs +2 -0
- package/src/components/AutomationSlice.res +279 -0
- package/src/components/AutomationSlice.res.mjs +30 -0
- package/src/components/Counter.res +24 -0
- package/src/components/Counter.res.mjs +2 -0
- package/src/components/DcbDecode.res +128 -0
- package/src/components/DcbDecode.res.mjs +117 -0
- package/src/components/DcbTag.res +1256 -0
- package/src/components/DcbTag.res.mjs +869 -0
- package/src/components/DcbValidation.res +362 -0
- package/src/components/DcbValidation.res.mjs +360 -0
- package/src/components/DisplayName.res +40 -0
- package/src/components/DisplayName.res.mjs +26 -0
- package/src/components/ExtensionPoint.res +27 -0
- package/src/components/ExtensionPoint.res.mjs +2 -0
- package/src/components/InboundTranslationSlice.res +79 -0
- package/src/components/InboundTranslationSlice.res.mjs +2 -0
- package/src/components/OutboundTranslationSlice.res +108 -0
- package/src/components/OutboundTranslationSlice.res.mjs +2 -0
- package/src/components/Plugin.res +373 -0
- package/src/components/Plugin.res.mjs +249 -0
- package/src/components/ReadModel.res +199 -0
- package/src/components/ReadModel.res.mjs +18 -0
- package/src/components/Reference.res +51 -0
- package/src/components/Reference.res.mjs +37 -0
- package/src/components/StateAnnotations.res +65 -0
- package/src/components/StateAnnotations.res.mjs +15 -0
- package/src/components/StateChangeSlice.res +131 -0
- package/src/components/StateChangeSlice.res.mjs +2 -0
- package/src/components/StateViewSlice.res +99 -0
- package/src/components/StateViewSlice.res.mjs +2 -0
- package/src/components/Task.res +62 -0
- package/src/components/Task.res.mjs +2 -0
- package/src/generator/Codegen.res +703 -0
- package/src/generator/Codegen.res.mjs +485 -0
- package/src/generator/Config.res +85 -0
- package/src/generator/Config.res.mjs +78 -0
- package/src/generator/Discovery.res +204 -0
- package/src/generator/Discovery.res.mjs +213 -0
- package/src/generator/Generator_Node.res +49 -0
- package/src/generator/Generator_Node.res.mjs +18 -0
- package/src/generator/Pairing.res +386 -0
- package/src/generator/Pairing.res.mjs +353 -0
- package/src/generator/PluginGenerator.res +53 -0
- package/src/generator/PluginGenerator.res.mjs +70 -0
- package/src/types/Authorization.res +23 -0
- package/src/types/Authorization.res.mjs +33 -0
- package/src/types/Behavior.res +78 -0
- package/src/types/Behavior.res.mjs +2 -0
- package/src/types/EventMapping.res +100 -0
- package/src/types/EventMapping.res.mjs +15 -0
- package/src/types/Handler.res +30 -0
- package/src/types/Handler.res.mjs +2 -0
- package/src/types/Id.res +75 -0
- package/src/types/Id.res.mjs +37 -0
- package/src/types/Identity.res +46 -0
- package/src/types/Identity.res.mjs +51 -0
- package/src/types/Message.res +197 -0
- package/src/types/Message.res.mjs +108 -0
- package/src/types/Projection.res +220 -0
- package/src/types/Projection.res.mjs +44 -0
- package/src/types/QueryEngine.res +123 -0
- package/src/types/QueryEngine.res.mjs +12 -0
- package/src/types/ReadConsistency.res +38 -0
- package/src/types/ReadConsistency.res.mjs +29 -0
- package/src/types/Schedule.res +65 -0
- package/src/types/Schedule.res.mjs +68 -0
- package/src/types/SideEffect.res +45 -0
- package/src/types/SideEffect.res.mjs +2 -0
- package/src/types/StoredEvent.res +46 -0
- package/src/types/StoredEvent.res.mjs +32 -0
- package/src/types/Visibility.res +24 -0
- package/src/types/Visibility.res.mjs +25 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Directory scanner: walks src/, classifies .res files by parent folder name.
|
|
2
|
+
|
|
3
|
+
type componentType =
|
|
4
|
+
| StateChangeSlice
|
|
5
|
+
| StateViewSlice
|
|
6
|
+
| StateViewSliceStream
|
|
7
|
+
| AutomationSlice
|
|
8
|
+
| InboundTranslationSlice
|
|
9
|
+
| OutboundTranslationSlice
|
|
10
|
+
| Aggregate
|
|
11
|
+
| ReadModel
|
|
12
|
+
| ReadModelStream
|
|
13
|
+
| Task
|
|
14
|
+
| ExtensionPoint
|
|
15
|
+
| Extension
|
|
16
|
+
|
|
17
|
+
// relPath: path relative to srcDir (e.g. "ReadModel/ProductsProjections.res")
|
|
18
|
+
type discoveredFile = {stem: string, componentType: componentType, epGroup: option<string>, relPath: string}
|
|
19
|
+
|
|
20
|
+
let folderToComponentType = (folder: string): option<componentType> =>
|
|
21
|
+
switch folder {
|
|
22
|
+
| "StateChange" | "StateChanges" | "StateChangeSlice" | "StateChangeSlices" =>
|
|
23
|
+
Some(StateChangeSlice)
|
|
24
|
+
| "StateView" | "StateViews" | "StateViewSlice" | "StateViewSlices" => Some(StateViewSlice)
|
|
25
|
+
| "StateViewSliceStream" | "StateViewSliceStreams" => Some(StateViewSliceStream)
|
|
26
|
+
| "Automation" | "Automations" | "AutomationSlice" | "AutomationSlices" => Some(AutomationSlice)
|
|
27
|
+
| "InboundTranslation"
|
|
28
|
+
| "InboundTranslations"
|
|
29
|
+
| "InboundTranslationSlice"
|
|
30
|
+
| "InboundTranslationSlices" =>
|
|
31
|
+
Some(InboundTranslationSlice)
|
|
32
|
+
| "OutboundTranslation"
|
|
33
|
+
| "OutboundTranslations"
|
|
34
|
+
| "OutboundTranslationSlice"
|
|
35
|
+
| "OutboundTranslationSlices" =>
|
|
36
|
+
Some(OutboundTranslationSlice)
|
|
37
|
+
| "Aggregate" | "Aggregates" => Some(Aggregate)
|
|
38
|
+
| "ReadModel" | "ReadModels" => Some(ReadModel)
|
|
39
|
+
| "ReadModelStream" | "ReadModelStreams" => Some(ReadModelStream)
|
|
40
|
+
| "Task" | "Tasks" => Some(Task)
|
|
41
|
+
| "ExtensionPoint" | "ExtensionPoints" => Some(ExtensionPoint)
|
|
42
|
+
| "Extension" | "Extensions" => Some(Extension)
|
|
43
|
+
| _ => None
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let isAlwaysExcludedDir = (name: string): bool =>
|
|
47
|
+
name === "Plugin" || name === "tests" || name === "lib"
|
|
48
|
+
|
|
49
|
+
// Simple glob matching: supports exact match, `/**` prefix, and `/*` single level.
|
|
50
|
+
let matchesGlob = (path: string, pattern: string): bool =>
|
|
51
|
+
if pattern === "**" {
|
|
52
|
+
true
|
|
53
|
+
} else if not(pattern->String.includes("*")) {
|
|
54
|
+
// Exact file match or directory prefix
|
|
55
|
+
path === pattern || path->String.startsWith(pattern ++ "/")
|
|
56
|
+
} else if pattern->String.endsWith("/**") {
|
|
57
|
+
let prefix = pattern->String.slice(~start=0, ~end=pattern->String.length - 3)
|
|
58
|
+
path === prefix || path->String.startsWith(prefix ++ "/")
|
|
59
|
+
} else if pattern->String.endsWith("/*") {
|
|
60
|
+
let prefix = pattern->String.slice(~start=0, ~end=pattern->String.length - 2)
|
|
61
|
+
path->String.startsWith(prefix ++ "/") &&
|
|
62
|
+
!(path
|
|
63
|
+
->String.slice(~start=prefix->String.length + 1, ~end=path->String.length)
|
|
64
|
+
->String.includes("/"))
|
|
65
|
+
} else {
|
|
66
|
+
path === pattern
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let isExcluded = (relPath: string, excludePatterns: array<string>): bool =>
|
|
70
|
+
excludePatterns->Array.some(p => matchesGlob(relPath, p))
|
|
71
|
+
|
|
72
|
+
let stemOf = (filename: string): option<string> =>
|
|
73
|
+
if filename->String.endsWith(".res") {
|
|
74
|
+
Some(filename->String.slice(~start=0, ~end=filename->String.length - 4))
|
|
75
|
+
} else {
|
|
76
|
+
None
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let isSkipped = (stem: string): bool =>
|
|
80
|
+
stem->String.endsWith("Test")
|
|
81
|
+
|| stem->String.endsWith("Fixtures")
|
|
82
|
+
// `_EventMappings` and `_Mappings` files in per-entity Aggregate/ folders
|
|
83
|
+
// are picked up by the dedicated [Pairing.findEventMappings] walker;
|
|
84
|
+
// treating them as Aggregate specs would hunt for a non-existent
|
|
85
|
+
// `_EventMappingsBehavior` / `_MappingsBehavior`.
|
|
86
|
+
|| stem->String.endsWith("_EventMappings")
|
|
87
|
+
|| stem->String.endsWith("_Mappings")
|
|
88
|
+
|
|
89
|
+
// Collect .res files directly in dir (non-recursive) into acc.
|
|
90
|
+
let collectFiles = (
|
|
91
|
+
~dir: string,
|
|
92
|
+
~relDir: string,
|
|
93
|
+
~componentType: componentType,
|
|
94
|
+
~epGroup: option<string>,
|
|
95
|
+
~exclude: array<string>,
|
|
96
|
+
~acc: array<discoveredFile>,
|
|
97
|
+
): unit =>
|
|
98
|
+
Generator_Node.readDir(dir)->Array.forEach(entry => {
|
|
99
|
+
if entry->Generator_Node.isFile {
|
|
100
|
+
let filename = entry->Generator_Node.direntName
|
|
101
|
+
let relPath = if relDir === "" {filename} else {relDir ++ "/" ++ filename}
|
|
102
|
+
if !isExcluded(relPath, exclude) {
|
|
103
|
+
switch stemOf(filename) {
|
|
104
|
+
| Some(stem) if !isSkipped(stem) => acc->Array.push({stem, componentType, epGroup, relPath})
|
|
105
|
+
| _ => ()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// Recursively walk srcDir, classifying files into acc.
|
|
112
|
+
let rec walkDir = (
|
|
113
|
+
~dir: string,
|
|
114
|
+
~relDir: string,
|
|
115
|
+
~parentComponentType: option<componentType>,
|
|
116
|
+
~epGroup: option<string>,
|
|
117
|
+
~exclude: array<string>,
|
|
118
|
+
~acc: array<discoveredFile>,
|
|
119
|
+
): unit =>
|
|
120
|
+
Generator_Node.readDir(dir)->Array.forEach(entry => {
|
|
121
|
+
let entryName = entry->Generator_Node.direntName
|
|
122
|
+
let relPath = if relDir === "" {entryName} else {relDir ++ "/" ++ entryName}
|
|
123
|
+
|
|
124
|
+
if isExcluded(relPath, exclude) {
|
|
125
|
+
()
|
|
126
|
+
} else if entry->Generator_Node.isDirectory {
|
|
127
|
+
if isAlwaysExcludedDir(entryName) {
|
|
128
|
+
()
|
|
129
|
+
} else {
|
|
130
|
+
switch folderToComponentType(entryName) {
|
|
131
|
+
| Some(ExtensionPoint) =>
|
|
132
|
+
let epDir = Generator_Node.join([dir, entryName])
|
|
133
|
+
let children = Generator_Node.readDir(epDir)
|
|
134
|
+
let hasSubDirs = children->Array.some(e => e->Generator_Node.isDirectory)
|
|
135
|
+
if hasSubDirs {
|
|
136
|
+
// Each subfolder is a named EP group
|
|
137
|
+
children->Array.forEach(child => {
|
|
138
|
+
if child->Generator_Node.isDirectory {
|
|
139
|
+
let groupName = child->Generator_Node.direntName
|
|
140
|
+
let groupDir = Generator_Node.join([epDir, groupName])
|
|
141
|
+
let groupRelDir = relPath ++ "/" ++ groupName
|
|
142
|
+
collectFiles(
|
|
143
|
+
~dir=groupDir,
|
|
144
|
+
~relDir=groupRelDir,
|
|
145
|
+
~componentType=ExtensionPoint,
|
|
146
|
+
~epGroup=Some(groupName),
|
|
147
|
+
~exclude,
|
|
148
|
+
~acc,
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
} else {
|
|
153
|
+
// Flat EP folder — all .res files are for one extension point
|
|
154
|
+
collectFiles(
|
|
155
|
+
~dir=epDir,
|
|
156
|
+
~relDir=relPath,
|
|
157
|
+
~componentType=ExtensionPoint,
|
|
158
|
+
~epGroup=None,
|
|
159
|
+
~exclude,
|
|
160
|
+
~acc,
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
| Some(ct) =>
|
|
164
|
+
// Recurse into component type folder, collecting files at any depth
|
|
165
|
+
walkDir(
|
|
166
|
+
~dir=Generator_Node.join([dir, entryName]),
|
|
167
|
+
~relDir=relPath,
|
|
168
|
+
~parentComponentType=Some(ct),
|
|
169
|
+
~epGroup=None,
|
|
170
|
+
~exclude,
|
|
171
|
+
~acc,
|
|
172
|
+
)
|
|
173
|
+
| None =>
|
|
174
|
+
// Chapter folder or other — recurse inheriting parent context
|
|
175
|
+
walkDir(
|
|
176
|
+
~dir=Generator_Node.join([dir, entryName]),
|
|
177
|
+
~relDir=relPath,
|
|
178
|
+
~parentComponentType,
|
|
179
|
+
~epGroup,
|
|
180
|
+
~exclude,
|
|
181
|
+
~acc,
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} else if entry->Generator_Node.isFile {
|
|
186
|
+
switch parentComponentType {
|
|
187
|
+
| None => ()
|
|
188
|
+
| Some(ct) =>
|
|
189
|
+
let filename = entryName
|
|
190
|
+
if !isExcluded(relPath, exclude) {
|
|
191
|
+
switch stemOf(filename) {
|
|
192
|
+
| Some(stem) if !isSkipped(stem) => acc->Array.push({stem, componentType: ct, epGroup, relPath})
|
|
193
|
+
| _ => ()
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
let scan = (~srcDir: string, ~exclude: array<string>): array<discoveredFile> => {
|
|
201
|
+
let acc: array<discoveredFile> = []
|
|
202
|
+
walkDir(~dir=srcDir, ~relDir="", ~parentComponentType=None, ~epGroup=None, ~exclude, ~acc)
|
|
203
|
+
acc
|
|
204
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodepath from "node:path";
|
|
4
|
+
import * as Generator_Node$Reventless from "./Generator_Node.res.mjs";
|
|
5
|
+
|
|
6
|
+
function folderToComponentType(folder) {
|
|
7
|
+
switch (folder) {
|
|
8
|
+
case "Aggregate" :
|
|
9
|
+
case "Aggregates" :
|
|
10
|
+
return "Aggregate";
|
|
11
|
+
case "Automation" :
|
|
12
|
+
case "AutomationSlice" :
|
|
13
|
+
case "AutomationSlices" :
|
|
14
|
+
case "Automations" :
|
|
15
|
+
return "AutomationSlice";
|
|
16
|
+
case "ExtensionPoint" :
|
|
17
|
+
case "ExtensionPoints" :
|
|
18
|
+
return "ExtensionPoint";
|
|
19
|
+
case "Extension" :
|
|
20
|
+
case "Extensions" :
|
|
21
|
+
return "Extension";
|
|
22
|
+
case "InboundTranslation" :
|
|
23
|
+
case "InboundTranslationSlice" :
|
|
24
|
+
case "InboundTranslationSlices" :
|
|
25
|
+
case "InboundTranslations" :
|
|
26
|
+
return "InboundTranslationSlice";
|
|
27
|
+
case "OutboundTranslation" :
|
|
28
|
+
case "OutboundTranslationSlice" :
|
|
29
|
+
case "OutboundTranslationSlices" :
|
|
30
|
+
case "OutboundTranslations" :
|
|
31
|
+
return "OutboundTranslationSlice";
|
|
32
|
+
case "ReadModelStream" :
|
|
33
|
+
case "ReadModelStreams" :
|
|
34
|
+
return "ReadModelStream";
|
|
35
|
+
case "ReadModel" :
|
|
36
|
+
case "ReadModels" :
|
|
37
|
+
return "ReadModel";
|
|
38
|
+
case "StateChange" :
|
|
39
|
+
case "StateChangeSlice" :
|
|
40
|
+
case "StateChangeSlices" :
|
|
41
|
+
case "StateChanges" :
|
|
42
|
+
return "StateChangeSlice";
|
|
43
|
+
case "StateViewSliceStream" :
|
|
44
|
+
case "StateViewSliceStreams" :
|
|
45
|
+
return "StateViewSliceStream";
|
|
46
|
+
case "StateView" :
|
|
47
|
+
case "StateViewSlice" :
|
|
48
|
+
case "StateViewSlices" :
|
|
49
|
+
case "StateViews" :
|
|
50
|
+
return "StateViewSlice";
|
|
51
|
+
case "Task" :
|
|
52
|
+
case "Tasks" :
|
|
53
|
+
return "Task";
|
|
54
|
+
default:
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isAlwaysExcludedDir(name) {
|
|
60
|
+
if (name === "Plugin" || name === "tests") {
|
|
61
|
+
return true;
|
|
62
|
+
} else {
|
|
63
|
+
return name === "lib";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function matchesGlob(path, pattern) {
|
|
68
|
+
if (pattern === "**") {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (!pattern.includes("*")) {
|
|
72
|
+
if (path === pattern) {
|
|
73
|
+
return true;
|
|
74
|
+
} else {
|
|
75
|
+
return path.startsWith(pattern + "/");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (pattern.endsWith("/**")) {
|
|
79
|
+
let prefix = pattern.slice(0, pattern.length - 3 | 0);
|
|
80
|
+
if (path === prefix) {
|
|
81
|
+
return true;
|
|
82
|
+
} else {
|
|
83
|
+
return path.startsWith(prefix + "/");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!pattern.endsWith("/*")) {
|
|
87
|
+
return path === pattern;
|
|
88
|
+
}
|
|
89
|
+
let prefix$1 = pattern.slice(0, pattern.length - 2 | 0);
|
|
90
|
+
if (path.startsWith(prefix$1 + "/")) {
|
|
91
|
+
return !path.slice(prefix$1.length + 1 | 0, path.length).includes("/");
|
|
92
|
+
} else {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isExcluded(relPath, excludePatterns) {
|
|
98
|
+
return excludePatterns.some(p => matchesGlob(relPath, p));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function stemOf(filename) {
|
|
102
|
+
if (filename.endsWith(".res")) {
|
|
103
|
+
return filename.slice(0, filename.length - 4 | 0);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isSkipped(stem) {
|
|
108
|
+
if (stem.endsWith("Test") || stem.endsWith("Fixtures") || stem.endsWith("_EventMappings")) {
|
|
109
|
+
return true;
|
|
110
|
+
} else {
|
|
111
|
+
return stem.endsWith("_Mappings");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function collectFiles(dir, relDir, componentType, epGroup, exclude, acc) {
|
|
116
|
+
Generator_Node$Reventless.readDir(dir).forEach(entry => {
|
|
117
|
+
if (!entry.isFile()) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
let filename = entry.name;
|
|
121
|
+
let relPath = relDir === "" ? filename : relDir + "/" + filename;
|
|
122
|
+
if (isExcluded(relPath, exclude)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
let stem = stemOf(filename);
|
|
126
|
+
if (stem !== undefined && !isSkipped(stem)) {
|
|
127
|
+
acc.push({
|
|
128
|
+
stem: stem,
|
|
129
|
+
componentType: componentType,
|
|
130
|
+
epGroup: epGroup,
|
|
131
|
+
relPath: relPath
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function walkDir(dir, relDir, parentComponentType, epGroup, exclude, acc) {
|
|
139
|
+
Generator_Node$Reventless.readDir(dir).forEach(entry => {
|
|
140
|
+
let entryName = entry.name;
|
|
141
|
+
let relPath = relDir === "" ? entryName : relDir + "/" + entryName;
|
|
142
|
+
if (isExcluded(relPath, exclude)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (entry.isDirectory()) {
|
|
146
|
+
if (isAlwaysExcludedDir(entryName)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let ct = folderToComponentType(entryName);
|
|
150
|
+
if (ct === undefined) {
|
|
151
|
+
return walkDir(Nodepath.join(dir, entryName), relPath, parentComponentType, epGroup, exclude, acc);
|
|
152
|
+
}
|
|
153
|
+
if (ct !== "ExtensionPoint") {
|
|
154
|
+
return walkDir(Nodepath.join(dir, entryName), relPath, ct, undefined, exclude, acc);
|
|
155
|
+
}
|
|
156
|
+
let epDir = Nodepath.join(dir, entryName);
|
|
157
|
+
let children = Generator_Node$Reventless.readDir(epDir);
|
|
158
|
+
let hasSubDirs = children.some(e => e.isDirectory());
|
|
159
|
+
if (hasSubDirs) {
|
|
160
|
+
children.forEach(child => {
|
|
161
|
+
if (!child.isDirectory()) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
let groupName = child.name;
|
|
165
|
+
let groupDir = Nodepath.join(epDir, groupName);
|
|
166
|
+
let groupRelDir = relPath + "/" + groupName;
|
|
167
|
+
collectFiles(groupDir, groupRelDir, "ExtensionPoint", groupName, exclude, acc);
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
} else {
|
|
171
|
+
return collectFiles(epDir, relPath, "ExtensionPoint", undefined, exclude, acc);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (!entry.isFile()) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (parentComponentType === undefined) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (isExcluded(relPath, exclude)) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
let stem = stemOf(entryName);
|
|
184
|
+
if (stem !== undefined && !isSkipped(stem)) {
|
|
185
|
+
acc.push({
|
|
186
|
+
stem: stem,
|
|
187
|
+
componentType: parentComponentType,
|
|
188
|
+
epGroup: epGroup,
|
|
189
|
+
relPath: relPath
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function scan(srcDir, exclude) {
|
|
197
|
+
let acc = [];
|
|
198
|
+
walkDir(srcDir, "", undefined, undefined, exclude, acc);
|
|
199
|
+
return acc;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export {
|
|
203
|
+
folderToComponentType,
|
|
204
|
+
isAlwaysExcludedDir,
|
|
205
|
+
matchesGlob,
|
|
206
|
+
isExcluded,
|
|
207
|
+
stemOf,
|
|
208
|
+
isSkipped,
|
|
209
|
+
collectFiles,
|
|
210
|
+
walkDir,
|
|
211
|
+
scan,
|
|
212
|
+
}
|
|
213
|
+
/* node:path Not a pure module */
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Node.js bindings for the plugin generator.
|
|
2
|
+
|
|
3
|
+
// ── File system ──────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@module("node:fs")
|
|
6
|
+
external existsSync: string => bool = "existsSync"
|
|
7
|
+
|
|
8
|
+
@module("node:fs")
|
|
9
|
+
external readFileSync: (string, @as("utf8") _) => string = "readFileSync"
|
|
10
|
+
|
|
11
|
+
@module("node:fs")
|
|
12
|
+
external writeFileSync: (string, string, @as("utf8") _) => unit = "writeFileSync"
|
|
13
|
+
|
|
14
|
+
type dirent
|
|
15
|
+
@send external isDirectory: dirent => bool = "isDirectory"
|
|
16
|
+
@send external isFile: dirent => bool = "isFile"
|
|
17
|
+
@get external direntName: dirent => string = "name"
|
|
18
|
+
|
|
19
|
+
type readdirOptions = {withFileTypes: bool}
|
|
20
|
+
|
|
21
|
+
@module("node:fs")
|
|
22
|
+
external readdirSyncRaw: (string, readdirOptions) => array<dirent> = "readdirSync"
|
|
23
|
+
|
|
24
|
+
let readDir = (dir: string): array<dirent> =>
|
|
25
|
+
try readdirSyncRaw(dir, {withFileTypes: true}) catch {
|
|
26
|
+
| _ => []
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ── Path ─────────────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
@module("node:path") @variadic
|
|
32
|
+
external join: array<string> => string = "join"
|
|
33
|
+
|
|
34
|
+
@module("node:path") @variadic
|
|
35
|
+
external resolve: array<string> => string = "resolve"
|
|
36
|
+
|
|
37
|
+
@module("node:path")
|
|
38
|
+
external dirname: string => string = "dirname"
|
|
39
|
+
|
|
40
|
+
@module("node:path")
|
|
41
|
+
external basename: string => string = "basename"
|
|
42
|
+
|
|
43
|
+
// ── Process ──────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
@val @scope("process")
|
|
46
|
+
external argv: array<string> = "argv"
|
|
47
|
+
|
|
48
|
+
@val @scope("process")
|
|
49
|
+
external cwd: unit => string = "cwd"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodefs from "node:fs";
|
|
4
|
+
|
|
5
|
+
function readDir(dir) {
|
|
6
|
+
try {
|
|
7
|
+
return Nodefs.readdirSync(dir, {
|
|
8
|
+
withFileTypes: true
|
|
9
|
+
});
|
|
10
|
+
} catch (exn) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
readDir,
|
|
17
|
+
}
|
|
18
|
+
/* node:fs Not a pure module */
|