usewagen 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,115 @@
1
+ import { _ as warnDev, h as ErrorCodes } from "../parsers-CA8aZuF-.mjs";
2
+ import { a as createLocalStorage, c as createStorage, o as createMemoryStorage, r as getActiveWagen, s as createSessionStorage } from "../wagen-C2p8oQgu.mjs";
3
+ import { a as toValueDeep, i as resolveParser, n as parseValue, r as serializeValue } from "../utils-EL2EiRpH.mjs";
4
+ import { computed, customRef, getCurrentScope, onWatcherCleanup, toValue, watch } from "vue";
5
+ //#region src/storage/define-storage-state.ts
6
+ function defineStorageState(options) {
7
+ const { key } = options;
8
+ const clearOnDefault = options.clearOnDefault ?? true;
9
+ const parser = resolveParser(options.parser);
10
+ let cache = null;
11
+ function resolved() {
12
+ const source = options.storage;
13
+ const mode = options.mode;
14
+ if (mode !== void 0 && source !== void 0 && typeof source !== "string") return {
15
+ instance: source,
16
+ optimistic: mode === "optimistic"
17
+ };
18
+ const wagen = getActiveWagen();
19
+ return {
20
+ instance: source === void 0 ? wagen.storage.default : typeof source === "string" ? wagen.storage[source] : source,
21
+ optimistic: (mode ?? wagen.storage.mode) === "optimistic"
22
+ };
23
+ }
24
+ function write(serialized) {
25
+ const { instance, optimistic } = resolved();
26
+ if (optimistic) cache = {
27
+ seen: instance.getItem(key),
28
+ raw: serialized
29
+ };
30
+ if (serialized === null) instance.removeItem(key);
31
+ else instance.setItem(key, serialized);
32
+ if (optimistic) cache = {
33
+ seen: instance.getItem(key),
34
+ raw: serialized
35
+ };
36
+ }
37
+ return {
38
+ key,
39
+ get storage() {
40
+ return resolved().instance;
41
+ },
42
+ get: () => {
43
+ const { instance, optimistic } = resolved();
44
+ const current = instance.getItem(key);
45
+ if (!optimistic) {
46
+ cache = null;
47
+ return parseValue(parser, current);
48
+ }
49
+ if (cache && cache.seen === current) return parseValue(parser, cache.raw);
50
+ cache = {
51
+ seen: current,
52
+ raw: current
53
+ };
54
+ return parseValue(parser, current);
55
+ },
56
+ set: (next) => write(serializeValue(parser, clearOnDefault, next)),
57
+ remove: () => write(null),
58
+ subscribe: (listener) => resolved().instance.subscribe(key, listener)
59
+ };
60
+ }
61
+ //#endregion
62
+ //#region src/storage/use-storage.ts
63
+ function isStorageState(input) {
64
+ return typeof input === "object" && input !== null && typeof input.get === "function";
65
+ }
66
+ function withWagenDefaults(options, wagen) {
67
+ const source = options.storage;
68
+ const storage = source === void 0 ? wagen.storage.default : typeof source === "string" ? wagen.storage[source] : source;
69
+ return {
70
+ ...options,
71
+ storage,
72
+ mode: options.mode ?? wagen.storage.mode
73
+ };
74
+ }
75
+ function useStorageState(input) {
76
+ if (isStorageState(input)) return computed(() => input);
77
+ const wagen = getActiveWagen();
78
+ return computed(() => defineStorageState(withWagenDefaults(toValueDeep(input), wagen)));
79
+ }
80
+ function useStorage(input) {
81
+ if (!getCurrentScope()) warnDev(ErrorCodes.NO_EFFECT_SCOPE, "useStorage");
82
+ const state = useStorageState(input);
83
+ let notify;
84
+ const value = customRef((track, trigger) => {
85
+ notify = trigger;
86
+ return {
87
+ get: () => {
88
+ track();
89
+ return state.value.get();
90
+ },
91
+ set: (next) => state.value.set(next)
92
+ };
93
+ });
94
+ watch(state, (current) => {
95
+ onWatcherCleanup(current.subscribe(notify));
96
+ }, {
97
+ immediate: true,
98
+ flush: "sync"
99
+ });
100
+ return value;
101
+ }
102
+ function useLocalStorage(options) {
103
+ return useStorage(() => ({
104
+ ...toValue(options),
105
+ storage: "local"
106
+ }));
107
+ }
108
+ function useSessionStorage(options) {
109
+ return useStorage(() => ({
110
+ ...toValue(options),
111
+ storage: "session"
112
+ }));
113
+ }
114
+ //#endregion
115
+ export { createLocalStorage, createMemoryStorage, createSessionStorage, createStorage, defineStorageState, useLocalStorage, useSessionStorage, useStorage };
@@ -0,0 +1,72 @@
1
+ import { MaybeRefOrGetter, Ref } from "vue";
2
+ //#region src/parser/parsers.d.ts
3
+ type ParserOptions<T> = {
4
+ parse: (raw: string) => T | null;
5
+ serialize?: (value: T) => string;
6
+ };
7
+ type DefaultValue<T> = T | (() => T);
8
+ type Parser<T> = {
9
+ parse: (raw: string) => T | null;
10
+ serialize: (value: T) => string;
11
+ withDefault: (value: DefaultValue<T>) => ParserWithDefault<T>;
12
+ };
13
+ type ParserWithDefault<T> = Parser<T> & {
14
+ readonly defaultValue: DefaultValue<T>;
15
+ };
16
+ declare function tryParse<I, R>(fn: (input: I) => R, input: I): R | null;
17
+ declare function defineParser<T>(options: ParserOptions<T>): Parser<T>;
18
+ declare function unwrapDefault<T>(value: DefaultValue<T>): T;
19
+ declare const parseAsString: Parser<string>;
20
+ declare const parseAsInteger: Parser<number>;
21
+ declare const parseAsFloat: Parser<number>;
22
+ declare const parseAsIndex: Parser<number>;
23
+ declare const parseAsBoolean: Parser<boolean>;
24
+ declare function parseAsStringLiteral<const T extends readonly string[]>(values: T): Parser<T[number]>;
25
+ declare function parseAsNumberLiteral<const T extends readonly number[]>(values: T): Parser<T[number]>;
26
+ declare function parseAsStringEnum<T extends string>(values: T[]): Parser<T>;
27
+ declare const parseAsDate: Parser<Date> & {
28
+ iso: () => Parser<Date>;
29
+ timestamp: () => Parser<Date>;
30
+ };
31
+ declare function parseAsArrayOf<T>(itemParser: Parser<T>, separator?: string): Parser<T[]>;
32
+ declare function parseAsJson<T>(): Parser<T>;
33
+ //#endregion
34
+ //#region src/parser/types.d.ts
35
+ type BuiltinParsers = {
36
+ parseAsString: Parser<string>;
37
+ parseAsInteger: Parser<number>;
38
+ parseAsFloat: Parser<number>;
39
+ parseAsIndex: Parser<number>;
40
+ parseAsBoolean: Parser<boolean>;
41
+ parseAsDate: Parser<Date>;
42
+ };
43
+ interface CustomParsers {}
44
+ type KnownParsers = BuiltinParsers & Omit<CustomParsers, keyof BuiltinParsers>;
45
+ type InferParserValue<P> = P extends Parser<infer T> ? T : never;
46
+ type NamedParserRef = { [K in keyof KnownParsers]: {
47
+ name: K;
48
+ defaultValue?: DefaultValue<InferParserValue<KnownParsers[K]>>;
49
+ }; }[keyof KnownParsers];
50
+ type ParserInput = (Parser<any> & {
51
+ name?: never;
52
+ }) | NamedParserRef;
53
+ type UnwrapParser<P> = P extends Ref<infer U> ? U : P extends (() => infer U) ? U : P;
54
+ type WithParser<T, P extends ParserInput | undefined> = Omit<T, 'parser'> & {
55
+ parser?: P;
56
+ };
57
+ type InferInputValue<P> = ResolveInputValue<UnwrapParser<P>>;
58
+ type ResolveInputValue<P> = [P] extends [undefined] ? string | null : P extends ParserWithDefault<infer T> ? T : P extends Parser<infer T> ? T | null : P extends {
59
+ name: infer K;
60
+ defaultValue: any;
61
+ } ? K extends keyof KnownParsers ? InferParserValue<KnownParsers[K]> : string : P extends {
62
+ name: infer K;
63
+ } ? K extends keyof KnownParsers ? InferParserValue<KnownParsers[K]> | null : string | null : string | null;
64
+ type InferInputWritable<P> = InferInputValue<P> | null | undefined;
65
+ //#endregion
66
+ //#region src/types.d.ts
67
+ type StateMode = 'optimistic' | 'source';
68
+ type MaybeRefsOrGetters<T> = { [K in keyof T]: MaybeRefOrGetter<T[K]>; };
69
+ type ReactiveFields<T, TStatic extends keyof T = never> = MaybeRefsOrGetters<Omit<T, TStatic>> & Pick<T, TStatic>;
70
+ type ReactiveOptions<T, TStatic extends keyof T = never> = MaybeRefOrGetter<ReactiveFields<T, TStatic>>;
71
+ //#endregion
72
+ export { unwrapDefault as A, parseAsInteger as C, parseAsStringEnum as D, parseAsString as E, parseAsStringLiteral as O, parseAsIndex as S, parseAsNumberLiteral as T, defineParser as _, CustomParsers as a, parseAsDate as b, InferParserValue as c, UnwrapParser as d, WithParser as f, ParserWithDefault as g, ParserOptions as h, BuiltinParsers as i, tryParse as k, KnownParsers as l, Parser as m, ReactiveOptions as n, InferInputValue as o, DefaultValue as p, StateMode as r, InferInputWritable as s, ReactiveFields as t, ParserInput as u, parseAsArrayOf as v, parseAsJson as w, parseAsFloat as x, parseAsBoolean as y };
@@ -0,0 +1,25 @@
1
+ import { p as DefaultValue, r as StateMode, u as ParserInput } from "./types-JtRmT3qo.mjs";
2
+ //#region src/parser/resolve.d.ts
3
+ type ResolvedParser<T> = {
4
+ parse: (raw: string) => T | null;
5
+ serialize: (value: T) => string;
6
+ defaultValue?: DefaultValue<T>;
7
+ };
8
+ //#endregion
9
+ //#region src/router/types.d.ts
10
+ type RouteStateSource = 'params' | 'query';
11
+ type HistoryMode = 'push' | 'replace';
12
+ interface RouteStateOptions {
13
+ key: string;
14
+ parser?: ParserInput;
15
+ urlKey?: string;
16
+ source?: RouteStateSource;
17
+ history?: HistoryMode;
18
+ clearOnDefault?: boolean;
19
+ mode?: StateMode;
20
+ }
21
+ type ResolvedRouteStateOptions = Omit<Required<RouteStateOptions>, 'parser'> & {
22
+ parser: ResolvedParser<any>;
23
+ };
24
+ //#endregion
25
+ export { RouteStateSource as i, ResolvedRouteStateOptions as n, RouteStateOptions as r, HistoryMode as t };
@@ -0,0 +1,79 @@
1
+ import { g as warn, h as ErrorCodes, m as unwrapDefault, u as parseAsString } from "./parsers-CA8aZuF-.mjs";
2
+ import { r as getActiveWagen } from "./wagen-C2p8oQgu.mjs";
3
+ import { n as isBuiltinParserName, t as builtinParsers } from "./builtins-DiCjLgsG.mjs";
4
+ import { toValue } from "vue";
5
+ //#region src/options.ts
6
+ function toValueDeep(input) {
7
+ const source = toValue(input);
8
+ const result = {};
9
+ for (const key in source) result[key] = toValue(source[key]);
10
+ return result;
11
+ }
12
+ //#endregion
13
+ //#region src/parser/resolve.ts
14
+ function getParser(name) {
15
+ if (isBuiltinParserName(name)) return builtinParsers[name];
16
+ const { parsers } = getActiveWagen();
17
+ return Object.hasOwn(parsers, name) ? parsers[name] : void 0;
18
+ }
19
+ function fromParser(parser) {
20
+ const resolved = {
21
+ parse: parser.parse,
22
+ serialize: parser.serialize
23
+ };
24
+ if ("defaultValue" in parser) resolved.defaultValue = parser.defaultValue;
25
+ return resolved;
26
+ }
27
+ function fromName(name, override) {
28
+ let warned = false;
29
+ function get() {
30
+ const found = getParser(name);
31
+ if (found) return found;
32
+ if (!warned) {
33
+ warned = true;
34
+ warn(ErrorCodes.UNKNOWN_PARSER_NAME, name);
35
+ }
36
+ return parseAsString;
37
+ }
38
+ const base = {
39
+ parse: (raw) => get().parse(raw),
40
+ serialize: (value) => get().serialize(value)
41
+ };
42
+ if (override) return {
43
+ ...base,
44
+ defaultValue: override.defaultValue
45
+ };
46
+ return {
47
+ ...base,
48
+ get defaultValue() {
49
+ return get().defaultValue;
50
+ }
51
+ };
52
+ }
53
+ function resolveParser(input = { name: "parseAsString" }) {
54
+ if ("parse" in input) return fromParser(input);
55
+ const override = "defaultValue" in input ? { defaultValue: input.defaultValue } : void 0;
56
+ return fromName(input.name, override);
57
+ }
58
+ //#endregion
59
+ //#region src/parser/utils.ts
60
+ function normalizeRaw(raw) {
61
+ return (Array.isArray(raw) ? raw.find((v) => v != null) : raw) ?? null;
62
+ }
63
+ function parseValue(parser, raw) {
64
+ const value = normalizeRaw(raw);
65
+ if (value === null) return parser.defaultValue !== void 0 ? unwrapDefault(parser.defaultValue) : null;
66
+ const parsed = parser.parse(value);
67
+ if (parsed !== null) return parsed;
68
+ return parser.defaultValue !== void 0 ? unwrapDefault(parser.defaultValue) : null;
69
+ }
70
+ function serializeValue(parser, clearOnDefault, next) {
71
+ if (next == null) return null;
72
+ const serialized = parser.serialize(next);
73
+ if (clearOnDefault && parser.defaultValue !== void 0) {
74
+ if (serialized === parser.serialize(unwrapDefault(parser.defaultValue))) return null;
75
+ }
76
+ return serialized;
77
+ }
78
+ //#endregion
79
+ export { toValueDeep as a, resolveParser as i, parseValue as n, serializeValue as r, normalizeRaw as t };
@@ -0,0 +1,19 @@
1
+ import { Plugin } from "vite";
2
+ //#region src/vite/index.d.ts
3
+ export declare const PARSERS_ID = "virtual:usewagen/parsers";
4
+ export declare const RESOLVED_PARSERS_ID = "\0virtual:usewagen/parsers";
5
+ export interface WagenPluginOptions {
6
+ /**
7
+ * Directory or directories to scan for parser files.
8
+ * @default 'src/parsers'
9
+ */
10
+ dirs?: string | string[];
11
+ /**
12
+ * Output path for the generated `.d.ts` file, or `false` to disable.
13
+ * @default 'usewagen.d.ts'
14
+ */
15
+ dts?: string | false;
16
+ }
17
+ export declare function usewagen(options?: WagenPluginOptions): Plugin;
18
+ //#endregion
19
+ export { usewagen as default };
@@ -0,0 +1,230 @@
1
+ import { g as warn, h as ErrorCodes } from "../parsers-CA8aZuF-.mjs";
2
+ import { n as isBuiltinParserName } from "../builtins-DiCjLgsG.mjs";
3
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
+ import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
5
+ //#region src/vite/generate.ts
6
+ const BANNER = "// Auto-generated by usewagen/vite — do not edit";
7
+ function toPosix(path) {
8
+ return path.split(sep).join("/");
9
+ }
10
+ function toSpecifier(from, file) {
11
+ const target = relative(from, file);
12
+ const specifier = toPosix(join(dirname(target), basename(target, extname(target))));
13
+ return specifier.startsWith(".") ? specifier : `./${specifier}`;
14
+ }
15
+ function generateModule(entries) {
16
+ const byFile = /* @__PURE__ */ new Map();
17
+ for (const { name, file } of entries) {
18
+ const names = byFile.get(file) ?? [];
19
+ names.push(name);
20
+ byFile.set(file, names);
21
+ }
22
+ const lines = [BANNER];
23
+ for (const [file, names] of byFile) lines.push(`import { ${names.join(", ")} } from ${JSON.stringify(toPosix(file))}`);
24
+ lines.push("");
25
+ if (entries.length === 0) {
26
+ lines.push("export const parsers = {}", "");
27
+ return lines.join("\n");
28
+ }
29
+ lines.push("export const parsers = {");
30
+ for (const { name } of entries) lines.push(` ${name},`);
31
+ lines.push("}", "");
32
+ return lines.join("\n");
33
+ }
34
+ function generateDeclaration(entries, dtsPath) {
35
+ const dtsDir = dirname(dtsPath);
36
+ const lines = [
37
+ BANNER,
38
+ "/// <reference types=\"usewagen/client\" />",
39
+ "export {}",
40
+ "",
41
+ "declare module 'usewagen' {",
42
+ " interface CustomParsers {"
43
+ ];
44
+ for (const { name, file } of entries) lines.push(` ${name}: typeof import('${toSpecifier(dtsDir, file)}')['${name}']`);
45
+ lines.push(" }", "}", "");
46
+ return lines.join("\n");
47
+ }
48
+ //#endregion
49
+ //#region src/vite/strip.ts
50
+ const DIVISION_PRECEDING = /[\w$)\]]/;
51
+ function stripNonCode(source) {
52
+ let output = "";
53
+ let index = 0;
54
+ let previous = "";
55
+ const push = (char) => {
56
+ output += char;
57
+ if (!/\s/.test(char)) previous = char;
58
+ };
59
+ while (index < source.length) {
60
+ const char = source[index];
61
+ const next = source[index + 1];
62
+ if (char === "/" && next === "/") {
63
+ while (index < source.length && source[index] !== "\n") index++;
64
+ continue;
65
+ }
66
+ if (char === "/" && next === "*") {
67
+ index += 2;
68
+ while (index < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
69
+ if (source[index] === "\n") output += "\n";
70
+ index++;
71
+ }
72
+ index += 2;
73
+ continue;
74
+ }
75
+ if (char === "\"" || char === "'" || char === "`") {
76
+ index++;
77
+ while (index < source.length && source[index] !== char) {
78
+ if (source[index] === "\\") index++;
79
+ index++;
80
+ }
81
+ index++;
82
+ push(char);
83
+ continue;
84
+ }
85
+ if (char === "/" && !DIVISION_PRECEDING.test(previous)) {
86
+ index++;
87
+ let inClass = false;
88
+ while (index < source.length && source[index] !== "\n") {
89
+ const current = source[index];
90
+ if (current === "\\") {
91
+ index += 2;
92
+ continue;
93
+ }
94
+ if (current === "[") inClass = true;
95
+ else if (current === "]") inClass = false;
96
+ else if (current === "/" && !inClass) break;
97
+ index++;
98
+ }
99
+ index++;
100
+ previous = "/";
101
+ continue;
102
+ }
103
+ push(char);
104
+ index++;
105
+ }
106
+ return output;
107
+ }
108
+ //#endregion
109
+ //#region src/vite/scan.ts
110
+ const MODULE_EXTENSIONS = /* @__PURE__ */ new Set([
111
+ ".js",
112
+ ".mjs",
113
+ ".ts",
114
+ ".mts"
115
+ ]);
116
+ const DECLARATION_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".mts"]);
117
+ const PARSER_EXPORT = /export\s+const\s+(parseAs\w+)/g;
118
+ function isDeclarationFile(name, extension) {
119
+ return DECLARATION_EXTENSIONS.has(extension) && basename(name, extension).endsWith(".d");
120
+ }
121
+ function isParserFile(name) {
122
+ const extension = extname(name);
123
+ return MODULE_EXTENSIONS.has(extension) && !isDeclarationFile(name, extension);
124
+ }
125
+ function extractNames(file) {
126
+ const source = stripNonCode(readFileSync(file, "utf-8"));
127
+ const names = [];
128
+ PARSER_EXPORT.lastIndex = 0;
129
+ let match;
130
+ while ((match = PARSER_EXPORT.exec(source)) !== null) {
131
+ const name = match[1];
132
+ if (isBuiltinParserName(name)) {
133
+ warn(ErrorCodes.RESERVED_PARSER_NAME, name, file);
134
+ continue;
135
+ }
136
+ names.push(name);
137
+ }
138
+ return names;
139
+ }
140
+ function walk(dir, entries) {
141
+ if (!existsSync(dir)) return;
142
+ for (const item of readdirSync(dir, { withFileTypes: true })) {
143
+ if (item.isDirectory()) {
144
+ walk(resolve(dir, item.name), entries);
145
+ continue;
146
+ }
147
+ if (!isParserFile(item.name)) continue;
148
+ const file = resolve(dir, item.name);
149
+ for (const name of extractNames(file)) entries.push({
150
+ name,
151
+ file
152
+ });
153
+ }
154
+ }
155
+ function dedupe(entries) {
156
+ const byName = /* @__PURE__ */ new Map();
157
+ for (const entry of entries) {
158
+ const previous = byName.get(entry.name);
159
+ if (previous) warn(ErrorCodes.DUPLICATE_PARSER_NAME, entry.name, previous.file, entry.file);
160
+ byName.set(entry.name, entry);
161
+ }
162
+ return [...byName.values()];
163
+ }
164
+ function scanParsers(dirs) {
165
+ const entries = [];
166
+ for (const dir of dirs) walk(dir, entries);
167
+ return dedupe(entries);
168
+ }
169
+ //#endregion
170
+ //#region src/vite/index.ts
171
+ const PARSERS_ID = "virtual:usewagen/parsers";
172
+ const RESOLVED_PARSERS_ID = `\0${PARSERS_ID}`;
173
+ function contains(dir, path) {
174
+ const target = relative(dir, path);
175
+ return !isAbsolute(target) && !target.startsWith(`..${sep}`);
176
+ }
177
+ function usewagen(options = {}) {
178
+ const { dirs: rawDirs = "src/parsers", dts = "usewagen.d.ts" } = options;
179
+ let dirs = [];
180
+ let dtsPath = "";
181
+ let entries = null;
182
+ function scan() {
183
+ entries ??= scanParsers(dirs);
184
+ return entries;
185
+ }
186
+ function writeDeclaration() {
187
+ if (dts === false) return;
188
+ const content = generateDeclaration(scan(), dtsPath);
189
+ const dir = dirname(dtsPath);
190
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
191
+ if ((existsSync(dtsPath) ? readFileSync(dtsPath, "utf-8") : "") !== content) writeFileSync(dtsPath, content, "utf-8");
192
+ }
193
+ function isScanned(path) {
194
+ return dirs.some((dir) => contains(dir, path)) && isParserFile(basename(path));
195
+ }
196
+ return {
197
+ name: "usewagen",
198
+ configResolved(config) {
199
+ dirs = (Array.isArray(rawDirs) ? rawDirs : [rawDirs]).map((dir) => resolve(config.root, dir));
200
+ if (dts !== false) dtsPath = resolve(config.root, dts);
201
+ entries = null;
202
+ writeDeclaration();
203
+ },
204
+ resolveId(id) {
205
+ if (id === "virtual:usewagen/parsers") return RESOLVED_PARSERS_ID;
206
+ },
207
+ load(id) {
208
+ if (id !== RESOLVED_PARSERS_ID) return;
209
+ const found = scan();
210
+ for (const dir of dirs) this.addWatchFile(dir);
211
+ for (const { file } of found) this.addWatchFile(file);
212
+ return generateModule(found);
213
+ },
214
+ configureServer(server) {
215
+ for (const dir of dirs) server.watcher.add(dir);
216
+ server.watcher.on("all", (event, path) => {
217
+ if (event !== "add" && event !== "unlink" && event !== "change") return;
218
+ if (!isScanned(path)) return;
219
+ entries = null;
220
+ writeDeclaration();
221
+ const mod = server.moduleGraph.getModuleById(RESOLVED_PARSERS_ID);
222
+ if (!mod) return;
223
+ server.moduleGraph.invalidateModule(mod);
224
+ server.ws.send({ type: "full-reload" });
225
+ });
226
+ }
227
+ };
228
+ }
229
+ //#endregion
230
+ export { PARSERS_ID, RESOLVED_PARSERS_ID, usewagen as default, usewagen };