@use-voltra/expo-plugin 2.2.0 → 2.3.1

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 (57) hide show
  1. package/build/cjs/constants.js +1 -3
  2. package/build/cjs/constants.js.map +1 -1
  3. package/build/cjs/dynamic-live-activity.js +6 -0
  4. package/build/cjs/dynamic-live-activity.js.map +1 -0
  5. package/build/cjs/index.js +15 -2
  6. package/build/cjs/index.js.map +1 -1
  7. package/build/cjs/serverUpdate.js +119 -0
  8. package/build/cjs/serverUpdate.js.map +1 -0
  9. package/build/cjs/utils/packageVersion.js +49 -0
  10. package/build/cjs/utils/packageVersion.js.map +1 -0
  11. package/build/cjs/utils/prerender.js +25 -159
  12. package/build/cjs/utils/prerender.js.map +1 -1
  13. package/build/cjs/widgetServerUpdate.js +63 -0
  14. package/build/cjs/widgetServerUpdate.js.map +1 -0
  15. package/build/esm/constants.js +0 -2
  16. package/build/esm/constants.js.map +1 -1
  17. package/build/esm/dynamic-live-activity.js +2 -0
  18. package/build/esm/dynamic-live-activity.js.map +1 -0
  19. package/build/esm/index.js +6 -2
  20. package/build/esm/index.js.map +1 -1
  21. package/build/esm/serverUpdate.js +112 -0
  22. package/build/esm/serverUpdate.js.map +1 -0
  23. package/build/esm/utils/packageVersion.js +13 -0
  24. package/build/esm/utils/packageVersion.js.map +1 -0
  25. package/build/esm/utils/prerender.js +24 -126
  26. package/build/esm/utils/prerender.js.map +1 -1
  27. package/build/esm/widgetServerUpdate.js +59 -0
  28. package/build/esm/widgetServerUpdate.js.map +1 -0
  29. package/build/types/constants.d.ts +0 -2
  30. package/build/types/constants.d.ts.map +1 -1
  31. package/build/types/dynamic-live-activity.d.ts +2 -0
  32. package/build/types/dynamic-live-activity.d.ts.map +1 -0
  33. package/build/types/index.d.ts +11 -4
  34. package/build/types/index.d.ts.map +1 -1
  35. package/build/types/serverUpdate.d.ts +80 -0
  36. package/build/types/serverUpdate.d.ts.map +1 -0
  37. package/build/types/types.d.ts +22 -0
  38. package/build/types/types.d.ts.map +1 -1
  39. package/build/types/utils/packageVersion.d.ts +2 -0
  40. package/build/types/utils/packageVersion.d.ts.map +1 -0
  41. package/build/types/utils/prerender.d.ts +22 -8
  42. package/build/types/utils/prerender.d.ts.map +1 -1
  43. package/build/types/widgetServerUpdate.d.ts +34 -0
  44. package/build/types/widgetServerUpdate.d.ts.map +1 -0
  45. package/package.json +3 -3
  46. package/src/constants.ts +0 -3
  47. package/src/dynamic-live-activity.node.test.ts +18 -0
  48. package/src/dynamic-live-activity.ts +1 -0
  49. package/src/index.ts +33 -3
  50. package/src/serverUpdate.node.test.ts +126 -0
  51. package/src/serverUpdate.ts +160 -0
  52. package/src/types.ts +25 -0
  53. package/src/utils/packageVersion.node.test.ts +24 -0
  54. package/src/utils/packageVersion.ts +19 -0
  55. package/src/utils/prerender.node.test.ts +2 -1
  56. package/src/utils/prerender.ts +34 -155
  57. package/src/widgetServerUpdate.ts +109 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Config rules for `serverUpdate`, shared by the Expo plugins and the `voltra` CLI.
