@spinajs/configuration 2.0.532 → 2.0.533

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.
@@ -1,11 +1,83 @@
1
1
  import { IConfigEntryOptions } from '@spinajs/configuration-common';
2
2
  import { Class } from '@spinajs/di';
3
3
  /**
4
- * Injects configuration value to given class property
4
+ * Injects configuration value into a class property.
5
+ *
6
+ * The decorated property is replaced with a lazy getter. Every read resolves the
7
+ * {@link Configuration} service and calls `config.get(path, options.defaultValue)`,
8
+ * so the property always reflects the current (possibly reloaded / watched) value
9
+ * instead of a snapshot taken at construction time.
10
+ *
11
+ * Besides defining the getter, the decorator registers `{ path, options }` in the DI
12
+ * container under `__configuration_property__`. Other modules listen for these
13
+ * registrations - eg. `@spinajs/configuration-db-source` uses them to persist
14
+ * (expose) entries in the database and to watch them for changes.
15
+ *
16
+ * ### Value resolution & priority
17
+ *
18
+ * The configuration is a merge of all registered `ConfigurationSource`s (json / js
19
+ * files, env, db, ...) applied in their `Order`. The getter reads the merged value at
20
+ * `path` with lodash `_.get` semantics:
21
+ *
22
+ * - `defaultValue` is a **fallback only**. It is returned when no source provides a
23
+ * value at `path` (the resolved value is `undefined`).
24
+ * - when any source provides a value at `path`, that value is returned and
25
+ * `defaultValue` is ignored. The db source loads last (`Order` 999), so an exposed
26
+ * db row overrides the same key coming from files.
27
+ * - with `expose: true` the entry is inserted into the `configuration` table on first
28
+ * run (InsertOrIgnore) with both `Value` and `Default` columns seeded from
29
+ * `defaultValue`. From then on the db row is the source of truth for that key:
30
+ * reading it - via `@Config` or plain `Configuration.get(path)` - returns the db
31
+ * `Value`, and editing the row changes what the property returns (immediately with
32
+ * `watch: true`, otherwise after restart / `Configuration.load()`). `defaultValue`
33
+ * is used again only when the row cannot be loaded (no db connection, table not
34
+ * migrated, row deleted, `Exposed` flag cleared).
35
+ * - reading a key without `defaultValue` simply returns whatever the sources loaded:
36
+ * for an exposed entry the db `Value`, or `undefined` / `null` when it is empty.
37
+ *
38
+ * ### Options ({@link IConfigEntryOptions})
39
+ *
40
+ * - `defaultValue` - value returned when `path` is not present in the merged config.
41
+ * When the entry is exposed it also seeds the db row (`Value` and `Default`).
42
+ * - `required` - marks the entry as required. Persisted to the `Required` column of
43
+ * the exposed db row (informational, for admin UIs); the getter does not enforce it.
44
+ * - `expose` - (db source) when `true` the entry is persisted in the `configuration`
45
+ * table so it can be administered at runtime. Only rows with the `Exposed` flag are
46
+ * loaded back into the config. Requires `@spinajs/configuration-db-source` and a
47
+ * resolved `Orm` - without the ORM nothing is written or watched.
48
+ * - `exposeOptions` - (db source) metadata of the exposed row:
49
+ * - `type` - entry type (`string`, `number`, `float`, `boolean`, `json`, `date`,
50
+ * `time`, `datetime`, `*-range`, `oneOf`, `manyOf`, `range`, `file`). Drives how
51
+ * `Value` is serialized to and parsed from the db.
52
+ * - `group` - display-only grouping label for admin UIs. It is NOT part of the
53
+ * config path - `Slug` (the `path` argument) is the canonical path.
54
+ * - `label`, `description` - human readable name and help text.
55
+ * - `meta` - validation hints for UIs (`min`, `max`, `oneOf`, `manyOf`, `minDate`,
56
+ * `maxDate`), stored as JSON.
57
+ * - `watch` - when `true` the db row is polled (every 3 min by default, override
58
+ * with the `__config_watch_interval__` DI value) and changes are pushed into
59
+ * the live configuration without restarting the app.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * class MailService {
64
+ * // value from files / env, "no-reply@example.com" when the key is missing
65
+ * @Config('mailer.fromAddress', { defaultValue: 'no-reply@example.com' })
66
+ * protected From: string;
67
+ *
68
+ * // exposed to db, editable at runtime, refreshed without restart
69
+ * @Config('mailer.retryCount', {
70
+ * defaultValue: 3,
71
+ * expose: true,
72
+ * exposeOptions: { type: 'number', group: 'mailer', label: 'Retry count', watch: true },
73
+ * })
74
+ * protected Retries: number;
75
+ * }
76
+ * ```
5
77
  *
6
78
  * @param path - path to configuration value eg. "app.dirs.stats"
7
- * @param dafaultValue - default value if path not exists
8
- * @returns
79
+ * @param options - entry options, see {@link IConfigEntryOptions}
80
+ * @returns property decorator
9
81
  */
