@thigasdevelopment/luam 0.11.1 → 0.13.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.
Files changed (4) hide show
  1. package/lua/env.lua +84 -11
  2. package/luam.mjs +101 -117
  3. package/package.json +1 -1
  4. package/lua/dotenv.lua +0 -160
package/lua/env.lua CHANGED
@@ -1,18 +1,91 @@
1
- local ENVIRONMENT_FILE = '.env'
1
+ local ENVIRONMENT_FILE = '__LUAM_ENV_FILE__'; -- Replaced at build time with the file the manifest selects. (.env, .env.development, ...)
2
2
 
3
- if localPlayer ~= nil then
4
- return
3
+ ---@param str string
4
+ ---@return string
5
+ local function trim (str)
6
+ return str:match ('^%s*(.-)%s*$');
5
7
  end
6
8
 
7
- if not fileExists(ENVIRONMENT_FILE) then
8
- if type(process) ~= 'table' then
9
- process = {}
10
- end
9
+ ---@param path string
10
+ ---@return string
11
+ local function load (path)
12
+ local pathType = type (path);
13
+ if (pathType ~= 'string') then
14
+ error ('bad argument #1 to \'load\' (\'string\' expected got \'' .. pathType .. '\').', 2);
15
+ end
11
16
 
12
- process.env = {}
13
- env = process.env
17
+ if (not fileExists (path)) then return end
14
18
 
15
- return
19
+ local file = fileOpen (path, true);
20
+ if (not file) then
21
+ error ('Failed to open environment file.', 2);
22
+ end
23
+
24
+ local content = fileRead (file, fileGetSize (file));
25
+ fileClose (file);
26
+
27
+ return content;
28
+ end
29
+
30
+ ---@param value string
31
+ ---@return boolean | number | string
32
+ local function normalize (value)
33
+ local number = tonumber (value);
34
+ if (number) then
35
+ value = number;
36
+ elseif (value:lower () == 'true') then
37
+ value = true;
38
+ elseif (value:lower () == 'false') then
39
+ value = false;
40
+ end
41
+ return value;
42
+ end
43
+
44
+ ---@param content string
45
+ ---@return table<string, any>
46
+ local function parse (content)
47
+ local result = { };
48
+
49
+ local lines = content:gmatch ('[^\r\n]+');
50
+ for line in lines do
51
+ line = trim (line);
52
+ if (line ~= '') and (not line:find ('^#')) then
53
+ local key, value = line:match ('^([%w_]+)%s*=%s*(.*)$');
54
+ if (key and value) then
55
+ if (value:sub (1, 1) == '"' and value:sub (-1) == '"') or (value:sub (1, 1) == "'" and value:sub (-1) == "'") then
56
+ value = value:sub (2, -2);
57
+ end
58
+
59
+ local value = normalize (value);
60
+ result[key] = value;
61
+ end
62
+ end
63
+ end
64
+
65
+ return result;
16
66
  end
17
67
 
18
- Dotenv.new(ENVIRONMENT_FILE):apply()
68
+ local content = load (ENVIRONMENT_FILE);
69
+ if (not content) then return end
70
+ content = parse (content);
71
+
72
+ env = setmetatable ({ }, {
73
+ ---@param _ string | number
74
+ ---@param key string
75
+ ---@return boolean | number | string
76
+ __index = function (_, key)
77
+ local value = content[key];
78
+ if (value == nil) then
79
+ error ('"' .. tostring(key) .. '" is not declared in "' .. ENVIRONMENT_FILE .. '".', 2);
80
+ end
81
+ return value;
82
+ end,
83
+
84
+ ---@param _ string | number
85
+ ---@param key string
86
+ __newindex = function (_, key)
87
+ error ('The environment is read-only and "' .. tostring(key) .. '" cannot be assigned.', 2);
88
+ end,
89
+
90
+ __metatable = false,
91
+ });
package/luam.mjs CHANGED
@@ -5279,15 +5279,7 @@ var RUNTIME_HELPERS = {
5279
5279
  injection: "automatic",
5280
5280
  features: ["class-declaration", "class-inheritance", "class-instantiation", "super-call", "enum-declaration"]
5281
5281
  },