3
+ *
4
+ * `serverUpdate` marks a widget as server-driven for both render engines. On a widget with
5
+ * `entry` the device fetches a JSON object and hands it to the bundled JS as props; without
6
+ * `entry` the server returns a full Voltra payload. Widgets without `entry` keep exactly the
7
+ * rules they had before ADR 0002, so no existing config breaks.
8
+ *
9
+ * `url` is optional. `serverUpdate: {}` means "server-driven, URL supplied at runtime" through
10
+ * `setWidgetServerUpdate`, which covers per-tenant backends whose URL is only known after login.
11
+ *
12
+ * These helpers report problems instead of throwing so each caller can raise its own error type.
13
+ *
14
+ * The `voltra` CLI validates `serverUpdate` from its own copy of this module; keep the two in
15
+ * sync.
16
+ */
17
+ /**
18
+ * Interval floor and default for a widget with `entry`. WorkManager cannot run periodic work
19
+ * more often than every 15 minutes, and WidgetKit stretches timelines requested closer together
20
+ * than five minutes, so a smaller number would only mislead.
21
+ */
22
+ export const DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES = 15;
23
+ /** Hosts allowed over plain `http`, for talking to a dev server from a simulator or emulator. */
24
+ const LOCAL_HTTP_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '10.0.2.2', '10.0.3.2']);
25
+ /**
26
+ * Resolves the interval a widget should be scheduled on.
27
+ *
28
+ * A widget with `entry` is clamped up to {@link DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES}
29
+ * with a warning, because a shorter interval is not something either platform can honour. A
30
+ * payload widget keeps the platform's existing rule and is rejected below the floor.
31
+ */
32
+ export function resolveServerUpdateInterval(options) {
33
+ const { intervalMinutes, context, hasEntry, defaultIntervalMinutes, minimumIntervalMinutes } = options;
34
+ const fallback = hasEntry ? DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES : defaultIntervalMinutes;
35
+ if (intervalMinutes === undefined) {
36
+ return { kind: 'ok', intervalMinutes: fallback };
37
+ }
38
+ if (typeof intervalMinutes !== 'number' || !Number.isFinite(intervalMinutes)) {
39
+ return { kind: 'invalid', error: `${context}.intervalMinutes must be a number` };
40
+ }
41
+ if (!Number.isInteger(intervalMinutes)) {
42
+ return { kind: 'invalid', error: `${context}.intervalMinutes must be an integer` };
43
+ }
44
+ if (hasEntry) {
45
+ if (intervalMinutes < DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES) {
46
+ return {
47
+ kind: 'clamped',
48
+ intervalMinutes: DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES,
49
+ warning: `${context}.intervalMinutes is ${intervalMinutes}, below the ` +
50
+ `${DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES} minute floor for widgets with an entry. ` +
51
+ `Using ${DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES}.`,
52
+ };
53
+ }
54
+ return { kind: 'ok', intervalMinutes };
55
+ }
56
+ if (intervalMinutes < minimumIntervalMinutes) {
57
+ return { kind: 'invalid', error: `${context}.intervalMinutes must be at least ${minimumIntervalMinutes}` };
58
+ }
59
+ return { kind: 'ok', intervalMinutes };
60
+ }
61
+ /**
62
+ * Checks `serverUpdate.url`. An absent URL is fine — the app supplies it at runtime through
63
+ * `setWidgetServerUpdate`.
64
+ *
65
+ * A URL that is not an absolute `http`/`https` URL is rejected: no platform HTTP stack here
66
+ * accepts one, so such a config could only ever have failed to fetch. Plain `http` to a
67
+ * non-local host is reported as insecure rather than rejected — App Transport Security and
68
+ * Android's cleartext policy already block it in a release build, and rejecting it outright
69
+ * would break configs that point at a LAN dev server.
70
+ */
71
+ export function resolveServerUpdateUrl(url, context) {
72
+ if (url === undefined) {
73
+ return { kind: 'ok' };
74
+ }
75
+ if (typeof url !== 'string' || !url.trim()) {
76
+ return { kind: 'invalid', error: `${context}.url must be a non-empty string` };
77
+ }
78
+ let parsed;
79
+ try {
80
+ parsed = new URL(url);
81
+ }
82
+ catch {
83
+ return { kind: 'invalid', error: `${context}.url must be an absolute http(s) URL, received '${url}'` };
84
+ }
85
+ if (parsed.protocol === 'https:') {
86
+ return { kind: 'ok' };
87
+ }
88
+ if (parsed.protocol !== 'http:') {
89
+ return { kind: 'invalid', error: `${context}.url must be an absolute http(s) URL, received '${url}'` };
90
+ }
91
+ if (isLocalHttpHost(parsed.hostname)) {
92
+ return { kind: 'ok' };
93
+ }
94
+ return {
95
+ kind: 'insecure',
96
+ warning: `${context}.url uses plain http ('${url}'). Release builds block cleartext traffic, so the ` +
97
+ 'widget will not fetch outside a development build. Use https, or a local dev host ' +
98
+ `(${[...LOCAL_HTTP_HOSTS].join(', ')}).`,
99
+ };
100
+ }
101
+ /** True for the hosts Voltra allows over plain `http` — dev servers reachable from a simulator. */
102
+ export function isLocalHttpHost(hostname) {
103
+ return LOCAL_HTTP_HOSTS.has(hostname.replace(/^\[|\]$/g, ''));
104
+ }
105
+ /** Validates `serverUpdate.refresh`. Returns an error message, or `undefined` when it is fine. */
106
+ export function validateServerUpdateRefresh(refresh, context) {
107
+ if (refresh !== undefined && typeof refresh !== 'boolean') {
108
+ return `${context}.refresh must be a boolean`;
109
+ }
110
+ return undefined;
111
+ }
112
+ //# sourceMappingURL=serverUpdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverUpdate.js","sourceRoot":"","sources":["../../src/serverUpdate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+ export function resolveInstalledPackageVersion(projectRoot, packageName) {
5
+ const projectRequire = createRequire(path.join(projectRoot, 'package.json'));
6
+ const packageJsonPath = projectRequire.resolve(`${packageName}/package.json`);
7
+ const manifest = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
8
+ if (typeof manifest.version !== 'string' || manifest.version.length === 0) {
9
+ throw new Error(`Package ${packageName} does not declare a valid version in ${packageJsonPath}.`);
10
+ }
11
+ return manifest.version;
12
+ }
13
+ //# sourceMappingURL=packageVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../../../src/utils/packageVersion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAM3C,MAAM,UAAU,8BAA8B,CAAC,WAAmB,EAAE,WAAmB;IACrF,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAA;IAC5E,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,WAAW,eAAe,CAAC,CAAA;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAoB,CAAA;IAExF,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,WAAW,WAAW,wCAAwC,eAAe,GAAG,CAAC,CAAA;IACnG,CAAC;IAED,OAAO,QAAQ,CAAC,OAAO,CAAA;AACzB,CAAC"}
@@ -1,141 +1,38 @@
1
- import fs from 'node:fs';
2
1
  import path from 'node:path';
