handoff-app 2.0.0-7 → 2.0.0-8
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.
- package/README.md +111 -11
- package/UPGRADE.md +20 -0
- package/dist/app-builder/build.js +10 -2
- package/dist/app-builder/client-config.js +3 -1
- package/dist/app-builder/watchers.js +17 -7
- package/dist/cache/build-cache.js +5 -1
- package/dist/cli/auth/device.d.ts +6 -1
- package/dist/cli/auth/device.js +5 -2
- package/dist/cli/auth/store.d.ts +15 -6
- package/dist/cli/auth/store.js +72 -19
- package/dist/commands/login/index.d.ts +5 -0
- package/dist/commands/login/index.js +18 -6
- package/dist/commands/logout/index.d.ts +5 -0
- package/dist/commands/logout/index.js +54 -15
- package/dist/commands/types.d.ts +2 -0
- package/dist/commands/utils.d.ts +21 -7
- package/dist/commands/utils.js +11 -10
- package/dist/config/catalog-include.d.ts +2 -2
- package/dist/config/defaults.d.ts +3 -3
- package/dist/config/defaults.js +54 -48
- package/dist/config/env.d.ts +9 -0
- package/dist/config/env.js +43 -0
- package/dist/config/errors.d.ts +4 -0
- package/dist/config/errors.js +11 -0
- package/dist/config/from-env.d.ts +24 -0
- package/dist/config/from-env.js +7 -0
- package/dist/config/helpers.d.ts +2 -0
- package/dist/config/helpers.js +3 -1
- package/dist/config/index.d.ts +2 -1
- package/dist/config/index.js +6 -1
- package/dist/config/loader.d.ts +29 -11
- package/dist/config/loader.js +119 -46
- package/dist/config/resolve-env.d.ts +5 -0
- package/dist/config/resolve-env.js +102 -0
- package/dist/config/runtime.d.ts +3 -3
- package/dist/config/validator.d.ts +2 -2
- package/dist/config/validator.js +2 -4
- package/dist/index.d.ts +33 -4
- package/dist/index.js +60 -16
- package/dist/pipeline/index.d.ts +1 -1
- package/dist/pipeline/index.js +1 -1
- package/dist/registry/asset-storage/adapters/vercel-blob.js +1 -1
- package/dist/registry/asset-storage/resolve.d.ts +2 -2
- package/dist/registry/asset-storage/resolve.js +4 -1
- package/dist/registry/checkout/index.js +4 -4
- package/dist/registry/connection.d.ts +28 -24
- package/dist/registry/connection.js +53 -67
- package/dist/registry/db/driver.d.ts +4 -11
- package/dist/registry/db/driver.js +4 -16
- package/dist/registry/db/index.d.ts +1 -1
- package/dist/registry/db/index.js +1 -2
- package/dist/registry/publish/index.js +4 -4
- package/dist/store/filesystem.d.ts +2 -2
- package/dist/types/config.d.ts +48 -29
- package/docs/api.md +31 -0
- package/docs/cli.md +2 -2
- package/package.json +1 -1
- package/src/app/pages/account/tokens.tsx +3 -1
- package/src/app-builder/build.ts +10 -2
- package/src/app-builder/client-config.ts +5 -3
- package/src/app-builder/watchers.ts +18 -8
- package/src/cache/build-cache.ts +5 -1
- package/src/cli/auth/device.ts +8 -3
- package/src/cli/auth/store.ts +75 -18
- package/src/commands/login/index.ts +20 -6
- package/src/commands/logout/index.ts +74 -20
- package/src/commands/types.ts +2 -0
- package/src/commands/utils.ts +14 -5
- package/src/config/README.md +61 -1
- package/src/config/catalog-include.ts +2 -2
- package/src/config/defaults.ts +24 -14
- package/src/config/env.ts +41 -0
- package/src/config/errors.ts +7 -0
- package/src/config/from-env.ts +26 -0
- package/src/config/helpers.ts +4 -2
- package/src/config/index.ts +4 -1
- package/src/config/loader.ts +156 -50
- package/src/config/resolve-env.ts +94 -0
- package/src/config/runtime.ts +3 -3
- package/src/config/validator.ts +4 -6
- package/src/index.d.ts +2 -2
- package/src/index.ts +85 -8
- package/src/pipeline/index.ts +1 -1
- package/src/registry/asset-storage/adapters/vercel-blob.ts +1 -1
- package/src/registry/asset-storage/resolve.ts +6 -3
- package/src/registry/checkout/index.ts +5 -5
- package/src/registry/connection.ts +72 -71
- package/src/registry/db/driver.ts +6 -17
- package/src/registry/db/index.ts +0 -1
- package/src/registry/publish/index.ts +5 -5
- package/src/store/filesystem.ts +2 -2
- package/src/types/config.ts +45 -29
- package/templates/default/env.tpl +10 -0
- package/templates/default/gitignore.tpl +7 -0
- package/templates/default/handoff.config.js.tpl +21 -172
- package/templates/default/handoff.config.ts.tpl +21 -156
- package/templates/default/handoff.config.with-examples.js.tpl +20 -171
- package/templates/default/handoff.config.with-examples.ts.tpl +20 -155
package/dist/config/loader.js
CHANGED
|
@@ -3,31 +3,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.initConfig = exports.initConfigWithMetadata = exports.HandoffConfigError = void 0;
|
|
6
|
+
exports.initConfig = exports.initConfigWithMetadata = exports.resolveProfileSelection = exports.HandoffConfigError = exports.CONFIG_FILE_PREFERENCE = void 0;
|
|
7
7
|
const esbuild_1 = __importDefault(require("esbuild"));
|
|
8
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const
|
|
9
|
+
const mergeWith_1 = __importDefault(require("lodash/mergeWith"));
|
|
10
10
|
const module_1 = require("module");
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const logger_1 = require("../utils/logger");
|
|
13
13
|
const path_2 = require("../utils/path");
|
|
14
14
|
const defaults_1 = require("./defaults");
|
|
15
|
-
const
|
|
15
|
+
const env_1 = require("./env");
|
|
16
|
+
const helpers_1 = require("./helpers");
|
|
17
|
+
const errors_1 = require("./errors");
|
|
18
|
+
const from_env_1 = require("./from-env");
|
|
19
|
+
const resolve_env_1 = require("./resolve-env");
|
|
20
|
+
exports.CONFIG_FILE_PREFERENCE = [
|
|
16
21
|
'handoff.config.ts',
|
|
17
22
|
'handoff.config.js',
|
|
18
23
|
'handoff.config.cjs',
|
|
19
24
|
'handoff.config.json',
|
|
20
25
|
];
|
|
21
26
|
/** Extensions the loader knows how to evaluate, derived from the discoverable file names. */
|
|
22
|
-
const SUPPORTED_CONFIG_EXTENSIONS = Array.from(new Set(CONFIG_FILE_PREFERENCE.map((fileName) => path_1.default.extname(fileName))));
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.name = 'HandoffConfigError';
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.HandoffConfigError = HandoffConfigError;
|
|
27
|
+
const SUPPORTED_CONFIG_EXTENSIONS = Array.from(new Set(exports.CONFIG_FILE_PREFERENCE.map((fileName) => path_1.default.extname(fileName))));
|
|
28
|
+
/** A profile name becomes part of a file name, so it stays lowercase letters, numbers, and hyphens. */
|
|
29
|
+
const PROFILE_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
30
|
+
var errors_2 = require("./errors");
|
|
31
|
+
Object.defineProperty(exports, "HandoffConfigError", { enumerable: true, get: function () { return errors_2.HandoffConfigError; } });
|
|
31
32
|
const evaluateTypeScriptConfig = (filePath, handoffModulePath) => {
|
|
32
33
|
var _a, _b;
|
|
33
34
|
const buildResult = esbuild_1.default.buildSync({
|
|
@@ -75,6 +76,28 @@ const loadConfigFile = (configPath) => {
|
|
|
75
76
|
const importedConfig = require(configPath);
|
|
76
77
|
return (importedConfig.default || importedConfig);
|
|
77
78
|
};
|
|
79
|
+
/**
|
|
80
|
+
* Normalize here and not only in `defineConfig`: a `.json` config, or a profile that skips the
|
|
81
|
+
* helper, would otherwise keep its camelCase keys. The rest of the codebase reads the runtime keys,
|
|
82
|
+
* so a later layer could not override an earlier one.
|
|
83
|
+
*/
|
|
84
|
+
const loadConfigLayer = (configPath) => (0, helpers_1.normalizeConfig)(loadConfigFile(configPath));
|
|
85
|
+
const pickExisting = (candidates) => {
|
|
86
|
+
const existing = candidates.filter((filePath) => fs_extra_1.default.existsSync(filePath));
|
|
87
|
+
if (!existing.length) {
|
|
88
|
+
return { selected: undefined, ignored: [] };
|
|
89
|
+
}
|
|
90
|
+
const [selected, ...ignored] = existing;
|
|
91
|
+
return { selected, ignored };
|
|
92
|
+
};
|
|
93
|
+
const warnIgnored = (selected, ignored) => {
|
|
94
|
+
if (!selected || ignored.length === 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
logger_1.Logger.warn(`Multiple config files found. Using "${path_1.default.basename(selected)}" and ignoring: ${ignored
|
|
98
|
+
.map((filePath) => `"${path_1.default.basename(filePath)}"`)
|
|
99
|
+
.join(', ')}.`);
|
|
100
|
+
};
|
|
78
101
|
/**
|
|
79
102
|
* Picks the config file to load. An explicitly requested file replaces discovery - it is resolved
|
|
80
103
|
* from `workingPath` and must exist in a format the loader can evaluate. Otherwise every known
|
|
@@ -84,70 +107,120 @@ const resolveConfigFilePath = (workingPath, requestedPath) => {
|
|
|
84
107
|
if (requestedPath) {
|
|
85
108
|
const selected = path_1.default.resolve(workingPath, requestedPath);
|
|
86
109
|
if (!fs_extra_1.default.existsSync(selected)) {
|
|
87
|
-
throw new HandoffConfigError(`Config file not found: "${requestedPath}" (resolved to ${selected})`);
|
|
110
|
+
throw new errors_1.HandoffConfigError(`Config file not found: "${requestedPath}" (resolved to ${selected})`);
|
|
88
111
|
}
|
|
89
112
|
if (!SUPPORTED_CONFIG_EXTENSIONS.includes(path_1.default.extname(selected))) {
|
|
90
|
-
throw new HandoffConfigError(`Unsupported config file "${path_1.default.basename(selected)}". Supported extensions: ${SUPPORTED_CONFIG_EXTENSIONS.join(', ')}`);
|
|
113
|
+
throw new errors_1.HandoffConfigError(`Unsupported config file "${path_1.default.basename(selected)}". Supported extensions: ${SUPPORTED_CONFIG_EXTENSIONS.join(', ')}`);
|
|
91
114
|
}
|
|
92
115
|
return { selected, ignored: [] };
|
|
93
116
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
return pickExisting(exports.CONFIG_FILE_PREFERENCE.map((fileName) => path_1.default.resolve(workingPath, fileName)));
|
|
118
|
+
};
|
|
119
|
+
/** `--profile` wins over `HANDOFF_PROFILE`, and an empty value counts as unset. */
|
|
120
|
+
const resolveProfileSelection = (requestedProfile) => {
|
|
121
|
+
var _a;
|
|
122
|
+
const fromOption = requestedProfile === null || requestedProfile === void 0 ? void 0 : requestedProfile.trim();
|
|
123
|
+
if (fromOption) {
|
|
124
|
+
return { name: fromOption, source: '--profile' };
|
|
99
125
|
}
|
|
100
|
-
const
|
|
101
|
-
|
|
126
|
+
const fromEnvironment = (_a = process.env.HANDOFF_PROFILE) === null || _a === void 0 ? void 0 : _a.trim();
|
|
127
|
+
if (fromEnvironment) {
|
|
128
|
+
return { name: fromEnvironment, source: 'HANDOFF_PROFILE' };
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
};
|
|
132
|
+
exports.resolveProfileSelection = resolveProfileSelection;
|
|
133
|
+
/**
|
|
134
|
+
* Picks the profile file for a selected profile. It sits beside the base config: the base file name
|
|
135
|
+
* without its extension, then the profile name, then any config extension. So `handoff.config.ts`
|
|
136
|
+
* pairs with `handoff.config.local.*`, and a config named through `-c` keeps its own name. A selected
|
|
137
|
+
* profile has to resolve - silently falling back to the base config would deploy the wrong settings.
|
|
138
|
+
* A name listed in `knownProfiles` resolves without a file, because it names something else that
|
|
139
|
+
* exists, such as a saved registry login.
|
|
140
|
+
*/
|
|
141
|
+
const resolveProfileFilePath = (workingPath, baseConfigPath, selection, context) => {
|
|
142
|
+
var _a;
|
|
143
|
+
if (!PROFILE_NAME_PATTERN.test(selection.name)) {
|
|
144
|
+
throw new errors_1.HandoffConfigError(`Invalid config profile "${selection.name}" (from ${selection.source}). ` +
|
|
145
|
+
`A profile name can contain lowercase letters, numbers, and hyphens.`);
|
|
146
|
+
}
|
|
147
|
+
const baseName = baseConfigPath
|
|
148
|
+
? path_1.default.join(path_1.default.dirname(baseConfigPath), path_1.default.basename(baseConfigPath, path_1.default.extname(baseConfigPath)))
|
|
149
|
+
: path_1.default.resolve(workingPath, 'handoff.config');
|
|
150
|
+
const candidates = SUPPORTED_CONFIG_EXTENSIONS.map((extension) => `${baseName}.${selection.name}${extension}`);
|
|
151
|
+
const { selected, ignored } = pickExisting(candidates);
|
|
152
|
+
if (!selected) {
|
|
153
|
+
if ((_a = context.knownProfiles) === null || _a === void 0 ? void 0 : _a.includes(selection.name)) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
throw new errors_1.HandoffConfigError(`Config profile "${selection.name}" (from ${selection.source}) not found. ` +
|
|
157
|
+
`Create one of: ${candidates.map((candidate) => path_1.default.basename(candidate)).join(', ')} in ${path_1.default.dirname(candidates[0])}.` +
|
|
158
|
+
(context.profileNotFoundHint ? ` ${context.profileNotFoundHint}` : ''));
|
|
159
|
+
}
|
|
160
|
+
warnIgnored(selected, ignored);
|
|
161
|
+
return selected;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Arrays and environment references are whole values: a later layer replaces them, including
|
|
165
|
+
* any reference default. Everything else keeps lodash semantics: plain
|
|
166
|
+
* objects merge recursively, scalars, `null` and functions replace, and `undefined` is skipped.
|
|
167
|
+
*/
|
|
168
|
+
const replaceValues = (destination, source) => {
|
|
169
|
+
if (source === undefined)
|
|
170
|
+
return undefined;
|
|
171
|
+
return Array.isArray(source) || (0, from_env_1.isEnvReference)(source) || (0, from_env_1.isEnvReference)(destination) ? source : undefined;
|
|
102
172
|
};
|
|
103
173
|
/**
|
|
104
174
|
* Loads the handoff configuration for the given working directory and returns metadata.
|
|
105
175
|
*/
|
|
106
176
|
const initConfigWithMetadata = (configOverride, context) => {
|
|
107
177
|
var _a, _b, _c;
|
|
108
|
-
|
|
109
|
-
const { selected: configPath, ignored } = resolveConfigFilePath(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
178
|
+
const workingPath = (_a = context === null || context === void 0 ? void 0 : context.workingPath) !== null && _a !== void 0 ? _a : (0, path_2.resolveWorkingPath)();
|
|
179
|
+
const { selected: configPath, ignored } = resolveConfigFilePath(workingPath, context === null || context === void 0 ? void 0 : context.configPath);
|
|
180
|
+
warnIgnored(configPath, ignored);
|
|
181
|
+
const profileSelection = (0, exports.resolveProfileSelection)(context === null || context === void 0 ? void 0 : context.profile);
|
|
182
|
+
const profileConfigPath = profileSelection ? resolveProfileFilePath(workingPath, configPath, profileSelection, context !== null && context !== void 0 ? context : {}) : undefined;
|
|
183
|
+
// Profile environment values must be present before the merged references resolve.
|
|
184
|
+
(0, env_1.loadProfileEnv)(profileSelection === null || profileSelection === void 0 ? void 0 : profileSelection.name);
|
|
185
|
+
const layers = [(0, defaults_1.defaultConfig)()];
|
|
115
186
|
if (configPath) {
|
|
116
|
-
|
|
187
|
+
layers.push(loadConfigLayer(configPath));
|
|
188
|
+
}
|
|
189
|
+
if (profileConfigPath) {
|
|
190
|
+
layers.push(loadConfigLayer(profileConfigPath));
|
|
117
191
|
}
|
|
118
|
-
// Apply overrides if provided
|
|
119
192
|
if (configOverride) {
|
|
120
|
-
|
|
121
|
-
if (value !== undefined) {
|
|
122
|
-
config[key] = value;
|
|
123
|
-
}
|
|
124
|
-
});
|
|
193
|
+
layers.push((0, helpers_1.normalizeConfig)(configOverride));
|
|
125
194
|
}
|
|
195
|
+
const profileLabel = profileSelection
|
|
196
|
+
? `"${profileSelection.name}" (from ${profileSelection.source})${profileConfigPath ? '' : ' - no config file, the base config is used unchanged'}`
|
|
197
|
+
: 'none selected';
|
|
198
|
+
logger_1.Logger.debug(`Config profile: ${profileLabel}`);
|
|
199
|
+
logger_1.Logger.debug(`Config files loaded: ${[configPath, profileConfigPath].filter(Boolean).join(', ') || 'none, using defaults'}`);
|
|
200
|
+
const merged = (0, mergeWith_1.default)({}, ...layers, replaceValues);
|
|
201
|
+
const config = (0, resolve_env_1.resolveConfigEnv)(merged, profileSelection === null || profileSelection === void 0 ? void 0 : profileSelection.name, layers[0]);
|
|
202
|
+
// Guards run on the resolved config so a profile cannot slip a removed setting past them.
|
|
126
203
|
const entries = config.entries;
|
|
127
204
|
if (entries && ('components' in entries || 'patterns' in entries)) {
|
|
128
|
-
throw new HandoffConfigError('entries.components and entries.patterns were removed. Use catalog.include. See UPGRADE.md#catalog-items.');
|
|
205
|
+
throw new errors_1.HandoffConfigError('entries.components and entries.patterns were removed. Use catalog.include. See UPGRADE.md#catalog-items.');
|
|
129
206
|
}
|
|
130
207
|
const format = (_c = (_b = config.runtime) === null || _b === void 0 ? void 0 : _b.workspace) === null || _c === void 0 ? void 0 : _c.declarationFormat;
|
|
131
208
|
if (format !== undefined && !['ts', 'js', 'cjs'].includes(format)) {
|
|
132
|
-
throw new HandoffConfigError('Item declarations support ts, js, and cjs. Convert JSON declarations to defineCatalogItem. See UPGRADE.md#catalog-items.');
|
|
209
|
+
throw new errors_1.HandoffConfigError('Item declarations support ts, js, and cjs. Convert JSON declarations to defineCatalogItem. See UPGRADE.md#catalog-items.');
|
|
133
210
|
}
|
|
134
|
-
|
|
135
|
-
// Top-level merge stays shallow to preserve 1.x semantics, except for the `runtime`
|
|
136
|
-
// block which is deep-merged so a partial user `runtime` (e.g. only `mode`) does not
|
|
137
|
-
// wipe the defaults supplied for the rest of the block.
|
|
138
|
-
const resolvedConfig = Object.assign(Object.assign(Object.assign({}, defaults), config), { runtime: (0, merge_1.default)({}, defaults.runtime, config.runtime) });
|
|
139
|
-
return { config: resolvedConfig, configPath };
|
|
211
|
+
return { config, configPath, profile: profileSelection === null || profileSelection === void 0 ? void 0 : profileSelection.name, profileConfigPath };
|
|
140
212
|
};
|
|
141
213
|
exports.initConfigWithMetadata = initConfigWithMetadata;
|
|
142
214
|
/**
|
|
143
215
|
* Loads the handoff configuration for the given working directory.
|
|
144
216
|
*
|
|
145
217
|
* Searches for config files in order: handoff.config.ts, handoff.config.js, handoff.config.cjs, handoff.config.json,
|
|
146
|
-
* unless `context.configPath` names one explicitly.
|
|
147
|
-
*
|
|
218
|
+
* unless `context.configPath` names one explicitly. A selected profile adds a `handoff.config.<profile>.*` sidecar,
|
|
219
|
+
* which only `context.knownProfiles` makes optional.
|
|
220
|
+
* Layers resolve as defaults, base config, profile, then the given overrides, merging plain objects recursively.
|
|
148
221
|
*
|
|
149
222
|
* @param configOverride - Optional partial config to override file-loaded values.
|
|
150
|
-
* @param context - Optional working directory
|
|
223
|
+
* @param context - Optional working directory, explicit config file, and profile to load.
|
|
151
224
|
* @returns The fully resolved Config object.
|
|
152
225
|
*/
|
|
153
226
|
const initConfig = (configOverride, context) => {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Config, ResolvedConfig } from '../types/config';
|
|
2
|
+
export declare const DEFERRED_PATHS: Set<string>;
|
|
3
|
+
export declare const configEnvName: (config: ResolvedConfig | null | undefined, path: string) => string | undefined;
|
|
4
|
+
/** Resolve only the merged winner. Functions and non-plain objects retain their identity. */
|
|
5
|
+
export declare const resolveConfigEnv: (config: Config, profile?: string, defaults?: Config) => ResolvedConfig;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveConfigEnv = exports.configEnvName = exports.DEFERRED_PATHS = void 0;
|
|
7
|
+
const isPlainObject_1 = __importDefault(require("lodash/isPlainObject"));
|
|
8
|
+
const logger_1 = require("../utils/logger");
|
|
9
|
+
const from_env_1 = require("./from-env");
|
|
10
|
+
const errors_1 = require("./errors");
|
|
11
|
+
exports.DEFERRED_PATHS = new Set(['runtime.registry.databaseUrl', 'runtime.registry.assetStorage.token']);
|
|
12
|
+
const SECRET_PATHS = new Set(['dev_access_token', 'devAccessToken', 'runtime.registryConnection.accessToken']);
|
|
13
|
+
/** Path prefixes whose resolved contents are JSON-baked into the bundle, so a reference would bake its value. */
|
|
14
|
+
const BAKED_PATHS = ['runtime.registry.assetStorage.options'];
|
|
15
|
+
const isBaked = (path) => BAKED_PATHS.some((baked) => path === baked || path.startsWith(`${baked}.`));
|
|
16
|
+
const ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17
|
+
const ALIASES = {
|
|
18
|
+
HANDOFF_REGISTRY_URL: 'HANDOFF_CLOUD_URL',
|
|
19
|
+
HANDOFF_REGISTRY_ACCESS_TOKEN: 'HANDOFF_CLOUD_TOKEN',
|
|
20
|
+
};
|
|
21
|
+
const warnedAliases = new Set();
|
|
22
|
+
const referenceNames = new WeakMap();
|
|
23
|
+
const configEnvName = (config, path) => { var _a; return (_a = referenceNames.get(config)) === null || _a === void 0 ? void 0 : _a.get(path); };
|
|
24
|
+
exports.configEnvName = configEnvName;
|
|
25
|
+
const readEnv = (name) => {
|
|
26
|
+
const value = process.env[name];
|
|
27
|
+
const alias = ALIASES[name];
|
|
28
|
+
if (!alias || (value === null || value === void 0 ? void 0 : value.trim()))
|
|
29
|
+
return value;
|
|
30
|
+
const inherited = process.env[alias];
|
|
31
|
+
if (!(inherited === null || inherited === void 0 ? void 0 : inherited.trim()))
|
|
32
|
+
return value;
|
|
33
|
+
if (!warnedAliases.has(alias)) {
|
|
34
|
+
warnedAliases.add(alias);
|
|
35
|
+
logger_1.Logger.warn(`${alias} is deprecated and will be removed in a future release; set ${name} instead.`);
|
|
36
|
+
}
|
|
37
|
+
return inherited;
|
|
38
|
+
};
|
|
39
|
+
/** Resolve only the merged winner. Functions and non-plain objects retain their identity. */
|
|
40
|
+
const resolveConfigEnv = (config, profile, defaults) => {
|
|
41
|
+
const names = new Map();
|
|
42
|
+
const fail = (path, message) => {
|
|
43
|
+
throw new errors_1.HandoffConfigError(`Config "${path}" (profile "${profile !== null && profile !== void 0 ? profile : 'default'}"): ${message}`);
|
|
44
|
+
};
|
|
45
|
+
const walk = (value, path, seed) => {
|
|
46
|
+
var _a;
|
|
47
|
+
const deferred = exports.DEFERRED_PATHS.has(path);
|
|
48
|
+
const secret = SECRET_PATHS.has(path);
|
|
49
|
+
if ((secret || deferred) && value !== undefined && !(0, from_env_1.isEnvReference)(value)) {
|
|
50
|
+
fail(path, 'Expected an environment reference, such as { $env: "VARIABLE_NAME" }. Literal values are not allowed.');
|
|
51
|
+
}
|
|
52
|
+
if ((0, from_env_1.isEnvReference)(value)) {
|
|
53
|
+
// Checked before the name, so the message names the supported pattern instead of the reference shape.
|
|
54
|
+
if (isBaked(path)) {
|
|
55
|
+
fail(path, 'Environment references are not allowed here because the resolved value is baked into the build. ' +
|
|
56
|
+
"Put the variable name in options and read it through the adapter factory's `env` argument.");
|
|
57
|
+
}
|
|
58
|
+
if (typeof value.$env !== 'string' || !ENV_NAME.test(value.$env)) {
|
|
59
|
+
fail(path, 'Invalid environment variable name. Use letters, digits, and underscores, starting with a letter or underscore.');
|
|
60
|
+
}
|
|
61
|
+
const name = value.$env;
|
|
62
|
+
names.set(path, name);
|
|
63
|
+
if (Object.keys(value).some((key) => key !== '$env' && key !== 'default')) {
|
|
64
|
+
fail(path, `Environment variable "${name}" has an invalid reference shape.`);
|
|
65
|
+
}
|
|
66
|
+
if (deferred) {
|
|
67
|
+
if ('default' in value)
|
|
68
|
+
fail(path, `Environment variable "${name}" cannot have a default because it is read by the deployed app.`);
|
|
69
|
+
return { $env: name };
|
|
70
|
+
}
|
|
71
|
+
// Secret defaults can mark an optional credential, but cannot embed a credential value.
|
|
72
|
+
if (secret && value.default !== undefined && value.default !== null && value.default !== '') {
|
|
73
|
+
fail(path, `Environment variable "${name}" cannot have a literal secret default.`);
|
|
74
|
+
}
|
|
75
|
+
const raw = readEnv(name);
|
|
76
|
+
if (raw === undefined) {
|
|
77
|
+
if (Object.prototype.hasOwnProperty.call(value, 'default'))
|
|
78
|
+
return secret ? value.default : walk(value.default, path, seed);
|
|
79
|
+
fail(path, `Environment variable "${name}" is not set and has no default.`);
|
|
80
|
+
}
|
|
81
|
+
const typeHint = (_a = value.default) !== null && _a !== void 0 ? _a : ((0, from_env_1.isEnvReference)(seed) ? seed.default : seed);
|
|
82
|
+
if (typeof typeHint === 'boolean')
|
|
83
|
+
return raw === 'true';
|
|
84
|
+
if (typeof typeHint === 'number') {
|
|
85
|
+
const number = Number(raw);
|
|
86
|
+
if (!Number.isFinite(number))
|
|
87
|
+
fail(path, `Environment variable "${name}" must contain a finite number.`);
|
|
88
|
+
return number;
|
|
89
|
+
}
|
|
90
|
+
return raw;
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(value))
|
|
93
|
+
return value.map((entry, index) => walk(entry, `${path}.${index}`, seed === null || seed === void 0 ? void 0 : seed[index]));
|
|
94
|
+
if (!(0, isPlainObject_1.default)(value))
|
|
95
|
+
return value;
|
|
96
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, walk(entry, path ? `${path}.${key}` : key, seed === null || seed === void 0 ? void 0 : seed[key])]));
|
|
97
|
+
};
|
|
98
|
+
const resolved = walk(config, '', defaults);
|
|
99
|
+
referenceNames.set(resolved, names);
|
|
100
|
+
return resolved;
|
|
101
|
+
};
|
|
102
|
+
exports.resolveConfigEnv = resolveConfigEnv;
|
package/dist/config/runtime.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ResolvedConfig, ConfigFileEntry, RuntimeConfig } from '../types/config';
|
|
2
2
|
/**
|
|
3
3
|
* Handoff instance shape needed by initRuntimeConfig.
|
|
4
4
|
* Avoids importing the full Handoff class to prevent circular deps.
|
|
5
5
|
*/
|
|
6
6
|
interface HandoffContext {
|
|
7
|
-
config:
|
|
7
|
+
config: ResolvedConfig;
|
|
8
8
|
workingPath: string;
|
|
9
9
|
modulePath: string;
|
|
10
10
|
}
|
|
@@ -15,7 +15,7 @@ export declare const resolveComponentDeclaration: (componentDir: string, compone
|
|
|
15
15
|
/**
|
|
16
16
|
* Expands catalog.include into item directories and removes duplicate paths.
|
|
17
17
|
*/
|
|
18
|
-
export declare const getCatalogItemDirectories: (config:
|
|
18
|
+
export declare const getCatalogItemDirectories: (config: ResolvedConfig, workingPath: string) => string[];
|
|
19
19
|
/**
|
|
20
20
|
* Initializes the runtime configuration by resolving component entries,
|
|
21
21
|
* SCSS/JS paths, and transformer options from the handoff config.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ResolvedConfig } from '../types/config';
|
|
2
2
|
/**
|
|
3
3
|
* Validates that the configuration has the required Figma credentials.
|
|
4
4
|
*
|
|
@@ -6,4 +6,4 @@ import { Config } from '../types/config';
|
|
|
6
6
|
* @returns The validated config (same reference).
|
|
7
7
|
* @throws {Error} If required Figma credentials are missing.
|
|
8
8
|
*/
|
|
9
|
-
export declare const validateConfig: (config:
|
|
9
|
+
export declare const validateConfig: (config: ResolvedConfig) => ResolvedConfig;
|
package/dist/config/validator.js
CHANGED
|
@@ -11,13 +11,11 @@ const logger_1 = require("../utils/logger");
|
|
|
11
11
|
*/
|
|
12
12
|
const validateConfig = (config) => {
|
|
13
13
|
// TODO: Check to see if the exported folder exists before we run start
|
|
14
|
-
if (!config.figma_project_id
|
|
15
|
-
// check to see if we can get this from the env
|
|
14
|
+
if (!config.figma_project_id) {
|
|
16
15
|
logger_1.Logger.error('Figma Project ID missing. Please set HANDOFF_FIGMA_PROJECT_ID or run "handoff-app fetch".');
|
|
17
16
|
throw new Error('Cannot initialize configuration');
|
|
18
17
|
}
|
|
19
|
-
if (!config.dev_access_token
|
|
20
|
-
// check to see if we can get this from the env
|
|
18
|
+
if (!config.dev_access_token) {
|
|
21
19
|
logger_1.Logger.error('Figma Access Token missing. Please set HANDOFF_DEV_ACCESS_TOKEN or run "handoff-app fetch".');
|
|
22
20
|
throw new Error('Cannot initialize configuration');
|
|
23
21
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import '
|
|
1
|
+
import './config/env';
|
|
2
2
|
import { Types as CoreTypes, Handoff as HandoffRunner } from 'handoff-core';
|
|
3
3
|
import { type BuildPackage, type BuildTarget } from './app-builder';
|
|
4
4
|
import { type RegistryEntityKind } from './registry/content-kinds';
|
|
5
5
|
import type { TransferEntityKind } from './registry/transfer';
|
|
6
6
|
import { type HandoffStore } from './store';
|
|
7
|
-
import { Config, ConfigFileEntry, RuntimeConfig } from './types/config';
|
|
7
|
+
import { Config, ResolvedConfig, ConfigFileEntry, RuntimeConfig } from './types/config';
|
|
8
8
|
/** How a {@link Handoff} instance is set up. */
|
|
9
9
|
export interface HandoffOptions {
|
|
10
10
|
debug?: boolean;
|
|
@@ -21,6 +21,19 @@ export interface HandoffOptions {
|
|
|
21
21
|
config?: Partial<Config>;
|
|
22
22
|
/** Explicit config file (the CLI's `-c, --config`), resolved from the working path. */
|
|
23
23
|
configPath?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Config profile to merge onto the base config (the CLI's `--profile`). It overrides
|
|
26
|
+
* `HANDOFF_PROFILE`, and a selected profile has to resolve to a `handoff.config.<profile>.*` file
|
|
27
|
+
* unless {@link profileWithoutConfig} widens that.
|
|
28
|
+
*/
|
|
29
|
+
profile?: string;
|
|
30
|
+
/**
|
|
31
|
+
* What a selected profile may resolve to when it has no config file. `'saved-login'` accepts a name
|
|
32
|
+
* a saved registry login uses, so publish and checkout can address a registry that no config file
|
|
33
|
+
* describes. `'any'` accepts any valid name, for the `login` command that creates the login. Unset,
|
|
34
|
+
* a profile must name a config file, so a typo cannot silently run with the base config.
|
|
35
|
+
*/
|
|
36
|
+
profileWithoutConfig?: 'saved-login' | 'any';
|
|
24
37
|
}
|
|
25
38
|
/**
|
|
26
39
|
* A content kind to act on, optionally narrowed to specific ids. The plain form is the common case
|
|
@@ -31,7 +44,7 @@ export type ContentTarget = RegistryEntityKind | {
|
|
|
31
44
|
ids?: string[];
|
|
32
45
|
};
|
|
33
46
|
declare class Handoff {
|
|
34
|
-
config:
|
|
47
|
+
config: ResolvedConfig | null;
|
|
35
48
|
debug: boolean;
|
|
36
49
|
force: boolean;
|
|
37
50
|
dryRun: boolean;
|
|
@@ -56,10 +69,18 @@ declare class Handoff {
|
|
|
56
69
|
private _configFilePaths;
|
|
57
70
|
private _configFileIndex;
|
|
58
71
|
private _mainConfigFilePath?;
|
|
72
|
+
private _profileConfigFilePath?;
|
|
73
|
+
private _profile?;
|
|
59
74
|
private _documentationObjectCache?;
|
|
60
75
|
private _handoffRunner?;
|
|
61
76
|
constructor(options?: HandoffOptions);
|
|
62
77
|
private construct;
|
|
78
|
+
/**
|
|
79
|
+
* What a selected profile may resolve to besides a config file, and how to explain a name that
|
|
80
|
+
* resolves to nothing. A command that does not accept a login still names one it found, so the
|
|
81
|
+
* difference between the two kinds of profile is visible rather than puzzling.
|
|
82
|
+
*/
|
|
83
|
+
private profilesWithoutConfig;
|
|
63
84
|
init(configOverride?: Partial<Config>): Handoff;
|
|
64
85
|
reload(): Handoff;
|
|
65
86
|
preRunner(validate?: boolean): Handoff;
|
|
@@ -215,6 +236,12 @@ declare class Handoff {
|
|
|
215
236
|
* Gets the selected main config file path if one exists.
|
|
216
237
|
*/
|
|
217
238
|
getMainConfigFilePath(): string | undefined;
|
|
239
|
+
getProfile(): string | undefined;
|
|
240
|
+
/**
|
|
241
|
+
* True for the base config file and for the profile file merged onto it. Both carry project-wide
|
|
242
|
+
* settings, so a change to either one invalidates every entity rather than a single declaration.
|
|
243
|
+
*/
|
|
244
|
+
isMainConfigFile(filePath: string): boolean;
|
|
218
245
|
getConfigFileEntry(configPath: string): ConfigFileEntry | undefined;
|
|
219
246
|
/**
|
|
220
247
|
* Clears all cached data
|
|
@@ -228,8 +255,10 @@ declare class Handoff {
|
|
|
228
255
|
*/
|
|
229
256
|
private readJsonFile;
|
|
230
257
|
}
|
|
231
|
-
export type { Config, RegisterHandlebarsHelpersContext } from './types/config';
|
|
258
|
+
export type { Config, ResolvedConfig, RegisterHandlebarsHelpersContext } from './types/config';
|
|
232
259
|
export { defineConfig } from './config';
|
|
260
|
+
export { fromEnv } from './config/from-env';
|
|
261
|
+
export type { EnvValue, EnvSecret, RuntimeEnvReference } from './config/from-env';
|
|
233
262
|
export type { CatalogItem, CatalogItemEntries, CatalogItemInput, CatalogItemMeta, CatalogPreview, CompositionRef, Preview, SourceDescriptor, SourceFormat, RendererKind, } from './catalog';
|
|
234
263
|
export { defineAssetStorage } from './registry/asset-storage/define';
|
|
235
264
|
export type { AssetStorage, AssetStorageContext, AssetStorageFactory, AssetStorageInput, AssetStorageReadResult, } from './registry/asset-storage/types';
|
package/dist/index.js
CHANGED
|
@@ -35,18 +35,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.CoreTypes = exports.CoreTransformerUtils = exports.CoreTransformers = exports.defineAssetStorage = exports.defineConfig = void 0;
|
|
39
|
-
require("
|
|
38
|
+
exports.CoreTypes = exports.CoreTransformerUtils = exports.CoreTransformers = exports.defineAssetStorage = exports.fromEnv = exports.defineConfig = void 0;
|
|
39
|
+
require("./config/env");
|
|
40
40
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
41
41
|
const handoff_core_1 = require("handoff-core");
|
|
42
42
|
const path_1 = __importDefault(require("path"));
|
|
43
43
|
const app_builder_1 = __importStar(require("./app-builder"));
|
|
44
44
|
const eject_1 = require("./cli/eject");
|
|
45
45
|
const make_1 = require("./cli/make");
|
|
46
|
+
const store_1 = require("./cli/auth/store");
|
|
46
47
|
const config_1 = require("./config");
|
|
47
48
|
const pipeline_1 = __importStar(require("./pipeline"));
|
|
48
49
|
const content_kinds_1 = require("./registry/content-kinds");
|
|
49
|
-
const
|
|
50
|
+
const store_2 = require("./store");
|
|
50
51
|
const builder_1 = __importStar(require("./transformers/preview/component/builder"));
|
|
51
52
|
const logger_1 = require("./utils/logger");
|
|
52
53
|
const path_2 = require("./utils/path");
|
|
@@ -114,7 +115,7 @@ class Handoff {
|
|
|
114
115
|
*/
|
|
115
116
|
get store() {
|
|
116
117
|
if (!this._store) {
|
|
117
|
-
this._store = (0,
|
|
118
|
+
this._store = (0, store_2.createFilesystemStore)(this);
|
|
118
119
|
}
|
|
119
120
|
return this._store;
|
|
120
121
|
}
|
|
@@ -134,24 +135,52 @@ class Handoff {
|
|
|
134
135
|
this.construct(options);
|
|
135
136
|
}
|
|
136
137
|
construct(options) {
|
|
137
|
-
var _a, _b, _c, _d;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.
|
|
141
|
-
this.
|
|
142
|
-
this.
|
|
138
|
+
var _a, _b, _c, _d, _e;
|
|
139
|
+
// Ahead of `Logger.init` so a profile env file can set `HANDOFF_LOG_LEVEL` and `HANDOFF_LOG_SCOPES`.
|
|
140
|
+
(0, config_1.loadProfileEnv)((_a = (0, config_1.resolveProfileSelection)(options.profile)) === null || _a === void 0 ? void 0 : _a.name);
|
|
141
|
+
this.debug = (_b = options.debug) !== null && _b !== void 0 ? _b : false;
|
|
142
|
+
this.force = (_c = options.force) !== null && _c !== void 0 ? _c : false;
|
|
143
|
+
this.dryRun = (_d = options.dryRun) !== null && _d !== void 0 ? _d : false;
|
|
144
|
+
this.skipBuild = (_e = options.skipBuild) !== null && _e !== void 0 ? _e : false;
|
|
143
145
|
logger_1.Logger.init({ debug: this.debug });
|
|
144
146
|
this.init(options.config);
|
|
145
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* What a selected profile may resolve to besides a config file, and how to explain a name that
|
|
150
|
+
* resolves to nothing. A command that does not accept a login still names one it found, so the
|
|
151
|
+
* difference between the two kinds of profile is visible rather than puzzling.
|
|
152
|
+
*/
|
|
153
|
+
profilesWithoutConfig() {
|
|
154
|
+
var _a;
|
|
155
|
+
const selected = (_a = (0, config_1.resolveProfileSelection)(this._options.profile)) === null || _a === void 0 ? void 0 : _a.name;
|
|
156
|
+
if (!selected) {
|
|
157
|
+
return {};
|
|
158
|
+
}
|
|
159
|
+
const accepts = this._options.profileWithoutConfig;
|
|
160
|
+
const names = (0, store_1.loginProfileNames)(this.workingPath);
|
|
161
|
+
if (!accepts) {
|
|
162
|
+
return names.includes(selected)
|
|
163
|
+
? {
|
|
164
|
+
profileNotFoundHint: 'A saved registry login uses that name, but only login, logout, publish, and checkout accept a profile without a config file.',
|
|
165
|
+
}
|
|
166
|
+
: {};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
knownProfiles: accepts === 'any' ? [...names, selected] : names,
|
|
170
|
+
profileNotFoundHint: 'No saved registry login uses that name either. Run `handoff-app login --profile <name> --url <registry-url>` to create one.',
|
|
171
|
+
};
|
|
172
|
+
}
|
|
146
173
|
init(configOverride) {
|
|
147
174
|
var _a, _b, _c;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
175
|
+
// Resolved before anything is assigned: a reload that throws - a deleted profile file, a
|
|
176
|
+
// broken config - then leaves the last good state in place for the watchers holding this
|
|
177
|
+
// instance.
|
|
178
|
+
const configResult = (0, config_1.initConfigWithMetadata)(configOverride !== null && configOverride !== void 0 ? configOverride : {}, Object.assign({ workingPath: this.workingPath, configPath: this._options.configPath, profile: this._options.profile }, this.profilesWithoutConfig()));
|
|
152
179
|
const config = configResult.config;
|
|
153
180
|
this.config = config;
|
|
154
181
|
this._mainConfigFilePath = configResult.configPath;
|
|
182
|
+
this._profileConfigFilePath = configResult.profileConfigPath;
|
|
183
|
+
this._profile = configResult.profile;
|
|
155
184
|
this.exportsDirectory = (_a = config.exportsOutputDirectory) !== null && _a !== void 0 ? _a : this.exportsDirectory;
|
|
156
185
|
this.sitesDirectory = (_b = config.sitesOutputDirectory) !== null && _b !== void 0 ? _b : this.exportsDirectory;
|
|
157
186
|
[this.runtimeConfig, this._configFilePaths, this._configFileIndex] = (0, config_1.initRuntimeConfig)(this);
|
|
@@ -569,8 +598,8 @@ class Handoff {
|
|
|
569
598
|
* @returns {string[]} Array of absolute paths to config files
|
|
570
599
|
*/
|
|
571
600
|
getConfigFilePaths() {
|
|
572
|
-
const
|
|
573
|
-
return Array.from(new Set(
|
|
601
|
+
const mainPaths = [this._mainConfigFilePath, this._profileConfigFilePath].filter(Boolean);
|
|
602
|
+
return Array.from(new Set([...mainPaths, ...this._configFilePaths]));
|
|
574
603
|
}
|
|
575
604
|
/**
|
|
576
605
|
* Gets the selected main config file path if one exists.
|
|
@@ -578,6 +607,19 @@ class Handoff {
|
|
|
578
607
|
getMainConfigFilePath() {
|
|
579
608
|
return this._mainConfigFilePath;
|
|
580
609
|
}
|
|
610
|
+
getProfile() {
|
|
611
|
+
return this._profile;
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* True for the base config file and for the profile file merged onto it. Both carry project-wide
|
|
615
|
+
* settings, so a change to either one invalidates every entity rather than a single declaration.
|
|
616
|
+
*/
|
|
617
|
+
isMainConfigFile(filePath) {
|
|
618
|
+
const normalized = (0, path_2.normalizePathForCompare)(filePath);
|
|
619
|
+
return [this._mainConfigFilePath, this._profileConfigFilePath]
|
|
620
|
+
.filter(Boolean)
|
|
621
|
+
.some((mainPath) => (0, path_2.normalizePathForCompare)(mainPath) === normalized);
|
|
622
|
+
}
|
|
581
623
|
getConfigFileEntry(configPath) {
|
|
582
624
|
return this._configFileIndex.get((0, path_2.normalizePathForCompare)(configPath));
|
|
583
625
|
}
|
|
@@ -606,6 +648,8 @@ class Handoff {
|
|
|
606
648
|
}
|
|
607
649
|
var config_2 = require("./config");
|
|
608
650
|
Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return config_2.defineConfig; } });
|
|
651
|
+
var from_env_1 = require("./config/from-env");
|
|
652
|
+
Object.defineProperty(exports, "fromEnv", { enumerable: true, get: function () { return from_env_1.fromEnv; } });
|
|
609
653
|
var define_1 = require("./registry/asset-storage/define");
|
|
610
654
|
Object.defineProperty(exports, "defineAssetStorage", { enumerable: true, get: function () { return define_1.defineAssetStorage; } });
|
|
611
655
|
// Export transformers and types from handoff-core
|
package/dist/pipeline/index.d.ts
CHANGED
package/dist/pipeline/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.buildPatterns = exports.buildComponents = exports.zipAssets = exports.zip = exports.readPrevJSONFile = void 0;
|
|
16
|
-
require("
|
|
16
|
+
require("../config/env");
|
|
17
17
|
const app_builder_1 = __importDefault(require("../app-builder"));
|
|
18
18
|
const logger_1 = require("../utils/logger");
|
|
19
19
|
const figma_1 = require("./figma");
|
|
@@ -52,7 +52,7 @@ const createVercelBlobStorage = (params) => {
|
|
|
52
52
|
const token = (_a = process.env[params.tokenEnv]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
53
53
|
if (!token) {
|
|
54
54
|
throw new Error(`Vercel Blob storage is configured but the token env var "${params.tokenEnv}" is not set. ` +
|
|
55
|
-
'Set it to a Blob read/write token, or change runtime.registry.assetStorage.
|
|
55
|
+
'Set it to a Blob read/write token, or change runtime.registry.assetStorage.token.');
|
|
56
56
|
}
|
|
57
57
|
return token;
|
|
58
58
|
};
|