blackmistcode commited on
Commit
0dc7194
·
verified ·
1 Parent(s): 8c6b969

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .claude/memory/feedback_no_chrome_devtools.md +11 -0
  2. .gitattributes +7 -0
  3. backend/node_modules/.prisma/client/libquery_engine-darwin-arm64.dylib.node +3 -0
  4. backend/node_modules/.prisma/client/query_engine_bg.wasm +3 -0
  5. backend/node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node +3 -0
  6. backend/node_modules/@prisma/engines/schema-engine-darwin-arm64 +3 -0
  7. backend/node_modules/c12/dist/index.d.mts +157 -0
  8. backend/node_modules/c12/dist/index.mjs +112 -0
  9. backend/node_modules/c12/dist/shared/c12.BXpNC6YI.mjs +401 -0
  10. backend/node_modules/c12/dist/update.d.mts +53 -0
  11. backend/node_modules/c12/dist/update.mjs +74 -0
  12. backend/node_modules/chokidar/esm/handler.d.ts +90 -0
  13. backend/node_modules/chokidar/esm/handler.js +629 -0
  14. backend/node_modules/chokidar/esm/index.d.ts +215 -0
  15. backend/node_modules/chokidar/esm/index.js +798 -0
  16. backend/node_modules/chokidar/esm/package.json +1 -0
  17. backend/node_modules/dotenv/lib/cli-options.js +17 -0
  18. backend/node_modules/dotenv/lib/env-options.js +28 -0
  19. backend/node_modules/dotenv/lib/main.d.ts +162 -0
  20. backend/node_modules/dotenv/lib/main.js +386 -0
  21. backend/node_modules/effect/src/internal/layer/circular.ts +214 -0
  22. backend/node_modules/effect/src/internal/metric/label.ts +41 -0
  23. backend/node_modules/effect/src/internal/metric/pair.ts +48 -0
  24. backend/node_modules/effect/src/internal/metric/polling.ts +149 -0
  25. backend/node_modules/effect/src/internal/metric/state.ts +290 -0
  26. backend/node_modules/effect/src/internal/opCodes/channelUpstreamPullStrategy.ts +11 -0
  27. backend/node_modules/effect/src/internal/schema/util.ts +50 -0
  28. backend/node_modules/effect/src/internal/supervisor/patch.ts +190 -0
  29. backend/node_modules/perfect-debounce/dist/index.cjs +59 -0
  30. backend/node_modules/perfect-debounce/dist/index.d.ts +34 -0
  31. backend/node_modules/perfect-debounce/dist/index.mjs +57 -0
  32. backend/node_modules/prisma/build/child.js +0 -0
  33. backend/node_modules/prisma/build/prisma_schema_build_bg.wasm +3 -0
  34. backend/node_modules/prisma/build/public/assets/alert.60ea9f84.svg +5 -0
  35. backend/node_modules/prisma/build/public/assets/array.1a36c222.svg +4 -0
  36. backend/node_modules/prisma/build/public/assets/boolean.9188b434.svg +4 -0
  37. backend/node_modules/prisma/build/public/assets/chevron-down.24f76e3c.svg +3 -0
  38. backend/node_modules/prisma/build/public/assets/cross.c2610cf5.svg +11 -0
  39. backend/node_modules/prisma/build/public/assets/datetime.a3bf710a.svg +4 -0
  40. backend/node_modules/prisma/build/public/assets/download.8d34b65a.svg +4 -0
  41. backend/node_modules/prisma/build/public/assets/ellipsis.a8c5a34a.svg +10 -0
  42. backend/node_modules/prisma/build/public/assets/enum.7ec0b64c.svg +6 -0
  43. backend/node_modules/prisma/build/public/assets/folder.d77b8eaf.svg +6 -0
  44. backend/node_modules/prisma/build/public/assets/hamburger.5fdadeac.svg +4 -0
  45. backend/node_modules/prisma/build/public/assets/index.js +0 -0
  46. backend/node_modules/prisma/build/public/assets/inter-all-400-normal.4c1f8a0d.woff +3 -0
  47. backend/node_modules/prisma/build/public/assets/inter-all-600-normal.d0a7c8a9.woff +3 -0
  48. backend/node_modules/prisma/build/public/assets/inter-cyrillic-400-normal.ac97a49e.woff2 +0 -0
  49. backend/node_modules/prisma/build/public/assets/inter-cyrillic-600-normal.2c917f10.woff2 +0 -0
  50. backend/node_modules/prisma/build/public/assets/inter-cyrillic-ext-400-normal.f21a6a97.woff2 +0 -0
