@decohere/flux 0.0.1-dev.108 → 0.0.1-dev.11

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.
Files changed (43) hide show
  1. package/commonjs/src/flux.command.js +2 -2
  2. package/commonjs/src/flux.module.js +7 -8
  3. package/commonjs/src/hot-reload-server.js +215 -302
  4. package/commonjs/src/index.js +2 -34
  5. package/commonjs/src/serve.action.js +5 -76
  6. package/commonjs/src/serve.command.js +3 -31
  7. package/es6/src/flux.command.js +2 -2
  8. package/es6/src/flux.module.js +7 -8
  9. package/es6/src/hot-reload-server.js +172 -283
  10. package/es6/src/index.js +3 -5
  11. package/es6/src/serve.action.js +7 -71
  12. package/es6/src/serve.command.js +3 -31
  13. package/package.json +6 -7
  14. package/types/src/flux.module.d.ts +0 -2
  15. package/types/src/hot-reload-server.d.ts +22 -55
  16. package/types/src/index.d.ts +1 -8
  17. package/types/src/serve.action.d.ts +1 -11
  18. package/types/src/serve.command.d.ts +0 -5
  19. package/README.md +0 -247
  20. package/commonjs/bench/load.bench.js +0 -145
  21. package/commonjs/src/deferred-script-runner.js +0 -56
  22. package/commonjs/src/flux.js +0 -56
  23. package/commonjs/src/rewrite-serve-specifier.js +0 -59
  24. package/commonjs/src/run.action.js +0 -47
  25. package/commonjs/src/run.command.js +0 -65
  26. package/commonjs/src/slice-serve.js +0 -130
  27. package/commonjs/src/source-module-loader.js +0 -237
  28. package/es6/bench/load.bench.js +0 -136
  29. package/es6/src/deferred-script-runner.js +0 -46
  30. package/es6/src/flux.js +0 -41
  31. package/es6/src/rewrite-serve-specifier.js +0 -49
  32. package/es6/src/run.action.js +0 -37
  33. package/es6/src/run.command.js +0 -55
  34. package/es6/src/slice-serve.js +0 -105
  35. package/es6/src/source-module-loader.js +0 -181
  36. package/types/bench/load.bench.d.ts +0 -1
  37. package/types/src/deferred-script-runner.d.ts +0 -18
  38. package/types/src/flux.d.ts +0 -43
  39. package/types/src/rewrite-serve-specifier.d.ts +0 -14
  40. package/types/src/run.action.d.ts +0 -15
  41. package/types/src/run.command.d.ts +0 -11
  42. package/types/src/slice-serve.d.ts +0 -52
  43. package/types/src/source-module-loader.d.ts +0 -58
