@blotch/angular-lynx 22.2.5 → 22.2.7
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/fesm2022/blotch-angular-lynx-arena-Cycr_O6y.mjs +755 -0
- package/fesm2022/blotch-angular-lynx-arena-Cycr_O6y.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx-const-MkK6UdZ7.mjs +30 -0
- package/fesm2022/blotch-angular-lynx-const-MkK6UdZ7.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx-drawn-scale-ExB6Yx-p.mjs +9 -0
- package/fesm2022/blotch-angular-lynx-drawn-scale-ExB6Yx-p.mjs.map +1 -0
- package/fesm2022/{blotch-angular-lynx-web-glass-zlVeee5K.mjs → blotch-angular-lynx-web-glass-Bmp-vSYh.mjs} +2 -7
- package/fesm2022/blotch-angular-lynx-web-glass-Bmp-vSYh.mjs.map +1 -0
- package/fesm2022/blotch-angular-lynx.mjs +4051 -3800
- package/fesm2022/blotch-angular-lynx.mjs.map +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/index.js +7 -3
- package/schematics/utility/pnpm-builds.js +210 -0
- package/types/blotch-angular-lynx.d.ts +214 -3
- package/fesm2022/blotch-angular-lynx-web-glass-zlVeee5K.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ const dependency_1 = require("@schematics/angular/utility/dependency");
|
|
|
5
5
|
const json_file_1 = require("@schematics/angular/utility/json-file");
|
|
6
6
|
const workspace_1 = require("@schematics/angular/utility/workspace");
|
|
7
7
|
const dev_logs_gitignore_1 = require("../utility/dev-logs-gitignore");
|
|
8
|
+
const pnpm_builds_1 = require("../utility/pnpm-builds");
|
|
8
9
|
const tailwind_1 = require("../utility/tailwind");
|
|
9
10
|
const extract_i18n_target_1 = require("../utility/extract-i18n-target");
|
|
10
11
|
const versions_1 = require("./versions");
|
|
@@ -14,9 +15,11 @@ const versions_1 = require("./versions");
|
|
|
14
15
|
* app.component.ts) with Lynx equivalents, points `ng build`, `ng serve`,
|
|
15
16
|
* `ng test` and `ng extract-i18n` at the AngularLynx builders and
|
|
16
17
|
* `ng generate` at its schematics, git-ignores the `.dev-logs` file that
|
|
17
|
-
* `ng serve` writes `LynxLogger`'s output to,
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* `ng serve` writes `LynxLogger`'s output to, denies the install scripts of
|
|
19
|
+
* Angular's build tools in a pnpm app (which current pnpm fails installs
|
|
20
|
+
* over), and optionally sets up Tailwind CSS (4, or 3 with the Lynx preset).
|
|
21
|
+
* Everything else stays as `ng new` left it: the app needs no build config
|
|
22
|
+
* besides angular.json.
|
|
20
23
|
* This is a one-shot destructive transform — the old browser-Angular files
|
|
21
24
|
* are deleted because they reference DOM APIs and HTML elements that don't
|
|
22
25
|
* exist on the Lynx runtime.
|
|
@@ -54,6 +57,7 @@ exports.default = (options) => async (tree) => {
|
|
|
54
57
|
useLynxSchematics(),
|
|
55
58
|
updatePackageScripts(),
|
|
56
59
|
(0, dev_logs_gitignore_1.ignoreDevLogs)(),
|
|
60
|
+
(0, pnpm_builds_1.denyAngularBuildScripts)(),
|
|
57
61
|
addCoreDependencies(),
|
|
58
62
|
];
|
|
59
63
|
// `"false"` is how `ng add ... --tailwind=false` arrives (see schema.ts).
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.denyAngularBuildScripts = exports.withAngularBuildsDenied = void 0;
|
|
4
|
+
const workspace_1 = require("@schematics/angular/utility/workspace");
|
|
5
|
+
const node_child_process_1 = require("node:child_process");
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
/**
|
|
9
|
+
* The dependencies of a new Angular app that have install scripts: Angular's
|
|
10
|
+
* build tools. `esbuild` and `@parcel/watcher` are `@angular/build`'s,
|
|
11
|
+
* `lmdb` is an optional one of it, and `msgpackr-extract` comes with `lmdb`.
|
|
12
|
+
*
|
|
13
|
+
* None of the scripts has anything to do. Each package gets its native binary
|
|
14
|
+
* from a prebuilt package for the platform, one of its optional dependencies.
|
|
15
|
+
* esbuild's script only checks that binary; @parcel/watcher's builds one from
|
|
16
|
+
* source only when asked to, and lmdb's and msgpackr-extract's only when no
|
|
17
|
+
* prebuilt one fits. Angular's own pnpm workspace denies all four.
|
|
18
|
+
*/
|
|
19
|
+
const ANGULAR_BUILD_SCRIPTS = [
|
|
20
|
+
'@parcel/watcher',
|
|
21
|
+
'esbuild',
|
|
22
|
+
'lmdb',
|
|
23
|
+
'msgpackr-extract',
|
|
24
|
+
];
|
|
25
|
+
const WORKSPACE_FILE = '/pnpm-workspace.yaml';
|
|
26
|
+
/**
|
|
27
|
+
* The value pnpm writes for a dependency whose build it's waiting for someone
|
|
28
|
+
* to allow or deny. It denies the build, but still fails the install.
|
|
29
|
+
*/
|
|
30
|
+
const UNDECIDED = /^(['"]?)set this to true or false\1$/;
|
|
31
|
+
/**
|
|
32
|
+
* `@parcel/watcher` needs quotes in YAML, since `@` can't start a plain key.
|
|
33
|
+
*/
|
|
34
|
+
const yamlKey = (name) => (name.startsWith('@') ? `'${name}'` : name);
|
|
35
|
+
/**
|
|
36
|
+
* The `allowBuilds` entries this sets, indented by `indent`.
|
|
37
|
+
*/
|
|
38
|
+
const entries = (names, indent) => names.map((name) => `${indent}${yamlKey(name)}: false`);
|
|
39
|
+
/**
|
|
40
|
+
* What a pnpm-workspace.yaml without `allowBuilds` gets, with a comment that
|
|
41
|
+
* says why it's there.
|
|
42
|
+
*/
|
|
43
|
+
const ALLOW_BUILDS_BLOCK = [
|
|
44
|
+
"# Angular's build tools come with their binaries prebuilt, so their install",
|
|
45
|
+
'# scripts have nothing to do. pnpm fails installs until each script is',
|
|
46
|
+
'# allowed (true) or denied (false).',
|
|
47
|
+
'allowBuilds:',
|
|
48
|
+
...entries(ANGULAR_BUILD_SCRIPTS, ' '),
|
|
49
|
+
];
|
|
50
|
+
/** An `allowBuilds` key at the top level, in any style. */
|
|
51
|
+
const ALLOW_BUILDS_KEY = /^allowBuilds[ \t]*:/;
|
|
52
|
+
/** An `allowBuilds` key whose entries follow on their own lines. */
|
|
53
|
+
const ALLOW_BUILDS_BLOCK_KEY = /^allowBuilds[ \t]*:[ \t]*(#.*)?$/;
|
|
54
|
+
/** One entry of a block mapping: its indent, quote, key and value. */
|
|
55
|
+
const ENTRY = /^([ \t]+)(['"]?)([^'"\s#][^'":#]*?)\2[ \t]*:[ \t]*(.*?)[ \t]*$/;
|
|
56
|
+
/**
|
|
57
|
+
* pnpm-workspace.yaml's text with Angular's build scripts denied in
|
|
58
|
+
* `allowBuilds`. Entries the app already decided on stay; ones pnpm left
|
|
59
|
+
* undecided become `false`. Undefined when `allowBuilds` is written in a
|
|
60
|
+
* style this doesn't edit, such as `allowBuilds: { esbuild: true }`.
|
|
61
|
+
*/
|
|
62
|
+
const withAngularBuildsDenied = (text) => {
|
|
63
|
+
const eol = text.includes('\r\n') ? '\r\n' : '\n';
|
|
64
|
+
const lines = text.split(/\r?\n/);
|
|
65
|
+
const start = lines.findIndex((line) => ALLOW_BUILDS_KEY.test(line));
|
|
66
|
+
if (start === -1) {
|
|
67
|
+
// Keep a blank line between the app's settings and the new block.
|
|
68
|
+
const body = text.trimEnd();
|
|
69
|
+
return [...(body ? [body, ''] : []), ...ALLOW_BUILDS_BLOCK, ''].join(eol);
|
|
70
|
+
}
|
|
71
|
+
if (!ALLOW_BUILDS_BLOCK_KEY.test(lines[start])) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
// The block runs over the indented lines after the key; new entries go
|
|
75
|
+
// after its last one, with its indent.
|
|
76
|
+
let end = start + 1;
|
|
77
|
+
let indent = ' ';
|
|
78
|
+
const decided = new Set();
|
|
79
|
+
for (let index = start + 1; index < lines.length; index++) {
|
|
80
|
+
const line = lines[index];
|
|
81
|
+
if (line.trim() === '' || /^[ \t]+#/.test(line)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (!/^[ \t]/.test(line)) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
end = index + 1;
|
|
88
|
+
const match = ENTRY.exec(line);
|
|
89
|
+
if (!match) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const [, entryIndent, quote, name, value] = match;
|
|
93
|
+
indent = entryIndent;
|
|
94
|
+
if (UNDECIDED.test(value)) {
|
|
95
|
+
lines[index] = `${entryIndent}${quote}${name}${quote}: false`;
|
|
96
|
+
}
|
|
97
|
+
decided.add(name);
|
|
98
|
+
}
|
|
99
|
+
const missing = ANGULAR_BUILD_SCRIPTS.filter((name) => !decided.has(name));
|
|
100
|
+
lines.splice(end, 0, ...entries(missing, indent));
|
|
101
|
+
return lines.join(eol);
|
|
102
|
+
};
|
|
103
|
+
exports.withAngularBuildsDenied = withAngularBuildsDenied;
|
|
104
|
+
/**
|
|
105
|
+
* The pnpm version in package.json's `packageManager` field (`pnpm@12.15.0`,
|
|
106
|
+
* maybe with a `+sha512...` hash), which `ng new --package-manager pnpm`
|
|
107
|
+
* writes. Undefined when the app uses pnpm at an unknown version; null when
|
|
108
|
+
* it uses another package manager.
|
|
109
|
+
*/
|
|
110
|
+
const pnpmVersionOf = async (tree) => {
|
|
111
|
+
const { packageManager } = tree.exists('/package.json')
|
|
112
|
+
? tree.readJson('/package.json')
|
|
113
|
+
: {};
|
|
114
|
+
if (typeof packageManager === 'string') {
|
|
115
|
+
const [name, version] = packageManager.split('@');
|
|
116
|
+
return name === 'pnpm' ? version : null;
|
|
117
|
+
}
|
|
118
|
+
// Without the field, the same signs Angular CLI goes by: angular.json's
|
|
119
|
+
// `cli.packageManager`, else the lockfile.
|
|
120
|
+
const workspace = await (0, workspace_1.getWorkspace)(tree);
|
|
121
|
+
const cli = workspace.extensions['cli'];
|
|
122
|
+
if (typeof cli?.packageManager === 'string') {
|
|
123
|
+
return cli.packageManager === 'pnpm' ? undefined : null;
|
|
124
|
+
}
|
|
125
|
+
return tree.exists('/pnpm-lock.yaml') || tree.exists(WORKSPACE_FILE)
|
|
126
|
+
? undefined
|
|
127
|
+
: null;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* The version `pnpm --version` prints here, the way Angular's own workspace
|
|
131
|
+
* schematic reads it for `packageManager`. Undefined when pnpm doesn't run.
|
|
132
|
+
*/
|
|
133
|
+
const installedPnpmVersion = () => {
|
|
134
|
+
try {
|
|
135
|
+
return (0, node_child_process_1.execSync)('pnpm --version', {
|
|
136
|
+
encoding: 'utf8',
|
|
137
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
138
|
+
}).trim();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Whether this pnpm reads `allowBuilds`, which it does from 10.26. Older
|
|
146
|
+
* pnpm doesn't fail an install over build scripts, and pnpm 9 and early
|
|
147
|
+
* pnpm 10 fail on a pnpm-workspace.yaml without `packages`, so they're better
|
|
148
|
+
* left without one.
|
|
149
|
+
*/
|
|
150
|
+
const readsAllowBuilds = (version) => {
|
|
151
|
+
const [major = 0, minor = 0] = version.split('.').map(Number);
|
|
152
|
+
return major > 10 || (major === 10 && minor >= 26);
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* The pnpm-workspace.yaml of a pnpm workspace above this one, as when the
|
|
156
|
+
* app was made inside a monorepo. pnpm takes its settings from there, and a
|
|
157
|
+
* file of the app's own would split the app off into a workspace of its own.
|
|
158
|
+
*/
|
|
159
|
+
const enclosingWorkspaceFile = () => {
|
|
160
|
+
for (let dir = process.cwd();; dir = (0, node_path_1.dirname)(dir)) {
|
|
161
|
+
const file = (0, node_path_1.join)(dir, 'pnpm-workspace.yaml');
|
|
162
|
+
if ((0, node_fs_1.existsSync)(file)) {
|
|
163
|
+
return file;
|
|
164
|
+
}
|
|
165
|
+
if ((0, node_path_1.dirname)(dir) === dir) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Denies the install scripts of Angular's build tools in a pnpm app's
|
|
172
|
+
* pnpm-workspace.yaml, in `allowBuilds`.
|
|
173
|
+
*
|
|
174
|
+
* pnpm 11 and later fail `pnpm install` and `pnpm add` while any
|
|
175
|
+
* dependency's build script is neither allowed nor denied there
|
|
176
|
+
* (`strictDepBuilds`). `ng new` and `ng add` install with `--ignore-scripts`,
|
|
177
|
+
* so they pass, and the app's first `pnpm add` fails. pnpm 11 reads its
|
|
178
|
+
* settings only from pnpm-workspace.yaml, not package.json.
|
|
179
|
+
*
|
|
180
|
+
* Apps on npm, Yarn or bun, and on pnpm older than 10.26, are left alone.
|
|
181
|
+
*/
|
|
182
|
+
const denyAngularBuildScripts = () => async (tree, context) => {
|
|
183
|
+
const pinned = await pnpmVersionOf(tree);
|
|
184
|
+
if (pinned === null) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const version = pinned ?? installedPnpmVersion();
|
|
188
|
+
if (version === undefined || !readsAllowBuilds(version)) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (!tree.exists(WORKSPACE_FILE)) {
|
|
192
|
+
const enclosing = enclosingWorkspaceFile();
|
|
193
|
+
if (enclosing) {
|
|
194
|
+
context.logger.warn(`This app is in the pnpm workspace of ${enclosing}. Add this to it, or pnpm will fail installs over Angular's build scripts:\n${ALLOW_BUILDS_BLOCK.join('\n')}`);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const text = tree.exists(WORKSPACE_FILE) ? tree.readText(WORKSPACE_FILE) : '';
|
|
199
|
+
const updated = (0, exports.withAngularBuildsDenied)(text);
|
|
200
|
+
if (updated === undefined) {
|
|
201
|
+
context.logger.warn(`pnpm-workspace.yaml's allowBuilds isn't a block mapping, so it was left as it is. Set these in it, or pnpm will fail installs over Angular's build scripts: ${ANGULAR_BUILD_SCRIPTS.map((name) => `${name}: false`).join(', ')}.`);
|
|
202
|
+
}
|
|
203
|
+
else if (!tree.exists(WORKSPACE_FILE)) {
|
|
204
|
+
tree.create(WORKSPACE_FILE, updated);
|
|
205
|
+
}
|
|
206
|
+
else if (updated !== text) {
|
|
207
|
+
tree.overwrite(WORKSPACE_FILE, updated);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
exports.denyAngularBuildScripts = denyAngularBuildScripts;
|
|
@@ -850,7 +850,8 @@ export declare class LynxLocale {
|
|
|
850
850
|
export declare const provideLocale: () => EnvironmentProviders;
|
|
851
851
|
/**
|
|
852
852
|
* Controls gesture state from within a callback.
|
|
853
|
-
* Wraps __SetGestureState and __ConsumeGesture PAPI calls
|
|
853
|
+
* Wraps the __SetGestureState and __ConsumeGesture PAPI calls (see
|
|
854
|
+
* gesture-papi.ts for Lynx for Web, which has neither).
|
|
854
855
|
* Passed as the second argument to gesture callbacks so handlers can
|
|
855
856
|
* programmatically drive the gesture state machine (e.g. activate a gesture
|
|
856
857
|
* only when a condition is met, or fail it early to let a competing gesture win).
|
|
@@ -1096,7 +1097,8 @@ type AnyGesture = BaseGesture<any, any>;
|
|
|
1096
1097
|
type GestureInput = AnyGesture | AnyGesture[] | ComposedGesture;
|
|
1097
1098
|
/**
|
|
1098
1099
|
* Directive that bridges Angular's gesture binding to Lynx's native gesture
|
|
1099
|
-
* system (__SetGestureDetector / __RemoveGestureDetector
|
|
1100
|
+
* system (__SetGestureDetector / __RemoveGestureDetector, or on Lynx for Web,
|
|
1101
|
+
* which has none, the runtime's port of it: see gesture-papi.ts). Accepts a single
|
|
1100
1102
|
* gesture, an array of gestures, or a ComposedGesture (simultaneous/exclusive).
|
|
1101
1103
|
* Each gesture is registered with the native engine via its unique numeric ID.
|
|
1102
1104
|
*
|
|
@@ -4321,6 +4323,100 @@ export declare class LynxSessionStorage {
|
|
|
4321
4323
|
static ɵfac: i0.ɵɵFactoryDeclaration<LynxSessionStorage, never>;
|
|
4322
4324
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
4323
4325
|
}
|
|
4326
|
+
/**
|
|
4327
|
+
* What {@link LynxLocalStorage} and {@link LynxSecureStorage} share: a
|
|
4328
|
+
* key-value store of JSON values with an async API, kept by a native module
|
|
4329
|
+
* of the apps `ng build --platform` makes, by `localStorage` on the web, and
|
|
4330
|
+
* in memory elsewhere.
|
|
4331
|
+
*/
|
|
4332
|
+
declare abstract class PersistentStorage {
|
|
4333
|
+
#private;
|
|
4334
|
+
/**
|
|
4335
|
+
* @param module - The native module's name in `NativeModules`.
|
|
4336
|
+
* @param webPrefix - What this store's keys start with in `localStorage`.
|
|
4337
|
+
*/
|
|
4338
|
+
constructor(module: string, webPrefix: string);
|
|
4339
|
+
/**
|
|
4340
|
+
* Resolves with the value stored under `key`, or `null` if there's none.
|
|
4341
|
+
*/
|
|
4342
|
+
getItem<T = unknown>(key: string): Promise<T | null>;
|
|
4343
|
+
/**
|
|
4344
|
+
* Stores `value` under `key`, as JSON: an object, an array, a string, a
|
|
4345
|
+
* number, a boolean or `null`. Resolves once it's stored.
|
|
4346
|
+
*/
|
|
4347
|
+
setItem<T = unknown>(key: string, value: T): Promise<void>;
|
|
4348
|
+
/**
|
|
4349
|
+
* Removes the value stored under `key`, if there is one.
|
|
4350
|
+
*/
|
|
4351
|
+
removeItem(key: string): Promise<void>;
|
|
4352
|
+
/**
|
|
4353
|
+
* Removes every value in this store.
|
|
4354
|
+
*/
|
|
4355
|
+
clear(): Promise<void>;
|
|
4356
|
+
}
|
|
4357
|
+
/**
|
|
4358
|
+
* A key-value store that keeps its values after the app closes, like the
|
|
4359
|
+
* browser's `localStorage`. Values are JSON (objects, arrays, strings,
|
|
4360
|
+
* numbers, booleans) and every method returns a promise.
|
|
4361
|
+
*
|
|
4362
|
+
* - **iOS:** `UserDefaults`, in a suite of its own.
|
|
4363
|
+
* - **Android:** `SharedPreferences`, in a file of its own.
|
|
4364
|
+
* - **Web:** the page's `localStorage`, with each key starting with
|
|
4365
|
+
* `angular-lynx:`.
|
|
4366
|
+
*
|
|
4367
|
+
* For tokens and other secrets, use {@link LynxSecureStorage}.
|
|
4368
|
+
*
|
|
4369
|
+
* Only the apps `ng build --platform` makes have the native module behind
|
|
4370
|
+
* it, `AngularLynxLocalStorage`. Elsewhere, such as in Lynx Explorer and
|
|
4371
|
+
* tests, it keeps values in memory, so they last until the app closes.
|
|
4372
|
+
*
|
|
4373
|
+
* @usageNotes
|
|
4374
|
+
* ```typescript
|
|
4375
|
+
* const storage = inject(LynxLocalStorage);
|
|
4376
|
+
*
|
|
4377
|
+
* await storage.setItem('settings', { units: 'metric' });
|
|
4378
|
+
* const settings = await storage.getItem<Settings>('settings');
|
|
4379
|
+
* await storage.removeItem('settings');
|
|
4380
|
+
* ```
|
|
4381
|
+
*/
|
|
4382
|
+
export declare class LynxLocalStorage extends PersistentStorage {
|
|
4383
|
+
constructor();
|
|
4384
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<LynxLocalStorage, never>;
|
|
4385
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
4386
|
+
}
|
|
4387
|
+
/**
|
|
4388
|
+
* A key-value store for secrets such as tokens, which keeps its values after
|
|
4389
|
+
* the app closes, encrypted by the platform. It has the same methods as
|
|
4390
|
+
* {@link LynxLocalStorage}.
|
|
4391
|
+
*
|
|
4392
|
+
* - **iOS:** the Keychain, readable once the phone has been unlocked after it
|
|
4393
|
+
* starts, and never copied to another device. The Keychain keeps its items
|
|
4394
|
+
* when the app is deleted, so a reinstalled app finds them again.
|
|
4395
|
+
* - **Android:** `SharedPreferences`, each value encrypted with AES-GCM by a
|
|
4396
|
+
* key the Android Keystore holds. The file is left out of backups, which
|
|
4397
|
+
* can't take the key with them.
|
|
4398
|
+
* - **Web:** the page's `localStorage`, with each key starting with
|
|
4399
|
+
* `angular-lynx-secure:`. Browsers have no store for secrets, and web
|
|
4400
|
+
* sign-in libraries keep their tokens there too.
|
|
4401
|
+
*
|
|
4402
|
+
* Only the apps `ng build --platform` makes have the native module behind
|
|
4403
|
+
* it, `AngularLynxSecureStorage`. Elsewhere, such as in Lynx Explorer and
|
|
4404
|
+
* tests, it keeps values in memory, so they last until the app closes.
|
|
4405
|
+
*
|
|
4406
|
+
* @usageNotes
|
|
4407
|
+
* ```typescript
|
|
4408
|
+
* const storage = inject(LynxSecureStorage);
|
|
4409
|
+
*
|
|
4410
|
+
* await storage.setItem('session', session);
|
|
4411
|
+
* const session = await storage.getItem<Session>('session');
|
|
4412
|
+
* await storage.removeItem('session');
|
|
4413
|
+
* ```
|
|
4414
|
+
*/
|
|
4415
|
+
export declare class LynxSecureStorage extends PersistentStorage {
|
|
4416
|
+
constructor();
|
|
4417
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<LynxSecureStorage, never>;
|
|
4418
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
4419
|
+
}
|
|
4324
4420
|
/**
|
|
4325
4421
|
* Wraps the global `SystemInfo` object as an Angular injectable,
|
|
4326
4422
|
* providing device and platform information from the Lynx runtime.
|
|
@@ -4629,6 +4725,75 @@ export declare class LynxTransitionGroup<T> {
|
|
|
4629
4725
|
"afterLeave": "afterLeave";
|
|
4630
4726
|
}, ["itemTemplate"], never, true, never>;
|
|
4631
4727
|
}
|
|
4728
|
+
/**
|
|
4729
|
+
* Why a web authentication session gave no callback URL:
|
|
4730
|
+
* - `canceled`: the person closed the sheet, or declined to open it.
|
|
4731
|
+
* - `unavailable`: the host can't open one. Only the apps that
|
|
4732
|
+
* `ng build --platform` makes can; Lynx Explorer, the web preview and
|
|
4733
|
+
* tests can't.
|
|
4734
|
+
* - `failed`: the platform couldn't open the page, or a session was already
|
|
4735
|
+
* open.
|
|
4736
|
+
*/
|
|
4737
|
+
type WebAuthSessionErrorCode = 'canceled' | 'unavailable' | 'failed';
|
|
4738
|
+
/** The error a {@link LynxWebAuthSession} rejects with. */
|
|
4739
|
+
export declare class WebAuthSessionError extends Error {
|
|
4740
|
+
readonly code: WebAuthSessionErrorCode;
|
|
4741
|
+
constructor(code: WebAuthSessionErrorCode, message: string);
|
|
4742
|
+
}
|
|
4743
|
+
/** What {@link LynxWebAuthSession.start} opens, and where it returns. */
|
|
4744
|
+
type WebAuthSessionOptions = {
|
|
4745
|
+
/** The page that starts the sign-in, such as a provider's authorize URL. */
|
|
4746
|
+
readonly url: string;
|
|
4747
|
+
/**
|
|
4748
|
+
* The URL scheme the page returns to, such as `myapp` for
|
|
4749
|
+
* `myapp://auth?code=…`. On Android it must also be one of the app's
|
|
4750
|
+
* `deepLinkSchemes`, so the redirect opens the app.
|
|
4751
|
+
*/
|
|
4752
|
+
readonly callbackScheme: string;
|
|
4753
|
+
/**
|
|
4754
|
+
* Opens the page without the browser's cookies and keeps none it sets, so
|
|
4755
|
+
* the person signs in afresh and nothing stays signed in afterwards. iOS
|
|
4756
|
+
* only: Android's Custom Tabs share the browser's cookies.
|
|
4757
|
+
*/
|
|
4758
|
+
readonly ephemeral?: boolean;
|
|
4759
|
+
};
|
|
4760
|
+
/**
|
|
4761
|
+
* Signs in through a web page, as OAuth and OpenID Connect providers need: it
|
|
4762
|
+
* opens the page in the platform's sign-in browser sheet, over the app, and
|
|
4763
|
+
* resolves with the URL the page redirects to on the app's own scheme. Read
|
|
4764
|
+
* the code or token from that URL.
|
|
4765
|
+
*
|
|
4766
|
+
* Lynx has no popups or redirects, so a web sign-in flow can't run inside
|
|
4767
|
+
* the app. The sheet is the platform's own: ASWebAuthenticationSession on
|
|
4768
|
+
* iOS, which asks before opening a site and shares Safari's sign-ins, and a
|
|
4769
|
+
* Custom Tab on Android, from which the redirect opens the app again.
|
|
4770
|
+
*
|
|
4771
|
+
* Only the apps `ng build --platform` makes have the native module behind
|
|
4772
|
+
* it. Elsewhere, such as Lynx Explorer, the web preview and tests, `start()`
|
|
4773
|
+
* rejects with `unavailable`.
|
|
4774
|
+
*
|
|
4775
|
+
* @usageNotes
|
|
4776
|
+
* ```typescript
|
|
4777
|
+
* const webAuth = inject(LynxWebAuthSession);
|
|
4778
|
+
*
|
|
4779
|
+
* const callback = await webAuth.start({
|
|
4780
|
+
* url: 'https://example.com/oauth/authorize?client_id=…&redirect_uri=myapp://auth',
|
|
4781
|
+
* callbackScheme: 'myapp',
|
|
4782
|
+
* });
|
|
4783
|
+
* const code = new URL(callback).searchParams.get('code');
|
|
4784
|
+
* ```
|
|
4785
|
+
*/
|
|
4786
|
+
export declare class LynxWebAuthSession {
|
|
4787
|
+
#private;
|
|
4788
|
+
/**
|
|
4789
|
+
* Opens `url` in the sign-in sheet and resolves with the whole URL the page
|
|
4790
|
+
* redirects to on `callbackScheme`, query and fragment included. Rejects
|
|
4791
|
+
* with a {@link WebAuthSessionError}.
|
|
4792
|
+
*/
|
|
4793
|
+
start({ url, callbackScheme, ephemeral }: WebAuthSessionOptions): Promise<string>;
|
|
4794
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<LynxWebAuthSession, never>;
|
|
4795
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
4796
|
+
}
|
|
4632
4797
|
/**
|
|
4633
4798
|
* Central DI configuration for the Lynx renderer. Must be included in every
|
|
4634
4799
|
* Lynx Angular app's providers (typically via app.config.ts). Sets up:
|
|
@@ -4639,6 +4804,44 @@ export declare class LynxTransitionGroup<T> {
|
|
|
4639
4804
|
* 5. Error handler (routes to _ReportError + __lynxLastError)
|
|
4640
4805
|
*/
|
|
4641
4806
|
export declare const provideRenderer: () => EnvironmentProviders;
|
|
4807
|
+
/**
|
|
4808
|
+
* The Lynx elements a component's host can be, besides the `<view>` every
|
|
4809
|
+
* host is by default.
|
|
4810
|
+
*/
|
|
4811
|
+
type HostElementTag = 'view' | 'text' | 'image' | 'scroll-view' | 'svg' | 'blur-view';
|
|
4812
|
+
/**
|
|
4813
|
+
* Makes a component's host element a Lynx element other than `<view>`, such
|
|
4814
|
+
* as a `<text>`. Call it once, next to the component:
|
|
4815
|
+
*
|
|
4816
|
+
* ```ts
|
|
4817
|
+
* @Component({
|
|
4818
|
+
* selector: 'app-title',
|
|
4819
|
+
* host: { class: 'text-2xl font-semibold' },
|
|
4820
|
+
* template: '<ng-content />',
|
|
4821
|
+
* })
|
|
4822
|
+
* export class AppTitle {}
|
|
4823
|
+
*
|
|
4824
|
+
* registerHostElement(AppTitle, 'text');
|
|
4825
|
+
* ```
|
|
4826
|
+
*
|
|
4827
|
+
* Every host is a `<view>` otherwise, a real element between the parent and
|
|
4828
|
+
* the component's template. A component that shows text then needs a
|
|
4829
|
+
* `<text>` inside its host, and a class the app writes on the component
|
|
4830
|
+
* (`<app-title class="mb-2">`) lands on the host, which Angular gives every
|
|
4831
|
+
* static attribute, as well as on whatever element the component passes it
|
|
4832
|
+
* to: a margin there applies twice. With a `<text>` host, the component is
|
|
4833
|
+
* one element, the way a component's `<span>` or `<p>` would be on the web.
|
|
4834
|
+
*
|
|
4835
|
+
* The registration covers each element name in the selector, wherever a
|
|
4836
|
+
* template uses the component. Content projected into a `<text>` host follows
|
|
4837
|
+
* `<text>`'s rules: raw text, and nested `<text>` that runs inline.
|
|
4838
|
+
*/
|
|
4839
|
+
export declare const registerHostElement: (component: Type<unknown>, element: HostElementTag) => void;
|
|
4840
|
+
/**
|
|
4841
|
+
* The Lynx element to create for a tag: the registered host element for a
|
|
4842
|
+
* component's tag, or the tag itself.
|
|
4843
|
+
*/
|
|
4844
|
+
declare const hostElementOf: (tag: string) => string;
|
|
4642
4845
|
/**
|
|
4643
4846
|
* Keeps the app on the screen it was showing when a hot update re-bootstraps
|
|
4644
4847
|
* it. Called with the old app's injector before it's destroyed, it saves the
|
|
@@ -4917,6 +5120,14 @@ declare const handlers: {
|
|
|
4917
5120
|
* module proxies (relayedModule() below) send their calls here.
|
|
4918
5121
|
*/
|
|
4919
5122
|
callModule: (kind: ModuleKind, name: string, method: string, args: unknown[]) => unknown;
|
|
5123
|
+
/**
|
|
5124
|
+
* Calls a native module method that answers through a callback, passed
|
|
5125
|
+
* after `args`, and resolves with the first value it passes back. Unlike a
|
|
5126
|
+
* function sent through callModule, the callback stays on this thread, so
|
|
5127
|
+
* the call leaves nothing registered on either thread: the storage
|
|
5128
|
+
* services make one of these per read and write.
|
|
5129
|
+
*/
|
|
5130
|
+
callNativeModuleAsync: (name: string, method: string, args: unknown[]) => Promise<unknown>;
|
|
4920
5131
|
registerJSModule: (name: string, module: unknown) => void;
|
|
4921
5132
|
/**
|
|
4922
5133
|
* The OS version, for LynxSystemInfo on the main thread: native Lynx builds
|
|
@@ -5068,4 +5279,4 @@ declare global {
|
|
|
5068
5279
|
catchmouseleave: MouseEvent;
|
|
5069
5280
|
}
|
|
5070
5281
|
}
|
|
5071
|
-
export type { AccessibilityTrait, AccessibilityTraitStates, BackgroundFnHandle, BaseLynxAnimation, BaseLynxElement, DataProcessorDefinition, DevToolsStats, DynamicColorRole, DynamicColorScheme, DynamicColors, ExposureEventDetail, FlingGestureEvent, GestureCallback, GestureCallbackWithState, GestureEvent, GlobalData, GlobalExposureEvent, InitData, InitDataRaw, LongPressGestureEvent, LynxAnimationOptions, LynxFontEntry, LynxFontFaceConfig, LynxFontStatus, LynxTraceOptions, MainThread, MainThreadFnHandle, NativeModuleMap, NativeModuleProxy, ObserverFrameRateOptions, PanGestureEvent, PinchGestureEvent, PortalConfig, PrefetchCacheTarget, PrefetchPriority, PrefetchRequest, PrefetchResultDetail, ResourcePrefetchData, ResourcePrefetchResult, RotationGestureEvent, SessionStorageSubscription, TapGestureEvent };
|
|
5282
|
+
export type { AccessibilityTrait, AccessibilityTraitStates, BackgroundFnHandle, BaseLynxAnimation, BaseLynxElement, DataProcessorDefinition, DevToolsStats, DynamicColorRole, DynamicColorScheme, DynamicColors, ExposureEventDetail, FlingGestureEvent, GestureCallback, GestureCallbackWithState, GestureEvent, GlobalData, GlobalExposureEvent, HostElementTag, InitData, InitDataRaw, LongPressGestureEvent, LynxAnimationOptions, LynxFontEntry, LynxFontFaceConfig, LynxFontStatus, LynxTraceOptions, MainThread, MainThreadFnHandle, NativeModuleMap, NativeModuleProxy, ObserverFrameRateOptions, PanGestureEvent, PinchGestureEvent, PortalConfig, PrefetchCacheTarget, PrefetchPriority, PrefetchRequest, PrefetchResultDetail, ResourcePrefetchData, ResourcePrefetchResult, RotationGestureEvent, SessionStorageSubscription, TapGestureEvent, WebAuthSessionErrorCode, WebAuthSessionOptions };
|