@codyswann/lisa 2.111.0 → 2.112.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/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.mcp.json +3 -3
- package/plugins/lisa-expo/THIRD-PARTY-NOTICES.md +57 -0
- package/plugins/lisa-expo/skills/add-app-clip/SKILL.md +280 -0
- package/plugins/lisa-expo/skills/add-app-clip/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/add-app-clip/references/native-module.md +96 -0
- package/plugins/lisa-expo/skills/building-native-ui/SKILL.md +321 -0
- package/plugins/lisa-expo/skills/building-native-ui/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/animations.md +220 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/controls.md +272 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/form-sheet.md +253 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/gradients.md +106 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/icons.md +213 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/media.md +198 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/route-structure.md +229 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/search.md +248 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/storage.md +121 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/tabs.md +433 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/toolbar-and-headers.md +284 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/visual-effects.md +197 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/webgpu-three.md +605 -0
- package/plugins/lisa-expo/skills/building-native-ui/references/zoom-transitions.md +158 -0
- package/plugins/lisa-expo/skills/eas-update-insights/SKILL.md +228 -0
- package/plugins/lisa-expo/skills/eas-update-insights/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/plugins/lisa-expo/skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/plugins/lisa-expo/skills/expo-api-routes/SKILL.md +369 -0
- package/plugins/lisa-expo/skills/expo-api-routes/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-brownfield/SKILL.md +54 -0
- package/plugins/lisa-expo/skills/expo-brownfield/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-brownfield/references/brownfield-integrated.md +526 -0
- package/plugins/lisa-expo/skills/expo-brownfield/references/brownfield-isolated.md +402 -0
- package/plugins/lisa-expo/skills/expo-brownfield/references/comparison.md +63 -0
- package/plugins/lisa-expo/skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/plugins/lisa-expo/skills/expo-cicd-workflows/SKILL.md +92 -0
- package/plugins/lisa-expo/skills/expo-cicd-workflows/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-cicd-workflows/scripts/fetch.js +113 -0
- package/plugins/lisa-expo/skills/expo-cicd-workflows/scripts/package.json +11 -0
- package/plugins/lisa-expo/skills/expo-cicd-workflows/scripts/validate.js +85 -0
- package/plugins/lisa-expo/skills/expo-deployment/SKILL.md +190 -0
- package/plugins/lisa-expo/skills/expo-deployment/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-deployment/references/app-store-metadata.md +479 -0
- package/plugins/lisa-expo/skills/expo-deployment/references/ios-app-store.md +355 -0
- package/plugins/lisa-expo/skills/expo-deployment/references/play-store.md +246 -0
- package/plugins/lisa-expo/skills/expo-deployment/references/testflight.md +58 -0
- package/plugins/lisa-expo/skills/expo-deployment/references/workflows.md +200 -0
- package/plugins/lisa-expo/skills/expo-dev-client/SKILL.md +164 -0
- package/plugins/lisa-expo/skills/expo-dev-client/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-module/SKILL.md +141 -0
- package/plugins/lisa-expo/skills/expo-module/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-module/references/config-plugin.md +90 -0
- package/plugins/lisa-expo/skills/expo-module/references/create-expo-module.md +206 -0
- package/plugins/lisa-expo/skills/expo-module/references/lifecycle.md +127 -0
- package/plugins/lisa-expo/skills/expo-module/references/module-config.md +48 -0
- package/plugins/lisa-expo/skills/expo-module/references/native-module.md +286 -0
- package/plugins/lisa-expo/skills/expo-module/references/native-view.md +171 -0
- package/plugins/lisa-expo/skills/expo-tailwind-setup/SKILL.md +480 -0
- package/plugins/lisa-expo/skills/expo-tailwind-setup/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-ui-jetpack-compose/SKILL.md +40 -0
- package/plugins/lisa-expo/skills/expo-ui-jetpack-compose/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-ui-swift-ui/SKILL.md +39 -0
- package/plugins/lisa-expo/skills/expo-ui-swift-ui/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/native-data-fetching/SKILL.md +507 -0
- package/plugins/lisa-expo/skills/native-data-fetching/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/native-data-fetching/references/expo-router-loaders.md +344 -0
- package/plugins/lisa-expo/skills/upgrading-expo/SKILL.md +134 -0
- package/plugins/lisa-expo/skills/upgrading-expo/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/expo-av-to-video.md +160 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/native-tabs.md +124 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/new-architecture.md +79 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/react-19.md +79 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/react-compiler.md +59 -0
- package/plugins/lisa-expo/skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
- package/plugins/lisa-expo/skills/use-dom/SKILL.md +417 -0
- package/plugins/lisa-expo/skills/use-dom/agents/openai.yaml +4 -0
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/src/expo/.mcp.json +3 -3
- package/plugins/src/expo/THIRD-PARTY-NOTICES.md +57 -0
- package/plugins/src/expo/skills/add-app-clip/SKILL.md +280 -0
- package/plugins/src/expo/skills/add-app-clip/references/native-module.md +96 -0
- package/plugins/src/expo/skills/building-native-ui/SKILL.md +321 -0
- package/plugins/src/expo/skills/building-native-ui/references/animations.md +220 -0
- package/plugins/src/expo/skills/building-native-ui/references/controls.md +272 -0
- package/plugins/src/expo/skills/building-native-ui/references/form-sheet.md +253 -0
- package/plugins/src/expo/skills/building-native-ui/references/gradients.md +106 -0
- package/plugins/src/expo/skills/building-native-ui/references/icons.md +213 -0
- package/plugins/src/expo/skills/building-native-ui/references/media.md +198 -0
- package/plugins/src/expo/skills/building-native-ui/references/route-structure.md +229 -0
- package/plugins/src/expo/skills/building-native-ui/references/search.md +248 -0
- package/plugins/src/expo/skills/building-native-ui/references/storage.md +121 -0
- package/plugins/src/expo/skills/building-native-ui/references/tabs.md +433 -0
- package/plugins/src/expo/skills/building-native-ui/references/toolbar-and-headers.md +284 -0
- package/plugins/src/expo/skills/building-native-ui/references/visual-effects.md +197 -0
- package/plugins/src/expo/skills/building-native-ui/references/webgpu-three.md +605 -0
- package/plugins/src/expo/skills/building-native-ui/references/zoom-transitions.md +158 -0
- package/plugins/src/expo/skills/eas-update-insights/SKILL.md +228 -0
- package/plugins/src/expo/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/plugins/src/expo/skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/plugins/src/expo/skills/expo-api-routes/SKILL.md +369 -0
- package/plugins/src/expo/skills/expo-brownfield/SKILL.md +54 -0
- package/plugins/src/expo/skills/expo-brownfield/references/brownfield-integrated.md +526 -0
- package/plugins/src/expo/skills/expo-brownfield/references/brownfield-isolated.md +402 -0
- package/plugins/src/expo/skills/expo-brownfield/references/comparison.md +63 -0
- package/plugins/src/expo/skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/plugins/src/expo/skills/expo-cicd-workflows/SKILL.md +92 -0
- package/plugins/src/expo/skills/expo-cicd-workflows/scripts/fetch.js +113 -0
- package/plugins/src/expo/skills/expo-cicd-workflows/scripts/package.json +11 -0
- package/plugins/src/expo/skills/expo-cicd-workflows/scripts/validate.js +85 -0
- package/plugins/src/expo/skills/expo-deployment/SKILL.md +190 -0
- package/plugins/src/expo/skills/expo-deployment/references/app-store-metadata.md +479 -0
- package/plugins/src/expo/skills/expo-deployment/references/ios-app-store.md +355 -0
- package/plugins/src/expo/skills/expo-deployment/references/play-store.md +246 -0
- package/plugins/src/expo/skills/expo-deployment/references/testflight.md +58 -0
- package/plugins/src/expo/skills/expo-deployment/references/workflows.md +200 -0
- package/plugins/src/expo/skills/expo-dev-client/SKILL.md +164 -0
- package/plugins/src/expo/skills/expo-module/SKILL.md +141 -0
- package/plugins/src/expo/skills/expo-module/references/config-plugin.md +90 -0
- package/plugins/src/expo/skills/expo-module/references/create-expo-module.md +206 -0
- package/plugins/src/expo/skills/expo-module/references/lifecycle.md +127 -0
- package/plugins/src/expo/skills/expo-module/references/module-config.md +48 -0
- package/plugins/src/expo/skills/expo-module/references/native-module.md +286 -0
- package/plugins/src/expo/skills/expo-module/references/native-view.md +171 -0
- package/plugins/src/expo/skills/expo-tailwind-setup/SKILL.md +480 -0
- package/plugins/src/expo/skills/expo-ui-jetpack-compose/SKILL.md +40 -0
- package/plugins/src/expo/skills/expo-ui-swift-ui/SKILL.md +39 -0
- package/plugins/src/expo/skills/native-data-fetching/SKILL.md +507 -0
- package/plugins/src/expo/skills/native-data-fetching/references/expo-router-loaders.md +344 -0
- package/plugins/src/expo/skills/upgrading-expo/SKILL.md +134 -0
- package/plugins/src/expo/skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
- package/plugins/src/expo/skills/upgrading-expo/references/expo-av-to-video.md +160 -0
- package/plugins/src/expo/skills/upgrading-expo/references/native-tabs.md +124 -0
- package/plugins/src/expo/skills/upgrading-expo/references/new-architecture.md +79 -0
- package/plugins/src/expo/skills/upgrading-expo/references/react-19.md +79 -0
- package/plugins/src/expo/skills/upgrading-expo/references/react-compiler.md +59 -0
- package/plugins/src/expo/skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
- package/plugins/src/expo/skills/use-dom/SKILL.md +417 -0
- package/scripts/generate-codex-plugin-artifacts.mjs +7 -2
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
|
|
8
|
+
const CACHE_DIRECTORY = resolve(import.meta.dirname, ".cache");
|
|
9
|
+
const DEFAULT_TTL_SECONDS = 15 * 60; // 15 minutes
|
|
10
|
+
|
|
11
|
+
export async function fetchCached(url) {
|
|
12
|
+
await mkdir(CACHE_DIRECTORY, { recursive: true });
|
|
13
|
+
|
|
14
|
+
const cacheFile = resolve(CACHE_DIRECTORY, hashUrl(url) + ".json");
|
|
15
|
+
const cached = await loadCacheEntry(cacheFile);
|
|
16
|
+
if (cached && cached.expires > Math.floor(Date.now() / 1000)) {
|
|
17
|
+
return cached.data;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Make request, with conditional If-None-Match if we have an ETag.
|
|
21
|
+
// Cache-Control: max-age=0 overrides Node's default 'no-cache' to allow 304 responses.
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const timeout = setTimeout(() => controller.abort(), 15000);
|
|
24
|
+
const response = await fetch(url, {
|
|
25
|
+
headers: {
|
|
26
|
+
"Cache-Control": "max-age=0",
|
|
27
|
+
...(cached?.etag && { "If-None-Match": cached.etag }),
|
|
28
|
+
},
|
|
29
|
+
signal: controller.signal,
|
|
30
|
+
});
|
|
31
|
+
clearTimeout(timeout);
|
|
32
|
+
|
|
33
|
+
if (response.status === 304 && cached) {
|
|
34
|
+
// Refresh expiration and return cached data
|
|
35
|
+
const entry = { ...cached, expires: getExpires(response.headers) };
|
|
36
|
+
await saveCacheEntry(cacheFile, entry);
|
|
37
|
+
return cached.data;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const etag = response.headers.get("etag");
|
|
45
|
+
const data = await response.text();
|
|
46
|
+
const expires = getExpires(response.headers);
|
|
47
|
+
|
|
48
|
+
await saveCacheEntry(cacheFile, { url, etag, expires, data });
|
|
49
|
+
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function hashUrl(url) {
|
|
54
|
+
return createHash("sha256").update(url).digest("hex").slice(0, 16);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function loadCacheEntry(cacheFile) {
|
|
58
|
+
try {
|
|
59
|
+
return JSON.parse(await readFile(cacheFile, "utf-8"));
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function saveCacheEntry(cacheFile, entry) {
|
|
66
|
+
await writeFile(cacheFile, JSON.stringify(entry, null, 2));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getExpires(headers) {
|
|
70
|
+
const now = Math.floor(Date.now() / 1000);
|
|
71
|
+
|
|
72
|
+
// Prefer Cache-Control: max-age
|
|
73
|
+
const maxAgeSeconds = parseMaxAge(headers.get("cache-control"));
|
|
74
|
+
if (maxAgeSeconds != null) {
|
|
75
|
+
return now + maxAgeSeconds;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Fall back to Expires header
|
|
79
|
+
const expires = headers.get("expires");
|
|
80
|
+
if (expires) {
|
|
81
|
+
const expiresTime = Date.parse(expires);
|
|
82
|
+
if (!Number.isNaN(expiresTime)) {
|
|
83
|
+
return Math.floor(expiresTime / 1000);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Default TTL
|
|
88
|
+
return now + DEFAULT_TTL_SECONDS;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function parseMaxAge(cacheControl) {
|
|
92
|
+
if (!cacheControl) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
const match = cacheControl.match(/max-age=(\d+)/i);
|
|
96
|
+
return match ? parseInt(match[1], 10) : null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (import.meta.main) {
|
|
100
|
+
const url = process.argv[2];
|
|
101
|
+
|
|
102
|
+
if (!url || url === "--help" || url === "-h") {
|
|
103
|
+
console.log(`Usage: fetch <url>
|
|
104
|
+
|
|
105
|
+
Fetches a URL with HTTP caching (ETags + Cache-Control/Expires).
|
|
106
|
+
Default TTL: ${DEFAULT_TTL_SECONDS / 60} minutes.
|
|
107
|
+
Cache is stored in: ${CACHE_DIRECTORY}/`);
|
|
108
|
+
process.exit(url ? 0 : 1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const data = await fetchCached(url);
|
|
112
|
+
console.log(data);
|
|
113
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
|
|
7
|
+
import Ajv2020 from "ajv/dist/2020.js";
|
|
8
|
+
import addFormats from "ajv-formats";
|
|
9
|
+
import yaml from "js-yaml";
|
|
10
|
+
|
|
11
|
+
import { fetchCached } from "./fetch.js";
|
|
12
|
+
|
|
13
|
+
const SCHEMA_URL = "https://api.expo.dev/v2/workflows/schema";
|
|
14
|
+
|
|
15
|
+
async function fetchSchema() {
|
|
16
|
+
const data = await fetchCached(SCHEMA_URL);
|
|
17
|
+
const body = JSON.parse(data);
|
|
18
|
+
return body.data;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createValidator(schema) {
|
|
22
|
+
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
23
|
+
addFormats(ajv);
|
|
24
|
+
return ajv.compile(schema);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function validateFile(validator, filePath) {
|
|
28
|
+
const content = await readFile(filePath, "utf-8");
|
|
29
|
+
|
|
30
|
+
let doc;
|
|
31
|
+
try {
|
|
32
|
+
doc = yaml.load(content);
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return { valid: false, error: `YAML parse error: ${e.message}` };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const valid = validator(doc);
|
|
38
|
+
if (!valid) {
|
|
39
|
+
return { valid: false, error: formatErrors(validator.errors) };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return { valid: true };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function formatErrors(errors) {
|
|
46
|
+
return errors
|
|
47
|
+
.map(error => {
|
|
48
|
+
const path = error.instancePath || "(root)";
|
|
49
|
+
const allowed = error.params?.allowedValues?.join(", ");
|
|
50
|
+
return ` ${path}: ${error.message}${allowed ? ` (allowed: ${allowed})` : ""}`;
|
|
51
|
+
})
|
|
52
|
+
.join("\n");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (import.meta.main) {
|
|
56
|
+
const args = process.argv.slice(2);
|
|
57
|
+
const files = args.filter(a => !a.startsWith("-"));
|
|
58
|
+
|
|
59
|
+
const wantsHelp = args.includes("--help") || args.includes("-h");
|
|
60
|
+
if (files.length === 0 || wantsHelp) {
|
|
61
|
+
console.log(`Usage: validate <workflow.yml> [workflow2.yml ...]
|
|
62
|
+
|
|
63
|
+
Validates EAS workflow YAML files against the official schema.`);
|
|
64
|
+
process.exit(wantsHelp ? 0 : 1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const schema = await fetchSchema();
|
|
68
|
+
const validator = createValidator(schema);
|
|
69
|
+
|
|
70
|
+
let hasErrors = false;
|
|
71
|
+
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
const filePath = resolve(process.cwd(), file);
|
|
74
|
+
const result = await validateFile(validator, filePath);
|
|
75
|
+
|
|
76
|
+
if (result.valid) {
|
|
77
|
+
console.log(`✓ ${file}`);
|
|
78
|
+
} else {
|
|
79
|
+
console.error(`✗ ${file}\n${result.error}`);
|
|
80
|
+
hasErrors = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
process.exit(hasErrors ? 1 : 0);
|
|
85
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: expo-deployment
|
|
3
|
+
description: Deploying Expo apps to iOS App Store, Android Play Store, web hosting, and API routes
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
license: MIT
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Deployment
|
|
9
|
+
|
|
10
|
+
This skill covers deploying Expo applications across all platforms using EAS (Expo Application Services).
|
|
11
|
+
|
|
12
|
+
## References
|
|
13
|
+
|
|
14
|
+
Consult these resources as needed:
|
|
15
|
+
|
|
16
|
+
- ./references/workflows.md -- CI/CD workflows for automated deployments and PR previews
|
|
17
|
+
- ./references/testflight.md -- Submitting iOS builds to TestFlight for beta testing
|
|
18
|
+
- ./references/app-store-metadata.md -- Managing App Store metadata and ASO optimization
|
|
19
|
+
- ./references/play-store.md -- Submitting Android builds to Google Play Store
|
|
20
|
+
- ./references/ios-app-store.md -- iOS App Store submission and review process
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Install EAS CLI
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g eas-cli
|
|
28
|
+
eas login
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Initialize EAS
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx eas-cli@latest init
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This creates `eas.json` with build profiles.
|
|
38
|
+
|
|
39
|
+
## Build Commands
|
|
40
|
+
|
|
41
|
+
### Production Builds
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# iOS App Store build
|
|
45
|
+
npx eas-cli@latest build -p ios --profile production
|
|
46
|
+
|
|
47
|
+
# Android Play Store build
|
|
48
|
+
npx eas-cli@latest build -p android --profile production
|
|
49
|
+
|
|
50
|
+
# Both platforms
|
|
51
|
+
npx eas-cli@latest build --profile production
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Submit to Stores
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# iOS: Build and submit to App Store Connect
|
|
58
|
+
npx eas-cli@latest build -p ios --profile production --submit
|
|
59
|
+
|
|
60
|
+
# Android: Build and submit to Play Store
|
|
61
|
+
npx eas-cli@latest build -p android --profile production --submit
|
|
62
|
+
|
|
63
|
+
# Shortcut for iOS TestFlight
|
|
64
|
+
npx testflight
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Web Deployment
|
|
68
|
+
|
|
69
|
+
Deploy web apps using EAS Hosting:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Deploy to production
|
|
73
|
+
npx expo export -p web
|
|
74
|
+
npx eas-cli@latest deploy --prod
|
|
75
|
+
|
|
76
|
+
# Deploy PR preview
|
|
77
|
+
npx eas-cli@latest deploy
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## EAS Configuration
|
|
81
|
+
|
|
82
|
+
Standard `eas.json` for production deployments:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"cli": {
|
|
87
|
+
"version": ">= 16.0.1",
|
|
88
|
+
"appVersionSource": "remote"
|
|
89
|
+
},
|
|
90
|
+
"build": {
|
|
91
|
+
"production": {
|
|
92
|
+
"autoIncrement": true,
|
|
93
|
+
"ios": {
|
|
94
|
+
"resourceClass": "m-medium"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"development": {
|
|
98
|
+
"developmentClient": true,
|
|
99
|
+
"distribution": "internal"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"submit": {
|
|
103
|
+
"production": {
|
|
104
|
+
"ios": {
|
|
105
|
+
"appleId": "your@email.com",
|
|
106
|
+
"ascAppId": "1234567890"
|
|
107
|
+
},
|
|
108
|
+
"android": {
|
|
109
|
+
"serviceAccountKeyPath": "./google-service-account.json",
|
|
110
|
+
"track": "internal"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Platform-Specific Guides
|
|
118
|
+
|
|
119
|
+
### iOS
|
|
120
|
+
|
|
121
|
+
- Use `npx testflight` for quick TestFlight submissions
|
|
122
|
+
- Configure Apple credentials via `eas credentials`
|
|
123
|
+
- See ./references/testflight.md for credential setup
|
|
124
|
+
- See ./references/ios-app-store.md for App Store submission
|
|
125
|
+
|
|
126
|
+
### Android
|
|
127
|
+
|
|
128
|
+
- Set up Google Play Console service account
|
|
129
|
+
- Configure tracks: internal → closed → open → production
|
|
130
|
+
- See ./references/play-store.md for detailed setup
|
|
131
|
+
|
|
132
|
+
### Web
|
|
133
|
+
|
|
134
|
+
- EAS Hosting provides preview URLs for PRs
|
|
135
|
+
- Production deploys to your custom domain
|
|
136
|
+
- See ./references/workflows.md for CI/CD automation
|
|
137
|
+
|
|
138
|
+
## Automated Deployments
|
|
139
|
+
|
|
140
|
+
Use EAS Workflows for CI/CD:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
# .eas/workflows/release.yml
|
|
144
|
+
name: Release
|
|
145
|
+
|
|
146
|
+
on:
|
|
147
|
+
push:
|
|
148
|
+
branches: [main]
|
|
149
|
+
|
|
150
|
+
jobs:
|
|
151
|
+
build-ios:
|
|
152
|
+
type: build
|
|
153
|
+
params:
|
|
154
|
+
platform: ios
|
|
155
|
+
profile: production
|
|
156
|
+
|
|
157
|
+
submit-ios:
|
|
158
|
+
type: submit
|
|
159
|
+
needs: [build-ios]
|
|
160
|
+
params:
|
|
161
|
+
platform: ios
|
|
162
|
+
profile: production
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
See ./references/workflows.md for more workflow examples.
|
|
166
|
+
|
|
167
|
+
## Version Management
|
|
168
|
+
|
|
169
|
+
EAS manages version numbers automatically with `appVersionSource: "remote"`:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Check current versions
|
|
173
|
+
eas build:version:get
|
|
174
|
+
|
|
175
|
+
# Manually set version
|
|
176
|
+
eas build:version:set -p ios --build-number 42
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Monitoring
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# List recent builds
|
|
183
|
+
eas build:list
|
|
184
|
+
|
|
185
|
+
# Check build status
|
|
186
|
+
eas build:view
|
|
187
|
+
|
|
188
|
+
# View submission status
|
|
189
|
+
eas submit:list
|
|
190
|
+
```
|