3
- import { createRequire } from 'node:module';
4
- import vm from 'node:vm';
5
- import * as babel from '@babel/core';
6
- import { MODULE_EXTENSIONS } from '../constants';
2
+ import { createWidgetModuleLoader } from '@use-voltra/compiler';
7
3
  import { logger } from './logger';
8
4
  import { isWidgetLocalizedMap } from './widgetLabel';
9
- const PRERENDER_PACKAGE_REDIRECTS = {
10
- '@use-voltra/ios-client': '@use-voltra/ios',
11
- '@use-voltra/android-client': '@use-voltra/android',
12
- };
13
5
  /**
14
- * Check if a module specifier is a relative or absolute path (local file)
15
- */
16
- function isLocalModule(moduleSpecifier) {
17
- return moduleSpecifier.startsWith('.') || moduleSpecifier.startsWith('/');
18
- }
19
- /**
20
- * Resolve a module path, trying different extensions
21
- */
22
- function resolveModulePath(moduleSpecifier, fromDir) {
23
- const basePath = path.resolve(fromDir, moduleSpecifier);
24
- for (const ext of MODULE_EXTENSIONS) {
25
- const fullPath = basePath + ext;
26
- if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
27
- return fullPath;
28
- }
29
- }
30
- // Try index files if it's a directory
31
- if (fs.existsSync(basePath) && fs.statSync(basePath).isDirectory()) {
32
- for (const ext of MODULE_EXTENSIONS) {
33
- const indexPath = path.join(basePath, 'index' + ext);
34
- if (fs.existsSync(indexPath)) {
35
- return indexPath;
36
- }
37
- }
38
- }
39
- return null;
40
- }
41
- function getProjectBabelConfigPath(projectRoot) {
42
- const configPath = path.join(projectRoot, 'babel.config.js');
43
- return fs.existsSync(configPath) ? configPath : null;
44
- }
45
- function getFallbackExpoPreset(projectRoot) {
46
- return require.resolve('babel-preset-expo', { paths: [projectRoot] });
47
- }
48
- /**
49
- * Transpile a file with Babel
6
+ * Create the loader used to evaluate widget source during prebuild.
7
+ *
8
+ * Evaluation rules live in `@use-voltra/compiler` so that prebuild, `voltra apply`, and
9
+ * the Metro widget bundler agree on what widget code may import.
50
10
  */