10
82
  export declare function Config(path: string, options?: IConfigEntryOptions): (target: any, key: string) => any;
11
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAA4B,KAAK,EAAuD,MAAM,aAAa,CAAC;AAGnH;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,YAChD,GAAG,OAAO,MAAM,KAAG,GAAG,CAevC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAoDpE"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAA4B,KAAK,EAAuD,MAAM,aAAa,CAAC;AAGnH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,YAChD,GAAG,OAAO,MAAM,KAAG,GAAG,CAevC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAoDpE"}
@@ -11,11 +11,83 @@ const configuration_common_1 = require("@spinajs/configuration-common");
11
11
  const di_1 = require("@spinajs/di");
12
12
  const internal_logger_1 = require("@spinajs/internal-logger");
13
13
  /**
14
- * Injects configuration value to given class property
14
+ * Injects configuration value into a class property.
15
+ *
16
+ * The decorated property is replaced with a lazy getter. Every read resolves the
17
+ * {@link Configuration} service and calls `config.get(path, options.defaultValue)`,
18
+ * so the property always reflects the current (possibly reloaded / watched) value
19
+ * instead of a snapshot taken at construction time.
20
+ *
21
+ * Besides defining the getter, the decorator registers `{ path, options }` in the DI
22
+ * container under `__configuration_property__`. Other modules listen for these
23
+ * registrations - eg. `@spinajs/configuration-db-source` uses them to persist
24
+ * (expose) entries in the database and to watch them for changes.
25
+ *
26
+ * ### Value resolution & priority
27
+ *
28
+ * The configuration is a merge of all registered `ConfigurationSource`s (json / js
29
+ * files, env, db, ...) applied in their `Order`. The getter reads the merged value at
30
+ * `path` with lodash `_.get` semantics:
31
+ *
32
+ * - `defaultValue` is a **fallback only**. It is returned when no source provides a
33
+ * value at `path` (the resolved value is `undefined`).
34
+ * - when any source provides a value at `path`, that value is returned and
35
+ * `defaultValue` is ignored. The db source loads last (`Order` 999), so an exposed
36
+ * db row overrides the same key coming from files.
37
+ * - with `expose: true` the entry is inserted into the `configuration` table on first
38
+ * run (InsertOrIgnore) with both `Value` and `Default` columns seeded from
39
+ * `defaultValue`. From then on the db row is the source of truth for that key:
40
+ * reading it - via `@Config` or plain `Configuration.get(path)` - returns the db
41
+ * `Value`, and editing the row changes what the property returns (immediately with
42
+ * `watch: true`, otherwise after restart / `Configuration.load()`). `defaultValue`
43
+ * is used again only when the row cannot be loaded (no db connection, table not
44
+ * migrated, row deleted, `Exposed` flag cleared).
45
+ * - reading a key without `defaultValue` simply returns whatever the sources loaded:
46
+ * for an exposed entry the db `Value`, or `undefined` / `null` when it is empty.
47
+ *
48
+ * ### Options ({@link IConfigEntryOptions})
49
+ *
50
+ * - `defaultValue` - value returned when `path` is not present in the merged config.
51
+ * When the entry is exposed it also seeds the db row (`Value` and `Default`).
52
+ * - `required` - marks the entry as required. Persisted to the `Required` column of
53
+ * the exposed db row (informational, for admin UIs); the getter does not enforce it.
54
+ * - `expose` - (db source) when `true` the entry is persisted in the `configuration`
55
+ * table so it can be administered at runtime. Only rows with the `Exposed` flag are
56
+ * loaded back into the config. Requires `@spinajs/configuration-db-source` and a
57
+ * resolved `Orm` - without the ORM nothing is written or watched.
58
+ * - `exposeOptions` - (db source) metadata of the exposed row:
59
+ * - `type` - entry type (`string`, `number`, `float`, `boolean`, `json`, `date`,
60
+ * `time`, `datetime`, `*-range`, `oneOf`, `manyOf`, `range`, `file`). Drives how
61
+ * `Value` is serialized to and parsed from the db.
62
+ * - `group` - display-only grouping label for admin UIs. It is NOT part of the
63
+ * config path - `Slug` (the `path` argument) is the canonical path.
64
+ * - `label`, `description` - human readable name and help text.
65
+ * - `meta` - validation hints for UIs (`min`, `max`, `oneOf`, `manyOf`, `minDate`,
66
+ * `maxDate`), stored as JSON.
67
+ * - `watch` - when `true` the db row is polled (every 3 min by default, override
68
+ * with the `__config_watch_interval__` DI value) and changes are pushed into
69
+ * the live configuration without restarting the app.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * class MailService {
74
+ * // value from files / env, "no-reply@example.com" when the key is missing
75
+ * @Config('mailer.fromAddress', { defaultValue: 'no-reply@example.com' })
76
+ * protected From: string;
77
+ *
78
+ * // exposed to db, editable at runtime, refreshed without restart
79
+ * @Config('mailer.retryCount', {
80
+ * defaultValue: 3,
81
+ * expose: true,
82
+ * exposeOptions: { type: 'number', group: 'mailer', label: 'Retry count', watch: true },
83
+ * })
84
+ * protected Retries: number;
85
+ * }
86
+ * ```
15
87
  *
16
88
  * @param path - path to configuration value eg. "app.dirs.stats"
17
- * @param dafaultValue - default value if path not exists
18
- * @returns
89
+ * @param options - entry options, see {@link IConfigEntryOptions}
90
+ * @returns property decorator
19
91
  */