@@ -1,145 +0,0 @@
1
- /**
2
- * Cold-load benchmark for flux: how long the load hook takes to compile and import a workspace
3
- * whose files import each other, the way an app's do (#513).
4
- *
5
- * pnpm bench:flux # 8 libraries × 40 files, 10 processes
6
- * BENCH_LIBS=4 BENCH_FILES=100 BENCH_RUNS=5 pnpm bench:flux
7
- *
8
- * Generates the workspace in a temp directory: each library re-exports a `models/` directory
9
- * through its index (a directory import), each model imports the previous one (relative, with
10
- * `.js`) and the previous library by package name, and has a decorated class. Each process
11
- * imports the last library twice under different URL versions with a fresh loader cache, so
12
- * both loads transpile every file: the first is a real cold start, the second runs with Node
13
- * and SWC warmed up. Prints the median of each and the time per file.
14
- */ "use strict";
15
- Object.defineProperty(exports, "__esModule", {
16
- value: true
17
- });
18
- const _nodechild_process = require("node:child_process");
19
- const _nodefs = require("node:fs");
20
- const _nodeos = require("node:os");
21
- const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
22
- const _nodeurl = require("node:url");
23
- const _forge = require("@decohere/forge");
24
- const _sourcemoduleloader = require("../src/source-module-loader.js");
25
- function _interop_require_default(obj) {
26
- return obj && obj.__esModule ? obj : {
27
- default: obj
28
- };
29
- }
30
- const libs = Number(process.env.BENCH_LIBS ?? 8);
31
- const filesPerLib = Number(process.env.BENCH_FILES ?? 40);
32
- const runs = Number(process.env.BENCH_RUNS ?? 10);
33
- function write(file, content) {
34
- (0, _nodefs.mkdirSync)(_nodepath.default.dirname(file), {
35
- recursive: true
36
- });
37
- (0, _nodefs.writeFileSync)(file, content);
38
- }
39
- function generate(root) {
40
- write(_nodepath.default.join(root, "package.json"), JSON.stringify({
41
- name: "flux-bench",
42
- type: "module"
43
- }));
44
- write(_nodepath.default.join(root, "tsconfig.json"), JSON.stringify({
45
- compilerOptions: {
46
- experimentalDecorators: true
47
- }
48
- }));
49
- for(let lib = 0; lib < libs; lib++){
50
- const dir = _nodepath.default.join(root, "projects", `lib-${lib}`);
51
- write(_nodepath.default.join(dir, "package.json"), JSON.stringify({
52
- name: `@bench/lib-${lib}`,
53
- type: "module",
54
- main: "src/index.ts"
55
- }));
56
- const previousLib = lib > 0 ? `@bench/lib-${lib - 1}` : null;
57
- write(_nodepath.default.join(dir, "src/index.ts"), `export * from "./models";\n`);
58
- const exports1 = [];
59
- for(let file = 0; file < filesPerLib; file++){
60
- const name = `Model${lib}x${file}`;
61
- const previous = file > 0 ? `Model${lib}x${file - 1}` : null;
62
- write(_nodepath.default.join(dir, "src/models", `model-${file}.ts`), [
63
- previous ? `import { ${previous} } from "./model-${file - 1}.js";` : "",
64
- previousLib && file === 0 ? `import { Model${lib - 1}x0 } from "${previousLib}";` : "",
65
- `const tag = (_target: unknown) => {};`,
66
- `@tag`,
67
- `export class ${name} {`,
68
- `\tpublic readonly id: number = ${file};`,
69
- `\tpublic constructor(public readonly label: string = "${name}") {}`,
70
- `\tpublic describe(): string { return \`\${this.label}:\${this.id}\`; }`,
71
- previous ? `\tpublic previous = ${previous};` : "",
72
- previousLib && file === 0 ? `\tpublic upstream = Model${lib - 1}x0;` : "",
73
- `}`
74
- ].filter(Boolean).join("\n"));
75
- exports1.push(`export * from "./model-${file}.js";`);
76
- }
77
- write(_nodepath.default.join(dir, "src/models/index.ts"), `${exports1.join("\n")}\n`);
78
- }
79
- return _nodepath.default.join(root, "projects", `lib-${libs - 1}`, "src/index.ts");
80
- }
81
- /** One sample, in this process: the first load (cold) and a second one (warm Node and SWC). */ async function sample() {
82
- const root = (0, _nodefs.mkdtempSync)(_nodepath.default.join((0, _nodeos.tmpdir)(), "flux-bench-"));
83
- try {
84
- const entry = generate(root);
85
- const workspace = await (0, _forge.createWorkspace)({
86
- rootDir: root
87
- });
88
- const loader = new _sourcemoduleloader.SourceModuleLoader();
89
- const load = async (version)=>{
90
- const started = performance.now();
91
- await loader.configure({
92
- buildConfig: "debug",
93
- workspace,
94
- versionFileUrl: (fileUrl)=>`${fileUrl}?v=${version}`
95
- });
96
- loader.registerHooks();
97
- await loader.importEntry(entry);
98
- return performance.now() - started;
99
- };
100
- const cold = await load(1);
101
- const warm = await load(2);
102
- return {
103
- files: [
104
- ...loader.sourceFilePaths()
105
- ].length,
106
- cold,
107
- warm
108
- };
109
- } finally{
110
- (0, _nodefs.rmSync)(root, {
111
- recursive: true,
112
- force: true
113
- });
114
- }
115
- }
116
- const median = (values)=>[
117
- ...values
118
- ].sort((a, b)=>a - b)[Math.floor(values.length / 2)] ?? 0;
119
- if (process.argv.includes("--sample")) {
120
- console.log(JSON.stringify(await sample()));
121
- } else {
122
- // Each sample runs in a fresh process: Node never unloads modules, so loads in one process
123
- // slow down as the heap grows and the numbers drift.
124
- const results = Array.from({
125
- length: runs
126
- }, ()=>{
127
- const child = (0, _nodechild_process.spawnSync)(process.execPath, [
128
- ...process.execArgv,
129
- (0, _nodeurl.fileURLToPath)(require("url").pathToFileURL(__filename).toString()),
130
- "--sample"
131
- ], {
132
- encoding: "utf8",
133
- env: process.env
134
- });
135
- if (child.status !== 0) throw new Error(`sample failed:\n${child.stderr}`);
136
- const last = child.stdout.trim().split("\n").at(-1) ?? "";
137
- return JSON.parse(last);
138
- });
139
- const files = results[0]?.files ?? 0;
140
- const report = (label, values)=>{
141
- const ms = median(values);
142
- return `${label} ${ms.toFixed(1)} ms (${(ms / files * 1000).toFixed(0)} µs/file)`;
143
- };
144
- console.log(`flux load, ${files} files, median of ${runs} processes: ` + `${report("first", results.map((r)=>r.cold))}, ` + `${report("second", results.map((r)=>r.warm))}`);
145
- }
@@ -1,56 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "DeferredScriptRunner", {
6
- enumerable: true,
7
- get: function() {
8
- return DeferredScriptRunner;
9
- }
10
- });
11
- const _nodechild_process = require("node:child_process");
12
- const _decorators = require("@decohere/crucible/decorators");
13
- const _interop = require("@decohere/nexus/interop");
14
- const _scribe = require("@decohere/scribe");
15
- function _ts_decorate(decorators, target, key, desc) {
16
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
17
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
18
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
19
- return c > 3 && r && Object.defineProperty(target, key, r), r;
20
- }
21
- class DeferredScriptRunner {
22
- logger = _scribe.scribe.logger(DeferredScriptRunner.name);
23
- children = [];
24
- start(options) {
25
- const pm = (0, _interop.detectPackageManager)(options.workspaceRoot) ?? (0, _interop.packageManagerFromString)("pnpm");
26
- this.logger.info(`deferred ${options.label} — running ${pm.name} run ${options.script} in ${options.cwd}`);
27
- const child = (0, _nodechild_process.spawn)(pm.name, [
28
- "run",
29
- options.script
30
- ], {
31
- cwd: options.cwd,
32
- stdio: "inherit",
33
- env: process.env,
34
- shell: false
35
- });
36
- child.on("exit", (code, signal)=>{
37
- if (signal) return;
38
- if (code != null && code !== 0) {
39
- this.logger.warn(`deferred ${options.label} exited with ${code}`);
40
- }
41
- });
42
- this.children.push(child);
43
- return child;
44
- }
45
- async [Symbol.asyncDispose]() {
46
- for (const child of this.children){
47
- if (!child.killed) {
48
- child.kill("SIGTERM");
49
- }
50
- }
51
- this.children.length = 0;
52
- }
53
- }
54
- DeferredScriptRunner = _ts_decorate([
55
- (0, _decorators.injectable)()
56
- ], DeferredScriptRunner);
@@ -1,56 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "flux", {
6
- enumerable: true,
7
- get: function() {
8
- return flux;
9
- }
10
- });
11
- const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
12
- const _hotreloadserver = require("./hot-reload-server.js");
13
- const _sourcemoduleloader = require("./source-module-loader.js");
14
- function _interop_require_default(obj) {
15
- return obj && obj.__esModule ? obj : {
16
- default: obj
17
- };
18
- }
19
- /** Process-level one-shot loader so a second `run()` reconfigures instead of stacking hooks. */ const runLoader = new _sourcemoduleloader.SourceModuleLoader();
20
- async function run(entry, options = {}) {
21
- const trimmed = entry.trim();
22
- if (trimmed == null || trimmed === "") {
23
- throw new Error("flux.run requires an entry file path");
24
- }
25
- const absoluteEntry = _nodepath.default.resolve(trimmed);
26
- await runLoader.configure({
27
- workspace: options.workspace,
28
- buildConfig: options.configuration ?? "debug"
29
- });
30
- runLoader.registerHooks();
31
- process.argv = [
32
- process.execPath,
33
- absoluteEntry,
34
- ...options.args ?? []
35
- ];
36
- return runLoader.importEntry(absoluteEntry);
37
- }
38
- async function serve(options = {}) {
39
- const server = new _hotreloadserver.HotReloadServer();
40
- await server.start({
41
- buildConfig: options.configuration ?? "debug",
42
- project: options.project,
43
- projects: options.projects,
44
- workspace: options.workspace,
45
- rebootDebounceMs: options.rebootDebounceMs
46
- });
47
- return server;
48
- }
49
- function dispose() {
50
- runLoader.dispose();
51
- }
52
- const flux = {
53
- run,
54
- serve,
55
- dispose
56
- };
@@ -1,59 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "rewriteServeSpecifier", {
6
- enumerable: true,
7
- get: function() {
8
- return rewriteServeSpecifier;
9
- }
10
- });
11
- const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
12
- const _nodeurl = require("node:url");
13
- const _mesh = require("@decohere/mesh");
14
- function _interop_require_default(obj) {
15
- return obj && obj.__esModule ? obj : {
16
- default: obj
17
- };
18
- }
19
- function rewriteServeSpecifier(options) {
20
- const { specifier, parentUrl, isWatchedTs, resolveBare, versionFileUrl } = options;
21
- const relativeTs = resolveRelativeWatchedTs(specifier, parentUrl, isWatchedTs);
22
- if (relativeTs != null) {
23
- return versionFileUrl((0, _nodeurl.pathToFileURL)(relativeTs).toString());
24
- }
25
- const bareTarget = resolveBare(specifier);
26
- const bareTs = bareTarget == null ? null : watchedTs(bareTarget, isWatchedTs);
27
- if (bareTs != null) {
28
- return versionFileUrl((0, _nodeurl.pathToFileURL)(bareTs).toString());
29
- }
30
- return null;
31
- }
32
- /**
33
- * The watched `.ts` file a path names: itself (with `.js` read as `.ts`, or `.ts` added), else
34
- * the `index.ts` of the directory it names. A file wins over a directory of the same name.
35
- */ function watchedTs(filePath, isWatchedTs) {
36
- const withoutSlash = filePath.replace(/[/\\]+$/, "");
37
- const stem = withoutSlash.replace(/\.(js|ts)$/, "");
38
- // From the stem: Mesh's alias lookup has already added `.ts` to a subpath that names a
39
- // directory (`@lib/models` arrives as `…/models.ts`).
40
- const candidates = [
41
- `${stem}.ts`,
42
- _nodepath.default.join(stem, "index.ts")
43
- ];
44
- return candidates.find((candidate)=>isWatchedTs(candidate)) ?? null;
45
- }
46
- function resolveRelativeWatchedTs(specifier, parentUrl, isWatchedTs) {
47
- if (_mesh.packageAliases.isBareSpecifier(specifier)) return null;
48
- if (!(specifier.startsWith(".") || specifier.startsWith("/"))) return null;
49
- const parentClean = parentUrl.split("?")[0];
50
- if (parentClean == null || parentClean === "") return null;
51
- let resolved;
52
- try {
53
- resolved = new URL(specifier, parentClean);
54
- } catch {
55
- return null;
56
- }
57
- if (resolved.protocol !== "file:") return null;
58
- return watchedTs((0, _nodeurl.fileURLToPath)(resolved), isWatchedTs);
59
- }
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "RunAction", {
6
- enumerable: true,
7
- get: function() {
8
- return RunAction;
9
- }
10
- });
11
- const _decorators = require("@decohere/crucible/decorators");
12
- const _mesh = require("@decohere/mesh");
13
- const _cli = require("@decohere/nexus/cli");
14
- const _scribe = require("@decohere/scribe");
15
- const _flux = require("./flux.js");
16
- function _ts_decorate(decorators, target, key, desc) {
17
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
18
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
19
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
- return c > 3 && r && Object.defineProperty(target, key, r), r;
21
- }
22
- function _ts_metadata(k, v) {
23
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
24
- }
25
- class RunAction {
26
- workspace;
27
- logger = _scribe.scribe.logger(RunAction.name);
28
- constructor(workspace){
29
- this.workspace = workspace;
30
- }
31
- async run(options) {
32
- this.logger.trace(`Running ${options.entry}`);
33
- await _flux.flux.run(options.entry, {
34
- configuration: options.configuration,
35
- args: options.args,
36
- workspace: this.workspace
37
- });
38
- return _cli.ActionResponse.Success(RunAction.name);
39
- }
40
- }
41
- RunAction = _ts_decorate([
42
- (0, _decorators.injectable)(),
43
- _ts_metadata("design:type", Function),
44
- _ts_metadata("design:paramtypes", [
45
- typeof _mesh.Workspace === "undefined" ? Object : _mesh.Workspace
46
- ])
47
- ], RunAction);
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "RunCommand", {
6
- enumerable: true,
7
- get: function() {
8
- return RunCommand;
9
- }
10
- });
11
- const _cli = require("@decohere/nexus/cli");
12
- const _runaction = require("./run.action.js");
13
- class RunCommand extends _cli.DecohereCommand {
14
- get actions() {
15
- return [
16
- _runaction.RunAction
17
- ];
18
- }
19
- constructor(name){
20
- super(name);
21
- this.description("Compile and run a TypeScript entry on the fly (no watch / HMR)");
22
- this.argument("<entry>", "Path to the TypeScript entry file");
23
- this.argument("[args...]", "Arguments forwarded to the entry after rewriting argv");
24
- this.addOption(new _cli.ConfigurationOption("debug"));
25
- }
26
- /**
27
- * Commander passes positionals before options when `<entry> [args...]` is declared.
28
- * The CLI host ModuleFactory expects `(opts, cmd)` — normalize and stash entry/args on opts.
29
- */ action(fn) {
30
- return super.action((...args)=>{
31
- const cmd = args.at(-1);
32
- const opts = args.at(-2);
33
- const { entry, entryArgs } = normalizeRunPositionals(args.slice(0, -2));
34
- cmd.setOptionValue("entry", entry);
35
- cmd.setOptionValue("args", entryArgs);
36
- return fn(opts, cmd);
37
- });
38
- }
39
- }
40
- /** Commander yields `[entry, args[]]` or sometimes a flat list depending on arity. */ function normalizeRunPositionals(positionals) {
41
- if (positionals.length === 0) {
42
- return {
43
- entry: "",
44
- entryArgs: []
45
- };
46
- }
47
- const first = positionals[0];
48
- if (typeof first !== "string" || first === "") {
49
- return {
50
- entry: "",
51
- entryArgs: []
52
- };
53
- }
54
- const second = positionals[1];
55
- if (Array.isArray(second)) {
56
- return {
57
- entry: first,
58
- entryArgs: second.filter((s)=>typeof s === "string")
59
- };
60
- }
61
- return {
62
- entry: first,
63
- entryArgs: positionals.slice(1).filter((s)=>typeof s === "string" && s !== "")
64
- };
65
- }
@@ -1,130 +0,0 @@
1
- /**
2
- * Directory-slice helpers for `flux serve <dir>…` — classify Mesh packages as
3
- * Flux apps, Nixpacks-style script deferrals, or libraries to skip.
4
- */ "use strict";
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- function _export(target, all) {
9
- for(var name in all)Object.defineProperty(target, name, {
10
- enumerable: true,
11
- get: Object.getOwnPropertyDescriptor(all, name).get
12
- });
13
- }
14
- _export(exports, {
15
- get DEFER_SCRIPT_CANDIDATES () {
16
- return DEFER_SCRIPT_CANDIDATES;
17
- },
18
- get classifySliceProject () {
19
- return classifySliceProject;
20
- },
21
- get classifySliceProjects () {
22
- return classifySliceProjects;
23
- },
24
- get isFluxAppMain () {
25
- return isFluxAppMain;
26
- },
27
- get isFluxOwnedScript () {
28
- return isFluxOwnedScript;
29
- },
30
- get isUnderSlice () {
31
- return isUnderSlice;
32
- },
33
- get normalizeSlicePrefix () {
34
- return normalizeSlicePrefix;
35
- },
36
- get projectsInSlice () {
37
- return projectsInSlice;
38
- },
39
- get projectsInSlices () {
40
- return projectsInSlices;
41
- },
42
- get resolveDeferScript () {
43
- return resolveDeferScript;
44
- }
45
- });
46
- const DEFER_SCRIPT_CANDIDATES = [
47
- "dev",
48
- "serve"
49
- ];
50
- function normalizeSlicePrefix(slice) {
51
- const trimmed = slice.replaceAll("\\", "/").replace(/\/+$/, "");
52
- if (trimmed === "" || trimmed === ".") {
53
- throw new Error("Slice directory must be a non-empty path");
54
- }
55
- if (trimmed === "projects" || trimmed.startsWith("projects/")) {
56
- return trimmed;
57
- }
58
- return `projects/${trimmed}`;
59
- }
60
- function isUnderSlice(projectDirectory, slicePrefix) {
61
- const dir = projectDirectory.replaceAll("\\", "/").replace(/\/+$/, "");
62
- const prefix = slicePrefix.replaceAll("\\", "/").replace(/\/+$/, "");
63
- if (dir === prefix || dir.startsWith(`${prefix}/`)) {
64
- return true;
65
- }
66
- // Flat monorepo packages: projects/<module>.<role>
67
- return dir.startsWith(`${prefix}.`);
68
- }
69
- function projectsInSlice(projects, slice) {
70
- const prefix = normalizeSlicePrefix(slice);
71
- return projects.filter((p)=>isUnderSlice(p.projectDirectory, prefix));
72
- }
73
- function projectsInSlices(projects, slices) {
74
- const byName = new Map();
75
- for (const slice of slices){
76
- for (const project of projectsInSlice(projects, slice)){
77
- byName.set(project.name, project);
78
- }
79
- }
80
- return [
81
- ...byName.values()
82
- ];
83
- }
84
- function isFluxOwnedScript(script) {
85
- return /\bflux\b/i.test(script);
86
- }
87
- function resolveDeferScript(scripts) {
88
- for (const name of DEFER_SCRIPT_CANDIDATES){
89
- const body = scripts[name];
90
- if (body != null && body !== "" && !isFluxOwnedScript(body)) {
91
- return name;
92
- }
93
- }
94
- return undefined;
95
- }
96
- function isFluxAppMain(main) {
97
- const normalized = main.replaceAll("\\", "/");
98
- return /(^|\/)main\.tsx?$/.test(normalized);
99
- }
100
- function classifySliceProject(project) {
101
- if (resolveDeferScript(project.scripts) != null) {
102
- return "defer";
103
- }
104
- if (isFluxAppMain(project.main)) {
105
- return "flux";
106
- }
107
- return "skip";
108
- }
109
- function classifySliceProjects(projects, slices) {
110
- const tokens = typeof slices === "string" ? [
111
- slices
112
- ] : [
113
- ...slices
114
- ];
115
- const inSlice = projectsInSlices(projects, tokens);
116
- const flux = [];
117
- const defer = [];
118
- const skip = [];
119
- for (const project of inSlice){
120
- const kind = classifySliceProject(project);
121
- if (kind === "flux") flux.push(project);
122
- else if (kind === "defer") defer.push(project);
123
- else skip.push(project);
124
- }
125
- return {
126
- flux,
127
- defer,
128
- skip
129
- };
130
- }