5282
- dotenv: {
5283
- name: "dotenv",
5284
- file: "dotenv.lua",
5285
- injection: "reference",
5286
- features: [],
5287
- globals: ["Dotenv"],
5288
- environment: "server"
5289
- },
5290
- env: { name: "env", file: "env.lua", injection: "manual", features: [], requires: ["dotenv"], environment: "server" },
5282
+ env: { name: "env", file: "env.lua", injection: "manual", features: [], environment: "server" },
5291
5283
  math: { name: "math", file: "math.lua", injection: "automatic", features: ["number-extension"] },
5292
5284
  string: { name: "string", file: "string.lua", injection: "automatic", features: ["string-extension", "template-string"] },
5293
5285
  table: { name: "table", file: "table.lua", injection: "automatic", features: ["table-extension"] },
@@ -6499,7 +6491,7 @@ import { tmpdir } from "node:os";
6499
6491
  import { join as join2 } from "node:path";
6500
6492
 
6501
6493
  // src/cli/version.ts
6502
- var VERSION = true ? "0.11.1" : "0.0.0-dev";
6494
+ var VERSION = true ? "0.13.0" : "0.0.0-dev";
6503
6495
  var PROGRAM_NAME = "luam";
6504
6496
  var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
6505
6497
 
@@ -7085,85 +7077,6 @@ function addProjectOptions(command) {
7085
7077
  return command.addOption(cwdOption()).addOption(manifestOption()).addOption(colorOption());
7086
7078
  }
7087
7079
 
