primitive-app 3.1.1 → 3.1.2
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/dist/dev-tools/blob-explorer/blobExplorerTypes.d.ts +9 -1
- package/dist/dev-tools/document-explorer/composables/useOptimisticList.d.ts +3 -3
- package/dist/dev-tools/document-explorer/utils.d.ts +1 -0
- package/dist/dev-tools/vite-plugin/generated-env-resolver-core.d.ts +89 -18
- package/dist/dev-tools/vite-plugin/index.cjs +3 -3
- package/dist/dev-tools/vite-plugin/index.js +110 -92
- package/dist/dev-tools/vite-plugin/primitive-env.d.ts +1 -3
- package/dist/index.cjs +4 -4
- package/dist/index.js +2601 -2598
- package/dist/lib-DcwHR2qs.cjs +1 -0
- package/dist/{lib-B7ZH2Pdd.js → lib-_MJ36YT6.js} +4 -4
- package/dist/primitive-app.css +1 -1
- package/dist/services/JsBaoClientService.d.ts +4 -2
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.js +1 -1
- package/package.json +2 -2
- package/dist/lib-CFnieS8T.cjs +0 -1
|
@@ -9,8 +9,16 @@ export interface BlobItem {
|
|
|
9
9
|
uploadedAt?: string | null;
|
|
10
10
|
sha256?: string;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* A blob as the list and get calls return it. Older servers report the size
|
|
14
|
+
* and upload time as `numBytes` and `createdAt`.
|
|
15
|
+
*/
|
|
16
|
+
export interface RawBlobItem extends BlobItem {
|
|
17
|
+
numBytes?: number | null;
|
|
18
|
+
createdAt?: string | null;
|
|
19
|
+
}
|
|
12
20
|
/** Result from a paginated blob list call */
|
|
13
21
|
export interface BlobListResult {
|
|
14
|
-
items:
|
|
22
|
+
items: RawBlobItem[];
|
|
15
23
|
cursor?: string;
|
|
16
24
|
}
|
|
@@ -14,21 +14,21 @@ export interface OptimisticListActions<T> {
|
|
|
14
14
|
* Optimistically remove item(s) matching `key === value` from the list,
|
|
15
15
|
* execute the async operation, and rollback on failure.
|
|
16
16
|
*/
|
|
17
|
-
optimisticRemove(matchValue: string, operation: () => Promise<void>)
|
|
17
|
+
optimisticRemove: (matchValue: string, operation: () => Promise<void>) => Promise<{
|
|
18
18
|
success: boolean;
|
|
19
19
|
}>;
|
|
20
20
|
/**
|
|
21
21
|
* Optimistically remove multiple items from the list by key values,
|
|
22
22
|
* execute the async operation, and rollback any that failed.
|
|
23
23
|
*/
|
|
24
|
-
optimisticBulkRemove(matchValues: string[], operation: (ids: string[]) => Promise<string[]>)
|
|
24
|
+
optimisticBulkRemove: (matchValues: string[], operation: (ids: string[]) => Promise<string[]>) => Promise<{
|
|
25
25
|
failedIds: string[];
|
|
26
26
|
}>;
|
|
27
27
|
/**
|
|
28
28
|
* Optimistically update a field on an item, execute the async operation,
|
|
29
29
|
* and rollback on failure.
|
|
30
30
|
*/
|
|
31
|
-
optimisticFieldUpdate<K extends keyof T>(matchValue: string, field: K, newValue: T[K], operation: () => Promise<void>)
|
|
31
|
+
optimisticFieldUpdate: <K extends keyof T>(matchValue: string, field: K, newValue: T[K], operation: () => Promise<void>) => Promise<{
|
|
32
32
|
success: boolean;
|
|
33
33
|
}>;
|
|
34
34
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FieldSchemaInfo, FilterMode, ModelFilter, ModelInfo, SortDirection, SortField } from "./types";
|
|
2
2
|
export declare function safeJsonStringify(value: unknown, indent?: number): string;
|
|
3
|
+
export declare function toDisplayString(value: unknown): string;
|
|
3
4
|
export declare function fuzzyMatch(text: string, query: string): boolean;
|
|
4
5
|
export declare function filterModeHasValue(mode: FilterMode): boolean;
|
|
5
6
|
export declare function applyFilterToRecord(record: Record<string, unknown>, filter: ModelFilter): boolean;
|
|
@@ -12,20 +12,62 @@
|
|
|
12
12
|
* gate if this committed copy drifts from the source. Edit the CLI file and
|
|
13
13
|
* regenerate; edits made here are overwritten.
|
|
14
14
|
*/
|
|
15
|
-
/** Schema version of
|
|
15
|
+
/** Schema version of `primitive/config.json` this core understands. */
|
|
16
16
|
export declare const PRIMITIVE_CONFIG_VERSION = 1;
|
|
17
17
|
/** Schema version of `.primitive/local.json` this core writes and reads. */
|
|
18
18
|
export declare const PRIMITIVE_LOCAL_STATE_VERSION = 1;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The two directories, split apart by #3153 so one name never means two
|
|
21
|
+
* things: `primitive/` is the COMMITTED tree (the config and every
|
|
22
|
+
* environment's TOML), `.primitive/` is MACHINE-LOCAL state (credentials, this
|
|
23
|
+
* machine's selection, snapshot backups) and is gitignored whole.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PROJECT_TREE_DIR = "primitive";
|
|
26
|
+
export declare const PROJECT_LOCAL_STATE_DIR = ".primitive";
|
|
20
27
|
export declare const PROJECT_CONFIG_FILENAME = "config.json";
|
|
21
28
|
export declare const LOCAL_STATE_FILENAME = "local.json";
|
|
22
|
-
export declare const PROJECT_CONFIG_DISPLAY_NAME = "
|
|
29
|
+
export declare const PROJECT_CONFIG_DISPLAY_NAME = "primitive/config.json";
|
|
23
30
|
export declare const LOCAL_STATE_DISPLAY_NAME = ".primitive/local.json";
|
|
31
|
+
/**
|
|
32
|
+
* The one refusal for a project that never migrated off the pre-#3153 layout:
|
|
33
|
+
* a `.primitive/config.json` with no `primitive/config.json` beside it.
|
|
34
|
+
*
|
|
35
|
+
* That shape is refused rather than walked past because the walk's next stop
|
|
36
|
+
* is the parent directory, and in a nested checkout the parent may be a
|
|
37
|
+
* DIFFERENT project — a command run in the unmigrated one would silently act
|
|
38
|
+
* on the other's app. Nothing else is refused (#3392): anything left under
|
|
39
|
+
* `.primitive/` beside a migrated tree is machine-local junk, not signal.
|
|
40
|
+
*
|
|
41
|
+
* One sentence, naming both halves — the file that was found and the file
|
|
42
|
+
* that is expected — and no document. The migration page this once pointed
|
|
43
|
+
* at was never published (#3155, won't-fix), and every reader that shares
|
|
44
|
+
* this refusal — this core, the generated Vite-plugin copy, the Swift
|
|
45
|
+
* pre-build script, the Vue template's deploy script — says the same thing.
|
|
46
|
+
*/
|
|
47
|
+
export declare function unmigratedProjectMessage(found: string, expected: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* The one refusal for a command run outside a Primitive project (#3154,
|
|
50
|
+
* intent criterion 5).
|
|
51
|
+
*
|
|
52
|
+
* There is exactly one way to resolve the configuration tree, the credentials
|
|
53
|
+
* and the app: the environment named by `primitive/config.json`. Outside a
|
|
54
|
+
* project there is no such thing, and the CLI says so once, in these words,
|
|
55
|
+
* wherever the question is asked — the resolver core, the CLI's
|
|
56
|
+
* `requireCurrentEnvironment()`, and the credentials store.
|
|
57
|
+
*
|
|
58
|
+
* Two constraints on the wording, both test-asserted:
|
|
59
|
+
*
|
|
60
|
+
* - it names `primitive init`, the one command that creates what is missing;
|
|
61
|
+
* - it never names `primitive env add`, which after this change also fails
|
|
62
|
+
* outside a project — an error may only offer an invocation it does not
|
|
63
|
+
* itself block.
|
|
64
|
+
*/
|
|
65
|
+
export declare function missingConfigMessage(where: string): string;
|
|
24
66
|
/**
|
|
25
67
|
* Error kinds callers branch on. Every failure is one of these — no reader is
|
|
26
68
|
* ever left guessing what a broken config meant.
|
|
27
69
|
*/
|
|
28
|
-
export type PrimitiveEnvErrorKind = "missing-config" | "malformed-config" | "unsupported-version" | "corrupt-local-state" | "unknown-environment" | "no-selection" | "missing-app-id";
|
|
70
|
+
export type PrimitiveEnvErrorKind = "missing-config" | "malformed-config" | "unsupported-version" | "corrupt-local-state" | "unknown-environment" | "no-selection" | "missing-app-id" | "stale-layout";
|
|
29
71
|
export declare class PrimitiveEnvError extends Error {
|
|
30
72
|
readonly kind: PrimitiveEnvErrorKind;
|
|
31
73
|
readonly path?: string;
|
|
@@ -33,7 +75,12 @@ export declare class PrimitiveEnvError extends Error {
|
|
|
33
75
|
}
|
|
34
76
|
export interface CoreEnvironmentEntry {
|
|
35
77
|
apiUrl: string;
|
|
36
|
-
|
|
78
|
+
/**
|
|
79
|
+
* The one app this environment names (#3152). Required: selecting an
|
|
80
|
+
* environment selects exactly one app, so there is no per-machine "current
|
|
81
|
+
* app" for a second reader to disagree with.
|
|
82
|
+
*/
|
|
83
|
+
appId: string;
|
|
37
84
|
appName?: string;
|
|
38
85
|
/**
|
|
39
86
|
* The app's web counterpart for this environment, as a normalized origin
|
|
@@ -64,7 +111,7 @@ export interface CoreEnvironmentEntry {
|
|
|
64
111
|
*
|
|
65
112
|
* `primitive env add --web-url` and the project-config validation reject those
|
|
66
113
|
* shapes with a field-named error, but neither is on the path from a
|
|
67
|
-
* hand-edited
|
|
114
|
+
* hand-edited `primitive/config.json` to an Xcode build: the Swift template's
|
|
68
115
|
* pre-build script reads the file directly. So every reader that feeds
|
|
69
116
|
* `primitive.json` applies the contract, and a value that misses it is read as
|
|
70
117
|
* "this environment has no web counterpart" — code-only email, no trusted
|
|
@@ -75,6 +122,21 @@ export interface CoreEnvironmentEntry {
|
|
|
75
122
|
* two agree.
|
|
76
123
|
*/
|
|
77
124
|
export declare function normalizeWebOrigin(value: unknown): string | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* The one remedy for an environment that names no app (#3152), shared by every
|
|
127
|
+
* reader that can hit it: this core, the CLI's `validateProjectConfig`, the
|
|
128
|
+
* Swift template's pre-build script, and the Vue template's cf-deploy.
|
|
129
|
+
*
|
|
130
|
+
* Two constraints on the wording, both test-asserted:
|
|
131
|
+
*
|
|
132
|
+
* - it never says `primitive env add <name>`, which REFUSES an environment
|
|
133
|
+
* name that already exists — the shape this error is always about;
|
|
134
|
+
* - it names no command the failure itself blocks. The CLI validates the
|
|
135
|
+
* project config before any command parses, so every `primitive` command
|
|
136
|
+
* run inside the broken project fails with this same error. The only
|
|
137
|
+
* invocation it may offer is one it says out loud to run elsewhere.
|
|
138
|
+
*/
|
|
139
|
+
export declare function missingAppIdMessage(name: string, configPath?: string): string;
|
|
78
140
|
export interface CoreProjectConfig {
|
|
79
141
|
version: number;
|
|
80
142
|
defaultEnvironment?: string;
|
|
@@ -87,7 +149,8 @@ export interface ResolvedPrimitiveEnv {
|
|
|
87
149
|
apiUrl: string;
|
|
88
150
|
/** Derived from apiUrl by scheme swap — never authored separately. */
|
|
89
151
|
wsUrl: string;
|
|
90
|
-
|
|
152
|
+
/** The app this environment names. Always present — see #3152. */
|
|
153
|
+
appId: string;
|
|
91
154
|
appName?: string;
|
|
92
155
|
/** The app's web counterpart for the SELECTED environment, if it has one. */
|
|
93
156
|
webUrl?: string;
|
|
@@ -106,11 +169,6 @@ export interface ResolveOptions {
|
|
|
106
169
|
explicitEnvName?: string | null;
|
|
107
170
|
/** Use this config file instead of discovering one. */
|
|
108
171
|
configPath?: string;
|
|
109
|
-
/**
|
|
110
|
-
* Identity consumers (the Vite plugin, cf-deploy, the Swift script) cannot
|
|
111
|
-
* work without an app ID; plain CLI resolution can, and always could.
|
|
112
|
-
*/
|
|
113
|
-
requireAppId?: boolean;
|
|
114
172
|
}
|
|
115
173
|
/**
|
|
116
174
|
* Derives the WebSocket URL from the API URL. Every apiUrl/wsUrl pair in
|
|
@@ -119,26 +177,39 @@ export interface ResolveOptions {
|
|
|
119
177
|
*/
|
|
120
178
|
export declare function deriveWsUrl(apiUrl: string): string;
|
|
121
179
|
/**
|
|
122
|
-
* Finds
|
|
180
|
+
* Finds `primitive/config.json` by walking up from `cwd`, or returns the
|
|
123
181
|
* PRIMITIVE_PROJECT_CONFIG override when it is set (and exists).
|
|
182
|
+
*
|
|
183
|
+
* The override is checked for provenance BEFORE the file is read (#3153, F2):
|
|
184
|
+
* it bypasses the walk, so without this an old-layout config could be handed
|
|
185
|
+
* straight to a reader and defeat the cutover. An override that points inside
|
|
186
|
+
* a `.primitive/` directory IS the old layout, named explicitly.
|
|
187
|
+
*
|
|
188
|
+
* This is the one function every reader goes through — `resolvePrimitiveEnv`
|
|
189
|
+
* and the CLI's own `loadProjectConfig`/`findProjectRoot` alike — so the
|
|
190
|
+
* unmigrated-project refusal lives HERE, in the walk, or the commands that
|
|
191
|
+
* never call `resolvePrimitiveEnv` would walk past the old anchor into the
|
|
192
|
+
* parent directory's project.
|
|
124
193
|
*/
|
|
125
194
|
export declare function findPrimitiveConfigPath(options?: {
|
|
126
195
|
cwd?: string;
|
|
127
196
|
env?: Record<string, string | undefined>;
|
|
128
197
|
}): string | null;
|
|
129
198
|
/**
|
|
130
|
-
* The project root for a config path: the parent of
|
|
199
|
+
* The project root for a config path: the parent of `primitive/`, or the
|
|
131
200
|
* containing directory when the config was pointed at directly (a fixture via
|
|
132
|
-
* PRIMITIVE_PROJECT_CONFIG, which is not inside a
|
|
201
|
+
* PRIMITIVE_PROJECT_CONFIG, which is not inside a `primitive/` directory).
|
|
133
202
|
*/
|
|
134
203
|
export declare function projectRootForConfigPath(configPath: string): string;
|
|
135
204
|
/**
|
|
136
|
-
*
|
|
137
|
-
* config
|
|
205
|
+
* Machine-local state lives under the project root's `.primitive/`, not beside
|
|
206
|
+
* the config — the config is committed now, and the two must not share a
|
|
207
|
+
* directory. A fixture-pointed bare config still gets its own `.primitive/`
|
|
208
|
+
* in its own directory, so it never picks up a real project's selection.
|
|
138
209
|
*/
|
|
139
210
|
export declare function localStatePathForConfigPath(configPath: string): string;
|
|
140
211
|
/**
|
|
141
|
-
* Reads and structurally validates
|
|
212
|
+
* Reads and structurally validates `primitive/config.json`. Throws rather
|
|
142
213
|
* than guessing: a config that cannot be understood is always louder than a
|
|
143
214
|
* silent fallback to the wrong backend.
|
|
144
215
|
*/
|
|
@@ -65,6 +65,6 @@ const observer = new MutationObserver(async (mutations, obs) => {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
68
|
-
`},transformIndexHtml(e){if(!h||!d)return e;let t=`<style data-primitive-devtools-sonner>${g}</style>`;return e.replace(`</body>`,`${t}\n<script type="module" src="/@id/__x00__virtual:primitive-devtools-init"><\/script>\n</body>`)},hotUpdate({file:e,server:t}){if(e.endsWith(`.primitive-test.ts`)){let e=t.moduleGraph.getModuleById(c);e&&(t.moduleGraph.invalidateModule(e),t.ws.send({type:`full-reload`}))}}}}var f=`.primitive`,
|
|
69
|
-
`)}function
|
|
70
|
-
`)}function
|
|
68
|
+
`},transformIndexHtml(e){if(!h||!d)return e;let t=`<style data-primitive-devtools-sonner>${g}</style>`;return e.replace(`</body>`,`${t}\n<script type="module" src="/@id/__x00__virtual:primitive-devtools-init"><\/script>\n</body>`)},hotUpdate({file:e,server:t}){if(e.endsWith(`.primitive-test.ts`)){let e=t.moduleGraph.getModuleById(c);e&&(t.moduleGraph.invalidateModule(e),t.ws.send({type:`full-reload`}))}}}}var f=`primitive`,p=`.primitive`,m=`config.json`,h=`local.json`,g=`primitive/config.json`,_=`.primitive/local.json`;function v(e,t){return`Found ${e} but no ${t}: this project still uses the retired layout under ${p}/, which is never read.`}function y(e){return`No ${g} found in ${e} or any parent directory. Primitive commands run inside a Primitive project: it is where the CLI reads the environment, the app that environment names, and the configuration tree from. Run 'primitive init' to create one.`}var b=class extends Error{kind;path;constructor(e,t,n){super(t),this.name=`PrimitiveEnvError`,this.kind=e,this.path=n}};function x(e){if(typeof e!=`string`)return;let t=e.trim();if(!t)return;let n;try{n=new URL(t)}catch{return}if(!(n.protocol!==`https:`&&n.protocol!==`http:`)&&!(n.protocol===`http:`&&n.hostname!==`localhost`&&n.hostname!==`127.0.0.1`)&&!(n.username||n.password)&&!(n.pathname!==`/`&&n.pathname!==``)&&!(n.search||n.hash))return n.origin}function S(e,t){return`Environment "${e}" in ${t?`${g} (${t})`:g} has no "appId". Every environment names exactly one app — add "appId": "<app-id>" to that environment in ${g}. Find the app id in the Primitive admin UI, with 'primitive apps list' run from another Primitive project, or as the residual "currentAppId" in .primitive/credentials.json if this environment was ever pointed at an app by the retired per-machine app selection.`}function C(e){if(typeof e==`string`)return e.trim()||void 0}function w(e){return e.startsWith(`https://`)?`wss://`+e.slice(8):e.startsWith(`http://`)?`ws://`+e.slice(7):e}function T(e={}){let n=(e.env??process.env).PRIMITIVE_PROJECT_CONFIG;if(n){let e=(0,a.resolve)(n);if((0,a.basename)((0,a.dirname)(e))===`.primitive`)throw new b(`stale-layout`,v(e,(0,a.join)((0,a.dirname)((0,a.dirname)(e)),f,m)),e);return(0,t.existsSync)(e)?e:null}let r=(0,a.resolve)(e.cwd??process.cwd());for(;;){let e=(0,a.join)(r,f,m);if((0,t.existsSync)(e))return e;let n=(0,a.join)(r,p,m);if((0,t.existsSync)(n))throw new b(`stale-layout`,v(n,e),n);let i=(0,a.dirname)(r);if(i===r)return null;r=i}}function E(e){let t=(0,a.dirname)(e);return(0,a.basename)(t)===`primitive`?(0,a.dirname)(t):t}function D(e){return(0,a.join)(E(e),p,h)}function O(e){return e instanceof Error?e.message:String(e)}function k(e){if(!(0,t.existsSync)(e))throw new b(`missing-config`,y((0,a.dirname)(e)),e);let n;try{n=(0,t.readFileSync)(e,`utf-8`)}catch(t){throw new b(`malformed-config`,`Failed to read ${g} (${e}): ${O(t)}`,e)}let r;try{r=JSON.parse(n)}catch(t){throw new b(`malformed-config`,`Failed to parse ${g} (${e}): ${O(t)}`,e)}if(!r||typeof r!=`object`||Array.isArray(r))throw new b(`malformed-config`,`${g} (${e}) must contain a JSON object at the top level.`,e);let i=r;if(typeof i.version!=`number`||!Number.isInteger(i.version))throw new b(`malformed-config`,`${g} (${e}) is missing required integer field "version".`,e);if(i.version!==1)throw new b(`unsupported-version`,`${g} (${e}) has version ${i.version}, but this tool understands version 1.`,e);if(!i.environments||typeof i.environments!=`object`||Array.isArray(i.environments))throw new b(`malformed-config`,`${g} (${e}) is missing required "environments" object.`,e);let o={};for(let[t,n]of Object.entries(i.environments)){if(!n||typeof n!=`object`||Array.isArray(n))throw new b(`malformed-config`,`Environment "${t}" must be an object in ${g} (${e}).`,e);let r=n;if(typeof r.apiUrl!=`string`||!r.apiUrl)throw new b(`malformed-config`,`Environment "${t}" must have a non-empty "apiUrl" string in ${g} (${e}).`,e);let i=C(r.appId);if(!i)throw new b(`missing-app-id`,S(t,e),e);o[t]={apiUrl:r.apiUrl.replace(/\/$/,``),appId:i,appName:typeof r.appName==`string`?r.appName:void 0,webUrl:x(r.webUrl),description:typeof r.description==`string`?r.description:void 0}}return{version:i.version,defaultEnvironment:typeof i.defaultEnvironment==`string`&&i.defaultEnvironment?i.defaultEnvironment:void 0,environments:o}}function A(e){let n=D(e);if(!(0,t.existsSync)(n))return null;let r=e=>{throw new b(`corrupt-local-state`,`${_} (${n}) is unreadable: ${e}. Delete the file or re-run 'primitive env use <name>'.`,n)},i;try{i=JSON.parse((0,t.readFileSync)(n,`utf-8`))}catch(e){return r(O(e))}if(!i||typeof i!=`object`||Array.isArray(i))return r(`expected a JSON object`);let a=i.selectedEnvironment;return a==null||a===``?null:typeof a==`string`?a:r(`"selectedEnvironment" must be a string`)}function j(e,t){let n=Object.keys(e.environments),r=n.join(`, `)||`(none)`,i=t.configPath?`${g} (${t.configPath})`:g,a=(n,a,o)=>{if(!e.environments[n])throw new b(`unknown-environment`,`Environment "${n}" is not defined in ${i} (selected ${o}). Available: ${r}`,t.configPath);return{name:n,source:a}};if(t.explicitEnvName)return a(t.explicitEnvName,`explicit`,`explicitly`);if(t.envVarName)return a(t.envVarName,`env-var`,`via PRIMITIVE_ENV`);if(t.localSelection)return a(t.localSelection,`local`,`in ${_}`);if(e.defaultEnvironment)return a(e.defaultEnvironment,`default`,`as "defaultEnvironment"`);if(n.length===1)return{name:n[0],source:`sole`};throw n.length===0?new b(`no-selection`,`${i} has no environments defined. Run 'primitive env add <name>' or 'primitive init'.`,t.configPath):new b(`no-selection`,`No environment selected. Run 'primitive env use <name>', set "defaultEnvironment" in ${i}, or export PRIMITIVE_ENV. Available: ${r}`,t.configPath)}function M(e={}){let t=e.env??process.env,n=e.configPath??T({cwd:e.cwd,env:t});if(!n)throw new b(`missing-config`,y(e.cwd??process.cwd()));let r=E(n),i=k(n),{name:a,source:o}=j(i,{explicitEnvName:e.explicitEnvName||null,envVarName:t.PRIMITIVE_ENV||null,localSelection:A(n),configPath:n}),s=i.environments[a];return{name:a,apiUrl:s.apiUrl,wsUrl:w(s.apiUrl),appId:s.appId,appName:s.appName,webUrl:s.webUrl,description:s.description,source:o,configPath:n,localStatePath:D(n),projectRoot:r}}var N=[`VITE_APP_ID`,`VITE_API_URL`,`VITE_WS_URL`,`VITE_APP_NAME`],P=`VITE_EXPECTED_PRIMITIVE_ENV`,F=new Map;function I(e,t){let n=process.env[e];n!==void 0&&n!==``&&F.get(e)!==n||(process.env[e]=t,F.set(e,t))}function L(e={}){return M({cwd:e.root,env:e.env,explicitEnvName:e.primitiveEnv??null})}function R(e,t,n){let r=e=>n.includes(e)?` (overridden)`:``,i=[`[primitive-env] Primitive environment: ${e.name} (selected: ${e.source})`,`[primitive-env] apiUrl: ${t.apiUrl}${r(`VITE_API_URL`)}`,`[primitive-env] wsUrl: ${t.wsUrl}${r(`VITE_WS_URL`)}`,`[primitive-env] appId: ${t.appId??`(unset)`}${r(`VITE_APP_ID`)}`,`[primitive-env] appName: ${t.appName??`(unset)`}${r(`VITE_APP_NAME`)}`,`[primitive-env] config: ${e.configPath}`];return n.length>0&&i.push(`[primitive-env] overridden by the environment: ${n.join(`, `)}`),i.join(`
|
|
69
|
+
`)}function z(e,t){let n=e?.envDir;return n===!1?null:typeof n==`string`&&n!==``?(0,a.resolve)(t,n):t}function B(e,t){let n=process.env[P];if(n!==void 0&&n!==``)return{value:n,where:`the process environment`};if(t===null)return null;for(let n of[`.env.${e}.local`,`.env.${e}`,`.env.local`,`.env`]){let e=G((0,a.join)(t,n))[P];if(e!==void 0)return{value:e,where:n}}return null}function V(e,t,n){return[`[primitive-env] Wrong pair: vite mode "${e}" is declared to run against Primitive environment "${t.value}", but "${n.name}" resolved.`,`[primitive-env] expected: ${t.value} (${P} in ${t.where})`,`[primitive-env] resolved: ${n.name} (selected: ${n.source})`,`[primitive-env] config: ${n.configPath}`,``,`Run the pair you meant — PRIMITIVE_ENV=${t.value} <command> --mode ${e}, or 'primitive env use ${t.value}' — or change/remove ${P} in ${t.where}.`,``,`A mode declares this when its .env.${e} carries values coupled to one backend, so continuing would run this environment's identity with another's configuration.`].join(`
|
|
70
|
+
`)}function H(e,t,n){let r=B(e,t);if(r&&r.value!==``&&r.value!==n.name)throw Error(V(e,r,n))}function U(e={}){let t=null,n=null,r,i=[],a=!1,o=null;return{name:`primitive-env`,enforce:`pre`,config(s,c){a=c?.command===`serve`,o=null;let l=s?.root??process.cwd(),u=c?.mode??`development`,d=W(u,l),f={};for(let e of N){let t=process.env[e],n=t!==void 0&&F.get(e)!==t?t:d[e];n!==void 0&&n!==``&&(f[e]=n)}let p;try{p=M({cwd:l,explicitEnvName:e.primitiveEnv??null})}catch(e){if(e instanceof b&&e.kind===`missing-config`&&f.VITE_APP_ID&&f.VITE_API_URL)return console.warn(`[primitive-env] No primitive/config.json found; using VITE_APP_ID / VITE_API_URL from the environment. Run 'primitive init' to make the project the source of truth.`),r=f.VITE_APP_NAME,{};throw e}if(!(f.VITE_APP_ID&&f.VITE_API_URL)){let e=z(s,l);H(u,e,p),o={root:l,mode:u,dir:e}}t=p,r=f.VITE_APP_NAME??p.appName;let m={VITE_APP_ID:p.appId,VITE_API_URL:p.apiUrl,VITE_WS_URL:p.wsUrl,VITE_APP_NAME:p.appName},h={"import.meta.env.VITE_PRIMITIVE_ENV":JSON.stringify(p.name)},g=[];for(let e of N){if(f[e]!==void 0){g.push(e);continue}let t=m[e];t!==void 0&&(h[`import.meta.env.${e}`]=JSON.stringify(t),I(e,t))}return I(`VITE_PRIMITIVE_ENV`,p.name),i=g,n={apiUrl:f.VITE_API_URL??p.apiUrl,wsUrl:f.VITE_WS_URL??p.wsUrl,appId:f.VITE_APP_ID??p.appId,appName:r},e.logResolved!==!1&&console.log(R(p,n,g)),g.length>0&&console.warn(`[primitive-env] Overridden by an explicit value in .env or the shell: ${g.join(`, `)}. Remove it to use primitive/config.json (deploys reject these outright).`),{define:h}},configResolved(e){if(!o||!t)return;let n=z(e,o.root),r=e?.mode??o.mode;n===o.dir&&r===o.mode||(H(r,n,t),o={root:o.root,mode:r,dir:n})},transformIndexHtml(){if(!a||!t||!n)return[];let e=`%c[primitive] env=${t.name} api=${n.apiUrl} app=${n.appId??`(unset)`} (${t.configPath})`+(i.length>0?` overridden: ${i.join(`, `)}`:``);return[{tag:`script`,injectTo:`head`,children:`console.info(${JSON.stringify(e)}, "color:#888");`}]},appName(){return r},resolved(){return t}}}function W(e,t){let n=[`.env`,`.env.local`,`.env.${e}`,`.env.${e}.local`],r={};for(let e of n)Object.assign(r,G((0,a.join)(t,e)));return r}function G(e){if(!(0,t.existsSync)(e))return{};let n={};for(let r of(0,t.readFileSync)(e,`utf-8`).split(/\r?\n/)){let e=r.trim();if(!e||e.startsWith(`#`))continue;let t=e.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);if(!t)continue;let i=t[2].trim(),a=i[0],o=a===`"`||a===`'`||a==="`"?i.indexOf(a,1):-1;n[t[1]]=o===-1?i.replace(/\s+#.*$/,``).trim():i.slice(1,o)}return n}exports.PrimitiveEnvError=b,exports.primitiveDevTools=d,exports.primitiveEnv=U,exports.resolvePrimitiveEnv=L;
|