bleam 0.0.12 → 0.0.14
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/ai.cjs +5 -4
- package/dist/ai.js +4 -3
- package/dist/app-storage-D8W4n8ey.cjs +39 -0
- package/dist/app-storage-Isi5Bo0R.js +34 -0
- package/dist/cli.cjs +149 -23
- package/dist/cli.d.cts +13 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +149 -23
- package/dist/elements-DX_YUveu.d.ts +341 -0
- package/dist/elements-gEI8YGl1.d.cts +341 -0
- package/dist/elements.cjs +1031 -0
- package/dist/elements.d.cts +2 -0
- package/dist/elements.d.ts +2 -0
- package/dist/elements.js +999 -0
- package/dist/{files-BXVkPrPN.js → files-DErLhzCB.js} +5 -11
- package/dist/{files-DxaQ-Nv0.cjs → files-lMk-CpL_.cjs} +5 -11
- package/dist/files.cjs +1 -1
- package/dist/files.js +1 -1
- package/dist/schema.cjs +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +1 -1
- package/dist/secrets.cjs +146 -0
- package/dist/secrets.d.cts +14 -0
- package/dist/secrets.d.ts +14 -0
- package/dist/secrets.js +142 -0
- package/dist/{state-LssDgpff.cjs → state-Bm9GiRnU.cjs} +61 -47
- package/dist/{state-Dh3HLixb.js → state-D8Firo9w.js} +60 -41
- package/dist/state.cjs +3 -2
- package/dist/state.d.cts +1 -1
- package/dist/state.d.ts +1 -1
- package/dist/state.js +3 -2
- package/dist/window.d.cts +1 -1
- package/dist/window.d.ts +1 -1
- package/package.json +14 -11
- package/templates/basic/app/index.tsx +7 -129
- package/templates/foundation-models/app/index.tsx +100 -41
- package/templates/image-generation/app/index.tsx +2 -2
- package/templates/native/ios/Podfile.lock +6 -0
- package/templates/native/modules/bleam-runtime/ios/AIModule.swift +7 -8
- package/templates/native/package.json +6 -1
- package/templates/native/yarn.lock +5392 -3749
- package/templates/state/app/index.tsx +2 -2
- package/templates/text-generation/app/index.tsx +4 -4
- package/templates/updates/README.md +1 -1
- package/dist/native-sqlite-xcGdamRD.js +0 -64
- package/dist/native-sqlite-yQLD5s9i.cjs +0 -66
- package/dist/ui-1WepaMS4.d.cts +0 -92
- package/dist/ui-D7bRLYee.d.ts +0 -92
- package/dist/ui.cjs +0 -364
- package/dist/ui.d.cts +0 -2
- package/dist/ui.d.ts +0 -2
- package/dist/ui.js +0 -357
- /package/dist/{schema-B5BfdswF.js → schema-B7ELMpuI.js} +0 -0
- /package/dist/{schema-BnVZOXfu.cjs → schema-B7SLUBLN.cjs} +0 -0
- /package/dist/{schema-D5eImHxu.d.cts → schema-BWsDPc6c.d.cts} +0 -0
- /package/dist/{schema-SSjokbtw.d.ts → schema-DsXZBnvc.d.ts} +0 -0
|
@@ -28,26 +28,20 @@ function ensureDirectory(path) {
|
|
|
28
28
|
function parentDirectory(path) {
|
|
29
29
|
return nsString(path).stringByDeletingLastPathComponent;
|
|
30
30
|
}
|
|
31
|
-
function appGroupIdentifier() {
|
|
32
|
-
return String(NSBundle.mainBundle.objectForInfoDictionaryKey("AppGroupIdentifier") ?? "group.dev.bleam.app");
|
|
33
|
-
}
|
|
34
|
-
function containerPath() {
|
|
35
|
-
const url = fileManager().containerURLForSecurityApplicationGroupIdentifier(appGroupIdentifier());
|
|
36
|
-
if (!url?.path) throw new Error("Shared container is unavailable");
|
|
37
|
-
return String(url.path);
|
|
38
|
-
}
|
|
39
31
|
function searchPath(directory) {
|
|
40
32
|
const value = NSSearchPathForDirectoriesInDomains(directory, NSSearchPathDomainMask.UserDomain, true)?.objectAtIndex(0);
|
|
41
33
|
if (typeof value !== "string") throw new Error("Native directory unavailable");
|
|
42
34
|
return value;
|
|
43
35
|
}
|
|
36
|
+
function bleamDirectory(directory, name) {
|
|
37
|
+
return nsString(searchPath(directory)).stringByAppendingPathComponent(`Bleam/${name}`);
|
|
38
|
+
}
|
|
44
39
|
function nativeDirectories() {
|
|
45
|
-
const shared = containerPath();
|
|
46
40
|
return {
|
|
47
41
|
cache: searchPath(NSSearchPathDirectory.Caches),
|
|
48
42
|
documents: searchPath(NSSearchPathDirectory.Document),
|
|
49
|
-
models:
|
|
50
|
-
shared,
|
|
43
|
+
models: bleamDirectory(NSSearchPathDirectory.Caches, "Models"),
|
|
44
|
+
shared: bleamDirectory(NSSearchPathDirectory.ApplicationSupport, "Shared"),
|
|
51
45
|
temporary: NSTemporaryDirectory()
|
|
52
46
|
};
|
|
53
47
|
}
|
|
@@ -28,26 +28,20 @@ function ensureDirectory(path) {
|
|
|
28
28
|
function parentDirectory(path) {
|
|
29
29
|
return nsString(path).stringByDeletingLastPathComponent;
|
|
30
30
|
}
|
|
31
|
-
function appGroupIdentifier() {
|
|
32
|
-
return String(NSBundle.mainBundle.objectForInfoDictionaryKey("AppGroupIdentifier") ?? "group.dev.bleam.app");
|
|
33
|
-
}
|
|
34
|
-
function containerPath() {
|
|
35
|
-
const url = fileManager().containerURLForSecurityApplicationGroupIdentifier(appGroupIdentifier());
|
|
36
|
-
if (!url?.path) throw new Error("Shared container is unavailable");
|
|
37
|
-
return String(url.path);
|
|
38
|
-
}
|
|
39
31
|
function searchPath(directory) {
|
|
40
32
|
const value = NSSearchPathForDirectoriesInDomains(directory, NSSearchPathDomainMask.UserDomain, true)?.objectAtIndex(0);
|
|
41
33
|
if (typeof value !== "string") throw new Error("Native directory unavailable");
|
|
42
34
|
return value;
|
|
43
35
|
}
|
|
36
|
+
function bleamDirectory(directory, name) {
|
|
37
|
+
return nsString(searchPath(directory)).stringByAppendingPathComponent(`Bleam/${name}`);
|
|
38
|
+
}
|
|
44
39
|
function nativeDirectories() {
|
|
45
|
-
const shared = containerPath();
|
|
46
40
|
return {
|
|
47
41
|
cache: searchPath(NSSearchPathDirectory.Caches),
|
|
48
42
|
documents: searchPath(NSSearchPathDirectory.Document),
|
|
49
|
-
models:
|
|
50
|
-
shared,
|
|
43
|
+
models: bleamDirectory(NSSearchPathDirectory.Caches, "Models"),
|
|
44
|
+
shared: bleamDirectory(NSSearchPathDirectory.ApplicationSupport, "Shared"),
|
|
51
45
|
temporary: NSTemporaryDirectory()
|
|
52
46
|
};
|
|
53
47
|
}
|
package/dist/files.cjs
CHANGED
package/dist/files.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "./native-runtime-C85Nuc4F.js";
|
|
2
|
-
import { i as files, n as DownloadTask, r as FileRef, t as DirectoryRef } from "./files-
|
|
2
|
+
import { i as files, n as DownloadTask, r as FileRef, t as DirectoryRef } from "./files-DErLhzCB.js";
|
|
3
3
|
|
|
4
4
|
export { DirectoryRef, DownloadTask, FileRef, files };
|
package/dist/schema.cjs
CHANGED
package/dist/schema.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as array, C as SchemaOutput, D as StandardSchema, E as SchemaShape, F as number, I as object, L as schema, M as getFieldSchema, N as getValueAtPath, O as StringField, P as literal, R as string, S as SchemaJSONSchema, T as SchemaResult, _ as ObjectField, a as FieldAtFieldPath, b as SchemaInput, c as FieldPath, d as FieldValue, f as InferInput, g as NumberField, h as LiteralField, i as DeepPartial, j as boolean, k as ValueAtFieldPath, l as FieldSchema, m as JSONValue, n as BleamSchema, o as FieldInput, p as InferOutput, r as BooleanField, s as FieldOutput, t as ArrayField, u as FieldToken, v as PrimitiveValue, w as SchemaPatch, x as SchemaIssue, y as SchemaError } from "./schema-
|
|
1
|
+
import { A as array, C as SchemaOutput, D as StandardSchema, E as SchemaShape, F as number, I as object, L as schema, M as getFieldSchema, N as getValueAtPath, O as StringField, P as literal, R as string, S as SchemaJSONSchema, T as SchemaResult, _ as ObjectField, a as FieldAtFieldPath, b as SchemaInput, c as FieldPath, d as FieldValue, f as InferInput, g as NumberField, h as LiteralField, i as DeepPartial, j as boolean, k as ValueAtFieldPath, l as FieldSchema, m as JSONValue, n as BleamSchema, o as FieldInput, p as InferOutput, r as BooleanField, s as FieldOutput, t as ArrayField, u as FieldToken, v as PrimitiveValue, w as SchemaPatch, x as SchemaIssue, y as SchemaError } from "./schema-BWsDPc6c.cjs";
|
|
2
2
|
export { ArrayField, BleamSchema, BooleanField, DeepPartial, FieldAtFieldPath, FieldInput, FieldOutput, FieldPath, FieldSchema, FieldToken, FieldValue, InferInput, InferOutput, JSONValue, LiteralField, NumberField, ObjectField, PrimitiveValue, SchemaError, SchemaInput, SchemaIssue, SchemaJSONSchema, SchemaOutput, SchemaPatch, SchemaResult, SchemaShape, StandardSchema, StringField, ValueAtFieldPath, array, boolean, getFieldSchema, getValueAtPath, literal, number, object, schema, string };
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as array, C as SchemaOutput, D as StandardSchema, E as SchemaShape, F as number, I as object, L as schema, M as getFieldSchema, N as getValueAtPath, O as StringField, P as literal, R as string, S as SchemaJSONSchema, T as SchemaResult, _ as ObjectField, a as FieldAtFieldPath, b as SchemaInput, c as FieldPath, d as FieldValue, f as InferInput, g as NumberField, h as LiteralField, i as DeepPartial, j as boolean, k as ValueAtFieldPath, l as FieldSchema, m as JSONValue, n as BleamSchema, o as FieldInput, p as InferOutput, r as BooleanField, s as FieldOutput, t as ArrayField, u as FieldToken, v as PrimitiveValue, w as SchemaPatch, x as SchemaIssue, y as SchemaError } from "./schema-
|
|
1
|
+
import { A as array, C as SchemaOutput, D as StandardSchema, E as SchemaShape, F as number, I as object, L as schema, M as getFieldSchema, N as getValueAtPath, O as StringField, P as literal, R as string, S as SchemaJSONSchema, T as SchemaResult, _ as ObjectField, a as FieldAtFieldPath, b as SchemaInput, c as FieldPath, d as FieldValue, f as InferInput, g as NumberField, h as LiteralField, i as DeepPartial, j as boolean, k as ValueAtFieldPath, l as FieldSchema, m as JSONValue, n as BleamSchema, o as FieldInput, p as InferOutput, r as BooleanField, s as FieldOutput, t as ArrayField, u as FieldToken, v as PrimitiveValue, w as SchemaPatch, x as SchemaIssue, y as SchemaError } from "./schema-DsXZBnvc.js";
|
|
2
2
|
export { ArrayField, BleamSchema, BooleanField, DeepPartial, FieldAtFieldPath, FieldInput, FieldOutput, FieldPath, FieldSchema, FieldToken, FieldValue, InferInput, InferOutput, JSONValue, LiteralField, NumberField, ObjectField, PrimitiveValue, SchemaError, SchemaInput, SchemaIssue, SchemaJSONSchema, SchemaOutput, SchemaPatch, SchemaResult, SchemaShape, StandardSchema, StringField, ValueAtFieldPath, array, boolean, getFieldSchema, getValueAtPath, literal, number, object, schema, string };
|
package/dist/schema.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as getValueAtPath, c as object, i as getFieldSchema, l as schema, n as array, o as literal, r as boolean, s as number, t as SchemaError, u as string } from "./schema-
|
|
1
|
+
import { a as getValueAtPath, c as object, i as getFieldSchema, l as schema, n as array, o as literal, r as boolean, s as number, t as SchemaError, u as string } from "./schema-B7ELMpuI.js";
|
|
2
2
|
|
|
3
3
|
export { SchemaError, array, boolean, getFieldSchema, getValueAtPath, literal, number, object, schema, string };
|
package/dist/secrets.cjs
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
const require_native_runtime = require('./native-runtime-CsXnXkQn.cjs');
|
|
2
|
+
const require_app_storage = require('./app-storage-D8W4n8ey.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/native-secrets.ts
|
|
5
|
+
var NativeSecretsError = class extends Error {
|
|
6
|
+
constructor(status, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.name = "NativeSecretsError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
let securityLoaded = false;
|
|
13
|
+
function ensureSecurity() {
|
|
14
|
+
if (securityLoaded) return;
|
|
15
|
+
const nativeScript = require_native_runtime.ensureNativeScript();
|
|
16
|
+
if (!nativeScript.isFrameworkLoaded("Security") && !nativeScript.loadFramework("Security")) throw new NativeSecretsError(void 0, "Keychain is unavailable");
|
|
17
|
+
securityLoaded = true;
|
|
18
|
+
}
|
|
19
|
+
function dictionary(capacity) {
|
|
20
|
+
return NSMutableDictionary.dictionaryWithCapacity(capacity);
|
|
21
|
+
}
|
|
22
|
+
function set(target, key, value) {
|
|
23
|
+
target.setObjectForKey(value, key);
|
|
24
|
+
}
|
|
25
|
+
function serviceName() {
|
|
26
|
+
return NSString.stringWithString(`dev.bleam.apps.${require_app_storage.currentAppStorageKey()}.secrets`);
|
|
27
|
+
}
|
|
28
|
+
function baseQuery(key) {
|
|
29
|
+
ensureSecurity();
|
|
30
|
+
const query = dictionary(4);
|
|
31
|
+
set(query, kSecClass, kSecClassGenericPassword);
|
|
32
|
+
set(query, kSecAttrService, serviceName());
|
|
33
|
+
set(query, kSecAttrAccount, NSString.stringWithString(key));
|
|
34
|
+
set(query, kSecUseDataProtectionKeychain, NSNumber.numberWithBool(true));
|
|
35
|
+
return query;
|
|
36
|
+
}
|
|
37
|
+
function statusMessage(status) {
|
|
38
|
+
const message = SecCopyErrorMessageString(status, null);
|
|
39
|
+
return message ? String(message) : `Keychain operation failed (${status})`;
|
|
40
|
+
}
|
|
41
|
+
function failure(status) {
|
|
42
|
+
return new NativeSecretsError(status, statusMessage(status));
|
|
43
|
+
}
|
|
44
|
+
function nativeSetItem(key, value) {
|
|
45
|
+
const query = baseQuery(key);
|
|
46
|
+
const encoded = NSString.stringWithString(value).dataUsingEncoding(NSUTF8StringEncoding);
|
|
47
|
+
const update = dictionary(1);
|
|
48
|
+
set(update, kSecValueData, encoded);
|
|
49
|
+
const updateStatus = SecItemUpdate(query, update);
|
|
50
|
+
if (updateStatus === errSecSuccess) return;
|
|
51
|
+
if (updateStatus !== errSecItemNotFound) throw failure(updateStatus);
|
|
52
|
+
set(query, kSecValueData, encoded);
|
|
53
|
+
set(query, kSecAttrAccessible, kSecAttrAccessibleWhenUnlockedThisDeviceOnly);
|
|
54
|
+
const addStatus = SecItemAdd(query, null);
|
|
55
|
+
if (addStatus === errSecSuccess) return;
|
|
56
|
+
if (addStatus === errSecDuplicateItem) {
|
|
57
|
+
const retryStatus = SecItemUpdate(baseQuery(key), update);
|
|
58
|
+
if (retryStatus === errSecSuccess) return;
|
|
59
|
+
throw failure(retryStatus);
|
|
60
|
+
}
|
|
61
|
+
throw failure(addStatus);
|
|
62
|
+
}
|
|
63
|
+
function nativeGetItem(key) {
|
|
64
|
+
const query = baseQuery(key);
|
|
65
|
+
set(query, kSecReturnData, NSNumber.numberWithBool(true));
|
|
66
|
+
set(query, kSecMatchLimit, kSecMatchLimitOne);
|
|
67
|
+
const result = new interop.Reference();
|
|
68
|
+
const status = SecItemCopyMatching(query, result);
|
|
69
|
+
if (status === errSecItemNotFound) return void 0;
|
|
70
|
+
if (status !== errSecSuccess) throw failure(status);
|
|
71
|
+
if (!result.value) throw new NativeSecretsError(errSecDecode, "Keychain returned invalid data");
|
|
72
|
+
const decoded = NSString.alloc().initWithDataEncoding(result.value, NSUTF8StringEncoding);
|
|
73
|
+
if (!decoded) throw new NativeSecretsError(errSecDecode, "Keychain returned invalid data");
|
|
74
|
+
return String(decoded);
|
|
75
|
+
}
|
|
76
|
+
function nativeHasItem(key) {
|
|
77
|
+
const status = SecItemCopyMatching(baseQuery(key), null);
|
|
78
|
+
if (status === errSecSuccess) return true;
|
|
79
|
+
if (status === errSecItemNotFound) return false;
|
|
80
|
+
throw failure(status);
|
|
81
|
+
}
|
|
82
|
+
function nativeRemoveItem(key) {
|
|
83
|
+
const status = SecItemDelete(baseQuery(key));
|
|
84
|
+
if (status === errSecSuccess || status === errSecItemNotFound) return;
|
|
85
|
+
throw failure(status);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/secrets.ts
|
|
90
|
+
var SecretsError = class extends Error {
|
|
91
|
+
constructor(code, message, status, cause) {
|
|
92
|
+
super(message);
|
|
93
|
+
this.code = code;
|
|
94
|
+
this.status = status;
|
|
95
|
+
this.cause = cause;
|
|
96
|
+
this.name = "SecretsError";
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
function validateKey(key) {
|
|
100
|
+
if (typeof key !== "string" || key.trim().length === 0) throw new SecretsError("invalid_key", "Secret key must not be empty");
|
|
101
|
+
}
|
|
102
|
+
function mapError(error) {
|
|
103
|
+
if (error instanceof SecretsError) return error;
|
|
104
|
+
if (!(error instanceof NativeSecretsError)) return new SecretsError("operation_failed", "Keychain operation failed", void 0, error);
|
|
105
|
+
return new SecretsError(error.status === void 0 || error.status === errSecNotAvailable ? "unavailable" : error.status === errSecInteractionNotAllowed ? "interaction_not_allowed" : error.status === errSecAuthFailed || error.status === errSecUserCanceled ? "authentication_failed" : error.status === errSecMissingEntitlement || error.status === errSecNoAccessForItem ? "permission_denied" : error.status === errSecDecode ? "invalid_data" : "operation_failed", error.message, error.status, error);
|
|
106
|
+
}
|
|
107
|
+
async function setItem(key, value) {
|
|
108
|
+
validateKey(key);
|
|
109
|
+
if (typeof value !== "string") throw new SecretsError("invalid_value", "Secret value must be a string");
|
|
110
|
+
try {
|
|
111
|
+
nativeSetItem(key, value);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
throw mapError(error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function getItem(key) {
|
|
117
|
+
validateKey(key);
|
|
118
|
+
try {
|
|
119
|
+
return nativeGetItem(key);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
throw mapError(error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function hasItem(key) {
|
|
125
|
+
validateKey(key);
|
|
126
|
+
try {
|
|
127
|
+
return nativeHasItem(key);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
throw mapError(error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function removeItem(key) {
|
|
133
|
+
validateKey(key);
|
|
134
|
+
try {
|
|
135
|
+
nativeRemoveItem(key);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw mapError(error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//#endregion
|
|
142
|
+
exports.SecretsError = SecretsError;
|
|
143
|
+
exports.getItem = getItem;
|
|
144
|
+
exports.hasItem = hasItem;
|
|
145
|
+
exports.removeItem = removeItem;
|
|
146
|
+
exports.setItem = setItem;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/secrets.d.ts
|
|
2
|
+
type SecretsErrorCode = 'invalid_key' | 'invalid_value' | 'unavailable' | 'interaction_not_allowed' | 'authentication_failed' | 'permission_denied' | 'invalid_data' | 'operation_failed';
|
|
3
|
+
declare class SecretsError extends Error {
|
|
4
|
+
readonly code: SecretsErrorCode;
|
|
5
|
+
readonly status?: number | undefined;
|
|
6
|
+
readonly cause?: unknown | undefined;
|
|
7
|
+
constructor(code: SecretsErrorCode, message: string, status?: number | undefined, cause?: unknown | undefined);
|
|
8
|
+
}
|
|
9
|
+
declare function setItem(key: string, value: string): Promise<void>;
|
|
10
|
+
declare function getItem(key: string): Promise<string | undefined>;
|
|
11
|
+
declare function hasItem(key: string): Promise<boolean>;
|
|
12
|
+
declare function removeItem(key: string): Promise<void>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { SecretsError, SecretsErrorCode, getItem, hasItem, removeItem, setItem };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/secrets.d.ts
|
|
2
|
+
type SecretsErrorCode = 'invalid_key' | 'invalid_value' | 'unavailable' | 'interaction_not_allowed' | 'authentication_failed' | 'permission_denied' | 'invalid_data' | 'operation_failed';
|
|
3
|
+
declare class SecretsError extends Error {
|
|
4
|
+
readonly code: SecretsErrorCode;
|
|
5
|
+
readonly status?: number | undefined;
|
|
6
|
+
readonly cause?: unknown | undefined;
|
|
7
|
+
constructor(code: SecretsErrorCode, message: string, status?: number | undefined, cause?: unknown | undefined);
|
|
8
|
+
}
|
|
9
|
+
declare function setItem(key: string, value: string): Promise<void>;
|
|
10
|
+
declare function getItem(key: string): Promise<string | undefined>;
|
|
11
|
+
declare function hasItem(key: string): Promise<boolean>;
|
|
12
|
+
declare function removeItem(key: string): Promise<void>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { SecretsError, SecretsErrorCode, getItem, hasItem, removeItem, setItem };
|
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { t as ensureNativeScript } from "./native-runtime-C85Nuc4F.js";
|
|
2
|
+
import { t as currentAppStorageKey } from "./app-storage-Isi5Bo0R.js";
|
|
3
|
+
|
|
4
|
+
//#region src/native-secrets.ts
|
|
5
|
+
var NativeSecretsError = class extends Error {
|
|
6
|
+
constructor(status, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.name = "NativeSecretsError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
let securityLoaded = false;
|
|
13
|
+
function ensureSecurity() {
|
|
14
|
+
if (securityLoaded) return;
|
|
15
|
+
const nativeScript = ensureNativeScript();
|
|
16
|
+
if (!nativeScript.isFrameworkLoaded("Security") && !nativeScript.loadFramework("Security")) throw new NativeSecretsError(void 0, "Keychain is unavailable");
|
|
17
|
+
securityLoaded = true;
|
|
18
|
+
}
|
|
19
|
+
function dictionary(capacity) {
|
|
20
|
+
return NSMutableDictionary.dictionaryWithCapacity(capacity);
|
|
21
|
+
}
|
|
22
|
+
function set(target, key, value) {
|
|
23
|
+
target.setObjectForKey(value, key);
|
|
24
|
+
}
|
|
25
|
+
function serviceName() {
|
|
26
|
+
return NSString.stringWithString(`dev.bleam.apps.${currentAppStorageKey()}.secrets`);
|
|
27
|
+
}
|
|
28
|
+
function baseQuery(key) {
|
|
29
|
+
ensureSecurity();
|
|
30
|
+
const query = dictionary(4);
|
|
31
|
+
set(query, kSecClass, kSecClassGenericPassword);
|
|
32
|
+
set(query, kSecAttrService, serviceName());
|
|
33
|
+
set(query, kSecAttrAccount, NSString.stringWithString(key));
|
|
34
|
+
set(query, kSecUseDataProtectionKeychain, NSNumber.numberWithBool(true));
|
|
35
|
+
return query;
|
|
36
|
+
}
|
|
37
|
+
function statusMessage(status) {
|
|
38
|
+
const message = SecCopyErrorMessageString(status, null);
|
|
39
|
+
return message ? String(message) : `Keychain operation failed (${status})`;
|
|
40
|
+
}
|
|
41
|
+
function failure(status) {
|
|
42
|
+
return new NativeSecretsError(status, statusMessage(status));
|
|
43
|
+
}
|
|
44
|
+
function nativeSetItem(key, value) {
|
|
45
|
+
const query = baseQuery(key);
|
|
46
|
+
const encoded = NSString.stringWithString(value).dataUsingEncoding(NSUTF8StringEncoding);
|
|
47
|
+
const update = dictionary(1);
|
|
48
|
+
set(update, kSecValueData, encoded);
|
|
49
|
+
const updateStatus = SecItemUpdate(query, update);
|
|
50
|
+
if (updateStatus === errSecSuccess) return;
|
|
51
|
+
if (updateStatus !== errSecItemNotFound) throw failure(updateStatus);
|
|
52
|
+
set(query, kSecValueData, encoded);
|
|
53
|
+
set(query, kSecAttrAccessible, kSecAttrAccessibleWhenUnlockedThisDeviceOnly);
|
|
54
|
+
const addStatus = SecItemAdd(query, null);
|
|
55
|
+
if (addStatus === errSecSuccess) return;
|
|
56
|
+
if (addStatus === errSecDuplicateItem) {
|
|
57
|
+
const retryStatus = SecItemUpdate(baseQuery(key), update);
|
|
58
|
+
if (retryStatus === errSecSuccess) return;
|
|
59
|
+
throw failure(retryStatus);
|
|
60
|
+
}
|
|
61
|
+
throw failure(addStatus);
|
|
62
|
+
}
|
|
63
|
+
function nativeGetItem(key) {
|
|
64
|
+
const query = baseQuery(key);
|
|
65
|
+
set(query, kSecReturnData, NSNumber.numberWithBool(true));
|
|
66
|
+
set(query, kSecMatchLimit, kSecMatchLimitOne);
|
|
67
|
+
const result = new interop.Reference();
|
|
68
|
+
const status = SecItemCopyMatching(query, result);
|
|
69
|
+
if (status === errSecItemNotFound) return void 0;
|
|
70
|
+
if (status !== errSecSuccess) throw failure(status);
|
|
71
|
+
if (!result.value) throw new NativeSecretsError(errSecDecode, "Keychain returned invalid data");
|
|
72
|
+
const decoded = NSString.alloc().initWithDataEncoding(result.value, NSUTF8StringEncoding);
|
|
73
|
+
if (!decoded) throw new NativeSecretsError(errSecDecode, "Keychain returned invalid data");
|
|
74
|
+
return String(decoded);
|
|
75
|
+
}
|
|
76
|
+
function nativeHasItem(key) {
|
|
77
|
+
const status = SecItemCopyMatching(baseQuery(key), null);
|
|
78
|
+
if (status === errSecSuccess) return true;
|
|
79
|
+
if (status === errSecItemNotFound) return false;
|
|
80
|
+
throw failure(status);
|
|
81
|
+
}
|
|
82
|
+
function nativeRemoveItem(key) {
|
|
83
|
+
const status = SecItemDelete(baseQuery(key));
|
|
84
|
+
if (status === errSecSuccess || status === errSecItemNotFound) return;
|
|
85
|
+
throw failure(status);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/secrets.ts
|
|
90
|
+
var SecretsError = class extends Error {
|
|
91
|
+
constructor(code, message, status, cause) {
|
|
92
|
+
super(message);
|
|
93
|
+
this.code = code;
|
|
94
|
+
this.status = status;
|
|
95
|
+
this.cause = cause;
|
|
96
|
+
this.name = "SecretsError";
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
function validateKey(key) {
|
|
100
|
+
if (typeof key !== "string" || key.trim().length === 0) throw new SecretsError("invalid_key", "Secret key must not be empty");
|
|
101
|
+
}
|
|
102
|
+
function mapError(error) {
|
|
103
|
+
if (error instanceof SecretsError) return error;
|
|
104
|
+
if (!(error instanceof NativeSecretsError)) return new SecretsError("operation_failed", "Keychain operation failed", void 0, error);
|
|
105
|
+
return new SecretsError(error.status === void 0 || error.status === errSecNotAvailable ? "unavailable" : error.status === errSecInteractionNotAllowed ? "interaction_not_allowed" : error.status === errSecAuthFailed || error.status === errSecUserCanceled ? "authentication_failed" : error.status === errSecMissingEntitlement || error.status === errSecNoAccessForItem ? "permission_denied" : error.status === errSecDecode ? "invalid_data" : "operation_failed", error.message, error.status, error);
|
|
106
|
+
}
|
|
107
|
+
async function setItem(key, value) {
|
|
108
|
+
validateKey(key);
|
|
109
|
+
if (typeof value !== "string") throw new SecretsError("invalid_value", "Secret value must be a string");
|
|
110
|
+
try {
|
|
111
|
+
nativeSetItem(key, value);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
throw mapError(error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function getItem(key) {
|
|
117
|
+
validateKey(key);
|
|
118
|
+
try {
|
|
119
|
+
return nativeGetItem(key);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
throw mapError(error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function hasItem(key) {
|
|
125
|
+
validateKey(key);
|
|
126
|
+
try {
|
|
127
|
+
return nativeHasItem(key);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
throw mapError(error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function removeItem(key) {
|
|
133
|
+
validateKey(key);
|
|
134
|
+
try {
|
|
135
|
+
nativeRemoveItem(key);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw mapError(error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//#endregion
|
|
142
|
+
export { SecretsError, getItem, hasItem, removeItem, setItem };
|
|
@@ -1,45 +1,16 @@
|
|
|
1
1
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
2
|
-
const require_native_runtime = require('./native-runtime-CsXnXkQn.cjs');
|
|
3
2
|
const require_crypto = require('./crypto-CT3VZ7lF.cjs');
|
|
4
|
-
const
|
|
3
|
+
const require_app_storage = require('./app-storage-D8W4n8ey.cjs');
|
|
4
|
+
const require_schema = require('./schema-B7SLUBLN.cjs');
|
|
5
5
|
let jotai_react = require("jotai/react");
|
|
6
6
|
jotai_react = require_chunk.__toESM(jotai_react);
|
|
7
7
|
let jotai_vanilla = require("jotai/vanilla");
|
|
8
8
|
jotai_vanilla = require_chunk.__toESM(jotai_vanilla);
|
|
9
9
|
let jotai_family = require("jotai-family");
|
|
10
10
|
jotai_family = require_chunk.__toESM(jotai_family);
|
|
11
|
+
let expo_sqlite = require("expo-sqlite");
|
|
12
|
+
expo_sqlite = require_chunk.__toESM(expo_sqlite);
|
|
11
13
|
|
|
12
|
-
//#region src/app-storage.ts
|
|
13
|
-
let cachedStorageKey;
|
|
14
|
-
function launchArgument(name) {
|
|
15
|
-
const argumentsList = NSProcessInfo.processInfo.arguments();
|
|
16
|
-
const count = Number(argumentsList.count ?? 0);
|
|
17
|
-
for (let index = 0; index < count - 1; index += 1) if (String(argumentsList.objectAtIndex(index)) === name) return String(argumentsList.objectAtIndex(index + 1));
|
|
18
|
-
}
|
|
19
|
-
function storageKey$1(name) {
|
|
20
|
-
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "app";
|
|
21
|
-
}
|
|
22
|
-
function currentAppStorageKey() {
|
|
23
|
-
if (cachedStorageKey) return cachedStorageKey;
|
|
24
|
-
require_native_runtime.ensureNativeScript();
|
|
25
|
-
const configPath = launchArgument("--bleam-project-config");
|
|
26
|
-
if (configPath) try {
|
|
27
|
-
const text = String(NSString.stringWithContentsOfFileEncodingError(configPath, NSUTF8StringEncoding, null));
|
|
28
|
-
const config = JSON.parse(text);
|
|
29
|
-
if (typeof config.id === "string" && config.id) {
|
|
30
|
-
cachedStorageKey = config.id;
|
|
31
|
-
return cachedStorageKey;
|
|
32
|
-
}
|
|
33
|
-
if (typeof config.name === "string" && config.name) {
|
|
34
|
-
cachedStorageKey = storageKey$1(config.name);
|
|
35
|
-
return cachedStorageKey;
|
|
36
|
-
}
|
|
37
|
-
} catch {}
|
|
38
|
-
cachedStorageKey = "app";
|
|
39
|
-
return cachedStorageKey;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
//#endregion
|
|
43
14
|
//#region src/state/atom.ts
|
|
44
15
|
const storedAtomsKey = Symbol.for("bleam.state.storedAtoms.v1");
|
|
45
16
|
function storedAtoms() {
|
|
@@ -62,7 +33,7 @@ function asWritableAtom(value) {
|
|
|
62
33
|
function storageKey(key) {
|
|
63
34
|
const trimmed = key.trim();
|
|
64
35
|
if (!trimmed) throw new Error("Atom storage key must not be empty");
|
|
65
|
-
return `bleam.apps.${currentAppStorageKey()}.atoms.${trimmed}`;
|
|
36
|
+
return `bleam.apps.${require_app_storage.currentAppStorageKey()}.atoms.${trimmed}`;
|
|
66
37
|
}
|
|
67
38
|
function assertStoredValue(value, seen = /* @__PURE__ */ new Set()) {
|
|
68
39
|
if (value === null) return;
|
|
@@ -159,6 +130,55 @@ function internalJotaiWritableAtom(value) {
|
|
|
159
130
|
}
|
|
160
131
|
const internalStore = (0, jotai_vanilla.getDefaultStore)();
|
|
161
132
|
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/native-sqlite.ts
|
|
135
|
+
const databases = /* @__PURE__ */ new Map();
|
|
136
|
+
function toExpoParameters(parameters) {
|
|
137
|
+
return parameters;
|
|
138
|
+
}
|
|
139
|
+
function toSQLiteValue(value) {
|
|
140
|
+
if (typeof value === "string" || typeof value === "number" || value === null) return value;
|
|
141
|
+
throw new Error("SQLite blobs are not supported by Bleam state yet");
|
|
142
|
+
}
|
|
143
|
+
function toSQLiteRow(row) {
|
|
144
|
+
const output = {};
|
|
145
|
+
for (const [key, value] of Object.entries(row)) output[key] = toSQLiteValue(value);
|
|
146
|
+
return output;
|
|
147
|
+
}
|
|
148
|
+
var NativeSQLiteDatabase = class NativeSQLiteDatabase {
|
|
149
|
+
constructor(database) {
|
|
150
|
+
this.database = database;
|
|
151
|
+
}
|
|
152
|
+
async execute(query, parameters) {
|
|
153
|
+
await this.database.runAsync(query, toExpoParameters(parameters) ?? []);
|
|
154
|
+
}
|
|
155
|
+
async select(query, parameters) {
|
|
156
|
+
return (await this.database.getAllAsync(query, toExpoParameters(parameters) ?? [])).map(toSQLiteRow);
|
|
157
|
+
}
|
|
158
|
+
async get(query, parameters) {
|
|
159
|
+
const row = await this.database.getFirstAsync(query, toExpoParameters(parameters) ?? []);
|
|
160
|
+
return row ? toSQLiteRow(row) : void 0;
|
|
161
|
+
}
|
|
162
|
+
async transaction(action) {
|
|
163
|
+
let result;
|
|
164
|
+
await this.database.withExclusiveTransactionAsync(async (transaction) => {
|
|
165
|
+
result = await action(new NativeSQLiteDatabase(transaction));
|
|
166
|
+
});
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
close() {
|
|
170
|
+
return this.database.closeAsync();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
function openNativeSQLiteDatabase(name = "bleam.sqlite3") {
|
|
174
|
+
let database = databases.get(name);
|
|
175
|
+
if (!database) {
|
|
176
|
+
database = (0, expo_sqlite.openDatabaseAsync)(name).then((value) => new NativeSQLiteDatabase(value));
|
|
177
|
+
databases.set(name, database);
|
|
178
|
+
}
|
|
179
|
+
return database;
|
|
180
|
+
}
|
|
181
|
+
|
|
162
182
|
//#endregion
|
|
163
183
|
//#region src/state/collection.ts
|
|
164
184
|
var CollectionVersionConflictError = class extends Error {
|
|
@@ -186,18 +206,18 @@ let jsonSqlSupportPromise;
|
|
|
186
206
|
let mutationPipeline = Promise.resolve();
|
|
187
207
|
let transactionCallbackStarting = false;
|
|
188
208
|
function getDatabase() {
|
|
189
|
-
databasePromise ??= Promise.resolve().then(() =>
|
|
209
|
+
databasePromise ??= Promise.resolve().then(() => openNativeSQLiteDatabase(`${require_app_storage.currentAppStorageKey()}.sqlite3`));
|
|
190
210
|
return databasePromise;
|
|
191
211
|
}
|
|
192
212
|
async function initializedDatabase() {
|
|
193
213
|
initializedPromise ??= (async () => {
|
|
194
214
|
const database = await getDatabase();
|
|
195
215
|
await database.execute("PRAGMA journal_mode = WAL");
|
|
196
|
-
if (numberValue(await database.get("PRAGMA user_version"), "user_version", 0) !== schemaVersion) await database.transaction(async () => {
|
|
197
|
-
await
|
|
198
|
-
await
|
|
199
|
-
await createTables(
|
|
200
|
-
await
|
|
216
|
+
if (numberValue(await database.get("PRAGMA user_version"), "user_version", 0) !== schemaVersion) await database.transaction(async (transaction) => {
|
|
217
|
+
await transaction.execute("DROP TABLE IF EXISTS links");
|
|
218
|
+
await transaction.execute("DROP TABLE IF EXISTS collections");
|
|
219
|
+
await createTables(transaction);
|
|
220
|
+
await transaction.execute(`PRAGMA user_version = ${schemaVersion}`);
|
|
201
221
|
});
|
|
202
222
|
else await createTables(database);
|
|
203
223
|
return database;
|
|
@@ -679,7 +699,7 @@ function enqueueMutation(action) {
|
|
|
679
699
|
const database = await initializedDatabase();
|
|
680
700
|
const changes = /* @__PURE__ */ new Map();
|
|
681
701
|
try {
|
|
682
|
-
const value = await database.transaction(() => action(
|
|
702
|
+
const value = await database.transaction((transaction) => action(transaction, changes));
|
|
683
703
|
publishChanges(changes);
|
|
684
704
|
resolve(value);
|
|
685
705
|
} catch (error) {
|
|
@@ -893,12 +913,6 @@ Object.defineProperty(exports, 'atomCollection', {
|
|
|
893
913
|
return atomCollection;
|
|
894
914
|
}
|
|
895
915
|
});
|
|
896
|
-
Object.defineProperty(exports, 'currentAppStorageKey', {
|
|
897
|
-
enumerable: true,
|
|
898
|
-
get: function () {
|
|
899
|
-
return currentAppStorageKey;
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
916
|
Object.defineProperty(exports, 'internalJotaiAtom', {
|
|
903
917
|
enumerable: true,
|
|
904
918
|
get: function () {
|