7088
- // ../compiler/src/project/env-file.ts
7089
- var ENTRY = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;
7090
- var SENSITIVE = /(password|secret|token|key|credential|dsn|private)/i;
7091
- var EMPTY_ENV_FILE = { entries: [], errors: [] };
7092
- function unquote(raw) {
7093
- const quote2 = raw.slice(0, 1);
7094
- if (quote2 !== '"' && quote2 !== "'") {
7095
- return null;
7096
- }
7097
- const closing = raw.lastIndexOf(quote2);
7098
- return closing > 0 ? raw.slice(1, closing) : null;
7099
- }
7100
- function stripComment(raw) {
7101
- return raw.replace(/\s+#.*$/, "").trim();
7102
- }
7103
- function classify(raw) {
7104
- const quoted = unquote(raw);
7105
- if (quoted !== null) {
7106
- return { value: quoted, kind: "string" };
7107
- }
7108
- const value = stripComment(raw);
7109
- if (value === "true" || value === "false") {
7110
- return { value, kind: "boolean" };
7111
- }
7112
- return { value, kind: value.length > 0 && Number.isFinite(Number(value)) ? "number" : "string" };
7113
- }
7114
- function parseEnvFile(source) {
7115
- const entries2 = [];
7116
- const errors = [];
7117
- source.split(/\r?\n/).forEach((raw, index) => {
7118
- const trimmed = raw.trim();
7119
- const line2 = index + 1;
7120
- if (trimmed.length === 0 || trimmed.startsWith("#")) {
7121
- return;
7122
- }
7123
- const match = ENTRY.exec(trimmed);
7124
- if (match === null || match[1] === void 0 || match[2] === void 0) {
7125
- errors.push({ line: line2, message: `Malformed entry on line ${line2}. Expected "KEY=value".` });
7126
- return;
7127
- }
7128
- const { value, kind } = classify(match[2]);
7129
- entries2.push({ key: match[1], value, kind, line: line2 });
7130
- });
7131
- return { entries: entries2, errors };
7132
- }
7133
- function isSensitiveKey(key) {
7134
- return SENSITIVE.test(key);
7135
- }
7136
- function mergeEnvFiles(base, overrides) {
7137
- const merged = new Map(base.entries.map((entry) => [entry.key, entry]));
7138
- for (const entry of overrides.entries) {
7139
- const declared = merged.get(entry.key);
7140
- if (declared !== void 0) {
7141
- merged.set(entry.key, { ...declared, value: entry.value });
7142
- }
7143
- }
7144
- return { entries: [...merged.values()], errors: [...base.errors, ...overrides.errors] };
7145
- }
7146
-
7147
- // src/build/env-template.ts
7148
- var HEADER = [
7149
- "# Deployment values for this resource.",
7150
- '# Generated once by "luam build" and owned by the server administrator.',
7151
- "# The compiler never overwrites this file, and it is never sent to clients.",
7152
- ""
7153
- ];
7154
- function quote(entry) {
7155
- if (entry.kind !== "string" || /^[A-Za-z0-9._:/@-]*$/.test(entry.value)) {
7156
- return entry.value;
7157
- }
7158
- return `"${entry.value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7159
- }
7160
- function line(entry) {
7161
- return `${entry.key}=${isSensitiveKey(entry.key) ? "" : quote(entry)}`;
7162
- }
7163
- function renderEnvironmentTemplate(file) {
7164
- return [...HEADER, ...file.entries.map(line), ""].join("\n");
7165
- }
7166
-
7167
7080
  // src/build/helper-files.ts
7168
7081
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
7169
7082
  import { fileURLToPath } from "node:url";
@@ -7549,8 +7462,8 @@ var ENVIRONMENT_ORDER = { shared: 0, server: 1, client: 2 };
7549
7462
  function outputPath(sourcePath) {
7550
7463
  return normalizePath(sourcePath).replace(/^\.\//, "").replace(/\.luam$/, ".lua");
7551
7464
  }
7552
- function libraryPath(environment, file) {
7553
- return `${LIBRARY_DIRECTORY}/${environment}/${file}`;
7465
+ function libraryPath(file) {
7466
+ return `${LIBRARY_DIRECTORY}/${file}`;
7554
7467
  }
7555
7468
  function mergeEnvironment(current, environment) {
7556
7469
  if (current === void 0) {
@@ -7573,7 +7486,7 @@ function collectHelpers(modules, manual) {
7573
7486
  }
7574
7487
  return [...environments.entries()].map(([helper, environment]) => {
7575
7488
  const file = RUNTIME_HELPERS[helper].file;
7576
- return { helper, file, path: libraryPath(environment, file), environment };
7489
+ return { helper, file, path: libraryPath(file), environment };
7577
7490
  }).sort((left, right) => helperDepth(left.helper) - helperDepth(right.helper) || left.path.localeCompare(right.path));
7578
7491
  }
7579
7492
  function collectDevelopmentLogHelpers(options) {
@@ -7588,7 +7501,7 @@ function collectDevelopmentLogHelpers(options) {
7588
7501
  return Object.values(DEVELOPMENT_RUNTIME_HELPERS).map((helper) => ({
7589
7502
  helper: helper.name,
7590
7503
  file: helper.file,
7591
- path: libraryPath(helper.environment, helper.file),
7504
+ path: libraryPath(helper.file),
7592
7505
  environment: helper.environment,
7593
7506
  replacements
7594
7507
  }));
@@ -7676,14 +7589,102 @@ function findDuplicateOutputs(scripts, assets) {
7676
7589
  return diagnostics;
7677
7590
  }
7678
7591
 
7592
+ // ../compiler/src/project/env-file.ts
7593
+ var ENTRY = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;
7594
+ var SENSITIVE = /(password|secret|token|key|credential|dsn|private)/i;
7595
+ var EMPTY_ENV_FILE = { entries: [], errors: [] };
7596
+ function unquote(raw) {
7597
+ const quote2 = raw.slice(0, 1);
7598
+ if (quote2 !== '"' && quote2 !== "'") {
7599
+ return null;
7600
+ }
7601
+ const closing = raw.lastIndexOf(quote2);
7602
+ return closing > 0 ? raw.slice(1, closing) : null;
7603
+ }
7604
+ function stripComment(raw) {
7605
+ return raw.replace(/\s+#.*$/, "").trim();
7606
+ }
7607
+ function classify(raw) {
7608
+ const quoted = unquote(raw);
7609
+ if (quoted !== null) {
7610
+ return { value: quoted, kind: "string" };
7611
+ }
7612
+ const value = stripComment(raw);
7613
+ if (value === "true" || value === "false") {
7614
+ return { value, kind: "boolean" };
7615
+ }
7616
+ return { value, kind: value.length > 0 && Number.isFinite(Number(value)) ? "number" : "string" };
7617
+ }
7618
+ function parseEnvFile(source) {
7619
+ const entries2 = [];
7620
+ const errors = [];
7621
+ source.split(/\r?\n/).forEach((raw, index) => {
7622
+ const trimmed = raw.trim();
7623
+ const line2 = index + 1;
7624
+ if (trimmed.length === 0 || trimmed.startsWith("#")) {
7625
+ return;
7626
+ }
7627
+ const match = ENTRY.exec(trimmed);
7628
+ if (match === null || match[1] === void 0 || match[2] === void 0) {
7629
+ errors.push({ line: line2, message: `Malformed entry on line ${line2}. Expected "KEY=value".` });
7630
+ return;
7631
+ }
7632
+ const { value, kind } = classify(match[2]);
7633
+ entries2.push({ key: match[1], value, kind, line: line2 });
7634
+ });
7635
+ return { entries: entries2, errors };
7636
+ }
7637
+ function isSensitiveKey(key) {
7638
+ return SENSITIVE.test(key);
7639
+ }
7640
+ function mergeEnvFiles(base, overrides) {
7641
+ const merged = new Map(base.entries.map((entry) => [entry.key, entry]));
7642
+ for (const entry of overrides.entries) {
7643
+ const declared = merged.get(entry.key);
7644
+ if (declared !== void 0) {
7645
+ merged.set(entry.key, { ...declared, value: entry.value });
7646
+ }
7647
+ }
7648
+ return { entries: [...merged.values()], errors: [...base.errors, ...overrides.errors] };
7649
+ }
7650
+
7651
+ // ../compiler/src/project/env-template.ts
7652
+ var HEADER = [
7653
+ "# Deployment values for this resource.",
7654
+ '# Generated once by "luam build" and owned by the server administrator.',
7655
+ "# The compiler never overwrites this file, and it is never sent to clients.",
7656
+ "#",
7657
+ "# Edit a value and restart the resource. A key left out falls back to nothing,",
7658
+ "# so keep every key the project declares.",
7659
+ ""
7660
+ ];
7661
+ function quote(entry) {
7662
+ if (entry.kind !== "string" || /^[A-Za-z0-9._:/@-]*$/.test(entry.value)) {
7663
+ return entry.value;
7664
+ }
7665
+ return `"${entry.value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7666
+ }
7667
+ function line(entry) {
7668
+ return `${entry.key}=${isSensitiveKey(entry.key) ? "" : quote(entry)}`;
7669
+ }
7670
+ function renderEnvironmentTemplate(file) {
7671
+ return [...HEADER, ...file.entries.map(line), ""].join("\n");
7672
+ }
7673
+
7679
7674
  // ../compiler/src/project/resource.ts
7680
7675
  var ENVIRONMENT_FILE = ".env";
7676
+ var ENVIRONMENT_FILE_PLACEHOLDER = "__LUAM_ENV_FILE__";
7681
7677
  function configurationScript(configuration) {
7682
7678
  if (configuration === null || configuration === void 0) {
7683
7679
  return null;
7684
7680
  }
7685
7681
  return { path: configuration.path, source: configuration.source, environment: "shared", content: configuration.content, lines: [] };
7686
7682
  }
7683
+ function withEnvironmentFile(helpers, file) {
7684
+ return helpers.map(
7685
+ (helper) => helper.helper === "env" ? { ...helper, replacements: { [ENVIRONMENT_FILE_PLACEHOLDER]: file ?? ENVIRONMENT_FILE } } : helper
7686
+ );
7687
+ }
7687
7688
  function helperEntry(helper) {
7688
7689
  return { src: helper.path, environment: helper.environment, group: "library" };
7689
7690
  }
@@ -7759,18 +7760,16 @@ function assembleResource(project, options, onStep) {
7759
7760
  if (project.hasErrors) {
7760
7761
  return { build: null, diagnostics: project.diagnostics };
7761
7762
  }
7762
- const helpers = [...collectHelpers(project.modules, options.helpers ?? []), ...collectDevelopmentLogHelpers(options.developmentLogs)];
7763
+ const collected = [...collectHelpers(project.modules, options.helpers ?? []), ...collectDevelopmentLogHelpers(options.developmentLogs)];
7764
+ const helpers = withEnvironmentFile(collected, options.environmentFile);
7763
7765
  const scripts = collectScripts(project.modules);
7764
7766
  const configuration = configurationScript(options.configuration);
7767
+ const deployment = configuration === null ? [] : [configuration];
7765
7768
  const sorted = [...options.assets ?? []].sort((left, right) => left.path.localeCompare(right.path));
7766
7769
  const order = resolveLoadOrder(options.loadOrder ?? [], scripts, sorted);
7767
7770
  const layout = options.layout ?? "tree";
7768
7771
  const bundles = layout === "bundle" ? collectBundles(helpers, scripts, order.scripts) : [];
7769
- const outputs = configuration === null ? scripts : [...scripts, configuration];
7770
- const duplicates = layout === "tree" ? findDuplicateOutputs(outputs, sorted) : [
7771
- ...findDuplicateOutputs(scripts, []),
7772
- ...findDuplicateOutputs(configuration === null ? [] : [configuration], sorted)
7773
- ];
7772
+ const duplicates = layout === "tree" ? findDuplicateOutputs([...scripts, ...deployment], sorted) : [...findDuplicateOutputs(scripts, []), ...findDuplicateOutputs(deployment, sorted)];
7774
7773
  const collisions = layout === "bundle" ? bundleDiagnostics(project, bundles, scripts, sorted) : [];
7775
7774
  const diagnostics = sortFileDiagnostics([...project.diagnostics, ...duplicates, ...collisions, ...order.diagnostics]);
7776
7775
  if (duplicates.length > 0 || collisions.length > 0 || order.diagnostics.length > 0) {
@@ -8026,8 +8025,6 @@ function fn(parameters, returnType, minimumArguments2, isVariadic = false) {
8026
8025
 
8027
8026
  // ../compiler/src/checker/project-declarations.ts
8028
8027
  var EMPTY_PROJECT_DECLARATIONS = { globals: [] };
8029
- var PROCESS_GLOBAL = "process";
8030
- var PROCESS_ENV = "process.env";
8031
8028
  var ENV_GLOBAL = "env";
8032
8029
  var VALUE_TYPES = { boolean: BOOLEAN, number: NUMBER, string: STRING };
8033
8030
  function envMembers(entries2) {
@@ -8037,11 +8034,6 @@ function envMembers(entries2) {
8037
8034
  }
8038
8035
  return [...members.values()].sort((left, right) => left.name.localeCompare(right.name));
8039
8036
  }
8040
- function environmentDeclaration(entries2, origin) {
8041
- const env = record(PROCESS_ENV, envMembers(entries2), origin);
8042
- const process2 = record(PROCESS_GLOBAL, [{ name: ENV_GLOBAL, type: env }], origin);
8043
- return { name: PROCESS_GLOBAL, environment: "server", source: "project", type: process2 };
8044
- }
8045
8037
  function envDeclaration(entries2, origin) {
8046
8038
  const env = record(ENV_GLOBAL, envMembers(entries2), origin);
8047
8039
  return { name: ENV_GLOBAL, environment: "server", source: "project", type: env };
@@ -8050,7 +8042,7 @@ function projectDeclarations(entries2, origin) {
8050
8042
  if (entries2 === null) {
8051
8043
  return EMPTY_PROJECT_DECLARATIONS;
8052
8044
  }
8053
- return { globals: [environmentDeclaration(entries2, origin), envDeclaration(entries2, origin)] };
8045
+ return { globals: [envDeclaration(entries2, origin)] };
8054
8046
  }
8055
8047
 
8056
8048
  // ../compiler/src/checker/ambient.ts
@@ -8313,16 +8305,7 @@ var ASYNC = record("Async", [
8313
8305
  { name: "getInterval", type: fn([], NUMBER, 0) },
8314
8306
  { name: "setInterval", type: fn([NUMBER], BOOLEAN, 1) }
8315
8307
  ]);
8316
- var DOTENV = record("Dotenv", [
8317
- { name: "path", type: STRING },
8318
- { name: "get", type: fn([STRING, ANY], ANY, 1) },
8319
- { name: "has", type: fn([STRING], BOOLEAN, 1) },
8320
- { name: "all", type: fn([], TABLE, 0) },
8321
- { name: "apply", type: fn([], TABLE, 0) }
8322
- ]);
8323
- var LUAM_RUNTIME_SERVER_GLOBALS = {
8324
- Dotenv: record("DotenvLibrary", [{ name: "new", type: fn([STRING], DOTENV, 0) }])
8325
- };
8308
+ var LUAM_RUNTIME_SERVER_GLOBALS = {};
8326
8309
  var LUAM_RUNTIME_GLOBALS = {
8327
8310
  bind: fn([ANY, ANY], ANY, 2),
8328
8311
  getClass: fn([STRING], optionalOf(TABLE), 1),
@@ -15367,6 +15350,7 @@ function resourceOptions(config, inputs, minMtaVersion, developmentLogs, layout)
15367
15350
  helpers: helperList(config, inputs),
15368
15351
  assets: inputs.assets,
15369
15352
  configuration: inputs.configuration,
15353
+ environmentFile: config.environment.file,
15370
15354
  loadOrder: config.loadOrder,
15371
15355
  minMtaVersion,
15372
15356
  developmentLogs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thigasdevelopment/luam",
3
- "version": "0.11.1",
3
+ "version": "0.13.0",
4
4
  "description": "The Luam compiler for Multi Theft Auto resources.",
5
5
  "keywords": [
6
6
  "mta",
package/lua/dotenv.lua DELETED
@@ -1,160 +0,0 @@
1
- local DEFAULT_FILE = '.env'
2
-
3
- local KEYWORDS = {
4
- ['true'] = true,
5
- ['false'] = false,
6
- }
7
-
8
- local ESCAPES = {
9
- ['n'] = '\n',
10
- ['r'] = '\r',
11
- ['t'] = '\t',
12
- ['"'] = '"',
13
- ["'"] = "'",
14
- ['\\'] = '\\',
15
- }
16
-
17
- local function trim(value)
18
- return value:match('^%s*(.-)%s*$') or ''
19
- end
20
-
21
- local function unescape(character)
22
- return ESCAPES[character] or ('\\' .. character)
23
- end
24
-
25
- local function cast(raw)
26
- local quote = raw:sub(1, 1)
27
-
28
- if quote == '"' or quote == "'" then
29
- local quoted = raw:match('^' .. quote .. '(.*)' .. quote)
30
-
31
- if quoted then
32
- return (quoted:gsub('\\(.)', unescape))
33
- end
34
- end
35
-
36
- local value = trim((raw:gsub('%s+#.*$', '')))
37
- local keyword = KEYWORDS[value]
38
-
39
- if keyword ~= nil then
40
- return keyword
41
- end
42
-
43
- return tonumber(value) or value
44
- end
45
-
46
- local function read(path)
47
- local file = fileOpen(path, true)
48
-
49
- if not file then
50
- return nil
51
- end
52
-
53
- local content = fileRead(file, fileGetSize(file))
54
-
55
- fileClose(file)
56
-
57
- return content
58
- end
59
-
60
- local function parse(path, content)
61
- local values = {}
62
- local number = 0
63
-
64
- for line in (content .. '\n'):gmatch('(.-)\r?\n') do
65
- number = number + 1
66
-
67
- local trimmed = trim(line)
68
-
69
- if trimmed ~= '' and trimmed:sub(1, 1) ~= '#' then
70
- local key, raw = trimmed:match('^([%a_][%w_]*)%s*=%s*(.*)$')
71
-
72
- if not key then
73
- error('Malformed entry in "' .. path .. '" on line ' .. number .. '. Expected "KEY=value".')
74
- end
75
-
76
- values[key] = cast(raw)
77
- end
78
- end
79
-
80
- return values
81
- end
82
-
83
- local function seal(path, values)
84
- return setmetatable({}, {
85
- __index = function(_, key)
86
- local value = values[key]
87
-
88
- if value == nil then
89
- error('"' .. tostring(key) .. '" is not declared in "' .. path .. '".', 2)
90
- end
91
-
92
- return value
93
- end,
94
-
95
- __newindex = function(_, key)
96
- error('The environment is read-only and "' .. tostring(key) .. '" cannot be assigned.', 2)
97
- end,
98
-
99
- __metatable = false,
100
- })
101
- end
102
-
103
- if localPlayer ~= nil then
104
- return
105
- end
106
-
107
- Dotenv = {}
108
- Dotenv.__index = Dotenv
109
-
110
- function Dotenv.new(path)
111
- path = path or DEFAULT_FILE
112
-
113
- local content = read(path)
114
-
115
- if not content then
116
- error('Failed to read the environment file "' .. tostring(path) .. '".', 2)
117
- end
118
-
119
- local self = setmetatable({}, Dotenv)
120
-
121
- self.path = path
122
- self.values = parse(path, content)
123
-
124
- return self
125
- end
126
-
127
- function Dotenv:get(key, default)
128
- local value = self.values[key]
129
-
130
- if value == nil then
131
- return default
132
- end
133
-
134
- return value
135
- end
136
-
137
- function Dotenv:has(key)
138
- return self.values[key] ~= nil
139
- end
140
-
141
- function Dotenv:all()
142
- local copy = {}
143
-
144
- for key, value in pairs(self.values) do
145
- copy[key] = value
146
- end
147
-
148
- return copy
149
- end
150
-
151
- function Dotenv:apply()
152
- if type(process) ~= 'table' then
153
- process = {}
154
- end
155
-
156
- process.env = seal(self.path, self.values)
157
- env = process.env
158
-
159
- return process.env
160
- end