51
- function transpileFile(filePath, projectRoot) {
52
- const code = fs.readFileSync(filePath, 'utf8');
53
- const projectBabelConfigPath = getProjectBabelConfigPath(projectRoot);
54
- const result = babel.transformSync(code, {
55
- cwd: projectRoot,
56
- filename: filePath,
57
- ...(projectBabelConfigPath
58
- ? { configFile: projectBabelConfigPath }
59
- : {
60
- babelrc: false,
61
- configFile: false,
62
- presets: [getFallbackExpoPreset(projectRoot)],
63
- }),
11
+ export function createPrerenderWidgetModuleLoader(projectRoot, platform) {
12
+ return createWidgetModuleLoader({
13
+ projectRoot,
14
+ platform,
15
+ onWarning: (message) => logger.warn(message),
64
16
  });
65
- if (!result || !result.code) {
66
- throw new Error(`Babel transpilation failed for ${filePath}`);
67
- }
68
- return result.code;
17
+ }
18
+ function resolveLoader({ projectRoot, platform, loader }) {
19
+ return loader ?? createPrerenderWidgetModuleLoader(projectRoot, platform);
69
20
  }
70
21
  /**
71
- * Evaluate a widget module using Babel transpilation and Node.js VM.
72
- * This allows executing widget code that uses JSX and React components.
73
- * Local module dependencies are also transpiled with the same Babel settings.
22
+ * Evaluate a widget module and return its exports object.
74
23
  *
75
24
  * Exported so platform-specific prerender flows can reuse the same module loader rather
76
- * than duplicating the Babel + VM scaffolding. The returned value is the module's exports
77
- * object — callers decide whether to read `.default`, a named export, etc.
25
+ * than duplicating the Babel + VM scaffolding. Callers decide whether to read `.default`,
26
+ * a named export, etc.
78
27
  */
79
- export function evaluateWidgetModuleExports(projectRoot, filePath, warnedRedirects = new Set()) {
80
- // Cache for already-evaluated modules to handle circular dependencies
81
- const moduleCache = new Map();
82
- const projectRequire = createRequire(path.join(projectRoot, 'package.json'));
83
- /**
84
- * Custom require that transpiles local modules with Babel
85
- */
86
- function customRequire(moduleSpecifier, currentDir) {
87
- // For non-local modules (npm packages), use native require
88
- if (!isLocalModule(moduleSpecifier)) {
89
- const redirectedSpecifier = PRERENDER_PACKAGE_REDIRECTS[moduleSpecifier];
90
- if (redirectedSpecifier) {
91
- if (!warnedRedirects.has(moduleSpecifier)) {
92
- warnedRedirects.add(moduleSpecifier);
93
- logger.warn(`Prerendering initial state imported '${moduleSpecifier}'. Using '${redirectedSpecifier}' instead.`);
94
- }
95
- return projectRequire(redirectedSpecifier);
96
- }
97
- return projectRequire(moduleSpecifier);
98
- }
99
- // Resolve the local module path
100
- const resolvedPath = resolveModulePath(moduleSpecifier, currentDir);
101
- if (!resolvedPath) {
102
- throw new Error(`Cannot resolve module '${moduleSpecifier}' from '${currentDir}'`);
103
- }
104
- // Return cached module if already evaluated
105
- if (moduleCache.has(resolvedPath)) {
106
- return moduleCache.get(resolvedPath);
107
- }
108
- // Transpile and evaluate the module
109
- const transpiledCode = transpileFile(resolvedPath, projectRoot);
110
- const moduleDir = path.dirname(resolvedPath);
111
- const mockModule = { exports: {} };
112
- // Create require function bound to the module's directory
113
- const boundRequire = (spec) => customRequire(spec, moduleDir);
114
- const context = vm.createContext({
115
- exports: mockModule.exports,
116
- module: mockModule,
117
- require: boundRequire,
118
- __filename: resolvedPath,
119
- __dirname: moduleDir,
120
- console: console,
121
- process: process,
122
- });
123
- // Cache before evaluation to handle circular dependencies
124
- moduleCache.set(resolvedPath, mockModule.exports);
125
- const script = new vm.Script(transpiledCode, { filename: resolvedPath });
126
- script.runInContext(context);
127
- // Update cache with final exports (in case module.exports was reassigned)
128
- moduleCache.set(resolvedPath, mockModule.exports);
129
- return mockModule.exports;
130
- }
131
- return customRequire(filePath, path.dirname(filePath));
28
+ export function evaluateWidgetModuleExports(filePath, options) {
29
+ return resolveLoader(options).load(filePath);
132
30
  }
133
31
  /**
134
32
  * Evaluate a widget file as a server-style WidgetVariants module and return its object export.
135
33
  */
136
- export function evaluateWidgetModule(projectRoot, filePath, warnedRedirects = new Set()) {
137
- const exports = evaluateWidgetModuleExports(projectRoot, filePath, warnedRedirects);
138
- const widgetVariants = exports.default || exports;
34
+ export function evaluateWidgetModule(filePath, options) {
35
+ const widgetVariants = resolveLoader(options).loadDefaultExport(filePath);
139
36
  if (!widgetVariants || typeof widgetVariants !== 'object') {
140
37
  throw new Error('Widget file must export a WidgetVariants object or have a default export of WidgetVariants');
141
38
  }
@@ -151,11 +48,12 @@ export function evaluateWidgetModule(projectRoot, filePath, warnedRedirects = ne
151
48
  * @param widgets - Array of widget configurations
152
49
  * @param projectRoot - Root directory of the Expo project
153
50
  * @param renderer - The renderer function to use (voltra/server or voltra/android/server)
51
+ * @param platform - Platform being prebuilt
154
52
  * @returns Map of widgetId -> (locale key -> prerendered JSON string)
155
53
  */
156
- export async function prerenderWidgetState(widgets, projectRoot, renderer) {
54
+ export async function prerenderWidgetState(widgets, projectRoot, renderer, platform) {
157
55
  const prerenderedStates = new Map();
158
- const warnedRedirects = new Set();
56
+ const loader = createPrerenderWidgetModuleLoader(projectRoot, platform);
159
57
  for (const widget of widgets) {
160
58
  if (!widget.initialStatePath) {
161
59
  continue;
@@ -168,7 +66,7 @@ export async function prerenderWidgetState(widgets, projectRoot, renderer) {
168
66
  try {
169
67
  for (const [localeKey, relativePath] of Object.entries(perLocalePaths)) {
170
68
  const absoluteWidgetPath = path.resolve(projectRoot, relativePath);
171
- const widgetVariants = evaluateWidgetModule(projectRoot, absoluteWidgetPath, warnedRedirects);
69
+ const widgetVariants = evaluateWidgetModule(absoluteWidgetPath, { projectRoot, platform, loader });
172
70
  const prerenderedState = renderer(widgetVariants);
173
71
  inner.set(localeKey, prerenderedState);
174
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prerender.js","sourceRoot":"","sources":["../../../src/utils/prerender.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prerender.js","sourceRoot":"","sources":["../../../src/utils/prerender.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { resolveServerUpdateInterval, resolveServerUpdateUrl, validateServerUpdateRefresh } from './serverUpdate';
2
+ import { logger } from './utils/logger';
3
+ export function validateWidgetServerUpdate(serverUpdate, widgetId, rules) {
4
+ if (serverUpdate === undefined) {
5
+ return;
6
+ }
7
+ const context = `Widget '${widgetId}': serverUpdate`;
8
+ if (typeof serverUpdate !== 'object' || serverUpdate === null || Array.isArray(serverUpdate)) {
9
+ throw new Error(`${context} must be an object`);
10
+ }
11
+ const { url, intervalMinutes, refresh } = serverUpdate;
12
+ const resolvedUrl = resolveServerUpdateUrl(url, context);
13
+ if (resolvedUrl.kind === 'invalid') {
14
+ throw new Error(resolvedUrl.error);
15
+ }
16
+ if (resolvedUrl.kind === 'insecure') {
17
+ logger.warn(resolvedUrl.warning);
18
+ }
19
+ const interval = resolveServerUpdateInterval({
20
+ intervalMinutes,
21
+ context,
22
+ hasEntry: rules.hasEntry,
23
+ defaultIntervalMinutes: rules.defaultIntervalMinutes,
24
+ minimumIntervalMinutes: rules.minimumIntervalMinutes,
25
+ });
26
+ if (interval.kind === 'invalid') {
27
+ throw new Error(interval.error);
28
+ }
29
+ if (interval.kind === 'clamped') {
30
+ logger.warn(interval.warning);
31
+ }
32
+ const refreshError = validateServerUpdateRefresh(refresh, context);
33
+ if (refreshError) {
34
+ throw new Error(refreshError);
35
+ }
36
+ }
37
+ /**
38
+ * Applies defaults to a validated `serverUpdate`. Generators call this instead of reading
39
+ * `intervalMinutes` directly, so the value written into a plist or a generated asset is the one
40
+ * the widget will actually be scheduled on.
41
+ */
42
+ export function resolveWidgetServerUpdate(serverUpdate, rules) {
43
+ const interval = resolveServerUpdateInterval({
44
+ intervalMinutes: serverUpdate.intervalMinutes,
45
+ context: 'serverUpdate',
46
+ hasEntry: rules.hasEntry,
47
+ defaultIntervalMinutes: rules.defaultIntervalMinutes,
48
+ minimumIntervalMinutes: rules.minimumIntervalMinutes,
49
+ });
50
+ return {
51
+ url: serverUpdate.url,
52
+ // An invalid interval cannot reach here — validateWidgetServerUpdate throws on it first — but
53
+ // if the two are ever called out of order, falling back to the platform's own default is less
54
+ // surprising than silently switching a payload widget to the Dynamic one.
55
+ intervalMinutes: interval.kind === 'invalid' ? rules.defaultIntervalMinutes : interval.intervalMinutes,
56
+ refresh: serverUpdate.refresh === true,
57
+ };
58
+ }
59
+ //# sourceMappingURL=widgetServerUpdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgetServerUpdate.js","sourceRoot":"","sources":["../../src/widgetServerUpdate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AACjH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAgCvC,MAAM,UAAU,0BAA0B,CACxC,YAAqB,EACrB,QAAgB,EAChB,KAA8B;IAE9B,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,QAAQ,iBAAiB,CAAA;IAEpD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7F,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,oBAAoB,CAAC,CAAA;IACjD,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,YAAwC,CAAA;IAElF,MAAM,WAAW,GAAG,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAExD,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IACpC,CAAC;IAED,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAED,MAAM,QAAQ,GAAG,2BAA2B,CAAC;QAC3C,eAAe;QACf,OAAO;QACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;KACrD,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;IAED,MAAM,YAAY,GAAG,2BAA2B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAElE,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,YAAsC,EACtC,KAA8B;IAE9B,MAAM,QAAQ,GAAG,2BAA2B,CAAC;QAC3C,eAAe,EAAE,YAAY,CAAC,eAAe;QAC7C,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;KACrD,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,EAAE,YAAY,CAAC,GAAG;QACrB,8FAA8F;QAC9F,8FAA8F;QAC9F,0EAA0E;QAC1E,eAAe,EAAE,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe;QACtG,OAAO,EAAE,YAAY,CAAC,OAAO,KAAK,IAAI;KACvC,CAAA;AACH,CAAC"}
@@ -1,5 +1,3 @@
1
- /** Extensions to try when resolving module paths for pre-rendering */
2
- export declare const MODULE_EXTENSIONS: string[];
3
1
  /** Maximum image size in bytes for widget / Live Activity assets (4KB limit) */
4
2
  export declare const MAX_IMAGE_SIZE_BYTES = 4096;
5
3
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,UAAqC,CAAA;AAEnE,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,OAAO,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,OAAO,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { getDynamicLiveActivityAttributesType } from '@use-voltra/core/dynamic-live-activity';
2
+ //# sourceMappingURL=dynamic-live-activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-live-activity.d.ts","sourceRoot":"","sources":["../../src/dynamic-live-activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAA"}
@@ -1,11 +1,18 @@
1
- export { MAX_IMAGE_SIZE_BYTES, MODULE_EXTENSIONS } from './constants';
2
- export type { DynamicWidgetEntryConfig, DynamicWidgetManifest, DynamicWidgetManifestWidget, DynamicWidgetPlatform, WidgetInitialStatePath, WidgetLabel, WidgetLocalizedCopy, } from './types';
1
+ export { MAX_IMAGE_SIZE_BYTES } from './constants';
2
+ export { getDynamicLiveActivityAttributesType } from './dynamic-live-activity';
3
+ export type { DynamicWidgetEntryConfig, DynamicLiveActivityEntryConfig, DynamicLiveActivityManifest, DynamicLiveActivityManifestDefinition, DynamicWidgetManifest, DynamicWidgetManifestWidget, DynamicWidgetPlatform, WidgetInitialStatePath, WidgetLabel, WidgetLocalizedCopy, } from './types';
4
+ export type { ServerUpdateIntervalResolution, ServerUpdateUrlResolution } from './serverUpdate';
5
+ export { DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES, isLocalHttpHost, resolveServerUpdateInterval, resolveServerUpdateUrl, validateServerUpdateRefresh, } from './serverUpdate';
6
+ export type { ResolvedWidgetServerUpdateConfig, WidgetServerUpdateConfig, WidgetServerUpdateRules, } from './widgetServerUpdate';
7
+ export { resolveWidgetServerUpdate, validateWidgetServerUpdate } from './widgetServerUpdate';
3
8
  export { assertValidLocaleKey, normalizeWidgetEntryPath, validateHomeScreenWidgetId, validateInitialStatePath, validateWidgetEntry, validateWidgetLabel, } from './validation';
4
9
  export { addApplicationGroupsEntitlement } from './utils/entitlements';
5
10
  export { resolveFontPaths } from './utils/fonts';
6
11
  export { normalizeLocaleTag, pickLocalizedValue } from './utils/localePick';
7
12
  export { logger } from './utils/logger';
8
- export type { PrerenderableWidget, PrerenderedWidgetStates, WidgetRenderer } from './utils/prerender';
9
- export { evaluateWidgetModule, evaluateWidgetModuleExports, prerenderWidgetState } from './utils/prerender';
13
+ export { resolveInstalledPackageVersion } from './utils/packageVersion';
14
+ export type { PrerenderableWidget, PrerenderedWidgetStates, WidgetModuleEvaluationOptions, WidgetRenderer, } from './utils/prerender';
15
+ export { createPrerenderWidgetModuleLoader, evaluateWidgetModule, evaluateWidgetModuleExports, prerenderWidgetState, } from './utils/prerender';
16
+ export type { WidgetModuleLoader, WidgetModulePlatform } from '@use-voltra/compiler';
10
17
  export { isWidgetLocalizedMap, widgetLabelEnglish } from './utils/widgetLabel';
11
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACrE,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACrG,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC3G,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,oCAAoC,EAAE,MAAM,yBAAyB,CAAA;AAC9E,YAAY,EACV,wBAAwB,EACxB,8BAA8B,EAC9B,2BAA2B,EAC3B,qCAAqC,EACrC,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,8BAA8B,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EACL,6CAA6C,EAC7C,eAAe,EACf,2BAA2B,EAC3B,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,gCAAgC,EAChC,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAC5F,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAA;AACvE,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,6BAA6B,EAC7B,cAAc,GACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,iCAAiC,EACjC,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AACpF,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Config rules for `serverUpdate`, shared by the Expo plugins and the `voltra` CLI.
3
+ *
4
+ * `serverUpdate` marks a widget as server-driven for both render engines. On a widget with
5
+ * `entry` the device fetches a JSON object and hands it to the bundled JS as props; without
6
+ * `entry` the server returns a full Voltra payload. Widgets without `entry` keep exactly the
7
+ * rules they had before ADR 0002, so no existing config breaks.
8
+ *
9
+ * `url` is optional. `serverUpdate: {}` means "server-driven, URL supplied at runtime" through
10
+ * `setWidgetServerUpdate`, which covers per-tenant backends whose URL is only known after login.
11
+ *
12
+ * These helpers report problems instead of throwing so each caller can raise its own error type.
13
+ *
14
+ * The `voltra` CLI validates `serverUpdate` from its own copy of this module; keep the two in
15
+ * sync.
16
+ */
17
+ /**
18
+ * Interval floor and default for a widget with `entry`. WorkManager cannot run periodic work
19
+ * more often than every 15 minutes, and WidgetKit stretches timelines requested closer together
20
+ * than five minutes, so a smaller number would only mislead.
21
+ */
22
+ export declare const DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES = 15;
23
+ /** Outcome of resolving `serverUpdate.intervalMinutes` against a platform's floor. */
24
+ export type ServerUpdateIntervalResolution = {
25
+ kind: 'ok';
26
+ intervalMinutes: number;
27
+ } | {
28
+ kind: 'clamped';
29
+ intervalMinutes: number;
30
+ warning: string;
31
+ } | {
32
+ kind: 'invalid';
33
+ error: string;
34
+ };
35
+ export interface ResolveServerUpdateIntervalOptions {
36
+ /** Raw `intervalMinutes` from app.json, if the widget set one. */
37
+ intervalMinutes: unknown;
38
+ /** Config path used in messages, e.g. `android.widgets[portfolio].serverUpdate`. */
39
+ context: string;
40
+ /** True when the widget has an `entry` and therefore renders on device. */
41
+ hasEntry: boolean;
42
+ /** Interval used when the widget does not set one. Ignored for widgets with `entry`. */
43
+ defaultIntervalMinutes: number;
44
+ /** Platform floor for payload widgets. Ignored for widgets with `entry`. */
45
+ minimumIntervalMinutes: number;
46
+ }
47
+ /**
48
+ * Resolves the interval a widget should be scheduled on.
49
+ *
50
+ * A widget with `entry` is clamped up to {@link DYNAMIC_WIDGET_SERVER_UPDATE_INTERVAL_MINUTES}
51
+ * with a warning, because a shorter interval is not something either platform can honour. A
52
+ * payload widget keeps the platform's existing rule and is rejected below the floor.
53
+ */
54
+ export declare function resolveServerUpdateInterval(options: ResolveServerUpdateIntervalOptions): ServerUpdateIntervalResolution;
55
+ /** Outcome of checking `serverUpdate.url`. */
56
+ export type ServerUpdateUrlResolution = {
57
+ kind: 'ok';
58
+ } | {
59
+ kind: 'insecure';
60
+ warning: string;
61
+ } | {
62
+ kind: 'invalid';
63
+ error: string;
64
+ };
65
+ /**
66
+ * Checks `serverUpdate.url`. An absent URL is fine — the app supplies it at runtime through
67
+ * `setWidgetServerUpdate`.
68
+ *
69
+ * A URL that is not an absolute `http`/`https` URL is rejected: no platform HTTP stack here
70
+ * accepts one, so such a config could only ever have failed to fetch. Plain `http` to a
71
+ * non-local host is reported as insecure rather than rejected — App Transport Security and
72
+ * Android's cleartext policy already block it in a release build, and rejecting it outright
73
+ * would break configs that point at a LAN dev server.
74
+ */
75
+ export declare function resolveServerUpdateUrl(url: unknown, context: string): ServerUpdateUrlResolution;
76
+ /** True for the hosts Voltra allows over plain `http` — dev servers reachable from a simulator. */
77
+ export declare function isLocalHttpHost(hostname: string): boolean;
78
+ /** Validates `serverUpdate.refresh`. Returns an error message, or `undefined` when it is fine. */
79
+ export declare function validateServerUpdateRefresh(refresh: unknown, context: string): string | undefined;
80
+ //# sourceMappingURL=serverUpdate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverUpdate.d.ts","sourceRoot":"","sources":["../../src/serverUpdate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;GAIG;AACH,eAAO,MAAM,6CAA6C,KAAK,CAAA;AAK/D,sFAAsF;AACtF,MAAM,MAAM,8BAA8B,GACtC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtC,MAAM,WAAW,kCAAkC;IACjD,kEAAkE;IAClE,eAAe,EAAE,OAAO,CAAA;IACxB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAA;IACjB,wFAAwF;IACxF,sBAAsB,EAAE,MAAM,CAAA;IAC9B,4EAA4E;IAC5E,sBAAsB,EAAE,MAAM,CAAA;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,kCAAkC,GAC1C,8BAA8B,CAoChC;AAED,8CAA8C;AAC9C,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtC;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,yBAAyB,CAoC/F;AAED,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,kGAAkG;AAClG,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMjG"}
@@ -21,6 +21,28 @@ export interface DynamicWidgetManifest {
21
21
  platform: DynamicWidgetPlatform;
22
22
  widgets: DynamicWidgetManifestWidget[];
23
23
  }
24
+ /**
25
+ * Generated by the iOS config plugin for Metro's Dynamic Live Activity pipeline.
26
+ * This intentionally does not share the Dynamic Widget manifest: an ID may exist in
27
+ * both collections and each collection has a separate runtime and bundle namespace.
28
+ */
29
+ export interface DynamicLiveActivityManifestDefinition {
30
+ id: string;
31
+ entry: string;
32
+ }
33
+ export interface DynamicLiveActivityManifest {
34
+ version: 1;
35
+ platform: 'ios';
36
+ liveActivities: DynamicLiveActivityManifestDefinition[];
37
+ }
38
+ /**
39
+ * Shared app.json entry contract for Dynamic Live Activities.
40
+ * @experimental
41
+ */
42
+ export interface DynamicLiveActivityEntryConfig {
43
+ id: string;
44
+ entry: string;
45
+ }
24
46
  /**
25
47
  * Per-locale strings for widget picker/gallery labels (`displayName`, `description`).
26
48
  * Keys should be BCP-47-style locale tags (e.g. `en`, `pl`, `pt-BR`). Plain `string` is still allowed for a single-language setup.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,SAAS,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,CAAA;IACV,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,OAAO,EAAE,2BAA2B,EAAE,CAAA;CACvC;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAExD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,mBAAmB,CAAA;AAEtD;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,mBAAmB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,SAAS,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,CAAA;IACV,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,OAAO,EAAE,2BAA2B,EAAE,CAAA;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,qCAAqC;IACpD,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,CAAC,CAAA;IACV,QAAQ,EAAE,KAAK,CAAA;IACf,cAAc,EAAE,qCAAqC,EAAE,CAAA;CACxD;AAED;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAExD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,mBAAmB,CAAA;AAEtD;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,mBAAmB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare function resolveInstalledPackageVersion(projectRoot: string, packageName: string): string;
2
+ //# sourceMappingURL=packageVersion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../../../src/utils/packageVersion.ts"],"names":[],"mappings":"AAQA,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAU/F"}