.claude/memory/feedback_no_chrome_devtools.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: No usar Chrome DevTools para verificar UI
3
+ description: El usuario prefiere verificar los cambios de UI él mismo, sin que Claude use Chrome DevTools
4
+ type: feedback
5
+ ---
6
+
7
+ No usar Chrome DevTools MCP para tomar screenshots o interactuar con el navegador después de hacer cambios de UI. El usuario prefiere revisar los cambios visualmente por su cuenta.
8
+
9
+ **Why:** El usuario lo indicó explícitamente cuando se usaban las herramientas de Chrome para verificar cambios CSS/JS.
10
+
11
+ **How to apply:** Después de hacer cambios de CSS o JS en la UI, describir los cambios realizados y dejar que el usuario los verifique en el navegador.
.gitattributes CHANGED
@@ -33,3 +33,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ backend/node_modules/prisma/libquery_engine-darwin-arm64.dylib.node filter=lfs diff=lfs merge=lfs -text
37
+ backend/node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node filter=lfs diff=lfs merge=lfs -text
38
+ backend/node_modules/@prisma/engines/schema-engine-darwin-arm64 filter=lfs diff=lfs merge=lfs -text
39
+ backend/node_modules/.prisma/client/libquery_engine-darwin-arm64.dylib.node filter=lfs diff=lfs merge=lfs -text
40
+ backend/node_modules/prisma/build/public/icon-1024.png filter=lfs diff=lfs merge=lfs -text
41
+ backend/node_modules/prisma/build/public/assets/inter-all-400-normal.4c1f8a0d.woff filter=lfs diff=lfs merge=lfs -text
42
+ backend/node_modules/prisma/build/public/assets/inter-all-600-normal.d0a7c8a9.woff filter=lfs diff=lfs merge=lfs -text
backend/node_modules/.prisma/client/libquery_engine-darwin-arm64.dylib.node ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:afb9cb5a12ea42caa6f6498e40e9cb75059cae17098aadcc1001c99bb262e1ee
3
+ size 19356128
backend/node_modules/.prisma/client/query_engine_bg.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7ec8cd57e69e5e061c71accb0ae4ea5a258b074e51da112c6d871d398e259eba
3
+ size 2171299
backend/node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:afb9cb5a12ea42caa6f6498e40e9cb75059cae17098aadcc1001c99bb262e1ee
3
+ size 19356128
backend/node_modules/@prisma/engines/schema-engine-darwin-arm64 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:caa2cf90d5b2cfe6cc06e47974f7e3275dd395b4d35cf140d5d4b2362c3b5bb1
3
+ size 21686160
backend/node_modules/c12/dist/index.d.mts ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Jiti, JitiOptions } from 'jiti';
2
+ import { DownloadTemplateOptions } from 'giget';
3
+ import { ChokidarOptions } from 'chokidar';
4
+ import { diff } from 'ohash/utils';
5
+
6
+ interface DotenvOptions {
7
+ /**
8
+ * The project root directory (either absolute or relative to the current working directory).
9
+ */
10
+ cwd: string;
11
+ /**
12
+ * What file to look in for environment variables (either absolute or relative
13
+ * to the current working directory). For example, `.env`.
14
+ */
15
+ fileName?: string;
16
+ /**
17
+ * Whether to interpolate variables within .env.
18
+ *
19
+ * @example
20
+ * ```env
21
+ * BASE_DIR="/test"
22
+ * # resolves to "/test/further"
23
+ * ANOTHER_DIR="${BASE_DIR}/further"
24
+ * ```
25
+ */
26
+ interpolate?: boolean;
27
+ /**
28
+ * An object describing environment variables (key, value pairs).
29
+ */
30
+ env?: NodeJS.ProcessEnv;
31
+ }
32
+ type Env = typeof process.env;
33
+ /**
34
+ * Load and interpolate environment variables into `process.env`.
35
+ * If you need more control (or access to the values), consider using `loadDotenv` instead
36
+ *
37
+ */
38
+ declare function setupDotenv(options: DotenvOptions): Promise<Env>;
39
+ /** Load environment variables into an object. */
40
+ declare function loadDotenv(options: DotenvOptions): Promise<Env>;
41
+ declare global {
42
+ var __c12_dotenv_vars__: Map<Record<string, any>, Set<string>>;
43
+ }
44
+
45
+ interface ConfigLayerMeta {
46
+ name?: string;
47
+ [key: string]: any;
48
+ }
49
+ type UserInputConfig = Record<string, any>;
50
+ interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
51
+ $test?: T;
52
+ $development?: T;
53
+ $production?: T;
54
+ $env?: Record<string, T>;
55
+ $meta?: MT;
56
+ }
57
+ type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
58
+ interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
59
+ /** Custom meta for layer */
60
+ meta?: MT;
61
+ /** Layer config overrides */
62
+ overrides?: T;
63
+ [key: string]: any;
64
+ /**
65
+ * Options for cloning remote sources
66
+ *
67
+ * @see https://giget.unjs.io
68
+ */
69
+ giget?: DownloadTemplateOptions;
70
+ /**
71
+ * Install dependencies after cloning
72
+ *
73
+ * @see https://nypm.unjs.io
74
+ */
75
+ install?: boolean;
76
+ /**
77
+ * Token for cloning private sources
78
+ *
79
+ * @see https://giget.unjs.io#providing-token-for-private-repositories
80
+ */
81
+ auth?: string;
82
+ }
83
+ interface ConfigLayer<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
84
+ config: T | null;
85
+ source?: string;
86
+ sourceOptions?: SourceOptions<T, MT>;
87
+ meta?: MT;
88
+ cwd?: string;
89
+ configFile?: string;
90
+ }
91
+ interface ResolvedConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends ConfigLayer<T, MT> {
92
+ config: T;
93
+ layers?: ConfigLayer<T, MT>[];
94
+ cwd?: string;
95
+ }
96
+ type ConfigSource = "overrides" | "main" | "rc" | "packageJson" | "defaultConfig";
97
+ interface ResolvableConfigContext<T extends UserInputConfig = UserInputConfig> {
98
+ configs: Record<ConfigSource, T | null | undefined>;
99
+ rawConfigs: Record<ConfigSource, ResolvableConfig<T> | null | undefined>;
100
+ }
101
+ type MaybePromise<T> = T | Promise<T>;
102
+ type ResolvableConfig<T extends UserInputConfig = UserInputConfig> = MaybePromise<T | null | undefined> | ((ctx: ResolvableConfigContext<T>) => MaybePromise<T | null | undefined>);
103
+ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
104
+ name?: string;
105
+ cwd?: string;
106
+ configFile?: string;
107
+ rcFile?: false | string;
108
+ globalRc?: boolean;
109
+ dotenv?: boolean | DotenvOptions;
110
+ envName?: string | false;
111
+ packageJson?: boolean | string | string[];
112
+ defaults?: T;
113
+ defaultConfig?: ResolvableConfig<T>;
114
+ overrides?: ResolvableConfig<T>;
115
+ omit$Keys?: boolean;
116
+ resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
117
+ jiti?: Jiti;
118
+ jitiOptions?: JitiOptions;
119
+ giget?: false | DownloadTemplateOptions;
120
+ merger?: (...sources: Array<T | null | undefined>) => T;
121
+ extend?: false | {
122
+ extendKey?: string | string[];
123
+ };
124
+ }
125
+ type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
126
+ declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
127
+
128
+ declare const SUPPORTED_EXTENSIONS: string[];
129
+ declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
130
+
131
+ type DiffEntries = ReturnType<typeof diff>;
132
+ type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
133
+ watchingFiles: string[];
134
+ unwatch: () => Promise<void>;
135
+ };
136
+ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends LoadConfigOptions<T, MT> {
137
+ chokidarOptions?: ChokidarOptions;
138
+ debounce?: false | number;
139
+ onWatch?: (event: {
140
+ type: "created" | "updated" | "removed";
141
+ path: string;
142
+ }) => void | Promise<void>;
143
+ acceptHMR?: (context: {
144
+ getDiff: () => DiffEntries;
145
+ newConfig: ResolvedConfig<T, MT>;
146
+ oldConfig: ResolvedConfig<T, MT>;
147
+ }) => void | boolean | Promise<void | boolean>;
148
+ onUpdate?: (context: {
149
+ getDiff: () => ReturnType<typeof diff>;
150
+ newConfig: ResolvedConfig<T, MT>;
151
+ oldConfig: ResolvedConfig<T, MT>;
152
+ }) => void | Promise<void>;
153
+ }
154
+ declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
155
+
156
+ export { SUPPORTED_EXTENSIONS, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
157
+ export type { C12InputConfig, ConfigLayer, ConfigLayerMeta, ConfigSource, ConfigWatcher, DefineConfig, DotenvOptions, Env, InputConfig, LoadConfigOptions, ResolvableConfig, ResolvableConfigContext, ResolvedConfig, SourceOptions, UserInputConfig, WatchConfigOptions };
backend/node_modules/c12/dist/index.mjs ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { l as loadConfig, S as SUPPORTED_EXTENSIONS } from './shared/c12.BXpNC6YI.mjs';
2
+ export { a as loadDotenv, s as setupDotenv } from './shared/c12.BXpNC6YI.mjs';
3
+ import { debounce } from 'perfect-debounce';
4
+ import { resolve } from 'pathe';
5
+ import 'node:fs';
6
+ import 'node:fs/promises';
7
+ import 'node:url';
8
+ import 'node:os';
9
+ import 'exsolve';
10
+ import 'jiti';
11
+ import 'rc9';
12
+ import 'defu';
13
+ import 'pkg-types';
14
+ import 'dotenv';
15
+
16
+ function createDefineConfig() {
17
+ return (input) => input;
18
+ }
19
+
20
+ const eventMap = {
21
+ add: "created",
22
+ change: "updated",
23
+ unlink: "removed"
24
+ };
25
+ async function watchConfig(options) {
26
+ let config = await loadConfig(options);
27
+ const configName = options.name || "config";
28
+ const configFileName = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
29
+ const watchingFiles = [
30
+ ...new Set(
31
+ (config.layers || []).filter((l) => l.cwd).flatMap((l) => [
32
+ ...SUPPORTED_EXTENSIONS.flatMap((ext) => [
33
+ resolve(l.cwd, configFileName + ext),
34
+ resolve(l.cwd, ".config", configFileName + ext),
35
+ resolve(
36
+ l.cwd,
37
+ ".config",
38
+ configFileName.replace(/\.config$/, "") + ext
39
+ )
40
+ ]),
41
+ l.source && resolve(l.cwd, l.source),
42
+ // TODO: Support watching rc from home and workspace
43
+ options.rcFile && resolve(
44
+ l.cwd,
45
+ typeof options.rcFile === "string" ? options.rcFile : `.${configName}rc`
46
+ ),
47
+ options.packageJson && resolve(l.cwd, "package.json")
48
+ ]).filter(Boolean)
49
+ )
50
+ ];
51
+ const watch = await import('chokidar').then((r) => r.watch || r.default || r);
52
+ const { diff } = await import('ohash/utils');
53
+ const _fswatcher = watch(watchingFiles, {
54
+ ignoreInitial: true,
55
+ ...options.chokidarOptions
56
+ });
57
+ const onChange = async (event, path) => {
58
+ const type = eventMap[event];
59
+ if (!type) {
60
+ return;
61
+ }
62
+ if (options.onWatch) {
63
+ await options.onWatch({
64
+ type,
65
+ path
66
+ });
67
+ }
68
+ const oldConfig = config;
69
+ try {
70
+ config = await loadConfig(options);
71
+ } catch (error) {
72
+ console.warn(`Failed to load config ${path}
73
+ ${error}`);
74
+ return;
75
+ }
76
+ const changeCtx = {
77
+ newConfig: config,
78
+ oldConfig,
79
+ getDiff: () => diff(oldConfig.config, config.config)
80
+ };
81
+ if (options.acceptHMR) {
82
+ const changeHandled = await options.acceptHMR(changeCtx);
83
+ if (changeHandled) {
84
+ return;
85
+ }
86
+ }
87
+ if (options.onUpdate) {
88
+ await options.onUpdate(changeCtx);
89
+ }
90
+ };
91
+ if (options.debounce === false) {
92
+ _fswatcher.on("all", onChange);
93
+ } else {
94
+ _fswatcher.on("all", debounce(onChange, options.debounce ?? 100));
95
+ }
96
+ const utils = {
97
+ watchingFiles,
98
+ unwatch: async () => {
99
+ await _fswatcher.close();
100
+ }
101
+ };
102
+ return new Proxy(utils, {
103
+ get(_, prop) {
104
+ if (prop in utils) {
105
+ return utils[prop];
106
+ }
107
+ return config[prop];
108
+ }
109
+ });
110
+ }
111
+
112
+ export { SUPPORTED_EXTENSIONS, createDefineConfig, loadConfig, watchConfig };
backend/node_modules/c12/dist/shared/c12.BXpNC6YI.mjs ADDED
@@ -0,0 +1,401 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { statSync, promises, existsSync } from 'node:fs';
2
+ import { rm, readFile } from 'node:fs/promises';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { homedir } from 'node:os';
5
+ import { resolve, join, dirname, basename, extname, normalize } from 'pathe';
6
+ import { resolveModulePath } from 'exsolve';
7
+ import { createJiti } from 'jiti';
8
+ import * as rc9 from 'rc9';
9
+ import { defu } from 'defu';
10
+ import { findWorkspaceDir, readPackageJSON } from 'pkg-types';
11
+ import * as dotenv from 'dotenv';
12
+
13
+ async function setupDotenv(options) {
14
+ const targetEnvironment = options.env ?? process.env;
15
+ const environment = await loadDotenv({
16
+ cwd: options.cwd,
17
+ fileName: options.fileName ?? ".env",
18
+ env: targetEnvironment,
19
+ interpolate: options.interpolate ?? true
20
+ });
21
+ const dotenvVars = getDotEnvVars(targetEnvironment);
22
+ for (const key in environment) {
23
+ if (key.startsWith("_")) {
24
+ continue;
25
+ }
26
+ if (targetEnvironment[key] === void 0 || dotenvVars.has(key)) {
27
+ targetEnvironment[key] = environment[key];
28
+ }
29
+ }
30
+ return environment;
31
+ }
32
+ async function loadDotenv(options) {
33
+ const environment = /* @__PURE__ */ Object.create(null);
34
+ const dotenvFile = resolve(options.cwd, options.fileName);
35
+ const dotenvVars = getDotEnvVars(options.env || {});
36
+ Object.assign(environment, options.env);
37
+ if (statSync(dotenvFile, { throwIfNoEntry: false })?.isFile()) {
38
+ const parsed = dotenv.parse(await promises.readFile(dotenvFile, "utf8"));
39
+ for (const key in parsed) {
40
+ if (key in environment && !dotenvVars.has(key)) {
41
+ continue;
42
+ }
43
+ environment[key] = parsed[key];
44
+ dotenvVars.add(key);
45
+ }
46
+ }
47
+ if (options.interpolate) {
48
+ interpolate(environment);
49
+ }
50
+ return environment;
51
+ }
52
+ function interpolate(target, source = {}, parse = (v) => v) {
53
+ function getValue(key) {
54
+ return source[key] === void 0 ? target[key] : source[key];
55
+ }
56
+ function interpolate2(value, parents = []) {
57
+ if (typeof value !== "string") {
58
+ return value;
59
+ }
60
+ const matches = value.match(/(.?\${?(?:[\w:]+)?}?)/g) || [];
61
+ return parse(
62
+ // eslint-disable-next-line unicorn/no-array-reduce
63
+ matches.reduce((newValue, match) => {
64
+ const parts = /(.?)\${?([\w:]+)?}?/g.exec(match) || [];
65
+ const prefix = parts[1];
66
+ let value2, replacePart;
67
+ if (prefix === "\\") {
68
+ replacePart = parts[0] || "";
69
+ value2 = replacePart.replace(String.raw`\$`, "$");
70
+ } else {
71
+ const key = parts[2];
72
+ replacePart = (parts[0] || "").slice(prefix.length);
73
+ if (parents.includes(key)) {
74
+ console.warn(
75
+ `Please avoid recursive environment variables ( loop: ${parents.join(
76
+ " > "
77
+ )} > ${key} )`
78
+ );
79
+ return "";
80
+ }
81
+ value2 = getValue(key);
82
+ value2 = interpolate2(value2, [...parents, key]);
83
+ }
84
+ return value2 === void 0 ? newValue : newValue.replace(replacePart, value2);
85
+ }, value)
86
+ );
87
+ }
88
+ for (const key in target) {
89
+ target[key] = interpolate2(getValue(key));
90
+ }
91
+ }
92
+ function getDotEnvVars(targetEnvironment) {
93
+ const globalRegistry = globalThis.__c12_dotenv_vars__ ||= /* @__PURE__ */ new Map();
94
+ if (!globalRegistry.has(targetEnvironment)) {
95
+ globalRegistry.set(targetEnvironment, /* @__PURE__ */ new Set());
96
+ }
97
+ return globalRegistry.get(targetEnvironment);
98
+ }
99
+
100
+ const _normalize = (p) => p?.replace(/\\/g, "/");
101
+ const ASYNC_LOADERS = {
102
+ ".yaml": () => import('confbox/yaml').then((r) => r.parseYAML),
103
+ ".yml": () => import('confbox/yaml').then((r) => r.parseYAML),
104
+ ".jsonc": () => import('confbox/jsonc').then((r) => r.parseJSONC),
105
+ ".json5": () => import('confbox/json5').then((r) => r.parseJSON5),
106
+ ".toml": () => import('confbox/toml').then((r) => r.parseTOML)
107
+ };
108
+ const SUPPORTED_EXTENSIONS = Object.freeze([
109
+ // with jiti
110
+ ".js",
111
+ ".ts",
112
+ ".mjs",
113
+ ".cjs",
114
+ ".mts",
115
+ ".cts",
116
+ ".json",
117
+ // with confbox
118
+ ".jsonc",
119
+ ".json5",
120
+ ".yaml",
121
+ ".yml",
122
+ ".toml"
123
+ ]);
124
+ async function loadConfig(options) {
125
+ options.cwd = resolve(process.cwd(), options.cwd || ".");
126
+ options.name = options.name || "config";
127
+ options.envName = options.envName ?? process.env.NODE_ENV;
128
+ options.configFile = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
129
+ options.rcFile = options.rcFile ?? `.${options.name}rc`;
130
+ if (options.extend !== false) {
131
+ options.extend = {
132
+ extendKey: "extends",
133
+ ...options.extend
134
+ };
135
+ }
136
+ const _merger = options.merger || defu;
137
+ options.jiti = options.jiti || createJiti(join(options.cwd, options.configFile), {
138
+ interopDefault: true,
139
+ moduleCache: false,
140
+ extensions: [...SUPPORTED_EXTENSIONS],
141
+ ...options.jitiOptions
142
+ });
143
+ const r = {
144
+ config: {},
145
+ cwd: options.cwd,
146
+ configFile: resolve(options.cwd, options.configFile),
147
+ layers: []
148
+ };
149
+ const rawConfigs = {
150
+ overrides: options.overrides,
151
+ main: void 0,
152
+ rc: void 0,
153
+ packageJson: void 0,
154
+ defaultConfig: options.defaultConfig
155
+ };
156
+ if (options.dotenv) {
157
+ await setupDotenv({
158
+ cwd: options.cwd,
159
+ ...options.dotenv === true ? {} : options.dotenv
160
+ });
161
+ }
162
+ const _mainConfig = await resolveConfig(".", options);
163
+ if (_mainConfig.configFile) {
164
+ rawConfigs.main = _mainConfig.config;
165
+ r.configFile = _mainConfig.configFile;
166
+ }
167
+ if (_mainConfig.meta) {
168
+ r.meta = _mainConfig.meta;
169
+ }
170
+ if (options.rcFile) {
171
+ const rcSources = [];
172
+ rcSources.push(rc9.read({ name: options.rcFile, dir: options.cwd }));
173
+ if (options.globalRc) {
174
+ const workspaceDir = await findWorkspaceDir(options.cwd).catch(() => {
175
+ });
176
+ if (workspaceDir) {
177
+ rcSources.push(rc9.read({ name: options.rcFile, dir: workspaceDir }));
178
+ }
179
+ rcSources.push(rc9.readUser({ name: options.rcFile, dir: options.cwd }));
180
+ }
181
+ rawConfigs.rc = _merger({}, ...rcSources);
182
+ }
183
+ if (options.packageJson) {
184
+ const keys = (Array.isArray(options.packageJson) ? options.packageJson : [
185
+ typeof options.packageJson === "string" ? options.packageJson : options.name
186
+ ]).filter((t) => t && typeof t === "string");
187
+ const pkgJsonFile = await readPackageJSON(options.cwd).catch(() => {
188
+ });
189
+ const values = keys.map((key) => pkgJsonFile?.[key]);
190
+ rawConfigs.packageJson = _merger({}, ...values);
191
+ }
192
+ const configs = {};
193
+ for (const key in rawConfigs) {
194
+ const value = rawConfigs[key];
195
+ configs[key] = await (typeof value === "function" ? value({ configs, rawConfigs }) : value);
196
+ }
197
+ r.config = _merger(
198
+ configs.overrides,
199
+ configs.main,
200
+ configs.rc,
201
+ configs.packageJson,
202
+ configs.defaultConfig
203
+ );
204
+ if (options.extend) {
205
+ await extendConfig(r.config, options);
206
+ r.layers = r.config._layers;
207
+ delete r.config._layers;
208
+ r.config = _merger(r.config, ...r.layers.map((e) => e.config));
209
+ }
210
+ const baseLayers = [
211
+ configs.overrides && {
212
+ config: configs.overrides,
213
+ configFile: void 0,
214
+ cwd: void 0
215
+ },
216
+ { config: configs.main, configFile: options.configFile, cwd: options.cwd },
217
+ configs.rc && { config: configs.rc, configFile: options.rcFile },
218
+ configs.packageJson && {
219
+ config: configs.packageJson,
220
+ configFile: "package.json"
221
+ }
222
+ ].filter((l) => l && l.config);
223
+ r.layers = [...baseLayers, ...r.layers];
224
+ if (options.defaults) {
225
+ r.config = _merger(r.config, options.defaults);
226
+ }
227
+ if (options.omit$Keys) {
228
+ for (const key in r.config) {
229
+ if (key.startsWith("$")) {
230
+ delete r.config[key];
231
+ }
232
+ }
233
+ }
234
+ return r;
235
+ }
236
+ async function extendConfig(config, options) {
237
+ config._layers = config._layers || [];
238
+ if (!options.extend) {
239
+ return;
240
+ }
241
+ let keys = options.extend.extendKey;
242
+ if (typeof keys === "string") {
243
+ keys = [keys];
244
+ }
245
+ const extendSources = [];
246
+ for (const key of keys) {
247
+ extendSources.push(
248
+ ...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(
249
+ Boolean
250
+ )
251
+ );
252
+ delete config[key];
253
+ }
254
+ for (let extendSource of extendSources) {
255
+ const originalExtendSource = extendSource;
256
+ let sourceOptions = {};
257
+ if (extendSource.source) {
258
+ sourceOptions = extendSource.options || {};
259
+ extendSource = extendSource.source;
260
+ }
261
+ if (Array.isArray(extendSource)) {
262
+ sourceOptions = extendSource[1] || {};
263
+ extendSource = extendSource[0];
264
+ }
265
+ if (typeof extendSource !== "string") {
266
+ console.warn(
267
+ `Cannot extend config from \`${JSON.stringify(
268
+ originalExtendSource
269
+ )}\` in ${options.cwd}`
270
+ );
271
+ continue;
272
+ }
273
+ const _config = await resolveConfig(extendSource, options, sourceOptions);
274
+ if (!_config.config) {
275
+ console.warn(
276
+ `Cannot extend config from \`${extendSource}\` in ${options.cwd}`
277
+ );
278
+ continue;
279
+ }
280
+ await extendConfig(_config.config, { ...options, cwd: _config.cwd });
281
+ config._layers.push(_config);
282
+ if (_config.config._layers) {
283
+ config._layers.push(..._config.config._layers);
284
+ delete _config.config._layers;
285
+ }
286
+ }
287
+ }
288
+ const GIGET_PREFIXES = [
289
+ "gh:",
290
+ "github:",
291
+ "gitlab:",
292
+ "bitbucket:",
293
+ "https://",
294
+ "http://"
295
+ ];
296
+ const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
297
+ async function resolveConfig(source, options, sourceOptions = {}) {
298
+ if (options.resolve) {
299
+ const res2 = await options.resolve(source, options);
300
+ if (res2) {
301
+ return res2;
302
+ }
303
+ }
304
+ const _merger = options.merger || defu;
305
+ const customProviderKeys = Object.keys(
306
+ sourceOptions.giget?.providers || {}
307
+ ).map((key) => `${key}:`);
308
+ const gigetPrefixes = customProviderKeys.length > 0 ? [.../* @__PURE__ */ new Set([...customProviderKeys, ...GIGET_PREFIXES])] : GIGET_PREFIXES;
309
+ if (options.giget !== false && gigetPrefixes.some((prefix) => source.startsWith(prefix))) {
310
+ const { downloadTemplate } = await import('giget');
311
+ const { digest } = await import('ohash');
312
+ const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + digest(source).slice(0, 10).replace(/[-_]/g, "");
313
+ let cloneDir;
314
+ const localNodeModules = resolve(options.cwd, "node_modules");
315
+ const parentDir = dirname(options.cwd);
316
+ if (basename(parentDir) === ".c12") {
317
+ cloneDir = join(parentDir, cloneName);
318
+ } else if (existsSync(localNodeModules)) {
319
+ cloneDir = join(localNodeModules, ".c12", cloneName);
320
+ } else {
321
+ cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : resolve(homedir(), ".cache/c12", cloneName);
322
+ }
323
+ if (existsSync(cloneDir) && !sourceOptions.install) {
324
+ await rm(cloneDir, { recursive: true });
325
+ }
326
+ const cloned = await downloadTemplate(source, {
327
+ dir: cloneDir,
328
+ install: sourceOptions.install,
329
+ force: sourceOptions.install,
330
+ auth: sourceOptions.auth,
331
+ ...options.giget,
332
+ ...sourceOptions.giget
333
+ });
334
+ source = cloned.dir;
335
+ }
336
+ if (NPM_PACKAGE_RE.test(source)) {
337
+ source = tryResolve(source, options) || source;
338
+ }
339
+ const ext = extname(source);
340
+ const isDir = !ext || ext === basename(source);
341
+ const cwd = resolve(options.cwd, isDir ? source : dirname(source));
342
+ if (isDir) {
343
+ source = options.configFile;
344
+ }
345
+ const res = {
346
+ config: void 0,
347
+ configFile: void 0,
348
+ cwd,
349
+ source,
350
+ sourceOptions
351
+ };
352
+ res.configFile = tryResolve(resolve(cwd, source), options) || tryResolve(
353
+ resolve(cwd, ".config", source.replace(/\.config$/, "")),
354
+ options
355
+ ) || tryResolve(resolve(cwd, ".config", source), options) || source;
356
+ if (!existsSync(res.configFile)) {
357
+ return res;
358
+ }
359
+ const configFileExt = extname(res.configFile) || "";
360
+ if (configFileExt in ASYNC_LOADERS) {
361
+ const asyncLoader = await ASYNC_LOADERS[configFileExt]();
362
+ const contents = await readFile(res.configFile, "utf8");
363
+ res.config = asyncLoader(contents);
364
+ } else {
365
+ res.config = await options.jiti.import(res.configFile, {
366
+ default: true
367
+ });
368
+ }
369
+ if (typeof res.config === "function") {
370
+ res.config = await res.config();
371
+ }
372
+ if (options.envName) {
373
+ const envConfig = {
374
+ ...res.config["$" + options.envName],
375
+ ...res.config.$env?.[options.envName]
376
+ };
377
+ if (Object.keys(envConfig).length > 0) {
378
+ res.config = _merger(envConfig, res.config);
379
+ }
380
+ }
381
+ res.meta = defu(res.sourceOptions.meta, res.config.$meta);
382
+ delete res.config.$meta;
383
+ if (res.sourceOptions.overrides) {
384
+ res.config = _merger(res.sourceOptions.overrides, res.config);
385
+ }
386
+ res.configFile = _normalize(res.configFile);
387
+ res.source = _normalize(res.source);
388
+ return res;
389
+ }
390
+ function tryResolve(id, options) {
391
+ const res = resolveModulePath(id, {
392
+ try: true,
393
+ from: pathToFileURL(join(options.cwd || ".", options.configFile || "/")),
394
+ suffixes: ["", "/index"],
395
+ extensions: SUPPORTED_EXTENSIONS,
396
+ cache: false
397
+ });
398
+ return res ? normalize(res) : void 0;
399
+ }
400
+
401
+ export { SUPPORTED_EXTENSIONS as S, loadDotenv as a, loadConfig as l, setupDotenv as s };
backend/node_modules/c12/dist/update.d.mts ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as magicast from 'magicast';
2
+
3
+ /**
4
+ * @experimental Update a config file or create a new one.
5
+ */
6
+ declare function updateConfig(opts: UpdateConfigOptions): Promise<UpdateConfigResult>;
7
+ interface UpdateConfigResult {
8
+ configFile?: string;
9
+ created?: boolean;
10
+ }
11
+ type MaybePromise<T> = T | Promise<T>;
12
+ type MagicAstOptions = Exclude<Parameters<(typeof magicast)["parseModule"]>[1], undefined>;
13
+ interface UpdateConfigOptions {
14
+ /**
15
+ * Current working directory
16
+ */
17
+ cwd: string;
18
+ /**
19
+ * Config file name
20
+ */
21
+ configFile: string;
22
+ /**
23
+ * Extension used for new config file.
24
+ */
25
+ createExtension?: string;
26
+ /**
27
+ * Magicast options
28
+ */
29
+ magicast?: MagicAstOptions;
30
+ /**
31
+ * Update function.
32
+ */
33
+ onUpdate?: (config: any) => MaybePromise<void>;
34
+ /**
35
+ * Handle default config creation.
36
+ *
37
+ * Tip: you can use this option as a hook to prompt users about config creation.
38
+ *
39
+ * Context object:
40
+ * - path: determined full path to the config file
41
+ *
42
+ * Returns types:
43
+ * - string: custom config template
44
+ * - true: write the template
45
+ * - false: abort the operation
46
+ */
47
+ onCreate?: (ctx: {
48
+ configFile: string;
49
+ }) => MaybePromise<string | boolean>;
50
+ }
51
+
52
+ export { updateConfig };
53
+ export type { UpdateConfigOptions, UpdateConfigResult };
backend/node_modules/c12/dist/update.mjs ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { resolveModulePath } from 'exsolve';
2
+ import { S as SUPPORTED_EXTENSIONS } from './shared/c12.BXpNC6YI.mjs';
3
+ import { join, normalize } from 'pathe';
4
+ import { mkdir, writeFile, readFile } from 'node:fs/promises';
5
+ import { dirname, extname } from 'node:path';
6
+ import 'node:fs';
7
+ import 'node:url';
8
+ import 'node:os';
9
+ import 'jiti';
10
+ import 'rc9';
11
+ import 'defu';
12
+ import 'pkg-types';
13
+ import 'dotenv';
14
+
15
+ const UPDATABLE_EXTS = [".js", ".ts", ".mjs", ".cjs", ".mts", ".cts"];
16
+ async function updateConfig(opts) {
17
+ const { parseModule } = await import('magicast');
18
+ let configFile = tryResolve(`./${opts.configFile}`, opts.cwd, SUPPORTED_EXTENSIONS) || tryResolve(
19
+ `./.config/${opts.configFile}`,
20
+ opts.cwd,
21
+ SUPPORTED_EXTENSIONS
22
+ ) || tryResolve(
23
+ `./.config/${opts.configFile.split(".")[0]}`,
24
+ opts.cwd,
25
+ SUPPORTED_EXTENSIONS
26
+ );
27
+ let created = false;
28
+ if (!configFile) {
29
+ configFile = join(
30
+ opts.cwd,
31
+ opts.configFile + (opts.createExtension || ".ts")
32
+ );
33
+ const createResult = await opts.onCreate?.({ configFile }) ?? true;
34
+ if (!createResult) {
35
+ throw new Error("Config file creation aborted.");
36
+ }
37
+ const content = typeof createResult === "string" ? createResult : `export default {}
38
+ `;
39
+ await mkdir(dirname(configFile), { recursive: true });
40
+ await writeFile(configFile, content, "utf8");
41
+ created = true;
42
+ }
43
+ const ext = extname(configFile);
44
+ if (!UPDATABLE_EXTS.includes(ext)) {
45
+ throw new Error(
46
+ `Unsupported config file extension: ${ext} (${configFile}) (supported: ${UPDATABLE_EXTS.join(", ")})`
47
+ );
48
+ }
49
+ const contents = await readFile(configFile, "utf8");
50
+ const _module = parseModule(contents, opts.magicast);
51
+ const defaultExport = _module.exports.default;
52
+ if (!defaultExport) {
53
+ throw new Error("Default export is missing in the config file!");
54
+ }
55
+ const configObj = defaultExport.$type === "function-call" ? defaultExport.$args[0] : defaultExport;
56
+ await opts.onUpdate?.(configObj);
57
+ await writeFile(configFile, _module.generate().code);
58
+ return {
59
+ configFile,
60
+ created
61
+ };
62
+ }
63
+ function tryResolve(path, cwd, extensions) {
64
+ const res = resolveModulePath(path, {
65
+ try: true,
66
+ from: join(cwd, "/"),
67
+ extensions,
68
+ suffixes: ["", "/index"],
69
+ cache: false
70
+ });
71
+ return res ? normalize(res) : void 0;
72
+ }
73
+
74
+ export { updateConfig };
backend/node_modules/chokidar/esm/handler.d.ts ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { WatchEventType, Stats, FSWatcher as NativeFsWatcher } from 'fs';
2
+ import type { FSWatcher, WatchHelper, Throttler } from './index.js';
3
+ import type { EntryInfo } from 'readdirp';
4
+ export type Path = string;
5
+ export declare const STR_DATA = "data";
6
+ export declare const STR_END = "end";
7
+ export declare const STR_CLOSE = "close";
8
+ export declare const EMPTY_FN: () => void;
9
+ export declare const IDENTITY_FN: (val: unknown) => unknown;
10
+ export declare const isWindows: boolean;
11
+ export declare const isMacos: boolean;
12
+ export declare const isLinux: boolean;
13
+ export declare const isFreeBSD: boolean;
14
+ export declare const isIBMi: boolean;
15
+ export declare const EVENTS: {
16
+ readonly ALL: "all";
17
+ readonly READY: "ready";
18
+ readonly ADD: "add";
19
+ readonly CHANGE: "change";
20
+ readonly ADD_DIR: "addDir";
21
+ readonly UNLINK: "unlink";
22
+ readonly UNLINK_DIR: "unlinkDir";
23
+ readonly RAW: "raw";
24
+ readonly ERROR: "error";
25
+ };
26
+ export type EventName = (typeof EVENTS)[keyof typeof EVENTS];
27
+ export type FsWatchContainer = {
28
+ listeners: (path: string) => void | Set<any>;
29
+ errHandlers: (err: unknown) => void | Set<any>;
30
+ rawEmitters: (ev: WatchEventType, path: string, opts: unknown) => void | Set<any>;
31
+ watcher: NativeFsWatcher;
32
+ watcherUnusable?: boolean;
33
+ };
34
+ export interface WatchHandlers {
35
+ listener: (path: string) => void;
36
+ errHandler: (err: unknown) => void;
37
+ rawEmitter: (ev: WatchEventType, path: string, opts: unknown) => void;
38
+ }
39
+ /**
40
+ * @mixin
41
+ */
42
+ export declare class NodeFsHandler {
43
+ fsw: FSWatcher;
44
+ _boundHandleError: (error: unknown) => void;
45
+ constructor(fsW: FSWatcher);
46
+ /**
47
+ * Watch file for changes with fs_watchFile or fs_watch.
48
+ * @param path to file or dir
49
+ * @param listener on fs change
50
+ * @returns closer for the watcher instance
51
+ */
52
+ _watchWithNodeFs(path: string, listener: (path: string, newStats?: any) => void | Promise<void>): (() => void) | undefined;
53
+ /**
54
+ * Watch a file and emit add event if warranted.
55
+ * @returns closer for the watcher instance
56
+ */
57
+ _handleFile(file: Path, stats: Stats, initialAdd: boolean): (() => void) | undefined;
58
+ /**
59
+ * Handle symlinks encountered while reading a dir.
60
+ * @param entry returned by readdirp
61
+ * @param directory path of dir being read
62
+ * @param path of this item
63
+ * @param item basename of this item
64
+ * @returns true if no more processing is needed for this entry.
65
+ */
66
+ _handleSymlink(entry: EntryInfo, directory: string, path: Path, item: string): Promise<boolean | undefined>;
67
+ _handleRead(directory: string, initialAdd: boolean, wh: WatchHelper, target: Path, dir: Path, depth: number, throttler: Throttler): Promise<unknown> | undefined;
68
+ /**
69
+ * Read directory to add / remove files from `@watched` list and re-read it on change.
70
+ * @param dir fs path
71
+ * @param stats
72
+ * @param initialAdd
73
+ * @param depth relative to user-supplied path
74
+ * @param target child path targeted for watch
75
+ * @param wh Common watch helpers for this path
76
+ * @param realpath
77
+ * @returns closer for the watcher instance.
78
+ */
79
+ _handleDir(dir: string, stats: Stats, initialAdd: boolean, depth: number, target: string, wh: WatchHelper, realpath: string): Promise<(() => void) | undefined>;
80
+ /**
81
+ * Handle added file, directory, or glob pattern.
82
+ * Delegates call to _handleFile / _handleDir after checks.
83
+ * @param path to file or ir
84
+ * @param initialAdd was the file added at watch instantiation?
85
+ * @param priorWh depth relative to user-supplied path
86
+ * @param depth Child path actually targeted for watch
87
+ * @param target Child path actually targeted for watch
88
+ */
89
+ _addToNodeFs(path: string, initialAdd: boolean, priorWh: WatchHelper | undefined, depth: number, target?: string): Promise<string | false | undefined>;
90
+ }
backend/node_modules/chokidar/esm/handler.js ADDED
@@ -0,0 +1,629 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { watchFile, unwatchFile, watch as fs_watch } from 'fs';
2
+ import { open, stat, lstat, realpath as fsrealpath } from 'fs/promises';
3
+ import * as sysPath from 'path';
4
+ import { type as osType } from 'os';
5
+ export const STR_DATA = 'data';
6
+ export const STR_END = 'end';
7
+ export const STR_CLOSE = 'close';
8
+ export const EMPTY_FN = () => { };
9
+ export const IDENTITY_FN = (val) => val;
10
+ const pl = process.platform;
11
+ export const isWindows = pl === 'win32';
12
+ export const isMacos = pl === 'darwin';
13
+ export const isLinux = pl === 'linux';
14
+ export const isFreeBSD = pl === 'freebsd';
15
+ export const isIBMi = osType() === 'OS400';
16
+ export const EVENTS = {
17
+ ALL: 'all',
18
+ READY: 'ready',
19
+ ADD: 'add',
20
+ CHANGE: 'change',
21
+ ADD_DIR: 'addDir',
22
+ UNLINK: 'unlink',
23
+ UNLINK_DIR: 'unlinkDir',
24
+ RAW: 'raw',
25
+ ERROR: 'error',
26
+ };
27
+ const EV = EVENTS;
28
+ const THROTTLE_MODE_WATCH = 'watch';
29
+ const statMethods = { lstat, stat };
30
+ const KEY_LISTENERS = 'listeners';
31
+ const KEY_ERR = 'errHandlers';
32
+ const KEY_RAW = 'rawEmitters';
33
+ const HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
34
+ // prettier-ignore
35
+ const binaryExtensions = new Set([
36
+ '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',
37
+ 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',
38
+ 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',
39
+ 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',
40
+ 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',
41
+ 'dtshd', 'dvb', 'dwg', 'dxf',
42
+ 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',
43
+ 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',
44
+ 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',
45
+ 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',
46
+ 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',
47
+ 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',
48
+ 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',
49
+ 'mobi', 'mov', 'movie', 'mp3',
50
+ 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',
51
+ 'nef', 'npx', 'numbers', 'nupkg',
52
+ 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',
53
+ 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',
54
+ 'potx', 'ppa', 'ppam',
55
+ 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',
56
+ 'qt',
57
+ 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',
58
+ 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',
59
+ 'stl', 'suo', 'sub', 'swf',
60
+ 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',
61
+ 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',
62
+ 'viv', 'vob',
63
+ 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',
64
+ 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',
65
+ 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',
66
+ 'xmind', 'xpi', 'xpm', 'xwd', 'xz',
67
+ 'z', 'zip', 'zipx',
68
+ ]);
69
+ const isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
70
+ // TODO: emit errors properly. Example: EMFILE on Macos.
71
+ const foreach = (val, fn) => {
72
+ if (val instanceof Set) {
73
+ val.forEach(fn);
74
+ }
75
+ else {
76
+ fn(val);
77
+ }
78
+ };
79
+ const addAndConvert = (main, prop, item) => {
80
+ let container = main[prop];
81
+ if (!(container instanceof Set)) {
82
+ main[prop] = container = new Set([container]);
83
+ }
84
+ container.add(item);
85
+ };
86
+ const clearItem = (cont) => (key) => {
87
+ const set = cont[key];
88
+ if (set instanceof Set) {
89
+ set.clear();
90
+ }
91
+ else {
92
+ delete cont[key];
93
+ }
94
+ };
95
+ const delFromSet = (main, prop, item) => {
96
+ const container = main[prop];
97
+ if (container instanceof Set) {
98
+ container.delete(item);
99
+ }
100
+ else if (container === item) {
101
+ delete main[prop];
102
+ }
103
+ };
104
+ const isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);
105
+ const FsWatchInstances = new Map();
106
+ /**
107
+ * Instantiates the fs_watch interface
108
+ * @param path to be watched
109
+ * @param options to be passed to fs_watch
110
+ * @param listener main event handler
111
+ * @param errHandler emits info about errors
112
+ * @param emitRaw emits raw event data
113
+ * @returns {NativeFsWatcher}
114
+ */
115
+ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
116
+ const handleEvent = (rawEvent, evPath) => {
117
+ listener(path);
118
+ emitRaw(rawEvent, evPath, { watchedPath: path });
119
+ // emit based on events occurring for files from a directory's watcher in
120
+ // case the file's watcher misses it (and rely on throttling to de-dupe)
121
+ if (evPath && path !== evPath) {
122
+ fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
123
+ }
124
+ };
125
+ try {
126
+ return fs_watch(path, {
127
+ persistent: options.persistent,
128
+ }, handleEvent);
129
+ }
130
+ catch (error) {
131
+ errHandler(error);
132
+ return undefined;
133
+ }
134
+ }
135
+ /**
136
+ * Helper for passing fs_watch event data to a collection of listeners
137
+ * @param fullPath absolute path bound to fs_watch instance
138
+ */
139
+ const fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
140
+ const cont = FsWatchInstances.get(fullPath);
141
+ if (!cont)
142
+ return;
143
+ foreach(cont[listenerType], (listener) => {
144
+ listener(val1, val2, val3);
145
+ });
146
+ };
147
+ /**
148
+ * Instantiates the fs_watch interface or binds listeners
149
+ * to an existing one covering the same file system entry
150
+ * @param path
151
+ * @param fullPath absolute path
152
+ * @param options to be passed to fs_watch
153
+ * @param handlers container for event listener functions
154
+ */
155
+ const setFsWatchListener = (path, fullPath, options, handlers) => {
156
+ const { listener, errHandler, rawEmitter } = handlers;
157
+ let cont = FsWatchInstances.get(fullPath);
158
+ let watcher;
159
+ if (!options.persistent) {
160
+ watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);
161
+ if (!watcher)
162
+ return;
163
+ return watcher.close.bind(watcher);
164
+ }
165
+ if (cont) {
166
+ addAndConvert(cont, KEY_LISTENERS, listener);
167
+ addAndConvert(cont, KEY_ERR, errHandler);
168
+ addAndConvert(cont, KEY_RAW, rawEmitter);
169
+ }
170
+ else {
171
+ watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here
172
+ fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
173
+ if (!watcher)
174
+ return;
175
+ watcher.on(EV.ERROR, async (error) => {
176
+ const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
177
+ if (cont)
178
+ cont.watcherUnusable = true; // documented since Node 10.4.1
179
+ // Workaround for https://github.com/joyent/node/issues/4337
180
+ if (isWindows && error.code === 'EPERM') {
181
+ try {
182
+ const fd = await open(path, 'r');
183
+ await fd.close();
184
+ broadcastErr(error);
185
+ }
186
+ catch (err) {
187
+ // do nothing
188
+ }
189
+ }
190
+ else {
191
+ broadcastErr(error);
192
+ }
193
+ });
194
+ cont = {
195
+ listeners: listener,
196
+ errHandlers: errHandler,
197
+ rawEmitters: rawEmitter,
198
+ watcher,
199
+ };
200
+ FsWatchInstances.set(fullPath, cont);
201
+ }
202
+ // const index = cont.listeners.indexOf(listener);
203
+ // removes this instance's listeners and closes the underlying fs_watch
204
+ // instance if there are no more listeners left
205
+ return () => {
206
+ delFromSet(cont, KEY_LISTENERS, listener);
207
+ delFromSet(cont, KEY_ERR, errHandler);
208
+ delFromSet(cont, KEY_RAW, rawEmitter);
209
+ if (isEmptySet(cont.listeners)) {
210
+ // Check to protect against issue gh-730.
211
+ // if (cont.watcherUnusable) {
212
+ cont.watcher.close();
213
+ // }
214
+ FsWatchInstances.delete(fullPath);
215
+ HANDLER_KEYS.forEach(clearItem(cont));
216
+ // @ts-ignore
217
+ cont.watcher = undefined;
218
+ Object.freeze(cont);
219
+ }
220
+ };
221
+ };
222
+ // fs_watchFile helpers
223
+ // object to hold per-process fs_watchFile instances
224
+ // (may be shared across chokidar FSWatcher instances)
225
+ const FsWatchFileInstances = new Map();
226
+ /**
227
+ * Instantiates the fs_watchFile interface or binds listeners
228
+ * to an existing one covering the same file system entry
229
+ * @param path to be watched
230
+ * @param fullPath absolute path
231
+ * @param options options to be passed to fs_watchFile
232
+ * @param handlers container for event listener functions
233
+ * @returns closer
234
+ */
235
+ const setFsWatchFileListener = (path, fullPath, options, handlers) => {
236
+ const { listener, rawEmitter } = handlers;
237
+ let cont = FsWatchFileInstances.get(fullPath);
238
+ // let listeners = new Set();
239
+ // let rawEmitters = new Set();
240
+ const copts = cont && cont.options;
241
+ if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
242
+ // "Upgrade" the watcher to persistence or a quicker interval.
243
+ // This creates some unlikely edge case issues if the user mixes
244
+ // settings in a very weird way, but solving for those cases
245
+ // doesn't seem worthwhile for the added complexity.
246
+ // listeners = cont.listeners;
247
+ // rawEmitters = cont.rawEmitters;
248
+ unwatchFile(fullPath);
249
+ cont = undefined;
250
+ }
251
+ if (cont) {
252
+ addAndConvert(cont, KEY_LISTENERS, listener);
253
+ addAndConvert(cont, KEY_RAW, rawEmitter);
254
+ }
255
+ else {
256
+ // TODO
257
+ // listeners.add(listener);
258
+ // rawEmitters.add(rawEmitter);
259
+ cont = {
260
+ listeners: listener,
261
+ rawEmitters: rawEmitter,
262
+ options,
263
+ watcher: watchFile(fullPath, options, (curr, prev) => {
264
+ foreach(cont.rawEmitters, (rawEmitter) => {
265
+ rawEmitter(EV.CHANGE, fullPath, { curr, prev });
266
+ });
267
+ const currmtime = curr.mtimeMs;
268
+ if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
269
+ foreach(cont.listeners, (listener) => listener(path, curr));
270
+ }
271
+ }),
272
+ };
273
+ FsWatchFileInstances.set(fullPath, cont);
274
+ }
275
+ // const index = cont.listeners.indexOf(listener);
276
+ // Removes this instance's listeners and closes the underlying fs_watchFile
277
+ // instance if there are no more listeners left.
278
+ return () => {
279
+ delFromSet(cont, KEY_LISTENERS, listener);
280
+ delFromSet(cont, KEY_RAW, rawEmitter);
281
+ if (isEmptySet(cont.listeners)) {
282
+ FsWatchFileInstances.delete(fullPath);
283
+ unwatchFile(fullPath);
284
+ cont.options = cont.watcher = undefined;
285
+ Object.freeze(cont);
286
+ }
287
+ };
288
+ };
289
+ /**
290
+ * @mixin
291
+ */
292
+ export class NodeFsHandler {
293
+ constructor(fsW) {
294
+ this.fsw = fsW;
295
+ this._boundHandleError = (error) => fsW._handleError(error);
296
+ }
297
+ /**
298
+ * Watch file for changes with fs_watchFile or fs_watch.
299
+ * @param path to file or dir
300
+ * @param listener on fs change
301
+ * @returns closer for the watcher instance
302
+ */
303
+ _watchWithNodeFs(path, listener) {
304
+ const opts = this.fsw.options;
305
+ const directory = sysPath.dirname(path);
306
+ const basename = sysPath.basename(path);
307
+ const parent = this.fsw._getWatchedDir(directory);
308
+ parent.add(basename);
309
+ const absolutePath = sysPath.resolve(path);
310
+ const options = {
311
+ persistent: opts.persistent,
312
+ };
313
+ if (!listener)
314
+ listener = EMPTY_FN;
315
+ let closer;
316
+ if (opts.usePolling) {
317
+ const enableBin = opts.interval !== opts.binaryInterval;
318
+ options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;
319
+ closer = setFsWatchFileListener(path, absolutePath, options, {
320
+ listener,
321
+ rawEmitter: this.fsw._emitRaw,
322
+ });
323
+ }
324
+ else {
325
+ closer = setFsWatchListener(path, absolutePath, options, {
326
+ listener,
327
+ errHandler: this._boundHandleError,
328
+ rawEmitter: this.fsw._emitRaw,
329
+ });
330
+ }
331
+ return closer;
332
+ }
333
+ /**
334
+ * Watch a file and emit add event if warranted.
335
+ * @returns closer for the watcher instance
336
+ */
337
+ _handleFile(file, stats, initialAdd) {
338
+ if (this.fsw.closed) {
339
+ return;
340
+ }
341
+ const dirname = sysPath.dirname(file);
342
+ const basename = sysPath.basename(file);
343
+ const parent = this.fsw._getWatchedDir(dirname);
344
+ // stats is always present
345
+ let prevStats = stats;
346
+ // if the file is already being watched, do nothing
347
+ if (parent.has(basename))
348
+ return;
349
+ const listener = async (path, newStats) => {
350
+ if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
351
+ return;
352
+ if (!newStats || newStats.mtimeMs === 0) {
353
+ try {
354
+ const newStats = await stat(file);
355
+ if (this.fsw.closed)
356
+ return;
357
+ // Check that change event was not fired because of changed only accessTime.
358
+ const at = newStats.atimeMs;
359
+ const mt = newStats.mtimeMs;
360
+ if (!at || at <= mt || mt !== prevStats.mtimeMs) {
361
+ this.fsw._emit(EV.CHANGE, file, newStats);
362
+ }
363
+ if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {
364
+ this.fsw._closeFile(path);
365
+ prevStats = newStats;
366
+ const closer = this._watchWithNodeFs(file, listener);
367
+ if (closer)
368
+ this.fsw._addPathCloser(path, closer);
369
+ }
370
+ else {
371
+ prevStats = newStats;
372
+ }
373
+ }
374
+ catch (error) {
375
+ // Fix issues where mtime is null but file is still present
376
+ this.fsw._remove(dirname, basename);
377
+ }
378
+ // add is about to be emitted if file not already tracked in parent
379
+ }
380
+ else if (parent.has(basename)) {
381
+ // Check that change event was not fired because of changed only accessTime.
382
+ const at = newStats.atimeMs;
383
+ const mt = newStats.mtimeMs;
384
+ if (!at || at <= mt || mt !== prevStats.mtimeMs) {
385
+ this.fsw._emit(EV.CHANGE, file, newStats);
386
+ }
387
+ prevStats = newStats;
388
+ }
389
+ };
390
+ // kick off the watcher
391
+ const closer = this._watchWithNodeFs(file, listener);
392
+ // emit an add event if we're supposed to
393
+ if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
394
+ if (!this.fsw._throttle(EV.ADD, file, 0))
395
+ return;
396
+ this.fsw._emit(EV.ADD, file, stats);
397
+ }
398
+ return closer;
399
+ }
400
+ /**
401
+ * Handle symlinks encountered while reading a dir.
402
+ * @param entry returned by readdirp
403
+ * @param directory path of dir being read
404
+ * @param path of this item
405
+ * @param item basename of this item
406
+ * @returns true if no more processing is needed for this entry.
407
+ */
408
+ async _handleSymlink(entry, directory, path, item) {
409
+ if (this.fsw.closed) {
410
+ return;
411
+ }
412
+ const full = entry.fullPath;
413
+ const dir = this.fsw._getWatchedDir(directory);
414
+ if (!this.fsw.options.followSymlinks) {
415
+ // watch symlink directly (don't follow) and detect changes
416
+ this.fsw._incrReadyCount();
417
+ let linkPath;
418
+ try {
419
+ linkPath = await fsrealpath(path);
420
+ }
421
+ catch (e) {
422
+ this.fsw._emitReady();
423
+ return true;
424
+ }
425
+ if (this.fsw.closed)
426
+ return;
427
+ if (dir.has(item)) {
428
+ if (this.fsw._symlinkPaths.get(full) !== linkPath) {
429
+ this.fsw._symlinkPaths.set(full, linkPath);
430
+ this.fsw._emit(EV.CHANGE, path, entry.stats);
431
+ }
432
+ }
433
+ else {
434
+ dir.add(item);
435
+ this.fsw._symlinkPaths.set(full, linkPath);
436
+ this.fsw._emit(EV.ADD, path, entry.stats);
437
+ }
438
+ this.fsw._emitReady();
439
+ return true;
440
+ }
441
+ // don't follow the same symlink more than once
442
+ if (this.fsw._symlinkPaths.has(full)) {
443
+ return true;
444
+ }
445
+ this.fsw._symlinkPaths.set(full, true);
446
+ }
447
+ _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
448
+ // Normalize the directory name on Windows
449
+ directory = sysPath.join(directory, '');
450
+ throttler = this.fsw._throttle('readdir', directory, 1000);
451
+ if (!throttler)
452
+ return;
453
+ const previous = this.fsw._getWatchedDir(wh.path);
454
+ const current = new Set();
455
+ let stream = this.fsw._readdirp(directory, {
456
+ fileFilter: (entry) => wh.filterPath(entry),
457
+ directoryFilter: (entry) => wh.filterDir(entry),
458
+ });
459
+ if (!stream)
460
+ return;
461
+ stream
462
+ .on(STR_DATA, async (entry) => {
463
+ if (this.fsw.closed) {
464
+ stream = undefined;
465
+ return;
466
+ }
467
+ const item = entry.path;
468
+ let path = sysPath.join(directory, item);
469
+ current.add(item);
470
+ if (entry.stats.isSymbolicLink() &&
471
+ (await this._handleSymlink(entry, directory, path, item))) {
472
+ return;
473
+ }
474
+ if (this.fsw.closed) {
475
+ stream = undefined;
476
+ return;
477
+ }
478
+ // Files that present in current directory snapshot
479
+ // but absent in previous are added to watch list and
480
+ // emit `add` event.
481
+ if (item === target || (!target && !previous.has(item))) {
482
+ this.fsw._incrReadyCount();
483
+ // ensure relativeness of path is preserved in case of watcher reuse
484
+ path = sysPath.join(dir, sysPath.relative(dir, path));
485
+ this._addToNodeFs(path, initialAdd, wh, depth + 1);
486
+ }
487
+ })
488
+ .on(EV.ERROR, this._boundHandleError);
489
+ return new Promise((resolve, reject) => {
490
+ if (!stream)
491
+ return reject();
492
+ stream.once(STR_END, () => {
493
+ if (this.fsw.closed) {
494
+ stream = undefined;
495
+ return;
496
+ }
497
+ const wasThrottled = throttler ? throttler.clear() : false;
498
+ resolve(undefined);
499
+ // Files that absent in current directory snapshot
500
+ // but present in previous emit `remove` event
501
+ // and are removed from @watched[directory].
502
+ previous
503
+ .getChildren()
504
+ .filter((item) => {
505
+ return item !== directory && !current.has(item);
506
+ })
507
+ .forEach((item) => {
508
+ this.fsw._remove(directory, item);
509
+ });
510
+ stream = undefined;
511
+ // one more time for any missed in case changes came in extremely quickly
512
+ if (wasThrottled)
513
+ this._handleRead(directory, false, wh, target, dir, depth, throttler);
514
+ });
515
+ });
516
+ }
517
+ /**
518
+ * Read directory to add / remove files from `@watched` list and re-read it on change.
519
+ * @param dir fs path
520
+ * @param stats
521
+ * @param initialAdd
522
+ * @param depth relative to user-supplied path
523
+ * @param target child path targeted for watch
524
+ * @param wh Common watch helpers for this path
525
+ * @param realpath
526
+ * @returns closer for the watcher instance.
527
+ */
528
+ async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
529
+ const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
530
+ const tracked = parentDir.has(sysPath.basename(dir));
531
+ if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
532
+ this.fsw._emit(EV.ADD_DIR, dir, stats);
533
+ }
534
+ // ensure dir is tracked (harmless if redundant)
535
+ parentDir.add(sysPath.basename(dir));
536
+ this.fsw._getWatchedDir(dir);
537
+ let throttler;
538
+ let closer;
539
+ const oDepth = this.fsw.options.depth;
540
+ if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
541
+ if (!target) {
542
+ await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
543
+ if (this.fsw.closed)
544
+ return;
545
+ }
546
+ closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
547
+ // if current directory is removed, do nothing
548
+ if (stats && stats.mtimeMs === 0)
549
+ return;
550
+ this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
551
+ });
552
+ }
553
+ return closer;
554
+ }
555
+ /**
556
+ * Handle added file, directory, or glob pattern.
557
+ * Delegates call to _handleFile / _handleDir after checks.
558
+ * @param path to file or ir
559
+ * @param initialAdd was the file added at watch instantiation?
560
+ * @param priorWh depth relative to user-supplied path
561
+ * @param depth Child path actually targeted for watch
562
+ * @param target Child path actually targeted for watch
563
+ */
564
+ async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
565
+ const ready = this.fsw._emitReady;
566
+ if (this.fsw._isIgnored(path) || this.fsw.closed) {
567
+ ready();
568
+ return false;
569
+ }
570
+ const wh = this.fsw._getWatchHelpers(path);
571
+ if (priorWh) {
572
+ wh.filterPath = (entry) => priorWh.filterPath(entry);
573
+ wh.filterDir = (entry) => priorWh.filterDir(entry);
574
+ }
575
+ // evaluate what is at the path we're being asked to watch
576
+ try {
577
+ const stats = await statMethods[wh.statMethod](wh.watchPath);
578
+ if (this.fsw.closed)
579
+ return;
580
+ if (this.fsw._isIgnored(wh.watchPath, stats)) {
581
+ ready();
582
+ return false;
583
+ }
584
+ const follow = this.fsw.options.followSymlinks;
585
+ let closer;
586
+ if (stats.isDirectory()) {
587
+ const absPath = sysPath.resolve(path);
588
+ const targetPath = follow ? await fsrealpath(path) : path;
589
+ if (this.fsw.closed)
590
+ return;
591
+ closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
592
+ if (this.fsw.closed)
593
+ return;
594
+ // preserve this symlink's target path
595
+ if (absPath !== targetPath && targetPath !== undefined) {
596
+ this.fsw._symlinkPaths.set(absPath, targetPath);
597
+ }
598
+ }
599
+ else if (stats.isSymbolicLink()) {
600
+ const targetPath = follow ? await fsrealpath(path) : path;
601
+ if (this.fsw.closed)
602
+ return;
603
+ const parent = sysPath.dirname(wh.watchPath);
604
+ this.fsw._getWatchedDir(parent).add(wh.watchPath);
605
+ this.fsw._emit(EV.ADD, wh.watchPath, stats);
606
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
607
+ if (this.fsw.closed)
608
+ return;
609
+ // preserve this symlink's target path
610
+ if (targetPath !== undefined) {
611
+ this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
612
+ }
613
+ }
614
+ else {
615
+ closer = this._handleFile(wh.watchPath, stats, initialAdd);
616
+ }
617
+ ready();
618
+ if (closer)
619
+ this.fsw._addPathCloser(path, closer);
620
+ return false;
621
+ }
622
+ catch (error) {
623
+ if (this.fsw._handleError(error)) {
624
+ ready();
625
+ return path;
626
+ }
627
+ }
628
+ }
629
+ }
backend/node_modules/chokidar/esm/index.d.ts ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
2
+ import { Stats } from 'fs';
3
+ import { EventEmitter } from 'events';
4
+ import { ReaddirpStream, ReaddirpOptions, EntryInfo } from 'readdirp';
5
+ import { NodeFsHandler, EventName, Path, EVENTS as EV, WatchHandlers } from './handler.js';
6
+ type AWF = {
7
+ stabilityThreshold: number;
8
+ pollInterval: number;
9
+ };
10
+ type BasicOpts = {
11
+ persistent: boolean;
12
+ ignoreInitial: boolean;
13
+ followSymlinks: boolean;
14
+ cwd?: string;
15
+ usePolling: boolean;
16
+ interval: number;
17
+ binaryInterval: number;
18
+ alwaysStat?: boolean;
19
+ depth?: number;
20
+ ignorePermissionErrors: boolean;
21
+ atomic: boolean | number;
22
+ };
23
+ export type Throttler = {
24
+ timeoutObject: NodeJS.Timeout;
25
+ clear: () => void;
26
+ count: number;
27
+ };
28
+ export type ChokidarOptions = Partial<BasicOpts & {
29
+ ignored: Matcher | Matcher[];
30
+ awaitWriteFinish: boolean | Partial<AWF>;
31
+ }>;
32
+ export type FSWInstanceOptions = BasicOpts & {
33
+ ignored: Matcher[];
34
+ awaitWriteFinish: false | AWF;
35
+ };
36
+ export type ThrottleType = 'readdir' | 'watch' | 'add' | 'remove' | 'change';
37
+ export type EmitArgs = [path: Path, stats?: Stats];
38
+ export type EmitErrorArgs = [error: Error, stats?: Stats];
39
+ export type EmitArgsWithName = [event: EventName, ...EmitArgs];
40
+ export type MatchFunction = (val: string, stats?: Stats) => boolean;
41
+ export interface MatcherObject {
42
+ path: string;
43
+ recursive?: boolean;
44
+ }
45
+ export type Matcher = string | RegExp | MatchFunction | MatcherObject;
46
+ /**
47
+ * Directory entry.
48
+ */
49
+ declare class DirEntry {
50
+ path: Path;
51
+ _removeWatcher: (dir: string, base: string) => void;
52
+ items: Set<Path>;
53
+ constructor(dir: Path, removeWatcher: (dir: string, base: string) => void);
54
+ add(item: string): void;
55
+ remove(item: string): Promise<void>;
56
+ has(item: string): boolean | undefined;
57
+ getChildren(): string[];
58
+ dispose(): void;
59
+ }
60
+ export declare class WatchHelper {
61
+ fsw: FSWatcher;
62
+ path: string;
63
+ watchPath: string;
64
+ fullWatchPath: string;
65
+ dirParts: string[][];
66
+ followSymlinks: boolean;
67
+ statMethod: 'stat' | 'lstat';
68
+ constructor(path: string, follow: boolean, fsw: FSWatcher);
69
+ entryPath(entry: EntryInfo): Path;
70
+ filterPath(entry: EntryInfo): boolean;
71
+ filterDir(entry: EntryInfo): boolean;
72
+ }
73
+ export interface FSWatcherKnownEventMap {
74
+ [EV.READY]: [];
75
+ [EV.RAW]: Parameters<WatchHandlers['rawEmitter']>;
76
+ [EV.ERROR]: Parameters<WatchHandlers['errHandler']>;
77
+ [EV.ALL]: [event: EventName, ...EmitArgs];
78
+ }
79
+ export type FSWatcherEventMap = FSWatcherKnownEventMap & {
80
+ [k in Exclude<EventName, keyof FSWatcherKnownEventMap>]: EmitArgs;
81
+ };
82
+ /**
83
+ * Watches files & directories for changes. Emitted events:
84
+ * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
85
+ *
86
+ * new FSWatcher()
87
+ * .add(directories)
88
+ * .on('add', path => log('File', path, 'was added'))
89
+ */
90
+ export declare class FSWatcher extends EventEmitter<FSWatcherEventMap> {
91
+ closed: boolean;
92
+ options: FSWInstanceOptions;
93
+ _closers: Map<string, Array<any>>;
94
+ _ignoredPaths: Set<Matcher>;
95
+ _throttled: Map<ThrottleType, Map<any, any>>;
96
+ _streams: Set<ReaddirpStream>;
97
+ _symlinkPaths: Map<Path, string | boolean>;
98
+ _watched: Map<string, DirEntry>;
99
+ _pendingWrites: Map<string, any>;
100
+ _pendingUnlinks: Map<string, EmitArgsWithName>;
101
+ _readyCount: number;
102
+ _emitReady: () => void;
103
+ _closePromise?: Promise<void>;
104
+ _userIgnored?: MatchFunction;
105
+ _readyEmitted: boolean;
106
+ _emitRaw: WatchHandlers['rawEmitter'];
107
+ _boundRemove: (dir: string, item: string) => void;
108
+ _nodeFsHandler: NodeFsHandler;
109
+ constructor(_opts?: ChokidarOptions);
110
+ _addIgnoredPath(matcher: Matcher): void;
111
+ _removeIgnoredPath(matcher: Matcher): void;
112
+ /**
113
+ * Adds paths to be watched on an existing FSWatcher instance.
114
+ * @param paths_ file or file list. Other arguments are unused
115
+ */
116
+ add(paths_: Path | Path[], _origAdd?: string, _internal?: boolean): FSWatcher;
117
+ /**
118
+ * Close watchers or start ignoring events from specified paths.
119
+ */
120
+ unwatch(paths_: Path | Path[]): FSWatcher;
121
+ /**
122
+ * Close watchers and remove all listeners from watched paths.
123
+ */
124
+ close(): Promise<void>;
125
+ /**
126
+ * Expose list of watched paths
127
+ * @returns for chaining
128
+ */
129
+ getWatched(): Record<string, string[]>;
130
+ emitWithAll(event: EventName, args: EmitArgs): void;
131
+ /**
132
+ * Normalize and emit events.
133
+ * Calling _emit DOES NOT MEAN emit() would be called!
134
+ * @param event Type of event
135
+ * @param path File or directory path
136
+ * @param stats arguments to be passed with event
137
+ * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
138
+ */
139
+ _emit(event: EventName, path: Path, stats?: Stats): Promise<this | undefined>;
140
+ /**
141
+ * Common handler for errors
142
+ * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
143
+ */
144
+ _handleError(error: Error): Error | boolean;
145
+ /**
146
+ * Helper utility for throttling
147
+ * @param actionType type being throttled
148
+ * @param path being acted upon
149
+ * @param timeout duration of time to suppress duplicate actions
150
+ * @returns tracking object or false if action should be suppressed
151
+ */
152
+ _throttle(actionType: ThrottleType, path: Path, timeout: number): Throttler | false;
153
+ _incrReadyCount(): number;
154
+ /**
155
+ * Awaits write operation to finish.
156
+ * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
157
+ * @param path being acted upon
158
+ * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
159
+ * @param event
160
+ * @param awfEmit Callback to be called when ready for event to be emitted.
161
+ */
162
+ _awaitWriteFinish(path: Path, threshold: number, event: EventName, awfEmit: (err?: Error, stat?: Stats) => void): void;
163
+ /**
164
+ * Determines whether user has asked to ignore this path.
165
+ */
166
+ _isIgnored(path: Path, stats?: Stats): boolean;
167
+ _isntIgnored(path: Path, stat?: Stats): boolean;
168
+ /**
169
+ * Provides a set of common helpers and properties relating to symlink handling.
170
+ * @param path file or directory pattern being watched
171
+ */
172
+ _getWatchHelpers(path: Path): WatchHelper;
173
+ /**
174
+ * Provides directory tracking objects
175
+ * @param directory path of the directory
176
+ */
177
+ _getWatchedDir(directory: string): DirEntry;
178
+ /**
179
+ * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
180
+ */
181
+ _hasReadPermissions(stats: Stats): boolean;
182
+ /**
183
+ * Handles emitting unlink events for
184
+ * files and directories, and via recursion, for
185
+ * files and directories within directories that are unlinked
186
+ * @param directory within which the following item is located
187
+ * @param item base path of item/directory
188
+ */
189
+ _remove(directory: string, item: string, isDirectory?: boolean): void;
190
+ /**
191
+ * Closes all watchers for a path
192
+ */
193
+ _closePath(path: Path): void;
194
+ /**
195
+ * Closes only file-specific watchers
196
+ */
197
+ _closeFile(path: Path): void;
198
+ _addPathCloser(path: Path, closer: () => void): void;
199
+ _readdirp(root: Path, opts?: Partial<ReaddirpOptions>): ReaddirpStream | undefined;
200
+ }
201
+ /**
202
+ * Instantiates watcher with paths to be tracked.
203
+ * @param paths file / directory paths
204
+ * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others
205
+ * @returns an instance of FSWatcher for chaining.
206
+ * @example
207
+ * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });
208
+ * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })
209
+ */
210
+ export declare function watch(paths: string | string[], options?: ChokidarOptions): FSWatcher;
211
+ declare const _default: {
212
+ watch: typeof watch;
213
+ FSWatcher: typeof FSWatcher;
214
+ };
215
+ export default _default;
backend/node_modules/chokidar/esm/index.js ADDED
@@ -0,0 +1,798 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
2
+ import { stat as statcb } from 'fs';
3
+ import { stat, readdir } from 'fs/promises';
4
+ import { EventEmitter } from 'events';
5
+ import * as sysPath from 'path';
6
+ import { readdirp } from 'readdirp';
7
+ import { NodeFsHandler, EVENTS as EV, isWindows, isIBMi, EMPTY_FN, STR_CLOSE, STR_END, } from './handler.js';
8
+ const SLASH = '/';
9
+ const SLASH_SLASH = '//';
10
+ const ONE_DOT = '.';
11
+ const TWO_DOTS = '..';
12
+ const STRING_TYPE = 'string';
13
+ const BACK_SLASH_RE = /\\/g;
14
+ const DOUBLE_SLASH_RE = /\/\//;
15
+ const DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
16
+ const REPLACER_RE = /^\.[/\\]/;
17
+ function arrify(item) {
18
+ return Array.isArray(item) ? item : [item];
19
+ }
20
+ const isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);
21
+ function createPattern(matcher) {
22
+ if (typeof matcher === 'function')
23
+ return matcher;
24
+ if (typeof matcher === 'string')
25
+ return (string) => matcher === string;
26
+ if (matcher instanceof RegExp)
27
+ return (string) => matcher.test(string);
28
+ if (typeof matcher === 'object' && matcher !== null) {
29
+ return (string) => {
30
+ if (matcher.path === string)
31
+ return true;
32
+ if (matcher.recursive) {
33
+ const relative = sysPath.relative(matcher.path, string);
34
+ if (!relative) {
35
+ return false;
36
+ }
37
+ return !relative.startsWith('..') && !sysPath.isAbsolute(relative);
38
+ }
39
+ return false;
40
+ };
41
+ }
42
+ return () => false;
43
+ }
44
+ function normalizePath(path) {
45
+ if (typeof path !== 'string')
46
+ throw new Error('string expected');
47
+ path = sysPath.normalize(path);
48
+ path = path.replace(/\\/g, '/');
49
+ let prepend = false;
50
+ if (path.startsWith('//'))
51
+ prepend = true;
52
+ const DOUBLE_SLASH_RE = /\/\//;
53
+ while (path.match(DOUBLE_SLASH_RE))
54
+ path = path.replace(DOUBLE_SLASH_RE, '/');
55
+ if (prepend)
56
+ path = '/' + path;
57
+ return path;
58
+ }
59
+ function matchPatterns(patterns, testString, stats) {
60
+ const path = normalizePath(testString);
61
+ for (let index = 0; index < patterns.length; index++) {
62
+ const pattern = patterns[index];
63
+ if (pattern(path, stats)) {
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+ function anymatch(matchers, testString) {
70
+ if (matchers == null) {
71
+ throw new TypeError('anymatch: specify first argument');
72
+ }
73
+ // Early cache for matchers.
74
+ const matchersArray = arrify(matchers);
75
+ const patterns = matchersArray.map((matcher) => createPattern(matcher));
76
+ if (testString == null) {
77
+ return (testString, stats) => {
78
+ return matchPatterns(patterns, testString, stats);
79
+ };
80
+ }
81
+ return matchPatterns(patterns, testString);
82
+ }
83
+ const unifyPaths = (paths_) => {
84
+ const paths = arrify(paths_).flat();
85
+ if (!paths.every((p) => typeof p === STRING_TYPE)) {
86
+ throw new TypeError(`Non-string provided as watch path: ${paths}`);
87
+ }
88
+ return paths.map(normalizePathToUnix);
89
+ };
90
+ // If SLASH_SLASH occurs at the beginning of path, it is not replaced
91
+ // because "//StoragePC/DrivePool/Movies" is a valid network path
92
+ const toUnix = (string) => {
93
+ let str = string.replace(BACK_SLASH_RE, SLASH);
94
+ let prepend = false;
95
+ if (str.startsWith(SLASH_SLASH)) {
96
+ prepend = true;
97
+ }
98
+ while (str.match(DOUBLE_SLASH_RE)) {
99
+ str = str.replace(DOUBLE_SLASH_RE, SLASH);
100
+ }
101
+ if (prepend) {
102
+ str = SLASH + str;
103
+ }
104
+ return str;
105
+ };
106
+ // Our version of upath.normalize
107
+ // TODO: this is not equal to path-normalize module - investigate why
108
+ const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
109
+ // TODO: refactor
110
+ const normalizeIgnored = (cwd = '') => (path) => {
111
+ if (typeof path === 'string') {
112
+ return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
113
+ }
114
+ else {
115
+ return path;
116
+ }
117
+ };
118
+ const getAbsolutePath = (path, cwd) => {
119
+ if (sysPath.isAbsolute(path)) {
120
+ return path;
121
+ }
122
+ return sysPath.join(cwd, path);
123
+ };
124
+ const EMPTY_SET = Object.freeze(new Set());
125
+ /**
126
+ * Directory entry.
127
+ */
128
+ class DirEntry {
129
+ constructor(dir, removeWatcher) {
130
+ this.path = dir;
131
+ this._removeWatcher = removeWatcher;
132
+ this.items = new Set();
133
+ }
134
+ add(item) {
135
+ const { items } = this;
136
+ if (!items)
137
+ return;
138
+ if (item !== ONE_DOT && item !== TWO_DOTS)
139
+ items.add(item);
140
+ }
141
+ async remove(item) {
142
+ const { items } = this;
143
+ if (!items)
144
+ return;
145
+ items.delete(item);
146
+ if (items.size > 0)
147
+ return;
148
+ const dir = this.path;
149
+ try {
150
+ await readdir(dir);
151
+ }
152
+ catch (err) {
153
+ if (this._removeWatcher) {
154
+ this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
155
+ }
156
+ }
157
+ }
158
+ has(item) {
159
+ const { items } = this;
160
+ if (!items)
161
+ return;
162
+ return items.has(item);
163
+ }
164
+ getChildren() {
165
+ const { items } = this;
166
+ if (!items)
167
+ return [];
168
+ return [...items.values()];
169
+ }
170
+ dispose() {
171
+ this.items.clear();
172
+ this.path = '';
173
+ this._removeWatcher = EMPTY_FN;
174
+ this.items = EMPTY_SET;
175
+ Object.freeze(this);
176
+ }
177
+ }
178
+ const STAT_METHOD_F = 'stat';
179
+ const STAT_METHOD_L = 'lstat';
180
+ export class WatchHelper {
181
+ constructor(path, follow, fsw) {
182
+ this.fsw = fsw;
183
+ const watchPath = path;
184
+ this.path = path = path.replace(REPLACER_RE, '');
185
+ this.watchPath = watchPath;
186
+ this.fullWatchPath = sysPath.resolve(watchPath);
187
+ this.dirParts = [];
188
+ this.dirParts.forEach((parts) => {
189
+ if (parts.length > 1)
190
+ parts.pop();
191
+ });
192
+ this.followSymlinks = follow;
193
+ this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
194
+ }
195
+ entryPath(entry) {
196
+ return sysPath.join(this.watchPath, sysPath.relative(this.watchPath, entry.fullPath));
197
+ }
198
+ filterPath(entry) {
199
+ const { stats } = entry;
200
+ if (stats && stats.isSymbolicLink())
201
+ return this.filterDir(entry);
202
+ const resolvedPath = this.entryPath(entry);
203
+ // TODO: what if stats is undefined? remove !
204
+ return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
205
+ }
206
+ filterDir(entry) {
207
+ return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
208
+ }
209
+ }
210
+ /**
211
+ * Watches files & directories for changes. Emitted events:
212
+ * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
213
+ *
214
+ * new FSWatcher()
215
+ * .add(directories)
216
+ * .on('add', path => log('File', path, 'was added'))
217
+ */
218
+ export class FSWatcher extends EventEmitter {
219
+ // Not indenting methods for history sake; for now.
220
+ constructor(_opts = {}) {
221
+ super();
222
+ this.closed = false;
223
+ this._closers = new Map();
224
+ this._ignoredPaths = new Set();
225
+ this._throttled = new Map();
226
+ this._streams = new Set();
227
+ this._symlinkPaths = new Map();
228
+ this._watched = new Map();
229
+ this._pendingWrites = new Map();
230
+ this._pendingUnlinks = new Map();
231
+ this._readyCount = 0;
232
+ this._readyEmitted = false;
233
+ const awf = _opts.awaitWriteFinish;
234
+ const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };
235
+ const opts = {
236
+ // Defaults
237
+ persistent: true,
238
+ ignoreInitial: false,
239
+ ignorePermissionErrors: false,
240
+ interval: 100,
241
+ binaryInterval: 300,
242
+ followSymlinks: true,
243
+ usePolling: false,
244
+ // useAsync: false,
245
+ atomic: true, // NOTE: overwritten later (depends on usePolling)
246
+ ..._opts,
247
+ // Change format
248
+ ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
249
+ awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,
250
+ };
251
+ // Always default to polling on IBM i because fs.watch() is not available on IBM i.
252
+ if (isIBMi)
253
+ opts.usePolling = true;
254
+ // Editor atomic write normalization enabled by default with fs.watch
255
+ if (opts.atomic === undefined)
256
+ opts.atomic = !opts.usePolling;
257
+ // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;
258
+ // Global override. Useful for developers, who need to force polling for all
259
+ // instances of chokidar, regardless of usage / dependency depth
260
+ const envPoll = process.env.CHOKIDAR_USEPOLLING;
261
+ if (envPoll !== undefined) {
262
+ const envLower = envPoll.toLowerCase();
263
+ if (envLower === 'false' || envLower === '0')
264
+ opts.usePolling = false;
265
+ else if (envLower === 'true' || envLower === '1')
266
+ opts.usePolling = true;
267
+ else
268
+ opts.usePolling = !!envLower;
269
+ }
270
+ const envInterval = process.env.CHOKIDAR_INTERVAL;
271
+ if (envInterval)
272
+ opts.interval = Number.parseInt(envInterval, 10);
273
+ // This is done to emit ready only once, but each 'add' will increase that?
274
+ let readyCalls = 0;
275
+ this._emitReady = () => {
276
+ readyCalls++;
277
+ if (readyCalls >= this._readyCount) {
278
+ this._emitReady = EMPTY_FN;
279
+ this._readyEmitted = true;
280
+ // use process.nextTick to allow time for listener to be bound
281
+ process.nextTick(() => this.emit(EV.READY));
282
+ }
283
+ };
284
+ this._emitRaw = (...args) => this.emit(EV.RAW, ...args);
285
+ this._boundRemove = this._remove.bind(this);
286
+ this.options = opts;
287
+ this._nodeFsHandler = new NodeFsHandler(this);
288
+ // You’re frozen when your heart’s not open.
289
+ Object.freeze(opts);
290
+ }
291
+ _addIgnoredPath(matcher) {
292
+ if (isMatcherObject(matcher)) {
293
+ // return early if we already have a deeply equal matcher object
294
+ for (const ignored of this._ignoredPaths) {
295
+ if (isMatcherObject(ignored) &&
296
+ ignored.path === matcher.path &&
297
+ ignored.recursive === matcher.recursive) {
298
+ return;
299
+ }
300
+ }
301
+ }
302
+ this._ignoredPaths.add(matcher);
303
+ }
304
+ _removeIgnoredPath(matcher) {
305
+ this._ignoredPaths.delete(matcher);
306
+ // now find any matcher objects with the matcher as path
307
+ if (typeof matcher === 'string') {
308
+ for (const ignored of this._ignoredPaths) {
309
+ // TODO (43081j): make this more efficient.
310
+ // probably just make a `this._ignoredDirectories` or some
311
+ // such thing.
312
+ if (isMatcherObject(ignored) && ignored.path === matcher) {
313
+ this._ignoredPaths.delete(ignored);
314
+ }
315
+ }
316
+ }
317
+ }
318
+ // Public methods
319
+ /**
320
+ * Adds paths to be watched on an existing FSWatcher instance.
321
+ * @param paths_ file or file list. Other arguments are unused
322
+ */
323
+ add(paths_, _origAdd, _internal) {
324
+ const { cwd } = this.options;
325
+ this.closed = false;
326
+ this._closePromise = undefined;
327
+ let paths = unifyPaths(paths_);
328
+ if (cwd) {
329
+ paths = paths.map((path) => {
330
+ const absPath = getAbsolutePath(path, cwd);
331
+ // Check `path` instead of `absPath` because the cwd portion can't be a glob
332
+ return absPath;
333
+ });
334
+ }
335
+ paths.forEach((path) => {
336
+ this._removeIgnoredPath(path);
337
+ });
338
+ this._userIgnored = undefined;
339
+ if (!this._readyCount)
340
+ this._readyCount = 0;
341
+ this._readyCount += paths.length;
342
+ Promise.all(paths.map(async (path) => {
343
+ const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);
344
+ if (res)
345
+ this._emitReady();
346
+ return res;
347
+ })).then((results) => {
348
+ if (this.closed)
349
+ return;
350
+ results.forEach((item) => {
351
+ if (item)
352
+ this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
353
+ });
354
+ });
355
+ return this;
356
+ }
357
+ /**
358
+ * Close watchers or start ignoring events from specified paths.
359
+ */
360
+ unwatch(paths_) {
361
+ if (this.closed)
362
+ return this;
363
+ const paths = unifyPaths(paths_);
364
+ const { cwd } = this.options;
365
+ paths.forEach((path) => {
366
+ // convert to absolute path unless relative path already matches
367
+ if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
368
+ if (cwd)
369
+ path = sysPath.join(cwd, path);
370
+ path = sysPath.resolve(path);
371
+ }
372
+ this._closePath(path);
373
+ this._addIgnoredPath(path);
374
+ if (this._watched.has(path)) {
375
+ this._addIgnoredPath({
376
+ path,
377
+ recursive: true,
378
+ });
379
+ }
380
+ // reset the cached userIgnored anymatch fn
381
+ // to make ignoredPaths changes effective
382
+ this._userIgnored = undefined;
383
+ });
384
+ return this;
385
+ }
386
+ /**
387
+ * Close watchers and remove all listeners from watched paths.
388
+ */
389
+ close() {
390
+ if (this._closePromise) {
391
+ return this._closePromise;
392
+ }
393
+ this.closed = true;
394
+ // Memory management.
395
+ this.removeAllListeners();
396
+ const closers = [];
397
+ this._closers.forEach((closerList) => closerList.forEach((closer) => {
398
+ const promise = closer();
399
+ if (promise instanceof Promise)
400
+ closers.push(promise);
401
+ }));
402
+ this._streams.forEach((stream) => stream.destroy());
403
+ this._userIgnored = undefined;
404
+ this._readyCount = 0;
405
+ this._readyEmitted = false;
406
+ this._watched.forEach((dirent) => dirent.dispose());
407
+ this._closers.clear();
408
+ this._watched.clear();
409
+ this._streams.clear();
410
+ this._symlinkPaths.clear();
411
+ this._throttled.clear();
412
+ this._closePromise = closers.length
413
+ ? Promise.all(closers).then(() => undefined)
414
+ : Promise.resolve();
415
+ return this._closePromise;
416
+ }
417
+ /**
418
+ * Expose list of watched paths
419
+ * @returns for chaining
420
+ */
421
+ getWatched() {
422
+ const watchList = {};
423
+ this._watched.forEach((entry, dir) => {
424
+ const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
425
+ const index = key || ONE_DOT;
426
+ watchList[index] = entry.getChildren().sort();
427
+ });
428
+ return watchList;
429
+ }
430
+ emitWithAll(event, args) {
431
+ this.emit(event, ...args);
432
+ if (event !== EV.ERROR)
433
+ this.emit(EV.ALL, event, ...args);
434
+ }
435
+ // Common helpers
436
+ // --------------
437
+ /**
438
+ * Normalize and emit events.
439
+ * Calling _emit DOES NOT MEAN emit() would be called!
440
+ * @param event Type of event
441
+ * @param path File or directory path
442
+ * @param stats arguments to be passed with event
443
+ * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
444
+ */
445
+ async _emit(event, path, stats) {
446
+ if (this.closed)
447
+ return;
448
+ const opts = this.options;
449
+ if (isWindows)
450
+ path = sysPath.normalize(path);
451
+ if (opts.cwd)
452
+ path = sysPath.relative(opts.cwd, path);
453
+ const args = [path];
454
+ if (stats != null)
455
+ args.push(stats);
456
+ const awf = opts.awaitWriteFinish;
457
+ let pw;
458
+ if (awf && (pw = this._pendingWrites.get(path))) {
459
+ pw.lastChange = new Date();
460
+ return this;
461
+ }
462
+ if (opts.atomic) {
463
+ if (event === EV.UNLINK) {
464
+ this._pendingUnlinks.set(path, [event, ...args]);
465
+ setTimeout(() => {
466
+ this._pendingUnlinks.forEach((entry, path) => {
467
+ this.emit(...entry);
468
+ this.emit(EV.ALL, ...entry);
469
+ this._pendingUnlinks.delete(path);
470
+ });
471
+ }, typeof opts.atomic === 'number' ? opts.atomic : 100);
472
+ return this;
473
+ }
474
+ if (event === EV.ADD && this._pendingUnlinks.has(path)) {
475
+ event = EV.CHANGE;
476
+ this._pendingUnlinks.delete(path);
477
+ }
478
+ }
479
+ if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {
480
+ const awfEmit = (err, stats) => {
481
+ if (err) {
482
+ event = EV.ERROR;
483
+ args[0] = err;
484
+ this.emitWithAll(event, args);
485
+ }
486
+ else if (stats) {
487
+ // if stats doesn't exist the file must have been deleted
488
+ if (args.length > 1) {
489
+ args[1] = stats;
490
+ }
491
+ else {
492
+ args.push(stats);
493
+ }
494
+ this.emitWithAll(event, args);
495
+ }
496
+ };
497
+ this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
498
+ return this;
499
+ }
500
+ if (event === EV.CHANGE) {
501
+ const isThrottled = !this._throttle(EV.CHANGE, path, 50);
502
+ if (isThrottled)
503
+ return this;
504
+ }
505
+ if (opts.alwaysStat &&
506
+ stats === undefined &&
507
+ (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {
508
+ const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
509
+ let stats;
510
+ try {
511
+ stats = await stat(fullPath);
512
+ }
513
+ catch (err) {
514
+ // do nothing
515
+ }
516
+ // Suppress event when fs_stat fails, to avoid sending undefined 'stat'
517
+ if (!stats || this.closed)
518
+ return;
519
+ args.push(stats);
520
+ }
521
+ this.emitWithAll(event, args);
522
+ return this;
523
+ }
524
+ /**
525
+ * Common handler for errors
526
+ * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
527
+ */
528
+ _handleError(error) {
529
+ const code = error && error.code;
530
+ if (error &&
531
+ code !== 'ENOENT' &&
532
+ code !== 'ENOTDIR' &&
533
+ (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {
534
+ this.emit(EV.ERROR, error);
535
+ }
536
+ return error || this.closed;
537
+ }
538
+ /**
539
+ * Helper utility for throttling
540
+ * @param actionType type being throttled
541
+ * @param path being acted upon
542
+ * @param timeout duration of time to suppress duplicate actions
543
+ * @returns tracking object or false if action should be suppressed
544
+ */
545
+ _throttle(actionType, path, timeout) {
546
+ if (!this._throttled.has(actionType)) {
547
+ this._throttled.set(actionType, new Map());
548
+ }
549
+ const action = this._throttled.get(actionType);
550
+ if (!action)
551
+ throw new Error('invalid throttle');
552
+ const actionPath = action.get(path);
553
+ if (actionPath) {
554
+ actionPath.count++;
555
+ return false;
556
+ }
557
+ // eslint-disable-next-line prefer-const
558
+ let timeoutObject;
559
+ const clear = () => {
560
+ const item = action.get(path);
561
+ const count = item ? item.count : 0;
562
+ action.delete(path);
563
+ clearTimeout(timeoutObject);
564
+ if (item)
565
+ clearTimeout(item.timeoutObject);
566
+ return count;
567
+ };
568
+ timeoutObject = setTimeout(clear, timeout);
569
+ const thr = { timeoutObject, clear, count: 0 };
570
+ action.set(path, thr);
571
+ return thr;
572
+ }
573
+ _incrReadyCount() {
574
+ return this._readyCount++;
575
+ }
576
+ /**
577
+ * Awaits write operation to finish.
578
+ * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
579
+ * @param path being acted upon
580
+ * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
581
+ * @param event
582
+ * @param awfEmit Callback to be called when ready for event to be emitted.
583
+ */
584
+ _awaitWriteFinish(path, threshold, event, awfEmit) {
585
+ const awf = this.options.awaitWriteFinish;
586
+ if (typeof awf !== 'object')
587
+ return;
588
+ const pollInterval = awf.pollInterval;
589
+ let timeoutHandler;
590
+ let fullPath = path;
591
+ if (this.options.cwd && !sysPath.isAbsolute(path)) {
592
+ fullPath = sysPath.join(this.options.cwd, path);
593
+ }
594
+ const now = new Date();
595
+ const writes = this._pendingWrites;
596
+ function awaitWriteFinishFn(prevStat) {
597
+ statcb(fullPath, (err, curStat) => {
598
+ if (err || !writes.has(path)) {
599
+ if (err && err.code !== 'ENOENT')
600
+ awfEmit(err);
601
+ return;
602
+ }
603
+ const now = Number(new Date());
604
+ if (prevStat && curStat.size !== prevStat.size) {
605
+ writes.get(path).lastChange = now;
606
+ }
607
+ const pw = writes.get(path);
608
+ const df = now - pw.lastChange;
609
+ if (df >= threshold) {
610
+ writes.delete(path);
611
+ awfEmit(undefined, curStat);
612
+ }
613
+ else {
614
+ timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
615
+ }
616
+ });
617
+ }
618
+ if (!writes.has(path)) {
619
+ writes.set(path, {
620
+ lastChange: now,
621
+ cancelWait: () => {
622
+ writes.delete(path);
623
+ clearTimeout(timeoutHandler);
624
+ return event;
625
+ },
626
+ });
627
+ timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
628
+ }
629
+ }
630
+ /**
631
+ * Determines whether user has asked to ignore this path.
632
+ */
633
+ _isIgnored(path, stats) {
634
+ if (this.options.atomic && DOT_RE.test(path))
635
+ return true;
636
+ if (!this._userIgnored) {
637
+ const { cwd } = this.options;
638
+ const ign = this.options.ignored;
639
+ const ignored = (ign || []).map(normalizeIgnored(cwd));
640
+ const ignoredPaths = [...this._ignoredPaths];
641
+ const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
642
+ this._userIgnored = anymatch(list, undefined);
643
+ }
644
+ return this._userIgnored(path, stats);
645
+ }
646
+ _isntIgnored(path, stat) {
647
+ return !this._isIgnored(path, stat);
648
+ }
649
+ /**
650
+ * Provides a set of common helpers and properties relating to symlink handling.
651
+ * @param path file or directory pattern being watched
652
+ */
653
+ _getWatchHelpers(path) {
654
+ return new WatchHelper(path, this.options.followSymlinks, this);
655
+ }
656
+ // Directory helpers
657
+ // -----------------
658
+ /**
659
+ * Provides directory tracking objects
660
+ * @param directory path of the directory
661
+ */
662
+ _getWatchedDir(directory) {
663
+ const dir = sysPath.resolve(directory);
664
+ if (!this._watched.has(dir))
665
+ this._watched.set(dir, new DirEntry(dir, this._boundRemove));
666
+ return this._watched.get(dir);
667
+ }
668
+ // File helpers
669
+ // ------------
670
+ /**
671
+ * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
672
+ */
673
+ _hasReadPermissions(stats) {
674
+ if (this.options.ignorePermissionErrors)
675
+ return true;
676
+ return Boolean(Number(stats.mode) & 0o400);
677
+ }
678
+ /**
679
+ * Handles emitting unlink events for
680
+ * files and directories, and via recursion, for
681
+ * files and directories within directories that are unlinked
682
+ * @param directory within which the following item is located
683
+ * @param item base path of item/directory
684
+ */
685
+ _remove(directory, item, isDirectory) {
686
+ // if what is being deleted is a directory, get that directory's paths
687
+ // for recursive deleting and cleaning of watched object
688
+ // if it is not a directory, nestedDirectoryChildren will be empty array
689
+ const path = sysPath.join(directory, item);
690
+ const fullPath = sysPath.resolve(path);
691
+ isDirectory =
692
+ isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
693
+ // prevent duplicate handling in case of arriving here nearly simultaneously
694
+ // via multiple paths (such as _handleFile and _handleDir)
695
+ if (!this._throttle('remove', path, 100))
696
+ return;
697
+ // if the only watched file is removed, watch for its return
698
+ if (!isDirectory && this._watched.size === 1) {
699
+ this.add(directory, item, true);
700
+ }
701
+ // This will create a new entry in the watched object in either case
702
+ // so we got to do the directory check beforehand
703
+ const wp = this._getWatchedDir(path);
704
+ const nestedDirectoryChildren = wp.getChildren();
705
+ // Recursively remove children directories / files.
706
+ nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));
707
+ // Check if item was on the watched list and remove it
708
+ const parent = this._getWatchedDir(directory);
709
+ const wasTracked = parent.has(item);
710
+ parent.remove(item);
711
+ // Fixes issue #1042 -> Relative paths were detected and added as symlinks
712
+ // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),
713
+ // but never removed from the map in case the path was deleted.
714
+ // This leads to an incorrect state if the path was recreated:
715
+ // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553
716
+ if (this._symlinkPaths.has(fullPath)) {
717
+ this._symlinkPaths.delete(fullPath);
718
+ }
719
+ // If we wait for this file to be fully written, cancel the wait.
720
+ let relPath = path;
721
+ if (this.options.cwd)
722
+ relPath = sysPath.relative(this.options.cwd, path);
723
+ if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
724
+ const event = this._pendingWrites.get(relPath).cancelWait();
725
+ if (event === EV.ADD)
726
+ return;
727
+ }
728
+ // The Entry will either be a directory that just got removed
729
+ // or a bogus entry to a file, in either case we have to remove it
730
+ this._watched.delete(path);
731
+ this._watched.delete(fullPath);
732
+ const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;
733
+ if (wasTracked && !this._isIgnored(path))
734
+ this._emit(eventName, path);
735
+ // Avoid conflicts if we later create another file with the same name
736
+ this._closePath(path);
737
+ }
738
+ /**
739
+ * Closes all watchers for a path
740
+ */
741
+ _closePath(path) {
742
+ this._closeFile(path);
743
+ const dir = sysPath.dirname(path);
744
+ this._getWatchedDir(dir).remove(sysPath.basename(path));
745
+ }
746
+ /**
747
+ * Closes only file-specific watchers
748
+ */
749
+ _closeFile(path) {
750
+ const closers = this._closers.get(path);
751
+ if (!closers)
752
+ return;
753
+ closers.forEach((closer) => closer());
754
+ this._closers.delete(path);
755
+ }
756
+ _addPathCloser(path, closer) {
757
+ if (!closer)
758
+ return;
759
+ let list = this._closers.get(path);
760
+ if (!list) {
761
+ list = [];
762
+ this._closers.set(path, list);
763
+ }
764
+ list.push(closer);
765
+ }
766
+ _readdirp(root, opts) {
767
+ if (this.closed)
768
+ return;
769
+ const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
770
+ let stream = readdirp(root, options);
771
+ this._streams.add(stream);
772
+ stream.once(STR_CLOSE, () => {
773
+ stream = undefined;
774
+ });
775
+ stream.once(STR_END, () => {
776
+ if (stream) {
777
+ this._streams.delete(stream);
778
+ stream = undefined;
779
+ }
780
+ });
781
+ return stream;
782
+ }
783
+ }
784
+ /**
785
+ * Instantiates watcher with paths to be tracked.
786
+ * @param paths file / directory paths
787
+ * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others
788
+ * @returns an instance of FSWatcher for chaining.
789
+ * @example
790
+ * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });
791
+ * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })
792
+ */
793
+ export function watch(paths, options = {}) {
794
+ const watcher = new FSWatcher(options);
795
+ watcher.add(paths);
796
+ return watcher;
797
+ }
798
+ export default { watch, FSWatcher };
backend/node_modules/chokidar/esm/package.json ADDED
@@ -0,0 +1 @@
 
 
1
+ { "type": "module", "sideEffects": false }
backend/node_modules/dotenv/lib/cli-options.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/
2
+
3
+ module.exports = function optionMatcher (args) {
4
+ const options = args.reduce(function (acc, cur) {
5
+ const matches = cur.match(re)
6
+ if (matches) {
7
+ acc[matches[1]] = matches[2]
8
+ }
9
+ return acc
10
+ }, {})
11
+
12
+ if (!('quiet' in options)) {
13
+ options.quiet = 'true'
14
+ }
15
+
16
+ return options
17
+ }
backend/node_modules/dotenv/lib/env-options.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ../config.js accepts options via environment variables
2
+ const options = {}
3
+
4
+ if (process.env.DOTENV_CONFIG_ENCODING != null) {
5
+ options.encoding = process.env.DOTENV_CONFIG_ENCODING
6
+ }
7
+
8
+ if (process.env.DOTENV_CONFIG_PATH != null) {
9
+ options.path = process.env.DOTENV_CONFIG_PATH
10
+ }
11
+
12
+ if (process.env.DOTENV_CONFIG_QUIET != null) {
13
+ options.quiet = process.env.DOTENV_CONFIG_QUIET
14
+ }
15
+
16
+ if (process.env.DOTENV_CONFIG_DEBUG != null) {
17
+ options.debug = process.env.DOTENV_CONFIG_DEBUG
18
+ }
19
+
20
+ if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
21
+ options.override = process.env.DOTENV_CONFIG_OVERRIDE
22
+ }
23
+
24
+ if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
25
+ options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY
26
+ }
27
+
28
+ module.exports = options
backend/node_modules/dotenv/lib/main.d.ts ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // TypeScript Version: 3.0
2
+ /// <reference types="node" />
3
+ import type { URL } from 'url';
4
+
5
+ export interface DotenvParseOutput {
6
+ [name: string]: string;
7
+ }
8
+
9
+ /**
10
+ * Parses a string or buffer in the .env file format into an object.
11
+ *
12
+ * See https://dotenvx.com/docs
13
+ *
14
+ * @param src - contents to be parsed. example: `'DB_HOST=localhost'`
15
+ * @returns an object with keys and values based on `src`. example: `{ DB_HOST : 'localhost' }`
16
+ */
17
+ export function parse<T extends DotenvParseOutput = DotenvParseOutput>(
18
+ src: string | Buffer
19
+ ): T;
20
+
21
+ export interface DotenvConfigOptions {
22
+ /**
23
+ * Default: `path.resolve(process.cwd(), '.env')`
24
+ *
25
+ * Specify a custom path if your file containing environment variables is located elsewhere.
26
+ * Can also be an array of strings, specifying multiple paths.
27
+ *
28
+ * example: `require('dotenv').config({ path: '/custom/path/to/.env' })`
29
+ * example: `require('dotenv').config({ path: ['/path/to/first.env', '/path/to/second.env'] })`
30
+ */
31
+ path?: string | string[] | URL;
32
+
33
+ /**
34
+ * Default: `utf8`
35
+ *
36
+ * Specify the encoding of your file containing environment variables.
37
+ *
38
+ * example: `require('dotenv').config({ encoding: 'latin1' })`
39
+ */
40
+ encoding?: string;
41
+
42
+ /**
43
+ * Default: `false`
44
+ *
45
+ * Suppress all output (except errors).
46
+ *
47
+ * example: `require('dotenv').config({ quiet: true })`
48
+ */
49
+ quiet?: boolean;
50
+
51
+ /**
52
+ * Default: `false`
53
+ *
54
+ * Turn on logging to help debug why certain keys or values are not being set as you expect.
55
+ *
56
+ * example: `require('dotenv').config({ debug: process.env.DEBUG })`
57
+ */
58
+ debug?: boolean;
59
+
60
+ /**
61
+ * Default: `false`
62
+ *
63
+ * Override any environment variables that have already been set on your machine with values from your .env file.
64
+ *
65
+ * example: `require('dotenv').config({ override: true })`
66
+ */
67
+ override?: boolean;
68
+
69
+ /**
70
+ * Default: `process.env`
71
+ *
72
+ * Specify an object to write your secrets to. Defaults to process.env environment variables.
73
+ *
74
+ * example: `const processEnv = {}; require('dotenv').config({ processEnv: processEnv })`
75
+ */
76
+ processEnv?: DotenvPopulateInput;
77
+
78
+ /**
79
+ * Default: `undefined`
80
+ *
81
+ * Pass the DOTENV_KEY directly to config options. Defaults to looking for process.env.DOTENV_KEY environment variable. Note this only applies to decrypting .env.vault files. If passed as null or undefined, or not passed at all, dotenv falls back to its traditional job of parsing a .env file.
82
+ *
83
+ * example: `require('dotenv').config({ DOTENV_KEY: 'dotenv://:key_1234…@dotenvx.com/vault/.env.vault?environment=production' })`
84
+ */
85
+ DOTENV_KEY?: string;
86
+ }
87
+
88
+ export interface DotenvConfigOutput {
89
+ error?: Error;
90
+ parsed?: DotenvParseOutput;
91
+ }
92
+
93
+ export interface DotenvPopulateOptions {
94
+ /**
95
+ * Default: `false`
96
+ *
97
+ * Turn on logging to help debug why certain keys or values are not being set as you expect.
98
+ *
99
+ * example: `require('dotenv').config({ debug: process.env.DEBUG })`
100
+ */
101
+ debug?: boolean;
102
+
103
+ /**
104
+ * Default: `false`
105
+ *
106
+ * Override any environment variables that have already been set on your machine with values from your .env file.
107
+ *
108
+ * example: `require('dotenv').config({ override: true })`
109
+ */
110
+ override?: boolean;
111
+ }
112
+
113
+ export interface DotenvPopulateInput {
114
+ [name: string]: string;
115
+ }
116
+
117
+ /**
118
+ * Loads `.env` file contents into process.env by default. If `DOTENV_KEY` is present, it smartly attempts to load encrypted `.env.vault` file contents into process.env.
119
+ *
120
+ * See https://dotenvx.com/docs
121
+ *
122
+ * @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', quiet: false, debug: true, override: false }`
123
+ * @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
124
+ *
125
+ */
126
+ export function config(options?: DotenvConfigOptions): DotenvConfigOutput;
127
+
128
+ /**
129
+ * Loads `.env` file contents into process.env.
130
+ *
131
+ * See https://dotenvx.com/docs
132
+ *
133
+ * @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', quiet: false, debug: true, override: false }`
134
+ * @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
135
+ *
136
+ */
137
+ export function configDotenv(options?: DotenvConfigOptions): DotenvConfigOutput;
138
+
139
+ /**
140
+ * Loads `source` json contents into `target` like process.env.
141
+ *
142
+ * See https://dotenvx.com/docs
143
+ *
144
+ * @param processEnv - the target JSON object. in most cases use process.env but you can also pass your own JSON object
145
+ * @param parsed - the source JSON object
146
+ * @param options - additional options. example: `{ quiet: false, debug: true, override: false }`
147
+ * @returns {void}
148
+ *
149
+ */
150
+ export function populate(processEnv: DotenvPopulateInput, parsed: DotenvPopulateInput, options?: DotenvConfigOptions): void;
151
+
152
+ /**
153
+ * Decrypt ciphertext
154
+ *
155
+ * See https://dotenvx.com/docs
156
+ *
157
+ * @param encrypted - the encrypted ciphertext string
158
+ * @param keyStr - the decryption key string
159
+ * @returns {string}
160
+ *
161
+ */
162
+ export function decrypt(encrypted: string, keyStr: string): string;
backend/node_modules/dotenv/lib/main.js ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const os = require('os')
4
+ const crypto = require('crypto')
5
+ const packageJson = require('../package.json')
6
+
7
+ const version = packageJson.version
8
+
9
+ const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
10
+
11
+ // Parse src into an Object
12
+ function parse (src) {
13
+ const obj = {}
14
+
15
+ // Convert buffer to string
16
+ let lines = src.toString()
17
+
18
+ // Convert line breaks to same format
19
+ lines = lines.replace(/\r\n?/mg, '\n')
20
+
21
+ let match
22
+ while ((match = LINE.exec(lines)) != null) {
23
+ const key = match[1]
24
+
25
+ // Default undefined or null to empty string
26
+ let value = (match[2] || '')
27
+
28
+ // Remove whitespace
29
+ value = value.trim()
30
+
31
+ // Check if double quoted
32
+ const maybeQuote = value[0]
33
+
34
+ // Remove surrounding quotes
35
+ value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
36
+
37
+ // Expand newlines if double quoted
38
+ if (maybeQuote === '"') {
39
+ value = value.replace(/\\n/g, '\n')
40
+ value = value.replace(/\\r/g, '\r')
41
+ }
42
+
43
+ // Add to object
44
+ obj[key] = value
45
+ }
46
+
47
+ return obj
48
+ }
49
+
50
+ function _parseVault (options) {
51
+ options = options || {}
52
+
53
+ const vaultPath = _vaultPath(options)
54
+ options.path = vaultPath // parse .env.vault
55
+ const result = DotenvModule.configDotenv(options)
56
+ if (!result.parsed) {
57
+ const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)
58
+ err.code = 'MISSING_DATA'
59
+ throw err
60
+ }
61
+
62
+ // handle scenario for comma separated keys - for use with key rotation
63
+ // example: DOTENV_KEY="dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod"
64
+ const keys = _dotenvKey(options).split(',')
65
+ const length = keys.length
66
+
67
+ let decrypted
68
+ for (let i = 0; i < length; i++) {
69
+ try {
70
+ // Get full key
71
+ const key = keys[i].trim()
72
+
73
+ // Get instructions for decrypt
74
+ const attrs = _instructions(result, key)
75
+
76
+ // Decrypt
77
+ decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)
78
+
79
+ break
80
+ } catch (error) {
81
+ // last key
82
+ if (i + 1 >= length) {
83
+ throw error
84
+ }
85
+ // try next key
86
+ }
87
+ }
88
+
89
+ // Parse decrypted .env string
90
+ return DotenvModule.parse(decrypted)
91
+ }
92
+
93
+ function _warn (message) {
94
+ console.log(`[dotenv@${version}][WARN] ${message}`)
95
+ }
96
+
97
+ function _debug (message) {
98
+ console.log(`[dotenv@${version}][DEBUG] ${message}`)
99
+ }
100
+
101
+ function _log (message) {
102
+ console.log(`[dotenv@${version}] ${message}`)
103
+ }
104
+
105
+ function _dotenvKey (options) {
106
+ // prioritize developer directly setting options.DOTENV_KEY
107
+ if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
108
+ return options.DOTENV_KEY
109
+ }
110
+
111
+ // secondary infra already contains a DOTENV_KEY environment variable
112
+ if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
113
+ return process.env.DOTENV_KEY
114
+ }
115
+
116
+ // fallback to empty string
117
+ return ''
118
+ }
119
+
120
+ function _instructions (result, dotenvKey) {
121
+ // Parse DOTENV_KEY. Format is a URI
122
+ let uri
123
+ try {
124
+ uri = new URL(dotenvKey)
125
+ } catch (error) {
126
+ if (error.code === 'ERR_INVALID_URL') {
127
+ const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')
128
+ err.code = 'INVALID_DOTENV_KEY'
129
+ throw err
130
+ }
131
+
132
+ throw error
133
+ }
134
+
135
+ // Get decrypt key
136
+ const key = uri.password
137
+ if (!key) {
138
+ const err = new Error('INVALID_DOTENV_KEY: Missing key part')
139
+ err.code = 'INVALID_DOTENV_KEY'
140
+ throw err
141
+ }
142
+
143
+ // Get environment
144
+ const environment = uri.searchParams.get('environment')
145
+ if (!environment) {
146
+ const err = new Error('INVALID_DOTENV_KEY: Missing environment part')
147
+ err.code = 'INVALID_DOTENV_KEY'
148
+ throw err
149
+ }
150
+
151
+ // Get ciphertext payload
152
+ const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`
153
+ const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION
154
+ if (!ciphertext) {
155
+ const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)
156
+ err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'
157
+ throw err
158
+ }
159
+
160
+ return { ciphertext, key }
161
+ }
162
+
163
+ function _vaultPath (options) {
164
+ let possibleVaultPath = null
165
+
166
+ if (options && options.path && options.path.length > 0) {
167
+ if (Array.isArray(options.path)) {
168
+ for (const filepath of options.path) {
169
+ if (fs.existsSync(filepath)) {
170
+ possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`
171
+ }
172
+ }
173
+ } else {
174
+ possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`
175
+ }
176
+ } else {
177
+ possibleVaultPath = path.resolve(process.cwd(), '.env.vault')
178
+ }
179
+
180
+ if (fs.existsSync(possibleVaultPath)) {
181
+ return possibleVaultPath
182
+ }
183
+
184
+ return null
185
+ }
186
+
187
+ function _resolveHome (envPath) {
188
+ return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
189
+ }
190
+
191
+ function _configVault (options) {
192
+ const debug = Boolean(options && options.debug)
193
+ const quiet = options && 'quiet' in options ? options.quiet : true
194
+
195
+ if (debug || !quiet) {
196
+ _log('Loading env from encrypted .env.vault')
197
+ }
198
+
199
+ const parsed = DotenvModule._parseVault(options)
200
+
201
+ let processEnv = process.env
202
+ if (options && options.processEnv != null) {
203
+ processEnv = options.processEnv
204
+ }
205
+
206
+ DotenvModule.populate(processEnv, parsed, options)
207
+
208
+ return { parsed }
209
+ }
210
+
211
+ function configDotenv (options) {
212
+ const dotenvPath = path.resolve(process.cwd(), '.env')
213
+ let encoding = 'utf8'
214
+ const debug = Boolean(options && options.debug)
215
+ const quiet = options && 'quiet' in options ? options.quiet : true
216
+
217
+ if (options && options.encoding) {
218
+ encoding = options.encoding
219
+ } else {
220
+ if (debug) {
221
+ _debug('No encoding is specified. UTF-8 is used by default')
222
+ }
223
+ }
224
+
225
+ let optionPaths = [dotenvPath] // default, look for .env
226
+ if (options && options.path) {
227
+ if (!Array.isArray(options.path)) {
228
+ optionPaths = [_resolveHome(options.path)]
229
+ } else {
230
+ optionPaths = [] // reset default
231
+ for (const filepath of options.path) {
232
+ optionPaths.push(_resolveHome(filepath))
233
+ }
234
+ }
235
+ }
236
+
237
+ // Build the parsed data in a temporary object (because we need to return it). Once we have the final
238
+ // parsed data, we will combine it with process.env (or options.processEnv if provided).
239
+ let lastError
240
+ const parsedAll = {}
241
+ for (const path of optionPaths) {
242
+ try {
243
+ // Specifying an encoding returns a string instead of a buffer
244
+ const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))
245
+
246
+ DotenvModule.populate(parsedAll, parsed, options)
247
+ } catch (e) {
248
+ if (debug) {
249
+ _debug(`Failed to load ${path} ${e.message}`)
250
+ }
251
+ lastError = e
252
+ }
253
+ }
254
+
255
+ let processEnv = process.env
256
+ if (options && options.processEnv != null) {
257
+ processEnv = options.processEnv
258
+ }
259
+
260
+ DotenvModule.populate(processEnv, parsedAll, options)
261
+
262
+ if (debug || !quiet) {
263
+ const keysCount = Object.keys(parsedAll).length
264
+ const shortPaths = []
265
+ for (const filePath of optionPaths) {
266
+ try {
267
+ const relative = path.relative(process.cwd(), filePath)
268
+ shortPaths.push(relative)
269
+ } catch (e) {
270
+ if (debug) {
271
+ _debug(`Failed to load ${filePath} ${e.message}`)
272
+ }
273
+ lastError = e
274
+ }
275
+ }
276
+
277
+ _log(`injecting env (${keysCount}) from ${shortPaths.join(',')}`)
278
+ }
279
+
280
+ if (lastError) {
281
+ return { parsed: parsedAll, error: lastError }
282
+ } else {
283
+ return { parsed: parsedAll }
284
+ }
285
+ }
286
+
287
+ // Populates process.env from .env file
288
+ function config (options) {
289
+ // fallback to original dotenv if DOTENV_KEY is not set
290
+ if (_dotenvKey(options).length === 0) {
291
+ return DotenvModule.configDotenv(options)
292
+ }
293
+
294
+ const vaultPath = _vaultPath(options)
295
+
296
+ // dotenvKey exists but .env.vault file does not exist
297
+ if (!vaultPath) {
298
+ _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)
299
+
300
+ return DotenvModule.configDotenv(options)
301
+ }
302
+
303
+ return DotenvModule._configVault(options)
304
+ }
305
+
306
+ function decrypt (encrypted, keyStr) {
307
+ const key = Buffer.from(keyStr.slice(-64), 'hex')
308
+ let ciphertext = Buffer.from(encrypted, 'base64')
309
+
310
+ const nonce = ciphertext.subarray(0, 12)
311
+ const authTag = ciphertext.subarray(-16)
312
+ ciphertext = ciphertext.subarray(12, -16)
313
+
314
+ try {
315
+ const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)
316
+ aesgcm.setAuthTag(authTag)
317
+ return `${aesgcm.update(ciphertext)}${aesgcm.final()}`
318
+ } catch (error) {
319
+ const isRange = error instanceof RangeError
320
+ const invalidKeyLength = error.message === 'Invalid key length'
321
+ const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'
322
+
323
+ if (isRange || invalidKeyLength) {
324
+ const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')
325
+ err.code = 'INVALID_DOTENV_KEY'
326
+ throw err
327
+ } else if (decryptionFailed) {
328
+ const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')
329
+ err.code = 'DECRYPTION_FAILED'
330
+ throw err
331
+ } else {
332
+ throw error
333
+ }
334
+ }
335
+ }
336
+
337
+ // Populate process.env with parsed values
338
+ function populate (processEnv, parsed, options = {}) {
339
+ const debug = Boolean(options && options.debug)
340
+ const override = Boolean(options && options.override)
341
+
342
+ if (typeof parsed !== 'object') {
343
+ const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')
344
+ err.code = 'OBJECT_REQUIRED'
345
+ throw err
346
+ }
347
+
348
+ // Set process.env
349
+ for (const key of Object.keys(parsed)) {
350
+ if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
351
+ if (override === true) {
352
+ processEnv[key] = parsed[key]
353
+ }
354
+
355
+ if (debug) {
356
+ if (override === true) {
357
+ _debug(`"${key}" is already defined and WAS overwritten`)
358
+ } else {
359
+ _debug(`"${key}" is already defined and was NOT overwritten`)
360
+ }
361
+ }
362
+ } else {
363
+ processEnv[key] = parsed[key]
364
+ }
365
+ }
366
+ }
367
+
368
+ const DotenvModule = {
369
+ configDotenv,
370
+ _configVault,
371
+ _parseVault,
372
+ config,
373
+ decrypt,
374
+ parse,
375
+ populate
376
+ }
377
+
378
+ module.exports.configDotenv = DotenvModule.configDotenv
379
+ module.exports._configVault = DotenvModule._configVault
380
+ module.exports._parseVault = DotenvModule._parseVault
381
+ module.exports.config = DotenvModule.config
382
+ module.exports.decrypt = DotenvModule.decrypt
383
+ module.exports.parse = DotenvModule.parse
384
+ module.exports.populate = DotenvModule.populate
385
+
386
+ module.exports = DotenvModule
backend/node_modules/effect/src/internal/layer/circular.ts ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type * as ConfigProvider from "../../ConfigProvider.js"
2
+ import * as Context from "../../Context.js"
3
+ import type * as Effect from "../../Effect.js"
4
+ import type * as Exit from "../../Exit.js"
5
+ import { dual } from "../../Function.js"
6
+ import * as HashSet from "../../HashSet.js"
7
+ import type * as Layer from "../../Layer.js"
8
+ import type * as Logger from "../../Logger.js"
9
+ import type * as LogLevel from "../../LogLevel.js"
10
+ import type { Scope } from "../../Scope.js"
11
+ import type * as Supervisor from "../../Supervisor.js"
12
+ import type * as Tracer from "../../Tracer.js"
13
+ import * as core from "../core.js"
14
+ import * as fiberRuntime from "../fiberRuntime.js"
15
+ import * as layer from "../layer.js"
16
+ import * as runtimeFlags from "../runtimeFlags.js"
17
+ import * as runtimeFlagsPatch from "../runtimeFlagsPatch.js"
18
+ import * as supervisor_ from "../supervisor.js"
19
+ import * as tracer from "../tracer.js"
20
+
21
+ // circular with Logger
22
+
23
+ /** @internal */
24
+ export const minimumLogLevel = (level: LogLevel.LogLevel): Layer.Layer<never> =>
25
+ layer.scopedDiscard(
26
+ fiberRuntime.fiberRefLocallyScoped(
27
+ fiberRuntime.currentMinimumLogLevel,
28
+ level
29
+ )
30
+ )
31
+
32
+ /** @internal */
33
+ export const withMinimumLogLevel = dual<
34
+ (level: LogLevel.LogLevel) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
35
+ <A, E, R>(self: Effect.Effect<A, E, R>, level: LogLevel.LogLevel) => Effect.Effect<A, E, R>
36
+ >(2, (self, level) =>
37
+ core.fiberRefLocally(
38
+ fiberRuntime.currentMinimumLogLevel,
39
+ level
40
+ )(self))
41
+
42
+ /** @internal */
43
+ export const addLogger = <A>(logger: Logger.Logger<unknown, A>): Layer.Layer<never> =>
44
+ layer.scopedDiscard(
45
+ fiberRuntime.fiberRefLocallyScopedWith(
46
+ fiberRuntime.currentLoggers,
47
+ HashSet.add(logger)
48
+ )
49
+ )
50
+
51
+ /** @internal */
52
+ export const addLoggerEffect = <A, E, R>(
53
+ effect: Effect.Effect<Logger.Logger<unknown, A>, E, R>
54
+ ): Layer.Layer<never, E, R> =>
55
+ layer.unwrapEffect(
56
+ core.map(effect, addLogger)
57
+ )
58
+
59
+ /** @internal */
60
+ export const addLoggerScoped = <A, E, R>(
61
+ effect: Effect.Effect<Logger.Logger<unknown, A>, E, R>
62
+ ): Layer.Layer<never, E, Exclude<R, Scope>> =>
63
+ layer.unwrapScoped(
64
+ core.map(effect, addLogger)
65
+ )
66
+
67
+ /** @internal */
68
+ export const removeLogger = <A>(logger: Logger.Logger<unknown, A>): Layer.Layer<never> =>
69
+ layer.scopedDiscard(
70
+ fiberRuntime.fiberRefLocallyScopedWith(
71
+ fiberRuntime.currentLoggers,
72
+ HashSet.remove(logger)
73
+ )
74
+ )
75
+
76
+ /** @internal */
77
+ export const replaceLogger = dual<
78
+ <B>(that: Logger.Logger<unknown, B>) => <A>(self: Logger.Logger<unknown, A>) => Layer.Layer<never>,
79
+ <A, B>(self: Logger.Logger<unknown, A>, that: Logger.Logger<unknown, B>) => Layer.Layer<never>
80
+ >(2, (self, that) => layer.flatMap(removeLogger(self), () => addLogger(that)))
81
+
82
+ /** @internal */
83
+ export const replaceLoggerEffect = dual<
84
+ <B, E, R>(
85
+ that: Effect.Effect<Logger.Logger<unknown, B>, E, R>
86
+ ) => <A>(self: Logger.Logger<unknown, A>) => Layer.Layer<never, E, R>,
87
+ <A, B, E, R>(
88
+ self: Logger.Logger<unknown, A>,
89
+ that: Effect.Effect<Logger.Logger<unknown, B>, E, R>
90
+ ) => Layer.Layer<never, E, R>
91
+ >(2, (self, that) => layer.flatMap(removeLogger(self), () => addLoggerEffect(that)))
92
+
93
+ /** @internal */
94
+ export const replaceLoggerScoped = dual<
95
+ <B, E, R>(
96
+ that: Effect.Effect<Logger.Logger<unknown, B>, E, R>
97
+ ) => <A>(self: Logger.Logger<unknown, A>) => Layer.Layer<never, E, Exclude<R, Scope>>,
98
+ <A, B, E, R>(
99
+ self: Logger.Logger<unknown, A>,
100
+ that: Effect.Effect<Logger.Logger<unknown, B>, E, R>
101
+ ) => Layer.Layer<never, E, Exclude<R, Scope>>
102
+ >(2, (self, that) => layer.flatMap(removeLogger(self), () => addLoggerScoped(that)))
103
+
104
+ /** @internal */
105
+ export const addSupervisor = <A>(supervisor: Supervisor.Supervisor<A>): Layer.Layer<never> =>
106
+ layer.scopedDiscard(
107
+ fiberRuntime.fiberRefLocallyScopedWith(
108
+ fiberRuntime.currentSupervisor,
109
+ (current) => new supervisor_.Zip(current, supervisor)
110
+ )
111
+ )
112
+
113
+ /** @internal */
114
+ export const enableCooperativeYielding: Layer.Layer<never> = layer.scopedDiscard(
115
+ fiberRuntime.withRuntimeFlagsScoped(
116
+ runtimeFlagsPatch.enable(runtimeFlags.CooperativeYielding)
117
+ )
118
+ )
119
+
120
+ /** @internal */
121
+ export const enableInterruption: Layer.Layer<never> = layer.scopedDiscard(
122
+ fiberRuntime.withRuntimeFlagsScoped(
123
+ runtimeFlagsPatch.enable(runtimeFlags.Interruption)
124
+ )
125
+ )
126
+
127
+ /** @internal */
128
+ export const enableOpSupervision: Layer.Layer<never> = layer.scopedDiscard(
129
+ fiberRuntime.withRuntimeFlagsScoped(
130
+ runtimeFlagsPatch.enable(runtimeFlags.OpSupervision)
131
+ )
132
+ )
133
+
134
+ /** @internal */
135
+ export const enableRuntimeMetrics: Layer.Layer<never> = layer.scopedDiscard(
136
+ fiberRuntime.withRuntimeFlagsScoped(
137
+ runtimeFlagsPatch.enable(runtimeFlags.RuntimeMetrics)
138
+ )
139
+ )
140
+
141
+ /** @internal */
142
+ export const enableWindDown: Layer.Layer<never> = layer.scopedDiscard(
143
+ fiberRuntime.withRuntimeFlagsScoped(
144
+ runtimeFlagsPatch.enable(runtimeFlags.WindDown)
145
+ )
146
+ )
147
+
148
+ /** @internal */
149
+ export const disableCooperativeYielding: Layer.Layer<never> = layer.scopedDiscard(
150
+ fiberRuntime.withRuntimeFlagsScoped(
151
+ runtimeFlagsPatch.disable(runtimeFlags.CooperativeYielding)
152
+ )
153
+ )
154
+
155
+ /** @internal */
156
+ export const disableInterruption: Layer.Layer<never> = layer.scopedDiscard(
157
+ fiberRuntime.withRuntimeFlagsScoped(
158
+ runtimeFlagsPatch.disable(runtimeFlags.Interruption)
159
+ )
160
+ )
161
+
162
+ /** @internal */
163
+ export const disableOpSupervision: Layer.Layer<never> = layer.scopedDiscard(
164
+ fiberRuntime.withRuntimeFlagsScoped(
165
+ runtimeFlagsPatch.disable(runtimeFlags.OpSupervision)
166
+ )
167
+ )
168
+
169
+ /** @internal */
170
+ export const disableRuntimeMetrics: Layer.Layer<never> = layer.scopedDiscard(
171
+ fiberRuntime.withRuntimeFlagsScoped(
172
+ runtimeFlagsPatch.disable(runtimeFlags.RuntimeMetrics)
173
+ )
174
+ )
175
+
176
+ /** @internal */
177
+ export const disableWindDown: Layer.Layer<never> = layer.scopedDiscard(
178
+ fiberRuntime.withRuntimeFlagsScoped(
179
+ runtimeFlagsPatch.disable(runtimeFlags.WindDown)
180
+ )
181
+ )
182
+
183
+ /** @internal */
184
+ export const setConfigProvider = (configProvider: ConfigProvider.ConfigProvider): Layer.Layer<never> =>
185
+ layer.scopedDiscard(fiberRuntime.withConfigProviderScoped(configProvider))
186
+
187
+ /** @internal */
188
+ export const parentSpan = (span: Tracer.AnySpan): Layer.Layer<Tracer.ParentSpan> =>
189
+ layer.succeedContext(Context.make(tracer.spanTag, span))
190
+
191
+ /** @internal */
192
+ export const span = (
193
+ name: string,
194
+ options?: Tracer.SpanOptions & {
195
+ readonly onEnd?:
196
+ | ((span: Tracer.Span, exit: Exit.Exit<unknown, unknown>) => Effect.Effect<void>)
197
+ | undefined
198
+ }
199
+ ): Layer.Layer<Tracer.ParentSpan> => {
200
+ options = tracer.addSpanStackTrace(options) as any
201
+ return layer.scoped(
202
+ tracer.spanTag,
203
+ options?.onEnd
204
+ ? core.tap(
205
+ fiberRuntime.makeSpanScoped(name, options),
206
+ (span) => fiberRuntime.addFinalizer((exit) => options.onEnd!(span, exit))
207
+ )
208
+ : fiberRuntime.makeSpanScoped(name, options)
209
+ )
210
+ }
211
+
212
+ /** @internal */
213
+ export const setTracer = (tracer: Tracer.Tracer): Layer.Layer<never> =>
214
+ layer.scopedDiscard(fiberRuntime.withTracerScoped(tracer))
backend/node_modules/effect/src/internal/metric/label.ts ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as Equal from "../../Equal.js"
2
+ import * as Hash from "../../Hash.js"
3
+ import type * as MetricLabel from "../../MetricLabel.js"
4
+ import { pipeArguments } from "../../Pipeable.js"
5
+ import { hasProperty } from "../../Predicate.js"
6
+
7
+ /** @internal */
8
+ const MetricLabelSymbolKey = "effect/MetricLabel"
9
+
10
+ /** @internal */
11
+ export const MetricLabelTypeId: MetricLabel.MetricLabelTypeId = Symbol.for(
12
+ MetricLabelSymbolKey
13
+ ) as MetricLabel.MetricLabelTypeId
14
+
15
+ /** @internal */
16
+ class MetricLabelImpl implements MetricLabel.MetricLabel {
17
+ readonly [MetricLabelTypeId]: MetricLabel.MetricLabelTypeId = MetricLabelTypeId
18
+ readonly _hash: number
19
+ constructor(readonly key: string, readonly value: string) {
20
+ this._hash = Hash.string(MetricLabelSymbolKey + this.key + this.value)
21
+ }
22
+ [Hash.symbol](): number {
23
+ return this._hash
24
+ }
25
+ [Equal.symbol](that: unknown): boolean {
26
+ return isMetricLabel(that) &&
27
+ this.key === that.key &&
28
+ this.value === that.value
29
+ }
30
+ pipe() {
31
+ return pipeArguments(this, arguments)
32
+ }
33
+ }
34
+
35
+ /** @internal */
36
+ export const make = (key: string, value: string): MetricLabel.MetricLabel => {
37
+ return new MetricLabelImpl(key, value)
38
+ }
39
+
40
+ /** @internal */
41
+ export const isMetricLabel = (u: unknown): u is MetricLabel.MetricLabel => hasProperty(u, MetricLabelTypeId)
backend/node_modules/effect/src/internal/metric/pair.ts ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type * as MetricKey from "../../MetricKey.js"
2
+ import type * as MetricKeyType from "../../MetricKeyType.js"
3
+ import type * as MetricPair from "../../MetricPair.js"
4
+ import type * as MetricState from "../../MetricState.js"
5
+ import { pipeArguments } from "../../Pipeable.js"
6
+
7
+ /** @internal */
8
+ const MetricPairSymbolKey = "effect/MetricPair"
9
+
10
+ /** @internal */
11
+ export const MetricPairTypeId: MetricPair.MetricPairTypeId = Symbol.for(
12
+ MetricPairSymbolKey
13
+ ) as MetricPair.MetricPairTypeId
14
+
15
+ const metricPairVariance = {
16
+ /* c8 ignore next */
17
+ _Type: (_: never) => _
18
+ }
19
+
20
+ /** @internal */
21
+ export const make = <Type extends MetricKeyType.MetricKeyType<any, any>>(
22
+ metricKey: MetricKey.MetricKey<Type>,
23
+ metricState: MetricState.MetricState<MetricKeyType.MetricKeyType.OutType<Type>>
24
+ ): MetricPair.MetricPair.Untyped => {
25
+ return {
26
+ [MetricPairTypeId]: metricPairVariance,
27
+ metricKey,
28
+ metricState,
29
+ pipe() {
30
+ return pipeArguments(this, arguments)
31
+ }
32
+ }
33
+ }
34
+
35
+ /** @internal */
36
+ export const unsafeMake = <Type extends MetricKeyType.MetricKeyType<any, any>>(
37
+ metricKey: MetricKey.MetricKey<Type>,
38
+ metricState: MetricState.MetricState.Untyped
39
+ ): MetricPair.MetricPair.Untyped => {
40
+ return {
41
+ [MetricPairTypeId]: metricPairVariance,
42
+ metricKey,
43
+ metricState,
44
+ pipe() {
45
+ return pipeArguments(this, arguments)
46
+ }
47
+ }
48
+ }
backend/node_modules/effect/src/internal/metric/polling.ts ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type * as Effect from "../../Effect.js"
2
+ import type * as Fiber from "../../Fiber.js"
3
+ import { dual, pipe } from "../../Function.js"
4
+ import type * as Metric from "../../Metric.js"
5
+ import type * as MetricPolling from "../../MetricPolling.js"
6
+ import { pipeArguments } from "../../Pipeable.js"
7
+ import type * as Schedule from "../../Schedule.js"
8
+ import type * as Scope from "../../Scope.js"
9
+ import * as core from "../core.js"
10
+ import * as metric from "../metric.js"
11
+ import * as schedule_ from "../schedule.js"
12
+
13
+ /** @internal */
14
+ const MetricPollingSymbolKey = "effect/MetricPolling"
15
+
16
+ /** @internal */
17
+ export const MetricPollingTypeId: MetricPolling.MetricPollingTypeId = Symbol.for(
18
+ MetricPollingSymbolKey
19
+ ) as MetricPolling.MetricPollingTypeId
20
+
21
+ /** @internal */
22
+ export const make = <Type, In, Out, R, E>(
23
+ metric: Metric.Metric<Type, In, Out>,
24
+ poll: Effect.Effect<In, E, R>
25
+ ): MetricPolling.MetricPolling<Type, In, R, E, Out> => {
26
+ return {
27
+ [MetricPollingTypeId]: MetricPollingTypeId,
28
+ pipe() {
29
+ return pipeArguments(this, arguments)
30
+ },
31
+ metric,
32
+ poll
33
+ }
34
+ }
35
+
36
+ /** @internal */
37
+ export const collectAll = <R, E, Out>(
38
+ iterable: Iterable<MetricPolling.MetricPolling<any, any, R, E, Out>>
39
+ ): MetricPolling.MetricPolling<Array<any>, Array<any>, R, E, Array<Out>> => {
40
+ const metrics = Array.from(iterable)
41
+ return {
42
+ [MetricPollingTypeId]: MetricPollingTypeId,
43
+ pipe() {
44
+ return pipeArguments(this, arguments)
45
+ },
46
+ metric: metric.make(
47
+ Array.of<any>(void 0) as Array<any>,
48
+ (inputs: Array<any>, extraTags) => {
49
+ for (let i = 0; i < inputs.length; i++) {
50
+ const pollingMetric = metrics[i]!
51
+ const input = pipe(inputs, (x) => x[i])
52
+ pollingMetric.metric.unsafeUpdate(input, extraTags)
53
+ }
54
+ },
55
+ (extraTags) =>
56
+ Array.from(
57
+ metrics.map((pollingMetric) => pollingMetric.metric.unsafeValue(extraTags))
58
+ ),
59
+ (inputs: Array<any>, extraTags) => {
60
+ for (let i = 0; i < inputs.length; i++) {
61
+ const pollingMetric = metrics[i]!
62
+ const input = pipe(inputs, (x) => x[i])
63
+ pollingMetric.metric.unsafeModify(input, extraTags)
64
+ }
65
+ }
66
+ ),
67
+ poll: core.forEachSequential(metrics, (metric) => metric.poll)
68
+ }
69
+ }
70
+
71
+ /** @internal */
72
+ export const launch = dual<
73
+ <A2, R2>(
74
+ schedule: Schedule.Schedule<A2, unknown, R2>
75
+ ) => <Type, In, R, E, Out>(
76
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>
77
+ ) => Effect.Effect<Fiber.Fiber<A2, E>, never, R | R2 | Scope.Scope>,
78
+ <Type, In, R, E, Out, A2, R2>(
79
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>,
80
+ schedule: Schedule.Schedule<A2, unknown, R2>
81
+ ) => Effect.Effect<Fiber.Fiber<A2, E>, never, R | R2 | Scope.Scope>
82
+ >(2, (self, schedule) =>
83
+ pipe(
84
+ pollAndUpdate(self),
85
+ core.zipRight(metric.value(self.metric)),
86
+ schedule_.scheduleForked(schedule)
87
+ ))
88
+
89
+ /** @internal */
90
+ export const poll = <Type, In, R, E, Out>(
91
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>
92
+ ): Effect.Effect<In, E, R> => self.poll
93
+
94
+ /** @internal */
95
+ export const pollAndUpdate = <Type, In, R, E, Out>(
96
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>
97
+ ): Effect.Effect<void, E, R> => core.flatMap(self.poll, (value) => metric.update(self.metric, value))
98
+
99
+ /** @internal */
100
+ export const retry = dual<
101
+ <X, E, R2>(
102
+ policy: Schedule.Schedule<X, E, R2>
103
+ ) => <Type, In, R, Out>(
104
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>
105
+ ) => MetricPolling.MetricPolling<Type, In, R | R2, E, Out>,
106
+ <Type, In, R, E, Out, X, R2>(
107
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>,
108
+ policy: Schedule.Schedule<X, E, R2>
109
+ ) => MetricPolling.MetricPolling<Type, In, R | R2, E, Out>
110
+ >(2, (self, policy) => ({
111
+ [MetricPollingTypeId]: MetricPollingTypeId,
112
+ pipe() {
113
+ return pipeArguments(this, arguments)
114
+ },
115
+ metric: self.metric,
116
+ poll: schedule_.retry_Effect(self.poll, policy)
117
+ }))
118
+
119
+ /** @internal */
120
+ export const zip = dual<
121
+ <Type2, In2, R2, E2, Out2>(
122
+ that: MetricPolling.MetricPolling<Type2, In2, R2, E2, Out2>
123
+ ) => <Type, In, R, E, Out>(
124
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>
125
+ ) => MetricPolling.MetricPolling<
126
+ readonly [Type, Type2],
127
+ readonly [In, In2],
128
+ R | R2,
129
+ E | E2,
130
+ [Out, Out2]
131
+ >,
132
+ <Type, In, R, E, Out, Type2, In2, R2, E2, Out2>(
133
+ self: MetricPolling.MetricPolling<Type, In, R, E, Out>,
134
+ that: MetricPolling.MetricPolling<Type2, In2, R2, E2, Out2>
135
+ ) => MetricPolling.MetricPolling<
136
+ readonly [Type, Type2],
137
+ readonly [In, In2],
138
+ R | R2,
139
+ E | E2,
140
+ [Out, Out2]
141
+ >
142
+ >(2, (self, that) => ({
143
+ [MetricPollingTypeId]: MetricPollingTypeId,
144
+ pipe() {
145
+ return pipeArguments(this, arguments)
146
+ },
147
+ metric: pipe(self.metric, metric.zip(that.metric)),
148
+ poll: core.zip(self.poll, that.poll)
149
+ }))
backend/node_modules/effect/src/internal/metric/state.ts ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as Arr from "../../Array.js"
2
+ import * as Equal from "../../Equal.js"
3
+ import { pipe } from "../../Function.js"
4
+ import * as Hash from "../../Hash.js"
5
+ import type * as MetricState from "../../MetricState.js"
6
+ import type * as Option from "../../Option.js"
7
+ import { pipeArguments } from "../../Pipeable.js"
8
+ import { hasProperty } from "../../Predicate.js"
9
+
10
+ /** @internal */
11
+ const MetricStateSymbolKey = "effect/MetricState"
12
+
13
+ /** @internal */
14
+ export const MetricStateTypeId: MetricState.MetricStateTypeId = Symbol.for(
15
+ MetricStateSymbolKey
16
+ ) as MetricState.MetricStateTypeId
17
+
18
+ /** @internal */
19
+ const CounterStateSymbolKey = "effect/MetricState/Counter"
20
+
21
+ /** @internal */
22
+ export const CounterStateTypeId: MetricState.CounterStateTypeId = Symbol.for(
23
+ CounterStateSymbolKey
24
+ ) as MetricState.CounterStateTypeId
25
+
26
+ /** @internal */
27
+ const FrequencyStateSymbolKey = "effect/MetricState/Frequency"
28
+
29
+ /** @internal */
30
+ export const FrequencyStateTypeId: MetricState.FrequencyStateTypeId = Symbol.for(
31
+ FrequencyStateSymbolKey
32
+ ) as MetricState.FrequencyStateTypeId
33
+
34
+ /** @internal */
35
+ const GaugeStateSymbolKey = "effect/MetricState/Gauge"
36
+
37
+ /** @internal */
38
+ export const GaugeStateTypeId: MetricState.GaugeStateTypeId = Symbol.for(
39
+ GaugeStateSymbolKey
40
+ ) as MetricState.GaugeStateTypeId
41
+
42
+ /** @internal */
43
+ const HistogramStateSymbolKey = "effect/MetricState/Histogram"
44
+
45
+ /** @internal */
46
+ export const HistogramStateTypeId: MetricState.HistogramStateTypeId = Symbol.for(
47
+ HistogramStateSymbolKey
48
+ ) as MetricState.HistogramStateTypeId
49
+
50
+ /** @internal */
51
+ const SummaryStateSymbolKey = "effect/MetricState/Summary"
52
+
53
+ /** @internal */
54
+ export const SummaryStateTypeId: MetricState.SummaryStateTypeId = Symbol.for(
55
+ SummaryStateSymbolKey
56
+ ) as MetricState.SummaryStateTypeId
57
+
58
+ const metricStateVariance = {
59
+ /* c8 ignore next */
60
+ _A: (_: unknown) => _
61
+ }
62
+
63
+ /** @internal */
64
+ class CounterState<A extends (number | bigint)> implements MetricState.MetricState.Counter<A> {
65
+ readonly [MetricStateTypeId] = metricStateVariance
66
+ readonly [CounterStateTypeId]: MetricState.CounterStateTypeId = CounterStateTypeId
67
+ constructor(readonly count: A) {}
68
+ [Hash.symbol](): number {
69
+ return pipe(
70
+ Hash.hash(CounterStateSymbolKey),
71
+ Hash.combine(Hash.hash(this.count)),
72
+ Hash.cached(this)
73
+ )
74
+ }
75
+ [Equal.symbol](that: unknown): boolean {
76
+ return isCounterState(that) && this.count === that.count
77
+ }
78
+ pipe() {
79
+ return pipeArguments(this, arguments)
80
+ }
81
+ }
82
+
83
+ const arrayEquals = Arr.getEquivalence(Equal.equals)
84
+
85
+ /** @internal */
86
+ class FrequencyState implements MetricState.MetricState.Frequency {
87
+ readonly [MetricStateTypeId] = metricStateVariance
88
+ readonly [FrequencyStateTypeId]: MetricState.FrequencyStateTypeId = FrequencyStateTypeId
89
+ constructor(readonly occurrences: ReadonlyMap<string, number>) {}
90
+ _hash: number | undefined;
91
+ [Hash.symbol](): number {
92
+ return pipe(
93
+ Hash.string(FrequencyStateSymbolKey),
94
+ Hash.combine(Hash.array(Arr.fromIterable(this.occurrences.entries()))),
95
+ Hash.cached(this)
96
+ )
97
+ }
98
+ [Equal.symbol](that: unknown): boolean {
99
+ return isFrequencyState(that) && arrayEquals(
100
+ Arr.fromIterable(this.occurrences.entries()),
101
+ Arr.fromIterable(that.occurrences.entries())
102
+ )
103
+ }
104
+ pipe() {
105
+ return pipeArguments(this, arguments)
106
+ }
107
+ }
108
+
109
+ /** @internal */
110
+ class GaugeState<A extends (number | bigint)> implements MetricState.MetricState.Gauge<A> {
111
+ readonly [MetricStateTypeId] = metricStateVariance
112
+ readonly [GaugeStateTypeId]: MetricState.GaugeStateTypeId = GaugeStateTypeId
113
+ constructor(readonly value: A) {}
114
+ [Hash.symbol](): number {
115
+ return pipe(
116
+ Hash.hash(GaugeStateSymbolKey),
117
+ Hash.combine(Hash.hash(this.value)),
118
+ Hash.cached(this)
119
+ )
120
+ }
121
+ [Equal.symbol](u: unknown): boolean {
122
+ return isGaugeState(u) && this.value === u.value
123
+ }
124
+ pipe() {
125
+ return pipeArguments(this, arguments)
126
+ }
127
+ }
128
+
129
+ /** @internal */
130
+ export class HistogramState implements MetricState.MetricState.Histogram {
131
+ readonly [MetricStateTypeId] = metricStateVariance
132
+ readonly [HistogramStateTypeId]: MetricState.HistogramStateTypeId = HistogramStateTypeId
133
+ constructor(
134
+ readonly buckets: ReadonlyArray<readonly [number, number]>,
135
+ readonly count: number,
136
+ readonly min: number,
137
+ readonly max: number,
138
+ readonly sum: number
139
+ ) {}
140
+ [Hash.symbol](): number {
141
+ return pipe(
142
+ Hash.hash(HistogramStateSymbolKey),
143
+ Hash.combine(Hash.hash(this.buckets)),
144
+ Hash.combine(Hash.hash(this.count)),
145
+ Hash.combine(Hash.hash(this.min)),
146
+ Hash.combine(Hash.hash(this.max)),
147
+ Hash.combine(Hash.hash(this.sum)),
148
+ Hash.cached(this)
149
+ )
150
+ }
151
+ [Equal.symbol](that: unknown): boolean {
152
+ return isHistogramState(that) &&
153
+ Equal.equals(this.buckets, that.buckets) &&
154
+ this.count === that.count &&
155
+ this.min === that.min &&
156
+ this.max === that.max &&
157
+ this.sum === that.sum
158
+ }
159
+ pipe() {
160
+ return pipeArguments(this, arguments)
161
+ }
162
+ }
163
+
164
+ /** @internal */
165
+ export class SummaryState implements MetricState.MetricState.Summary {
166
+ readonly [MetricStateTypeId] = metricStateVariance
167
+ readonly [SummaryStateTypeId]: MetricState.SummaryStateTypeId = SummaryStateTypeId
168
+ constructor(
169
+ readonly error: number,
170
+ readonly quantiles: ReadonlyArray<readonly [number, Option.Option<number>]>,
171
+ readonly count: number,
172
+ readonly min: number,
173
+ readonly max: number,
174
+ readonly sum: number
175
+ ) {}
176
+ [Hash.symbol](): number {
177
+ return pipe(
178
+ Hash.hash(SummaryStateSymbolKey),
179
+ Hash.combine(Hash.hash(this.error)),
180
+ Hash.combine(Hash.hash(this.quantiles)),
181
+ Hash.combine(Hash.hash(this.count)),
182
+ Hash.combine(Hash.hash(this.min)),
183
+ Hash.combine(Hash.hash(this.max)),
184
+ Hash.combine(Hash.hash(this.sum)),
185
+ Hash.cached(this)
186
+ )
187
+ }
188
+ [Equal.symbol](that: unknown): boolean {
189
+ return isSummaryState(that) &&
190
+ this.error === that.error &&
191
+ Equal.equals(this.quantiles, that.quantiles) &&
192
+ this.count === that.count &&
193
+ this.min === that.min &&
194
+ this.max === that.max &&
195
+ this.sum === that.sum
196
+ }
197
+ pipe() {
198
+ return pipeArguments(this, arguments)
199
+ }
200
+ }
201
+
202
+ /** @internal */
203
+ export const counter: {
204
+ (count: number): MetricState.MetricState.Counter<number>
205
+ (count: bigint): MetricState.MetricState.Counter<bigint>
206
+ } = (count) => new CounterState(count) as any
207
+
208
+ /** @internal */
209
+ export const frequency = (occurrences: ReadonlyMap<string, number>): MetricState.MetricState.Frequency => {
210
+ return new FrequencyState(occurrences)
211
+ }
212
+
213
+ /** @internal */
214
+ export const gauge: {
215
+ (count: number): MetricState.MetricState.Gauge<number>
216
+ (count: bigint): MetricState.MetricState.Gauge<bigint>
217
+ } = (count) => new GaugeState(count) as any
218
+
219
+ /** @internal */
220
+ export const histogram = (
221
+ options: {
222
+ readonly buckets: ReadonlyArray<readonly [number, number]>
223
+ readonly count: number
224
+ readonly min: number
225
+ readonly max: number
226
+ readonly sum: number
227
+ }
228
+ ): MetricState.MetricState.Histogram =>
229
+ new HistogramState(
230
+ options.buckets,
231
+ options.count,
232
+ options.min,
233
+ options.max,
234
+ options.sum
235
+ )
236
+
237
+ /** @internal */
238
+ export const summary = (
239
+ options: {
240
+ readonly error: number
241
+ readonly quantiles: ReadonlyArray<readonly [number, Option.Option<number>]>
242
+ readonly count: number
243
+ readonly min: number
244
+ readonly max: number
245
+ readonly sum: number
246
+ }
247
+ ): MetricState.MetricState.Summary =>
248
+ new SummaryState(
249
+ options.error,
250
+ options.quantiles,
251
+ options.count,
252
+ options.min,
253
+ options.max,
254
+ options.sum
255
+ )
256
+
257
+ /** @internal */
258
+ export const isMetricState = (u: unknown): u is MetricState.MetricState.Counter<number | bigint> =>
259
+ hasProperty(u, MetricStateTypeId)
260
+
261
+ /** @internal */
262
+ export const isCounterState = (u: unknown): u is MetricState.MetricState.Counter<number | bigint> =>
263
+ hasProperty(u, CounterStateTypeId)
264
+
265
+ /**
266
+ * @since 2.0.0
267
+ * @category refinements
268
+ */
269
+ export const isFrequencyState = (u: unknown): u is MetricState.MetricState.Frequency =>
270
+ hasProperty(u, FrequencyStateTypeId)
271
+
272
+ /**
273
+ * @since 2.0.0
274
+ * @category refinements
275
+ */
276
+ export const isGaugeState = (u: unknown): u is MetricState.MetricState.Gauge<number | bigint> =>
277
+ hasProperty(u, GaugeStateTypeId)
278
+
279
+ /**
280
+ * @since 2.0.0
281
+ * @category refinements
282
+ */
283
+ export const isHistogramState = (u: unknown): u is MetricState.MetricState.Histogram =>
284
+ hasProperty(u, HistogramStateTypeId)
285
+
286
+ /**
287
+ * @since 2.0.0
288
+ * @category refinements
289
+ */
290
+ export const isSummaryState = (u: unknown): u is MetricState.MetricState.Summary => hasProperty(u, SummaryStateTypeId)
backend/node_modules/effect/src/internal/opCodes/channelUpstreamPullStrategy.ts ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @internal */
2
+ export const OP_PULL_AFTER_NEXT = "PullAfterNext" as const
3
+
4
+ /** @internal */
5
+ export type OP_PULL_AFTER_NEXT = typeof OP_PULL_AFTER_NEXT
6
+
7
+ /** @internal */
8
+ export const OP_PULL_AFTER_ALL_ENQUEUED = "PullAfterAllEnqueued" as const
9
+
10
+ /** @internal */
11
+ export type OP_PULL_AFTER_ALL_ENQUEUED = typeof OP_PULL_AFTER_ALL_ENQUEUED
backend/node_modules/effect/src/internal/schema/util.ts ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { NonEmptyReadonlyArray } from "../../Array.js"
2
+ import * as Inspectable from "../../Inspectable.js"
3
+ import type * as ParseResult from "../../ParseResult.js"
4
+ import type * as AST from "../../SchemaAST.js"
5
+
6
+ /** @internal */
7
+ export const getKeysForIndexSignature = (
8
+ input: { readonly [x: PropertyKey]: unknown },
9
+ parameter: AST.Parameter
10
+ ): ReadonlyArray<string> | ReadonlyArray<symbol> => {
11
+ switch (parameter._tag) {
12
+ case "StringKeyword":
13
+ case "TemplateLiteral":
14
+ return Object.keys(input)
15
+ case "SymbolKeyword":
16
+ return Object.getOwnPropertySymbols(input)
17
+ case "Refinement":
18
+ return getKeysForIndexSignature(input, parameter.from)
19
+ }
20
+ }
21
+
22
+ /** @internal */
23
+ export const memoizeThunk = <A>(f: () => A): () => A => {
24
+ let done = false
25
+ let a: A
26
+ return () => {
27
+ if (done) {
28
+ return a
29
+ }
30
+ a = f()
31
+ done = true
32
+ return a
33
+ }
34
+ }
35
+
36
+ /** @internal */
37
+ export type SingleOrArray<A> = A | ReadonlyArray<A>
38
+
39
+ /** @internal */
40
+ export const isNonEmpty = <A>(x: ParseResult.SingleOrNonEmpty<A>): x is NonEmptyReadonlyArray<A> => Array.isArray(x)
41
+
42
+ /** @internal */
43
+ export const isSingle = <A>(x: A | ReadonlyArray<A>): x is A => !Array.isArray(x)
44
+
45
+ /** @internal */
46
+ export const formatPathKey = (key: PropertyKey): string => `[${Inspectable.formatPropertyKey(key)}]`
47
+
48
+ /** @internal */
49
+ export const formatPath = (path: ParseResult.Path): string =>
50
+ isNonEmpty(path) ? path.map(formatPathKey).join("") : formatPathKey(path)
backend/node_modules/effect/src/internal/supervisor/patch.ts ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as Chunk from "../../Chunk.js"
2
+ import * as Differ from "../../Differ.js"
3
+ import * as Equal from "../../Equal.js"
4
+ import { pipe } from "../../Function.js"
5
+ import * as HashSet from "../../HashSet.js"
6
+ import type * as Supervisor from "../../Supervisor.js"
7
+ import * as supervisor from "../supervisor.js"
8
+
9
+ /** @internal */
10
+ export type SupervisorPatch = Empty | AddSupervisor | RemoveSupervisor | AndThen
11
+
12
+ /** @internal */
13
+ export const OP_EMPTY = "Empty" as const
14
+
15
+ /** @internal */
16
+ export type OP_EMPTY = typeof OP_EMPTY
17
+
18
+ /** @internal */
19
+ export const OP_ADD_SUPERVISOR = "AddSupervisor" as const
20
+
21
+ /** @internal */
22
+ export type OP_ADD_SUPERVISOR = typeof OP_ADD_SUPERVISOR
23
+
24
+ /** @internal */
25
+ export const OP_REMOVE_SUPERVISOR = "RemoveSupervisor" as const
26
+
27
+ /** @internal */
28
+ export type OP_REMOVE_SUPERVISOR = typeof OP_REMOVE_SUPERVISOR
29
+
30
+ /** @internal */
31
+ export const OP_AND_THEN = "AndThen" as const
32
+
33
+ /** @internal */
34
+ export type OP_AND_THEN = typeof OP_AND_THEN
35
+
36
+ /** @internal */
37
+ export interface Empty {
38
+ readonly _tag: OP_EMPTY
39
+ }
40
+
41
+ /** @internal */
42
+ export interface AddSupervisor {
43
+ readonly _tag: OP_ADD_SUPERVISOR
44
+ readonly supervisor: Supervisor.Supervisor<any>
45
+ }
46
+
47
+ /** @internal */
48
+ export interface RemoveSupervisor {
49
+ readonly _tag: OP_REMOVE_SUPERVISOR
50
+ readonly supervisor: Supervisor.Supervisor<any>
51
+ }
52
+
53
+ /** @internal */
54
+ export interface AndThen {
55
+ readonly _tag: OP_AND_THEN
56
+ readonly first: SupervisorPatch
57
+ readonly second: SupervisorPatch
58
+ }
59
+
60
+ /**
61
+ * The empty `SupervisorPatch`.
62
+ *
63
+ * @internal
64
+ */
65
+ export const empty: SupervisorPatch = { _tag: OP_EMPTY }
66
+
67
+ /**
68
+ * Combines two patches to produce a new patch that describes applying the
69
+ * updates from this patch and then the updates from the specified patch.
70
+ *
71
+ * @internal
72
+ */
73
+ export const combine = (self: SupervisorPatch, that: SupervisorPatch): SupervisorPatch => {
74
+ return {
75
+ _tag: OP_AND_THEN,
76
+ first: self,
77
+ second: that
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Applies a `SupervisorPatch` to a `Supervisor` to produce a new `Supervisor`.
83
+ *
84
+ * @internal
85
+ */
86
+ export const patch = (
87
+ self: SupervisorPatch,
88
+ supervisor: Supervisor.Supervisor<any>
89
+ ): Supervisor.Supervisor<any> => {
90
+ return patchLoop(supervisor, Chunk.of(self))
91
+ }
92
+
93
+ /** @internal */
94
+ const patchLoop = (
95
+ _supervisor: Supervisor.Supervisor<any>,
96
+ _patches: Chunk.Chunk<SupervisorPatch>
97
+ ): Supervisor.Supervisor<any> => {
98
+ let supervisor = _supervisor
99
+ let patches = _patches
100
+ while (Chunk.isNonEmpty(patches)) {
101
+ const head = Chunk.headNonEmpty(patches)
102
+ switch (head._tag) {
103
+ case OP_EMPTY: {
104
+ patches = Chunk.tailNonEmpty(patches)
105
+ break
106
+ }
107
+ case OP_ADD_SUPERVISOR: {
108
+ supervisor = supervisor.zip(head.supervisor)
109
+ patches = Chunk.tailNonEmpty(patches)
110
+ break
111
+ }
112
+ case OP_REMOVE_SUPERVISOR: {
113
+ supervisor = removeSupervisor(supervisor, head.supervisor)
114
+ patches = Chunk.tailNonEmpty(patches)
115
+ break
116
+ }
117
+ case OP_AND_THEN: {
118
+ patches = Chunk.prepend(head.first)(Chunk.prepend(head.second)(Chunk.tailNonEmpty(patches)))
119
+ break
120
+ }
121
+ }
122
+ }
123
+ return supervisor
124
+ }
125
+
126
+ /** @internal */
127
+ const removeSupervisor = (
128
+ self: Supervisor.Supervisor<any>,
129
+ that: Supervisor.Supervisor<any>
130
+ ): Supervisor.Supervisor<any> => {
131
+ if (Equal.equals(self, that)) {
132
+ return supervisor.none
133
+ } else {
134
+ if (supervisor.isZip(self)) {
135
+ return removeSupervisor(self.left, that).zip(removeSupervisor(self.right, that))
136
+ } else {
137
+ return self
138
+ }
139
+ }
140
+ }
141
+
142
+ /** @internal */
143
+ const toSet = (self: Supervisor.Supervisor<any>): HashSet.HashSet<Supervisor.Supervisor<any>> => {
144
+ if (Equal.equals(self, supervisor.none)) {
145
+ return HashSet.empty()
146
+ } else {
147
+ if (supervisor.isZip(self)) {
148
+ return pipe(toSet(self.left), HashSet.union(toSet(self.right)))
149
+ } else {
150
+ return HashSet.make(self)
151
+ }
152
+ }
153
+ }
154
+
155
+ /** @internal */
156
+ export const diff = (
157
+ oldValue: Supervisor.Supervisor<any>,
158
+ newValue: Supervisor.Supervisor<any>
159
+ ): SupervisorPatch => {
160
+ if (Equal.equals(oldValue, newValue)) {
161
+ return empty
162
+ }
163
+ const oldSupervisors = toSet(oldValue)
164
+ const newSupervisors = toSet(newValue)
165
+ const added = pipe(
166
+ newSupervisors,
167
+ HashSet.difference(oldSupervisors),
168
+ HashSet.reduce(
169
+ empty as SupervisorPatch,
170
+ (patch, supervisor) => combine(patch, { _tag: OP_ADD_SUPERVISOR, supervisor })
171
+ )
172
+ )
173
+ const removed = pipe(
174
+ oldSupervisors,
175
+ HashSet.difference(newSupervisors),
176
+ HashSet.reduce(
177
+ empty as SupervisorPatch,
178
+ (patch, supervisor) => combine(patch, { _tag: OP_REMOVE_SUPERVISOR, supervisor })
179
+ )
180
+ )
181
+ return combine(added, removed)
182
+ }
183
+
184
+ /** @internal */
185
+ export const differ = Differ.make<Supervisor.Supervisor<any>, SupervisorPatch>({
186
+ empty,
187
+ patch,
188
+ combine,
189
+ diff
190
+ })
backend/node_modules/perfect-debounce/dist/index.cjs ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+
3
+ const DEBOUNCE_DEFAULTS = {
4
+ trailing: true
5
+ };
6
+ function debounce(fn, wait = 25, options = {}) {
7
+ options = { ...DEBOUNCE_DEFAULTS, ...options };
8
+ if (!Number.isFinite(wait)) {
9
+ throw new TypeError("Expected `wait` to be a finite number");
10
+ }
11
+ let leadingValue;
12
+ let timeout;
13
+ let resolveList = [];
14
+ let currentPromise;
15
+ let trailingArgs;
16
+ const applyFn = (_this, args) => {
17
+ currentPromise = _applyPromised(fn, _this, args);
18
+ currentPromise.finally(() => {
19
+ currentPromise = null;
20
+ if (options.trailing && trailingArgs && !timeout) {
21
+ const promise = applyFn(_this, trailingArgs);
22
+ trailingArgs = null;
23
+ return promise;
24
+ }
25
+ });
26
+ return currentPromise;
27
+ };
28
+ return function(...args) {
29
+ if (currentPromise) {
30
+ if (options.trailing) {
31
+ trailingArgs = args;
32
+ }
33
+ return currentPromise;
34
+ }
35
+ return new Promise((resolve) => {
36
+ const shouldCallNow = !timeout && options.leading;
37
+ clearTimeout(timeout);
38
+ timeout = setTimeout(() => {
39
+ timeout = null;
40
+ const promise = options.leading ? leadingValue : applyFn(this, args);
41
+ for (const _resolve of resolveList) {
42
+ _resolve(promise);
43
+ }
44
+ resolveList = [];
45
+ }, wait);
46
+ if (shouldCallNow) {
47
+ leadingValue = applyFn(this, args);
48
+ resolve(leadingValue);
49
+ } else {
50
+ resolveList.push(resolve);
51
+ }
52
+ });
53
+ };
54
+ }
55
+ async function _applyPromised(fn, _this, args) {
56
+ return await fn.apply(_this, args);
57
+ }
58
+
59
+ exports.debounce = debounce;
backend/node_modules/perfect-debounce/dist/index.d.ts ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ interface DebounceOptions {
2
+ /**
3
+ Call the `fn` on the [leading edge of the timeout](https://css-tricks.com/debouncing-throttling-explained-examples/#article-header-id-1).
4
+ Meaning immediately, instead of waiting for `wait` milliseconds.
5
+ @default false
6
+ */
7
+ readonly leading?: boolean;
8
+ /**
9
+ Call the `fn` on trailing edge with last used arguments. Result of call is from previous call.
10
+ @default false
11
+ */
12
+ readonly trailing?: boolean;
13
+ }
14
+ /**
15
+ Debounce functions
16
+ @param fn - Promise-returning/async function to debounce.
17
+ @param wait - Milliseconds to wait before calling `fn`. Default value is 25ms
18
+ @returns A function that delays calling `fn` until after `wait` milliseconds have elapsed since the last time it was called.
19
+ @example
20
+ ```
21
+ import { debounce } from 'perfect-debounce';
22
+ const expensiveCall = async input => input;
23
+ const debouncedFn = debounce(expensiveCall, 200);
24
+ for (const number of [1, 2, 3]) {
25
+ console.log(await debouncedFn(number));
26
+ }
27
+ //=> 3
28
+ //=> 3
29
+ //=> 3
30
+ ```
31
+ */
32
+ declare function debounce<ArgumentsT extends unknown[], ReturnT>(fn: (...args: ArgumentsT) => PromiseLike<ReturnT> | ReturnT, wait?: number, options?: DebounceOptions): (...args: ArgumentsT) => Promise<ReturnT>;
33
+
34
+ export { DebounceOptions, debounce };
backend/node_modules/perfect-debounce/dist/index.mjs ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const DEBOUNCE_DEFAULTS = {
2
+ trailing: true
3
+ };
4
+ function debounce(fn, wait = 25, options = {}) {
5
+ options = { ...DEBOUNCE_DEFAULTS, ...options };
6
+ if (!Number.isFinite(wait)) {
7
+ throw new TypeError("Expected `wait` to be a finite number");
8
+ }
9
+ let leadingValue;
10
+ let timeout;
11
+ let resolveList = [];
12
+ let currentPromise;
13
+ let trailingArgs;
14
+ const applyFn = (_this, args) => {
15
+ currentPromise = _applyPromised(fn, _this, args);
16
+ currentPromise.finally(() => {
17
+ currentPromise = null;
18
+ if (options.trailing && trailingArgs && !timeout) {
19
+ const promise = applyFn(_this, trailingArgs);
20
+ trailingArgs = null;
21
+ return promise;
22
+ }
23
+ });
24
+ return currentPromise;
25
+ };
26
+ return function(...args) {
27
+ if (currentPromise) {
28
+ if (options.trailing) {
29
+ trailingArgs = args;
30
+ }
31
+ return currentPromise;
32
+ }
33
+ return new Promise((resolve) => {
34
+ const shouldCallNow = !timeout && options.leading;
35
+ clearTimeout(timeout);
36
+ timeout = setTimeout(() => {
37
+ timeout = null;
38
+ const promise = options.leading ? leadingValue : applyFn(this, args);
39
+ for (const _resolve of resolveList) {
40
+ _resolve(promise);
41
+ }
42
+ resolveList = [];
43
+ }, wait);
44
+ if (shouldCallNow) {
45
+ leadingValue = applyFn(this, args);
46
+ resolve(leadingValue);
47
+ } else {
48
+ resolveList.push(resolve);
49
+ }
50
+ });
51
+ };
52
+ }
53
+ async function _applyPromised(fn, _this, args) {
54
+ return await fn.apply(_this, args);
55
+ }
56
+
57
+ export { debounce };
backend/node_modules/prisma/build/child.js ADDED
The diff for this file is too large to render. See raw diff
 
backend/node_modules/prisma/build/prisma_schema_build_bg.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bca8b35bd5ebe0164323d5f761a7a5075fa6ad00e1dfc7906e9da5d4c13c0287
3
+ size 2966822
backend/node_modules/prisma/build/public/assets/alert.60ea9f84.svg ADDED
backend/node_modules/prisma/build/public/assets/array.1a36c222.svg ADDED
backend/node_modules/prisma/build/public/assets/boolean.9188b434.svg ADDED
backend/node_modules/prisma/build/public/assets/chevron-down.24f76e3c.svg ADDED
backend/node_modules/prisma/build/public/assets/cross.c2610cf5.svg ADDED
backend/node_modules/prisma/build/public/assets/datetime.a3bf710a.svg ADDED
backend/node_modules/prisma/build/public/assets/download.8d34b65a.svg ADDED
backend/node_modules/prisma/build/public/assets/ellipsis.a8c5a34a.svg ADDED
backend/node_modules/prisma/build/public/assets/enum.7ec0b64c.svg ADDED
backend/node_modules/prisma/build/public/assets/folder.d77b8eaf.svg ADDED
backend/node_modules/prisma/build/public/assets/hamburger.5fdadeac.svg ADDED
backend/node_modules/prisma/build/public/assets/index.js ADDED
The diff for this file is too large to render. See raw diff
 
backend/node_modules/prisma/build/public/assets/inter-all-400-normal.4c1f8a0d.woff ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4c1f8a0d5ef1e04d7e14d194a4ef624345e7c7c1cdb4ff61d4552e32a60ac1d0
3
+ size 121716
backend/node_modules/prisma/build/public/assets/inter-all-600-normal.d0a7c8a9.woff ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d0a7c8a993b9310ebb74a893fa564133bc129f6af41126eb98d207c813b96093
3
+ size 131632
backend/node_modules/prisma/build/public/assets/inter-cyrillic-400-normal.ac97a49e.woff2 ADDED
Binary file (6.5 kB). View file
 
backend/node_modules/prisma/build/public/assets/inter-cyrillic-600-normal.2c917f10.woff2 ADDED
Binary file (6.93 kB). View file
 
backend/node_modules/prisma/build/public/assets/inter-cyrillic-ext-400-normal.f21a6a97.woff2 ADDED
Binary file (9.75 kB). View file