lakebed-native-cli 0.1.0
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/cli/apple/branding.d.ts +9 -0
- package/dist/cli/apple/branding.d.ts.map +1 -0
- package/dist/cli/apple/branding.js +40 -0
- package/dist/cli/apple/branding.js.map +1 -0
- package/dist/cli/apple/build-cloud.d.ts +6 -0
- package/dist/cli/apple/build-cloud.d.ts.map +1 -0
- package/dist/cli/apple/build-cloud.js +34 -0
- package/dist/cli/apple/build-cloud.js.map +1 -0
- package/dist/cli/apple/build-local.d.ts +16 -0
- package/dist/cli/apple/build-local.d.ts.map +1 -0
- package/dist/cli/apple/build-local.js +97 -0
- package/dist/cli/apple/build-local.js.map +1 -0
- package/dist/cli/apple/choose-path.d.ts +23 -0
- package/dist/cli/apple/choose-path.d.ts.map +1 -0
- package/dist/cli/apple/choose-path.js +78 -0
- package/dist/cli/apple/choose-path.js.map +1 -0
- package/dist/cli/apple/device-pack.d.ts +36 -0
- package/dist/cli/apple/device-pack.d.ts.map +1 -0
- package/dist/cli/apple/device-pack.js +210 -0
- package/dist/cli/apple/device-pack.js.map +1 -0
- package/dist/cli/apple/devices.d.ts +6 -0
- package/dist/cli/apple/devices.d.ts.map +1 -0
- package/dist/cli/apple/devices.js +49 -0
- package/dist/cli/apple/devices.js.map +1 -0
- package/dist/cli/apple/eas-delegate.d.ts +25 -0
- package/dist/cli/apple/eas-delegate.d.ts.map +1 -0
- package/dist/cli/apple/eas-delegate.js +63 -0
- package/dist/cli/apple/eas-delegate.js.map +1 -0
- package/dist/cli/apple/index.d.ts +9 -0
- package/dist/cli/apple/index.d.ts.map +1 -0
- package/dist/cli/apple/index.js +12 -0
- package/dist/cli/apple/index.js.map +1 -0
- package/dist/cli/apple/route-device-build.d.ts +16 -0
- package/dist/cli/apple/route-device-build.d.ts.map +1 -0
- package/dist/cli/apple/route-device-build.js +54 -0
- package/dist/cli/apple/route-device-build.js.map +1 -0
- package/dist/cli/apple/setup.d.ts +5 -0
- package/dist/cli/apple/setup.d.ts.map +1 -0
- package/dist/cli/apple/setup.js +69 -0
- package/dist/cli/apple/setup.js.map +1 -0
- package/dist/cli/apple/shell-ipa.d.ts +7 -0
- package/dist/cli/apple/shell-ipa.d.ts.map +1 -0
- package/dist/cli/apple/shell-ipa.js +73 -0
- package/dist/cli/apple/shell-ipa.js.map +1 -0
- package/dist/cli/apple/sign-ios.d.ts +24 -0
- package/dist/cli/apple/sign-ios.d.ts.map +1 -0
- package/dist/cli/apple/sign-ios.js +148 -0
- package/dist/cli/apple/sign-ios.js.map +1 -0
- package/dist/cli/apple/status.d.ts +64 -0
- package/dist/cli/apple/status.d.ts.map +1 -0
- package/dist/cli/apple/status.js +249 -0
- package/dist/cli/apple/status.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +7 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/bundler.d.ts +16 -0
- package/dist/cli/bundler.d.ts.map +1 -0
- package/dist/cli/bundler.js +109 -0
- package/dist/cli/bundler.js.map +1 -0
- package/dist/cli/capsule-eas.d.ts +27 -0
- package/dist/cli/capsule-eas.d.ts.map +1 -0
- package/dist/cli/capsule-eas.js +131 -0
- package/dist/cli/capsule-eas.js.map +1 -0
- package/dist/cli/cloud/index.d.ts +14 -0
- package/dist/cli/cloud/index.d.ts.map +1 -0
- package/dist/cli/cloud/index.js +118 -0
- package/dist/cli/cloud/index.js.map +1 -0
- package/dist/cli/cloud-client.d.ts +38 -0
- package/dist/cli/cloud-client.d.ts.map +1 -0
- package/dist/cli/cloud-client.js +71 -0
- package/dist/cli/cloud-client.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +2 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +18 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/build-native.d.ts +18 -0
- package/dist/cli/commands/build-native.d.ts.map +1 -0
- package/dist/cli/commands/build-native.js +156 -0
- package/dist/cli/commands/build-native.js.map +1 -0
- package/dist/cli/commands/build.d.ts +6 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +57 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +2 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +2 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/db.d.ts +7 -0
- package/dist/cli/commands/db.d.ts.map +1 -0
- package/dist/cli/commands/db.js +18 -0
- package/dist/cli/commands/db.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +10 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +101 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +5 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +46 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/devices.d.ts +4 -0
- package/dist/cli/commands/devices.d.ts.map +1 -0
- package/dist/cli/commands/devices.js +27 -0
- package/dist/cli/commands/devices.js.map +1 -0
- package/dist/cli/commands/domains.d.ts +5 -0
- package/dist/cli/commands/domains.d.ts.map +1 -0
- package/dist/cli/commands/domains.js +36 -0
- package/dist/cli/commands/domains.js.map +1 -0
- package/dist/cli/commands/inspect.d.ts +7 -0
- package/dist/cli/commands/inspect.d.ts.map +1 -0
- package/dist/cli/commands/inspect.js +15 -0
- package/dist/cli/commands/inspect.js.map +1 -0
- package/dist/cli/commands/logs.d.ts +7 -0
- package/dist/cli/commands/logs.d.ts.map +1 -0
- package/dist/cli/commands/logs.js +15 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/new.d.ts +6 -0
- package/dist/cli/commands/new.d.ts.map +1 -0
- package/dist/cli/commands/new.js +17 -0
- package/dist/cli/commands/new.js.map +1 -0
- package/dist/cli/commands/open.d.ts +5 -0
- package/dist/cli/commands/open.d.ts.map +1 -0
- package/dist/cli/commands/open.js +14 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/pack.d.ts +32 -0
- package/dist/cli/commands/pack.d.ts.map +1 -0
- package/dist/cli/commands/pack.js +273 -0
- package/dist/cli/commands/pack.js.map +1 -0
- package/dist/cli/commands/screenshot.d.ts +5 -0
- package/dist/cli/commands/screenshot.d.ts.map +1 -0
- package/dist/cli/commands/screenshot.js +8 -0
- package/dist/cli/commands/screenshot.js.map +1 -0
- package/dist/cli/commands/shell-fetch.d.ts +5 -0
- package/dist/cli/commands/shell-fetch.d.ts.map +1 -0
- package/dist/cli/commands/shell-fetch.js +123 -0
- package/dist/cli/commands/shell-fetch.js.map +1 -0
- package/dist/cli/commands/shell.d.ts +2 -0
- package/dist/cli/commands/shell.d.ts.map +1 -0
- package/dist/cli/commands/shell.js +2 -0
- package/dist/cli/commands/shell.js.map +1 -0
- package/dist/cli/commands/submit.d.ts +2 -0
- package/dist/cli/commands/submit.d.ts.map +1 -0
- package/dist/cli/commands/submit.js +2 -0
- package/dist/cli/commands/submit.js.map +1 -0
- package/dist/cli/commands/tree.d.ts +5 -0
- package/dist/cli/commands/tree.d.ts.map +1 -0
- package/dist/cli/commands/tree.js +23 -0
- package/dist/cli/commands/tree.js.map +1 -0
- package/dist/cli/deploy-metadata.d.ts +10 -0
- package/dist/cli/deploy-metadata.d.ts.map +1 -0
- package/dist/cli/deploy-metadata.js +50 -0
- package/dist/cli/deploy-metadata.js.map +1 -0
- package/dist/cli/deploy-runtime.d.ts +4 -0
- package/dist/cli/deploy-runtime.d.ts.map +1 -0
- package/dist/cli/deploy-runtime.js +14 -0
- package/dist/cli/deploy-runtime.js.map +1 -0
- package/dist/cli/dev-config.d.ts +2 -0
- package/dist/cli/dev-config.d.ts.map +1 -0
- package/dist/cli/dev-config.js +36 -0
- package/dist/cli/dev-config.js.map +1 -0
- package/dist/cli/hosted-client.d.ts +39 -0
- package/dist/cli/hosted-client.d.ts.map +1 -0
- package/dist/cli/hosted-client.js +275 -0
- package/dist/cli/hosted-client.js.map +1 -0
- package/dist/cli/hosted-v1-store.d.ts +73 -0
- package/dist/cli/hosted-v1-store.d.ts.map +1 -0
- package/dist/cli/hosted-v1-store.js +96 -0
- package/dist/cli/hosted-v1-store.js.map +1 -0
- package/dist/cli/hosted.d.ts +13 -0
- package/dist/cli/hosted.d.ts.map +1 -0
- package/dist/cli/hosted.js +337 -0
- package/dist/cli/hosted.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +261 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/kit-paths.d.ts +8 -0
- package/dist/cli/kit-paths.d.ts.map +1 -0
- package/dist/cli/kit-paths.js +67 -0
- package/dist/cli/kit-paths.js.map +1 -0
- package/dist/cli/loader.d.ts +2 -0
- package/dist/cli/loader.d.ts.map +1 -0
- package/dist/cli/loader.js +5 -0
- package/dist/cli/loader.js.map +1 -0
- package/dist/cli/native-deploy-payload.d.ts +17 -0
- package/dist/cli/native-deploy-payload.d.ts.map +1 -0
- package/dist/cli/native-deploy-payload.js +29 -0
- package/dist/cli/native-deploy-payload.js.map +1 -0
- package/dist/cli/platform-detect.d.ts +11 -0
- package/dist/cli/platform-detect.d.ts.map +1 -0
- package/dist/cli/platform-detect.js +54 -0
- package/dist/cli/platform-detect.js.map +1 -0
- package/dist/cli/site.d.ts +6 -0
- package/dist/cli/site.d.ts.map +1 -0
- package/dist/cli/site.js +9 -0
- package/dist/cli/site.js.map +1 -0
- package/dist/cli/util.d.ts +12 -0
- package/dist/cli/util.d.ts.map +1 -0
- package/dist/cli/util.js +118 -0
- package/dist/cli/util.js.map +1 -0
- package/dist/cli/web-deploy-envelope.d.ts +15 -0
- package/dist/cli/web-deploy-envelope.d.ts.map +1 -0
- package/dist/cli/web-deploy-envelope.js +156 -0
- package/dist/cli/web-deploy-envelope.js.map +1 -0
- package/metro.lakebed-native.cjs +94 -0
- package/package.json +38 -0
- package/templates/camera-note/.env.lakebed.native.server +1 -0
- package/templates/camera-note/.lakebed-native/dev.json +6 -0
- package/templates/camera-note/.lakebed-native/metro/.expo/README.md +8 -0
- package/templates/camera-note/.lakebed-native/metro/.expo/devices.json +3 -0
- package/templates/camera-note/.lakebed-native/metro/index.js +2 -0
- package/templates/camera-note/.lakebed-native/metro/metro.config.js +4 -0
- package/templates/camera-note/.lakebed-native/metro/package.json +4 -0
- package/templates/camera-note/AGENTS.md +1 -0
- package/templates/camera-note/README.md +1 -0
- package/templates/camera-note/app/index.tsx +64 -0
- package/templates/camera-note/server/index.ts +23 -0
- package/templates/error-fixture/.env.lakebed.native.server +1 -0
- package/templates/error-fixture/.lakebed-native/dev.json +6 -0
- package/templates/error-fixture/.lakebed-native/metro/.expo/README.md +8 -0
- package/templates/error-fixture/.lakebed-native/metro/.expo/devices.json +3 -0
- package/templates/error-fixture/.lakebed-native/metro/index.js +2 -0
- package/templates/error-fixture/.lakebed-native/metro/metro.config.js +4 -0
- package/templates/error-fixture/.lakebed-native/metro/package.json +4 -0
- package/templates/error-fixture/AGENTS.md +1 -0
- package/templates/error-fixture/README.md +1 -0
- package/templates/error-fixture/app/index.tsx +31 -0
- package/templates/error-fixture/server/index.ts +19 -0
- package/templates/form/.env.lakebed.native.server +1 -0
- package/templates/form/.lakebed-native/dev.json +6 -0
- package/templates/form/.lakebed-native/metro/.expo/README.md +8 -0
- package/templates/form/.lakebed-native/metro/.expo/devices.json +3 -0
- package/templates/form/.lakebed-native/metro/index.js +2 -0
- package/templates/form/.lakebed-native/metro/metro.config.js +4 -0
- package/templates/form/.lakebed-native/metro/package.json +4 -0
- package/templates/form/AGENTS.md +1 -0
- package/templates/form/README.md +1 -0
- package/templates/form/app/index.tsx +56 -0
- package/templates/form/server/index.ts +27 -0
- package/templates/guestbook/.env.lakebed.native.server +1 -0
- package/templates/guestbook/AGENTS.md +1 -0
- package/templates/guestbook/README.md +3 -0
- package/templates/guestbook/app/index.tsx +45 -0
- package/templates/guestbook/server/index.ts +31 -0
- package/templates/location-checkin/.env.lakebed.native.server +1 -0
- package/templates/location-checkin/.lakebed-native/dev.json +6 -0
- package/templates/location-checkin/.lakebed-native/metro/.expo/README.md +8 -0
- package/templates/location-checkin/.lakebed-native/metro/.expo/devices.json +3 -0
- package/templates/location-checkin/.lakebed-native/metro/index.js +2 -0
- package/templates/location-checkin/.lakebed-native/metro/metro.config.js +4 -0
- package/templates/location-checkin/.lakebed-native/metro/package.json +4 -0
- package/templates/location-checkin/AGENTS.md +1 -0
- package/templates/location-checkin/README.md +1 -0
- package/templates/location-checkin/app/index.tsx +52 -0
- package/templates/location-checkin/server/index.ts +34 -0
- package/templates/tabs/.env.lakebed.native.server +1 -0
- package/templates/tabs/AGENTS.md +1 -0
- package/templates/tabs/README.md +1 -0
- package/templates/tabs/app/index.tsx +39 -0
- package/templates/tabs/server/index.ts +9 -0
- package/templates/todo/.env.lakebed.native.server +1 -0
- package/templates/todo/AGENTS.md +27 -0
- package/templates/todo/README.md +18 -0
- package/templates/todo/app/index.tsx +112 -0
- package/templates/todo/server/index.ts +51 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
|
|
4
|
+
function resolvePackage(projectRoot, workspaceRoot, packageName) {
|
|
5
|
+
const local = path.join(projectRoot, "node_modules", packageName);
|
|
6
|
+
if (fs.existsSync(local)) return local;
|
|
7
|
+
const root = path.join(workspaceRoot, "node_modules", packageName);
|
|
8
|
+
if (fs.existsSync(root)) return root;
|
|
9
|
+
return local;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Metro resolver for Lakebed Native monorepo — maps packages and .js → .ts/.tsx */
|
|
13
|
+
function createLakebedNativeMetroConfig(projectRoot, workspaceRoot) {
|
|
14
|
+
const root = workspaceRoot ?? path.resolve(projectRoot, "..", "..", "..");
|
|
15
|
+
const workspace = fs.existsSync(path.join(root, "packages", "shared"))
|
|
16
|
+
? root
|
|
17
|
+
: path.resolve(projectRoot, "..");
|
|
18
|
+
const { getDefaultConfig } = require("expo/metro-config");
|
|
19
|
+
const config = getDefaultConfig(projectRoot);
|
|
20
|
+
|
|
21
|
+
const reactRoot = resolvePackage(projectRoot, workspace, "react");
|
|
22
|
+
const rnRoot = resolvePackage(projectRoot, workspace, "react-native");
|
|
23
|
+
|
|
24
|
+
config.watchFolders = [workspace];
|
|
25
|
+
config.resolver.nodeModulesPaths = [
|
|
26
|
+
path.resolve(projectRoot, "node_modules"),
|
|
27
|
+
path.resolve(workspace, "node_modules"),
|
|
28
|
+
];
|
|
29
|
+
const extraNodeModules = {
|
|
30
|
+
react: reactRoot,
|
|
31
|
+
"react-native": rnRoot,
|
|
32
|
+
"react/jsx-runtime": path.join(reactRoot, "jsx-runtime.js"),
|
|
33
|
+
"react/jsx-dev-runtime": path.join(reactRoot, "jsx-dev-runtime.js"),
|
|
34
|
+
"@lakebed-native/shared": path.resolve(workspace, "packages/shared/dist"),
|
|
35
|
+
"lakebed-native/client": path.resolve(workspace, "packages/client/src/client"),
|
|
36
|
+
"lakebed-native/ui": path.resolve(workspace, "packages/ui/src/ui"),
|
|
37
|
+
"lakebed-native/capabilities": path.resolve(
|
|
38
|
+
workspace,
|
|
39
|
+
"packages/capabilities/src/capabilities"
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
const optionalExpoModules = [
|
|
43
|
+
"expo-crypto", "expo-secure-store", "expo-web-browser", "expo-linking",
|
|
44
|
+
];
|
|
45
|
+
for (const mod of optionalExpoModules) {
|
|
46
|
+
const resolved = resolvePackage(projectRoot, workspace, mod);
|
|
47
|
+
if (fs.existsSync(resolved)) extraNodeModules[mod] = resolved;
|
|
48
|
+
}
|
|
49
|
+
config.resolver.extraNodeModules = extraNodeModules;
|
|
50
|
+
|
|
51
|
+
const defaultResolve = config.resolver.resolveRequest;
|
|
52
|
+
config.resolver.resolveRequest = (context, moduleName, platform) => {
|
|
53
|
+
if (moduleName === "react" || moduleName === "react-native") {
|
|
54
|
+
const root = moduleName === "react" ? reactRoot : rnRoot;
|
|
55
|
+
const entry = path.join(root, moduleName === "react" ? "index.js" : "index.js");
|
|
56
|
+
if (fs.existsSync(entry)) {
|
|
57
|
+
return { type: "sourceFile", filePath: entry };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// TypeScript ESM uses .js extensions; Metro needs .ts/.tsx
|
|
62
|
+
if (moduleName.startsWith(".") && moduleName.endsWith(".js")) {
|
|
63
|
+
const origin = path.dirname(context.originModulePath);
|
|
64
|
+
const withoutJs = path.join(origin, moduleName.slice(0, -3));
|
|
65
|
+
const resolved = resolveFile(withoutJs);
|
|
66
|
+
if (resolved) return { type: "sourceFile", filePath: resolved };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (defaultResolve) {
|
|
70
|
+
return defaultResolve(context, moduleName, platform);
|
|
71
|
+
}
|
|
72
|
+
return context.resolveRequest(context, moduleName, platform);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return config;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function resolveFile(basePath) {
|
|
79
|
+
const candidates = [
|
|
80
|
+
basePath,
|
|
81
|
+
`${basePath}.tsx`,
|
|
82
|
+
`${basePath}.ts`,
|
|
83
|
+
`${basePath}.jsx`,
|
|
84
|
+
`${basePath}.js`,
|
|
85
|
+
path.join(basePath, "index.tsx"),
|
|
86
|
+
path.join(basePath, "index.ts"),
|
|
87
|
+
];
|
|
88
|
+
for (const candidate of candidates) {
|
|
89
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { createLakebedNativeMetroConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lakebed-native-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Lakebed Native CLI — dev, deploy, pack, and device builds",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/mawlicious/lakebed-native.git",
|
|
9
|
+
"directory": "packages/cli"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"templates",
|
|
17
|
+
"metro.lakebed-native.cjs"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"bin": {
|
|
21
|
+
"lakebed-native": "./dist/cli/bin.js"
|
|
22
|
+
},
|
|
23
|
+
"main": "./dist/cli/index.js",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.json && node scripts/copy-kit-assets.mjs",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@lakebed-native/shared": "0.1.0",
|
|
30
|
+
"commander": "^13.1.0",
|
|
31
|
+
"esbuild": "^0.25.4",
|
|
32
|
+
"lakebed": "npm:@lakebed-native/server@0.1.0",
|
|
33
|
+
"ws": "^8.18.2"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/ws": "^8.18.1"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CAPSULE_NAME=camera-note
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"serverUrl": "http://localhost:3000",
|
|
3
|
+
"bundleUrl": "http://localhost:3100/index.bundle?platform=ios&dev=true&minify=false",
|
|
4
|
+
"capsuleEntry": "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/camera-note/app/index.tsx",
|
|
5
|
+
"openUrl": "lakebed-native://capsule?server=http%3A%2F%2Flocalhost%3A3000&bundle=http%3A%2F%2Flocalhost%3A3100%2Findex.bundle%3Fplatform%3Dios%26dev%3Dtrue%26minify%3Dfalse"
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
> Why do I have a folder named ".expo" in my project?
|
|
2
|
+
The ".expo" folder is created when an Expo project is started using "expo start" command.
|
|
3
|
+
> What do the files contain?
|
|
4
|
+
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
|
|
5
|
+
- "settings.json": contains the server configuration that is used to serve the application manifest.
|
|
6
|
+
> Should I commit the ".expo" folder?
|
|
7
|
+
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
|
|
8
|
+
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { createLakebedNativeMetroConfig } = require("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/metro.lakebed-native.cjs");
|
|
4
|
+
module.exports = createLakebedNativeMetroConfig("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/camera-note/.lakebed-native/metro", "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use lakebed-native/ui first.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Camera Note template
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Router, Stack, Route, Screen, Text, Button, Input, List, Card, Image } from "lakebed-native/ui";
|
|
3
|
+
import { useQuery, useMutation } from "lakebed-native/client";
|
|
4
|
+
import { camera, imagePicker } from "lakebed-native/capabilities";
|
|
5
|
+
|
|
6
|
+
function CameraNotes() {
|
|
7
|
+
const { data: notes, refetch } = useQuery<Array<{ id: string; uri: string; caption: string }>>("listNotes");
|
|
8
|
+
const { mutate: saveNote } = useMutation<{ uri: string; caption: string }>("saveNote");
|
|
9
|
+
const [caption, setCaption] = useState("");
|
|
10
|
+
const [uri, setUri] = useState<string | null>(null);
|
|
11
|
+
|
|
12
|
+
const takePhoto = async () => {
|
|
13
|
+
const result = await camera.takePhoto();
|
|
14
|
+
if (result.ok) setUri(result.data.uri);
|
|
15
|
+
else alert(result.message);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const pickPhoto = async () => {
|
|
19
|
+
const result = await imagePicker.pick();
|
|
20
|
+
if (result.ok) setUri(result.data.uri);
|
|
21
|
+
else alert(result.message);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Screen title="Camera Notes" testID="camera-note-screen">
|
|
26
|
+
<Button title="Take Photo" onPress={takePhoto} testID="take-photo-button" />
|
|
27
|
+
<Button title="Pick Photo" onPress={pickPhoto} testID="pick-photo-button" />
|
|
28
|
+
{uri ? <Image source={{ uri }} style={{ width: "100%", height: 200 }} testID="preview-image" /> : null}
|
|
29
|
+
<Input value={caption} onChangeText={setCaption} placeholder="Caption" testID="caption-input" />
|
|
30
|
+
<Button
|
|
31
|
+
title="Save Note"
|
|
32
|
+
testID="save-note-button"
|
|
33
|
+
onPress={async () => {
|
|
34
|
+
if (!uri) return;
|
|
35
|
+
await saveNote({ uri, caption });
|
|
36
|
+
setCaption("");
|
|
37
|
+
setUri(null);
|
|
38
|
+
await refetch();
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
<List
|
|
42
|
+
data={notes ?? []}
|
|
43
|
+
keyExtractor={(n) => n.id}
|
|
44
|
+
testID="notes-list"
|
|
45
|
+
renderItem={({ item }) => (
|
|
46
|
+
<Card testID={`note-${item.id}`}>
|
|
47
|
+
<Image source={{ uri: item.uri }} style={{ width: "100%", height: 120 }} />
|
|
48
|
+
<Text>{item.caption || "(no caption)"}</Text>
|
|
49
|
+
</Card>
|
|
50
|
+
)}
|
|
51
|
+
/>
|
|
52
|
+
</Screen>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default function App() {
|
|
57
|
+
return (
|
|
58
|
+
<Router>
|
|
59
|
+
<Stack>
|
|
60
|
+
<Route path="/" element={<CameraNotes />} />
|
|
61
|
+
</Stack>
|
|
62
|
+
</Router>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { capsule, query, mutation, table, string, text } from "lakebed/server";
|
|
2
|
+
|
|
3
|
+
const notes = table("notes", {
|
|
4
|
+
uri: string(),
|
|
5
|
+
caption: text(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export default capsule({
|
|
9
|
+
name: "camera-note",
|
|
10
|
+
tables: [notes],
|
|
11
|
+
queries: [query("listNotes", (ctx) => ctx.db.table("notes").orderBy("id", "desc").all())],
|
|
12
|
+
mutations: [
|
|
13
|
+
mutation("saveNote", (ctx, args: { uri?: string; caption?: string }) => {
|
|
14
|
+
if (!args?.uri) throw new Error("Photo URI required");
|
|
15
|
+
ctx.log.info("Saving note", { uri: args.uri });
|
|
16
|
+
return ctx.db.table("notes").insert({
|
|
17
|
+
uri: args.uri,
|
|
18
|
+
caption: args.caption?.trim() ?? "",
|
|
19
|
+
});
|
|
20
|
+
}),
|
|
21
|
+
],
|
|
22
|
+
endpoints: [],
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CAPSULE_NAME=error-fixture
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"serverUrl": "http://localhost:3000",
|
|
3
|
+
"bundleUrl": "http://localhost:3100/index.bundle?platform=ios&dev=true&minify=false",
|
|
4
|
+
"capsuleEntry": "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/error-fixture/app/index.tsx",
|
|
5
|
+
"openUrl": "lakebed-native://capsule?server=http%3A%2F%2Flocalhost%3A3000&bundle=http%3A%2F%2Flocalhost%3A3100%2Findex.bundle%3Fplatform%3Dios%26dev%3Dtrue%26minify%3Dfalse"
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
> Why do I have a folder named ".expo" in my project?
|
|
2
|
+
The ".expo" folder is created when an Expo project is started using "expo start" command.
|
|
3
|
+
> What do the files contain?
|
|
4
|
+
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
|
|
5
|
+
- "settings.json": contains the server configuration that is used to serve the application manifest.
|
|
6
|
+
> Should I commit the ".expo" folder?
|
|
7
|
+
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
|
|
8
|
+
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { createLakebedNativeMetroConfig } = require("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/metro.lakebed-native.cjs");
|
|
4
|
+
module.exports = createLakebedNativeMetroConfig("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/error-fixture/.lakebed-native/metro", "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use lakebed-native/ui first.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Error fixture template for logs E2E testing
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Router, Stack, Route, Screen, Button, Text } from "lakebed-native/ui";
|
|
3
|
+
import { useMutation } from "lakebed-native/client";
|
|
4
|
+
|
|
5
|
+
function ErrorFixture() {
|
|
6
|
+
const { mutate: triggerServer } = useMutation("triggerServerError");
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<Screen title="Error Fixture" testID="error-fixture-screen">
|
|
10
|
+
<Button
|
|
11
|
+
title="Trigger JS Error"
|
|
12
|
+
testID="trigger-js-error"
|
|
13
|
+
onPress={() => {
|
|
14
|
+
throw new Error("Client-side E2E error");
|
|
15
|
+
}}
|
|
16
|
+
/>
|
|
17
|
+
<Button
|
|
18
|
+
title="Trigger Server Error"
|
|
19
|
+
testID="trigger-server-error"
|
|
20
|
+
onPress={() => triggerServer({})}
|
|
21
|
+
/>
|
|
22
|
+
<Text testID="error-fixture-hint">Use logs CLI after triggering errors</Text>
|
|
23
|
+
</Screen>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function App() {
|
|
28
|
+
return (
|
|
29
|
+
<Router><Stack><Route path="/" element={<ErrorFixture />} /></Stack></Router>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { capsule, query, mutation } from "lakebed/server";
|
|
2
|
+
|
|
3
|
+
export default capsule({
|
|
4
|
+
name: "error-fixture",
|
|
5
|
+
tables: [],
|
|
6
|
+
queries: [
|
|
7
|
+
query("triggerError", () => {
|
|
8
|
+
throw new Error("Intentional E2E error fixture");
|
|
9
|
+
}),
|
|
10
|
+
],
|
|
11
|
+
mutations: [
|
|
12
|
+
mutation("triggerServerError", (ctx) => {
|
|
13
|
+
ctx.log.error("Intentional E2E server error");
|
|
14
|
+
throw new Error("Intentional E2E server error");
|
|
15
|
+
}),
|
|
16
|
+
mutation("triggerClientError", () => ({ ok: true })),
|
|
17
|
+
],
|
|
18
|
+
endpoints: [],
|
|
19
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CAPSULE_NAME=form
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"serverUrl": "http://localhost:3000",
|
|
3
|
+
"bundleUrl": "http://localhost:3100/index.bundle?platform=ios&dev=true&minify=false",
|
|
4
|
+
"capsuleEntry": "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/form/app/index.tsx",
|
|
5
|
+
"openUrl": "lakebed-native://capsule?server=http%3A%2F%2Flocalhost%3A3000&bundle=http%3A%2F%2Flocalhost%3A3100%2Findex.bundle%3Fplatform%3Dios%26dev%3Dtrue%26minify%3Dfalse"
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
> Why do I have a folder named ".expo" in my project?
|
|
2
|
+
The ".expo" folder is created when an Expo project is started using "expo start" command.
|
|
3
|
+
> What do the files contain?
|
|
4
|
+
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
|
|
5
|
+
- "settings.json": contains the server configuration that is used to serve the application manifest.
|
|
6
|
+
> Should I commit the ".expo" folder?
|
|
7
|
+
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
|
|
8
|
+
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { createLakebedNativeMetroConfig } = require("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/metro.lakebed-native.cjs");
|
|
4
|
+
module.exports = createLakebedNativeMetroConfig("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/form/.lakebed-native/metro", "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use lakebed-native/ui first.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Form template
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Router, Stack, Route, Screen, Form, Field, Input, TextArea, Text, List, Card } from "lakebed-native/ui";
|
|
3
|
+
import { useQuery, useMutation } from "lakebed-native/client";
|
|
4
|
+
|
|
5
|
+
function FormScreen() {
|
|
6
|
+
const { mutate: submitForm } = useMutation<{ name: string; email: string; notes: string }>("submitForm");
|
|
7
|
+
const { data: submissions, refetch } = useQuery<Array<{ id: string; name: string; email: string; notes: string }>>("listSubmissions");
|
|
8
|
+
const [name, setName] = useState("");
|
|
9
|
+
const [email, setEmail] = useState("");
|
|
10
|
+
const [notes, setNotes] = useState("");
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<Screen title="Contact Form" testID="form-screen">
|
|
14
|
+
<Form
|
|
15
|
+
onSubmit={async () => {
|
|
16
|
+
await submitForm({ name, email, notes });
|
|
17
|
+
setName("");
|
|
18
|
+
setEmail("");
|
|
19
|
+
setNotes("");
|
|
20
|
+
await refetch();
|
|
21
|
+
}}
|
|
22
|
+
>
|
|
23
|
+
<Field label="Name">
|
|
24
|
+
<Input value={name} onChangeText={setName} testID="form-name" />
|
|
25
|
+
</Field>
|
|
26
|
+
<Field label="Email">
|
|
27
|
+
<Input value={email} onChangeText={setEmail} testID="form-email" />
|
|
28
|
+
</Field>
|
|
29
|
+
<Field label="Notes">
|
|
30
|
+
<TextArea value={notes} onChangeText={setNotes} testID="form-notes" />
|
|
31
|
+
</Field>
|
|
32
|
+
</Form>
|
|
33
|
+
<List
|
|
34
|
+
data={submissions ?? []}
|
|
35
|
+
keyExtractor={(s) => s.id}
|
|
36
|
+
testID="submissions-list"
|
|
37
|
+
renderItem={({ item }) => (
|
|
38
|
+
<Card testID={`submission-${item.id}`}>
|
|
39
|
+
<Text>{item.name} — {item.email}</Text>
|
|
40
|
+
<Text>{item.notes}</Text>
|
|
41
|
+
</Card>
|
|
42
|
+
)}
|
|
43
|
+
/>
|
|
44
|
+
</Screen>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default function App() {
|
|
49
|
+
return (
|
|
50
|
+
<Router>
|
|
51
|
+
<Stack>
|
|
52
|
+
<Route path="/" element={<FormScreen />} />
|
|
53
|
+
</Stack>
|
|
54
|
+
</Router>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { capsule, query, mutation, table, string, text } from "lakebed/server";
|
|
2
|
+
|
|
3
|
+
const submissions = table("submissions", {
|
|
4
|
+
name: string(),
|
|
5
|
+
email: string(),
|
|
6
|
+
notes: text(),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export default capsule({
|
|
10
|
+
name: "form",
|
|
11
|
+
tables: [submissions],
|
|
12
|
+
queries: [query("listSubmissions", (ctx) => ctx.db.table("submissions").all())],
|
|
13
|
+
mutations: [
|
|
14
|
+
mutation("submitForm", (ctx, args: { name?: string; email?: string; notes?: string }) => {
|
|
15
|
+
const name = args?.name?.trim();
|
|
16
|
+
const email = args?.email?.trim();
|
|
17
|
+
if (!name) throw new Error("Name is required");
|
|
18
|
+
if (!email) throw new Error("Email is required");
|
|
19
|
+
return ctx.db.table("submissions").insert({
|
|
20
|
+
name,
|
|
21
|
+
email,
|
|
22
|
+
notes: args?.notes?.trim() ?? "",
|
|
23
|
+
});
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
endpoints: [],
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CAPSULE_NAME=guestbook
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use lakebed-native/ui first. See todo template AGENTS.md for rules.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Router, Stack, Route, Screen, Text, Button, Input, List, Card } from "lakebed-native/ui";
|
|
3
|
+
import { useQuery, useMutation } from "lakebed-native/client";
|
|
4
|
+
|
|
5
|
+
function Guestbook() {
|
|
6
|
+
const { data: entries, refetch } = useQuery<Array<{ id: string; authorName: string; message: string }>>("listEntries");
|
|
7
|
+
const { mutate: addEntry } = useMutation<{ message: string }>("addEntry");
|
|
8
|
+
const [message, setMessage] = useState("");
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<Screen title="Guestbook" testID="guestbook-screen">
|
|
12
|
+
<Input value={message} onChangeText={setMessage} placeholder="Leave a message" testID="guestbook-input" />
|
|
13
|
+
<Button
|
|
14
|
+
title="Sign Guestbook"
|
|
15
|
+
testID="add-entry-button"
|
|
16
|
+
onPress={async () => {
|
|
17
|
+
await addEntry({ message });
|
|
18
|
+
setMessage("");
|
|
19
|
+
await refetch();
|
|
20
|
+
}}
|
|
21
|
+
/>
|
|
22
|
+
<List
|
|
23
|
+
data={entries ?? []}
|
|
24
|
+
keyExtractor={(e) => e.id}
|
|
25
|
+
testID="guestbook-list"
|
|
26
|
+
renderItem={({ item }) => (
|
|
27
|
+
<Card testID={`entry-${item.id}`}>
|
|
28
|
+
<Text style={{ fontWeight: "600" }}>{item.authorName}</Text>
|
|
29
|
+
<Text>{item.message}</Text>
|
|
30
|
+
</Card>
|
|
31
|
+
)}
|
|
32
|
+
/>
|
|
33
|
+
</Screen>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default function App() {
|
|
38
|
+
return (
|
|
39
|
+
<Router>
|
|
40
|
+
<Stack>
|
|
41
|
+
<Route path="/" title="Guestbook" element={<Guestbook />} />
|
|
42
|
+
</Stack>
|
|
43
|
+
</Router>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { capsule, query, mutation, table, string, text } from "lakebed/server";
|
|
2
|
+
|
|
3
|
+
const entries = table("entries", {
|
|
4
|
+
authorId: string(),
|
|
5
|
+
authorName: string(),
|
|
6
|
+
message: text(),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export default capsule({
|
|
10
|
+
name: "guestbook",
|
|
11
|
+
tables: [entries],
|
|
12
|
+
queries: [
|
|
13
|
+
query("listEntries", (ctx) =>
|
|
14
|
+
ctx.db.table("entries").orderBy("id", "desc").limit(50).all()
|
|
15
|
+
),
|
|
16
|
+
],
|
|
17
|
+
mutations: [
|
|
18
|
+
mutation("addEntry", (ctx, args: { message?: string }) => {
|
|
19
|
+
const message = args?.message?.trim() ?? "";
|
|
20
|
+
if (!message) throw new Error("Message is required");
|
|
21
|
+
if (message.length > 280) throw new Error("Message must be 280 characters or less");
|
|
22
|
+
const user = ctx.auth.user;
|
|
23
|
+
return ctx.db.table("entries").insert({
|
|
24
|
+
authorId: user?.id ?? "guest",
|
|
25
|
+
authorName: user?.name ?? "Guest",
|
|
26
|
+
message,
|
|
27
|
+
});
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
endpoints: [],
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CAPSULE_NAME=location-checkin
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"serverUrl": "http://localhost:3000",
|
|
3
|
+
"bundleUrl": "http://localhost:3100/index.bundle?platform=ios&dev=true&minify=false",
|
|
4
|
+
"capsuleEntry": "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/location-checkin/app/index.tsx",
|
|
5
|
+
"openUrl": "lakebed-native://capsule?server=http%3A%2F%2Flocalhost%3A3000&bundle=http%3A%2F%2Flocalhost%3A3100%2Findex.bundle%3Fplatform%3Dios%26dev%3Dtrue%26minify%3Dfalse"
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
> Why do I have a folder named ".expo" in my project?
|
|
2
|
+
The ".expo" folder is created when an Expo project is started using "expo start" command.
|
|
3
|
+
> What do the files contain?
|
|
4
|
+
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
|
|
5
|
+
- "settings.json": contains the server configuration that is used to serve the application manifest.
|
|
6
|
+
> Should I commit the ".expo" folder?
|
|
7
|
+
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
|
|
8
|
+
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { createLakebedNativeMetroConfig } = require("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/metro.lakebed-native.cjs");
|
|
4
|
+
module.exports = createLakebedNativeMetroConfig("/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor/templates/location-checkin/.lakebed-native/metro", "/Users/yahiaelramal/MAS_Projects/lakebed-native-cursor");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use lakebed-native/ui first.
|