20
92
  function Config(path, options) {
21
93
  return (target, key) => {
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,83 @@
1
1
  import { IConfigEntryOptions } from '@spinajs/configuration-common';
2
2
  import { Class } from '@spinajs/di';
3
3
  /**
4
- * Injects configuration value to given class property
4
+ * Injects configuration value into a class property.
5
+ *
6
+ * The decorated property is replaced with a lazy getter. Every read resolves the
7
+ * {@link Configuration} service and calls `config.get(path, options.defaultValue)`,
8
+ * so the property always reflects the current (possibly reloaded / watched) value
9
+ * instead of a snapshot taken at construction time.
10
+ *
11
+ * Besides defining the getter, the decorator registers `{ path, options }` in the DI
12
+ * container under `__configuration_property__`. Other modules listen for these
13
+ * registrations - eg. `@spinajs/configuration-db-source` uses them to persist
14
+ * (expose) entries in the database and to watch them for changes.
15
+ *
16
+ * ### Value resolution & priority
17
+ *
18
+ * The configuration is a merge of all registered `ConfigurationSource`s (json / js
19
+ * files, env, db, ...) applied in their `Order`. The getter reads the merged value at
20
+ * `path` with lodash `_.get` semantics:
21
+ *
22
+ * - `defaultValue` is a **fallback only**. It is returned when no source provides a
23
+ * value at `path` (the resolved value is `undefined`).
24
+ * - when any source provides a value at `path`, that value is returned and
25
+ * `defaultValue` is ignored. The db source loads last (`Order` 999), so an exposed
26
+ * db row overrides the same key coming from files.
27
+ * - with `expose: true` the entry is inserted into the `configuration` table on first
28
+ * run (InsertOrIgnore) with both `Value` and `Default` columns seeded from
29
+ * `defaultValue`. From then on the db row is the source of truth for that key:
30
+ * reading it - via `@Config` or plain `Configuration.get(path)` - returns the db
31
+ * `Value`, and editing the row changes what the property returns (immediately with
32
+ * `watch: true`, otherwise after restart / `Configuration.load()`). `defaultValue`
33
+ * is used again only when the row cannot be loaded (no db connection, table not
34
+ * migrated, row deleted, `Exposed` flag cleared).
35
+ * - reading a key without `defaultValue` simply returns whatever the sources loaded:
36
+ * for an exposed entry the db `Value`, or `undefined` / `null` when it is empty.
37
+ *
38
+ * ### Options ({@link IConfigEntryOptions})
39
+ *
40
+ * - `defaultValue` - value returned when `path` is not present in the merged config.
41
+ * When the entry is exposed it also seeds the db row (`Value` and `Default`).
42
+ * - `required` - marks the entry as required. Persisted to the `Required` column of
43
+ * the exposed db row (informational, for admin UIs); the getter does not enforce it.
44
+ * - `expose` - (db source) when `true` the entry is persisted in the `configuration`
45
+ * table so it can be administered at runtime. Only rows with the `Exposed` flag are
46
+ * loaded back into the config. Requires `@spinajs/configuration-db-source` and a
47
+ * resolved `Orm` - without the ORM nothing is written or watched.
48
+ * - `exposeOptions` - (db source) metadata of the exposed row:
49
+ * - `type` - entry type (`string`, `number`, `float`, `boolean`, `json`, `date`,
50
+ * `time`, `datetime`, `*-range`, `oneOf`, `manyOf`, `range`, `file`). Drives how
51
+ * `Value` is serialized to and parsed from the db.
52
+ * - `group` - display-only grouping label for admin UIs. It is NOT part of the
53
+ * config path - `Slug` (the `path` argument) is the canonical path.
54
+ * - `label`, `description` - human readable name and help text.
55
+ * - `meta` - validation hints for UIs (`min`, `max`, `oneOf`, `manyOf`, `minDate`,
56
+ * `maxDate`), stored as JSON.
57
+ * - `watch` - when `true` the db row is polled (every 3 min by default, override
58
+ * with the `__config_watch_interval__` DI value) and changes are pushed into
59
+ * the live configuration without restarting the app.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * class MailService {
64
+ * // value from files / env, "no-reply@example.com" when the key is missing
65
+ * @Config('mailer.fromAddress', { defaultValue: 'no-reply@example.com' })
66
+ * protected From: string;
67
+ *
68
+ * // exposed to db, editable at runtime, refreshed without restart
69
+ * @Config('mailer.retryCount', {
70
+ * defaultValue: 3,
71
+ * expose: true,
72
+ * exposeOptions: { type: 'number', group: 'mailer', label: 'Retry count', watch: true },
73
+ * })
74
+ * protected Retries: number;
75
+ * }
76
+ * ```
5
77
  *
6
78
  * @param path - path to configuration value eg. "app.dirs.stats"
7
- * @param dafaultValue - default value if path not exists
8
- * @returns
79
+ * @param options - entry options, see {@link IConfigEntryOptions}
80
+ * @returns property decorator
9
81
  */
10
82
  export declare function Config(path: string, options?: IConfigEntryOptions): (target: any, key: string) => any;
11
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAA4B,KAAK,EAAuD,MAAM,aAAa,CAAC;AAGnH;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,YAChD,GAAG,OAAO,MAAM,KAAG,GAAG,CAevC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAoDpE"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAA4B,KAAK,EAAuD,MAAM,aAAa,CAAC;AAGnH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,YAChD,GAAG,OAAO,MAAM,KAAG,GAAG,CAevC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAoDpE"}
@@ -4,11 +4,83 @@ import { Configuration } from '@spinajs/configuration-common';
4
4
  import { AddDependencyForProperty, DI } from '@spinajs/di';
5
5
  import { InternalLogger } from '@spinajs/internal-logger';
6
6
  /**
7
- * Injects configuration value to given class property
7
+ * Injects configuration value into a class property.
8
+ *
9
+ * The decorated property is replaced with a lazy getter. Every read resolves the
10
+ * {@link Configuration} service and calls `config.get(path, options.defaultValue)`,
11
+ * so the property always reflects the current (possibly reloaded / watched) value
12
+ * instead of a snapshot taken at construction time.
13
+ *
14
+ * Besides defining the getter, the decorator registers `{ path, options }` in the DI
15
+ * container under `__configuration_property__`. Other modules listen for these
16
+ * registrations - eg. `@spinajs/configuration-db-source` uses them to persist
17
+ * (expose) entries in the database and to watch them for changes.
18
+ *
19
+ * ### Value resolution & priority
20
+ *
21
+ * The configuration is a merge of all registered `ConfigurationSource`s (json / js
22
+ * files, env, db, ...) applied in their `Order`. The getter reads the merged value at
23
+ * `path` with lodash `_.get` semantics:
24
+ *
25
+ * - `defaultValue` is a **fallback only**. It is returned when no source provides a
26
+ * value at `path` (the resolved value is `undefined`).
27
+ * - when any source provides a value at `path`, that value is returned and
28
+ * `defaultValue` is ignored. The db source loads last (`Order` 999), so an exposed
29
+ * db row overrides the same key coming from files.
30
+ * - with `expose: true` the entry is inserted into the `configuration` table on first
31
+ * run (InsertOrIgnore) with both `Value` and `Default` columns seeded from
32
+ * `defaultValue`. From then on the db row is the source of truth for that key:
33
+ * reading it - via `@Config` or plain `Configuration.get(path)` - returns the db
34
+ * `Value`, and editing the row changes what the property returns (immediately with
35
+ * `watch: true`, otherwise after restart / `Configuration.load()`). `defaultValue`
36
+ * is used again only when the row cannot be loaded (no db connection, table not
37
+ * migrated, row deleted, `Exposed` flag cleared).
38
+ * - reading a key without `defaultValue` simply returns whatever the sources loaded:
39
+ * for an exposed entry the db `Value`, or `undefined` / `null` when it is empty.
40
+ *
41
+ * ### Options ({@link IConfigEntryOptions})
42
+ *
43
+ * - `defaultValue` - value returned when `path` is not present in the merged config.
44
+ * When the entry is exposed it also seeds the db row (`Value` and `Default`).
45
+ * - `required` - marks the entry as required. Persisted to the `Required` column of
46
+ * the exposed db row (informational, for admin UIs); the getter does not enforce it.
47
+ * - `expose` - (db source) when `true` the entry is persisted in the `configuration`
48
+ * table so it can be administered at runtime. Only rows with the `Exposed` flag are
49
+ * loaded back into the config. Requires `@spinajs/configuration-db-source` and a
50
+ * resolved `Orm` - without the ORM nothing is written or watched.
51
+ * - `exposeOptions` - (db source) metadata of the exposed row:
52
+ * - `type` - entry type (`string`, `number`, `float`, `boolean`, `json`, `date`,
53
+ * `time`, `datetime`, `*-range`, `oneOf`, `manyOf`, `range`, `file`). Drives how
54
+ * `Value` is serialized to and parsed from the db.
55
+ * - `group` - display-only grouping label for admin UIs. It is NOT part of the
56
+ * config path - `Slug` (the `path` argument) is the canonical path.
57
+ * - `label`, `description` - human readable name and help text.
58
+ * - `meta` - validation hints for UIs (`min`, `max`, `oneOf`, `manyOf`, `minDate`,
59
+ * `maxDate`), stored as JSON.
60
+ * - `watch` - when `true` the db row is polled (every 3 min by default, override
61
+ * with the `__config_watch_interval__` DI value) and changes are pushed into
62
+ * the live configuration without restarting the app.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * class MailService {
67
+ * // value from files / env, "no-reply@example.com" when the key is missing
68
+ * @Config('mailer.fromAddress', { defaultValue: 'no-reply@example.com' })
69
+ * protected From: string;
70
+ *
71
+ * // exposed to db, editable at runtime, refreshed without restart
72
+ * @Config('mailer.retryCount', {
73
+ * defaultValue: 3,
74
+ * expose: true,
75
+ * exposeOptions: { type: 'number', group: 'mailer', label: 'Retry count', watch: true },
76
+ * })
77
+ * protected Retries: number;
78
+ * }
79
+ * ```
8
80
  *
9
81
  * @param path - path to configuration value eg. "app.dirs.stats"
10
- * @param dafaultValue - default value if path not exists
11
- * @returns
82
+ * @param options - entry options, see {@link IConfigEntryOptions}
83
+ * @returns property decorator
12
84
  */
13
85
  export function Config(path, options) {
14
86
  return (target, key) => {
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}