@tamagui/cli 1.0.1-rc.1.4

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.
Files changed (68) hide show
  1. package/dist/cjs/build.js +81 -0
  2. package/dist/cjs/build.js.map +7 -0
  3. package/dist/cjs/cli.js +94 -0
  4. package/dist/cjs/cli.js.map +7 -0
  5. package/dist/cjs/create.js +2 -0
  6. package/dist/cjs/create.js.map +7 -0
  7. package/dist/cjs/dev.js +75 -0
  8. package/dist/cjs/dev.js.map +7 -0
  9. package/dist/cjs/generate.js +77 -0
  10. package/dist/cjs/generate.js.map +7 -0
  11. package/dist/cjs/index.js +4 -0
  12. package/dist/cjs/index.js.map +7 -0
  13. package/dist/cjs/studio.js +85 -0
  14. package/dist/cjs/studio.js.map +7 -0
  15. package/dist/cjs/tamaguiConfigUtils.js +95 -0
  16. package/dist/cjs/tamaguiConfigUtils.js.map +7 -0
  17. package/dist/cjs/test.js +39 -0
  18. package/dist/cjs/test.js.map +7 -0
  19. package/dist/cjs/types.js +17 -0
  20. package/dist/cjs/types.js.map +7 -0
  21. package/dist/cjs/utils.js +110 -0
  22. package/dist/cjs/utils.js.map +7 -0
  23. package/dist/esm/build.js +50 -0
  24. package/dist/esm/build.js.map +7 -0
  25. package/dist/esm/cli.js +75 -0
  26. package/dist/esm/cli.js.map +7 -0
  27. package/dist/esm/create.js +1 -0
  28. package/dist/esm/create.js.map +7 -0
  29. package/dist/esm/dev.js +45 -0
  30. package/dist/esm/dev.js.map +7 -0
  31. package/dist/esm/generate.js +46 -0
  32. package/dist/esm/generate.js.map +7 -0
  33. package/dist/esm/index.js +3 -0
  34. package/dist/esm/index.js.map +7 -0
  35. package/dist/esm/studio.js +54 -0
  36. package/dist/esm/studio.js.map +7 -0
  37. package/dist/esm/tamaguiConfigUtils.js +64 -0
  38. package/dist/esm/tamaguiConfigUtils.js.map +7 -0
  39. package/dist/esm/test.js +9 -0
  40. package/dist/esm/test.js.map +7 -0
  41. package/dist/esm/types.js +1 -0
  42. package/dist/esm/types.js.map +7 -0
  43. package/dist/esm/utils.js +77 -0
  44. package/dist/esm/utils.js.map +7 -0
  45. package/package.json +62 -0
  46. package/src/build.ts +63 -0
  47. package/src/cli.ts +153 -0
  48. package/src/create.ts +0 -0
  49. package/src/dev.ts +60 -0
  50. package/src/generate.ts +69 -0
  51. package/src/index.ts +3 -0
  52. package/src/studio.ts +69 -0
  53. package/src/tamaguiConfigUtils.ts +85 -0
  54. package/src/test.ts +12 -0
  55. package/src/types.ts +30 -0
  56. package/src/utils.ts +80 -0
  57. package/types/build.d.ts +3 -0
  58. package/types/cli.d.ts +2 -0
  59. package/types/create.d.ts +1 -0
  60. package/types/dev.d.ts +3 -0
  61. package/types/generate.d.ts +7 -0
  62. package/types/index.d.ts +3 -0
  63. package/types/studio.d.ts +3 -0
  64. package/types/tamagui-config.d.ts +5 -0
  65. package/types/tamaguiConfigUtils.d.ts +5 -0
  66. package/types/test.d.ts +3 -0
  67. package/types/types.d.ts +29 -0
  68. package/types/utils.d.ts +8 -0
@@ -0,0 +1,9 @@
1
+ const test = async (options) => {
2
+ const { dev } = await import("./dev.js");
3
+ void dev(options);
4
+ console.log("run tests");
5
+ };
6
+ export {
7
+ test
8
+ };
9
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/test.ts"],
4
+ "sourcesContent": ["/* eslint-disable no-console */\nimport { ResolvedOptions } from './types.js'\n\nexport const test = async (options: ResolvedOptions) => {\n const { dev } = await import('./dev.js')\n\n // failing on startup \"Tamagui error bundling components require() of ES Module\"\n\n void dev(options)\n\n console.log('run tests')\n}\n"],
5
+ "mappings": "AAGO,MAAM,OAAO,OAAO,YAA6B;AACtD,QAAM,EAAE,IAAI,IAAI,MAAM,OAAO;AAI7B,OAAK,IAAI,OAAO;AAEhB,UAAQ,IAAI,WAAW;AACzB;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,77 @@
1
+ import { join } from "path";
2
+ import { loadTamagui as loadTamaguiStatic } from "@tamagui/static";
3
+ import chalk from "chalk";
4
+ import fs, { pathExists, readJSON } from "fs-extra";
5
+ async function getOptions({
6
+ root = process.cwd(),
7
+ tsconfigPath = "tsconfig.json",
8
+ tamaguiOptions,
9
+ host,
10
+ debug
11
+ } = {}) {
12
+ const tsConfigFilePath = join(root, tsconfigPath);
13
+ ensure(await fs.pathExists(tsConfigFilePath), `No tsconfig found: ${tsConfigFilePath}`);
14
+ const dotDir = join(root, ".tamagui");
15
+ const pkgJson = await readJSON(join(root, "package.json"));
16
+ return {
17
+ mode: process.env.NODE_ENV === "production" ? "production" : "development",
18
+ root,
19
+ host,
20
+ pkgJson,
21
+ debug,
22
+ tsconfigPath,
23
+ tamaguiOptions: {
24
+ components: ["tamagui"],
25
+ config: await getDefaultTamaguiConfigPath(),
26
+ ...tamaguiOptions
27
+ },
28
+ paths: {
29
+ dotDir,
30
+ conf: join(dotDir, "tamagui.config.json"),
31
+ types: join(dotDir, "types.json")
32
+ }
33
+ };
34
+ }
35
+ function ensure(condition, message) {
36
+ if (!condition) {
37
+ console.error(chalk.red.bold("Error:"), chalk.yellow(`${message}`));
38
+ process.exit(1);
39
+ }
40
+ }
41
+ const defaultPaths = ["tamagui.config.ts", join("src", "tamagui.config.ts")];
42
+ let cachedPath = "";
43
+ async function getDefaultTamaguiConfigPath() {
44
+ if (cachedPath)
45
+ return cachedPath;
46
+ const existing = (await Promise.all(defaultPaths.map((path) => pathExists(path)))).findIndex(
47
+ (x) => !!x
48
+ );
49
+ const found = defaultPaths[existing];
50
+ if (!found) {
51
+ throw new Error(`No found tamagui.config.ts`);
52
+ }
53
+ cachedPath = found;
54
+ return found;
55
+ }
56
+ let cached = null;
57
+ const loadTamagui = async (opts) => {
58
+ return cached ??= await loadTamaguiStatic({
59
+ config: await getDefaultTamaguiConfigPath(),
60
+ components: ["tamagui"],
61
+ ...opts
62
+ });
63
+ };
64
+ function closeEvent(server) {
65
+ return new Promise((resolve) => {
66
+ server.ws.on("close", () => {
67
+ return resolve();
68
+ });
69
+ });
70
+ }
71
+ export {
72
+ closeEvent,
73
+ ensure,
74
+ getOptions,
75
+ loadTamagui
76
+ };
77
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils.ts"],
4
+ "sourcesContent": ["import { join } from 'path'\n\nimport type { TamaguiOptions, TamaguiProjectInfo } from '@tamagui/static'\nimport { loadTamagui as loadTamaguiStatic } from '@tamagui/static'\nimport chalk from 'chalk'\nimport fs, { pathExists, readJSON } from 'fs-extra'\nimport { ViteDevServer } from 'vite'\n\nimport { ResolvedOptions, UserOptions } from './types.js'\n\nexport async function getOptions({\n root = process.cwd(),\n tsconfigPath = 'tsconfig.json',\n tamaguiOptions,\n host,\n debug,\n}: Partial<UserOptions> = {}): Promise<ResolvedOptions> {\n const tsConfigFilePath = join(root, tsconfigPath)\n ensure(await fs.pathExists(tsConfigFilePath), `No tsconfig found: ${tsConfigFilePath}`)\n const dotDir = join(root, '.tamagui')\n const pkgJson = await readJSON(join(root, 'package.json'))\n\n return {\n mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',\n root,\n host,\n pkgJson,\n debug,\n tsconfigPath,\n tamaguiOptions: {\n components: ['tamagui'],\n config: await getDefaultTamaguiConfigPath(),\n ...tamaguiOptions,\n },\n paths: {\n dotDir,\n conf: join(dotDir, 'tamagui.config.json'),\n types: join(dotDir, 'types.json'),\n },\n }\n}\n\nexport function ensure(condition: boolean, message: string) {\n if (!condition) {\n console.error(chalk.red.bold('Error:'), chalk.yellow(`${message}`))\n process.exit(1)\n }\n}\n\nconst defaultPaths = ['tamagui.config.ts', join('src', 'tamagui.config.ts')]\nlet cachedPath = ''\nasync function getDefaultTamaguiConfigPath() {\n if (cachedPath) return cachedPath\n const existing = (await Promise.all(defaultPaths.map((path) => pathExists(path)))).findIndex(\n (x) => !!x\n )\n const found = defaultPaths[existing]\n if (!found) {\n throw new Error(`No found tamagui.config.ts`)\n }\n cachedPath = found\n return found\n}\n\nlet cached: TamaguiProjectInfo | null = null\nexport const loadTamagui = async (opts: Partial<TamaguiOptions>): Promise<TamaguiProjectInfo> => {\n return (cached ??= await loadTamaguiStatic({\n config: await getDefaultTamaguiConfigPath(),\n components: ['tamagui'],\n ...opts,\n }))\n}\n\nexport function closeEvent(server: ViteDevServer): Promise<void> {\n return new Promise((resolve) => {\n server.ws.on('close', () => {\n return resolve()\n })\n })\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAY;AAGrB,SAAS,eAAe,yBAAyB;AACjD,OAAO,WAAW;AAClB,OAAO,MAAM,YAAY,gBAAgB;AAKzC,eAAsB,WAAW;AAAA,EAC/B,OAAO,QAAQ,IAAI;AAAA,EACnB,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF,IAA0B,CAAC,GAA6B;AACtD,QAAM,mBAAmB,KAAK,MAAM,YAAY;AAChD,SAAO,MAAM,GAAG,WAAW,gBAAgB,GAAG,sBAAsB,kBAAkB;AACtF,QAAM,SAAS,KAAK,MAAM,UAAU;AACpC,QAAM,UAAU,MAAM,SAAS,KAAK,MAAM,cAAc,CAAC;AAEzD,SAAO;AAAA,IACL,MAAM,QAAQ,IAAI,aAAa,eAAe,eAAe;AAAA,IAC7D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,MACd,YAAY,CAAC,SAAS;AAAA,MACtB,QAAQ,MAAM,4BAA4B;AAAA,MAC1C,GAAG;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAQ,qBAAqB;AAAA,MACxC,OAAO,KAAK,QAAQ,YAAY;AAAA,IAClC;AAAA,EACF;AACF;AAEO,SAAS,OAAO,WAAoB,SAAiB;AAC1D,MAAI,CAAC,WAAW;AACd,YAAQ,MAAM,MAAM,IAAI,KAAK,QAAQ,GAAG,MAAM,OAAO,GAAG,SAAS,CAAC;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,MAAM,eAAe,CAAC,qBAAqB,KAAK,OAAO,mBAAmB,CAAC;AAC3E,IAAI,aAAa;AACjB,eAAe,8BAA8B;AAC3C,MAAI;AAAY,WAAO;AACvB,QAAM,YAAY,MAAM,QAAQ,IAAI,aAAa,IAAI,CAAC,SAAS,WAAW,IAAI,CAAC,CAAC,GAAG;AAAA,IACjF,CAAC,MAAM,CAAC,CAAC;AAAA,EACX;AACA,QAAM,QAAQ,aAAa;AAC3B,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AACA,eAAa;AACb,SAAO;AACT;AAEA,IAAI,SAAoC;AACjC,MAAM,cAAc,OAAO,SAA+D;AAC/F,SAAQ,WAAW,MAAM,kBAAkB;AAAA,IACzC,QAAQ,MAAM,4BAA4B;AAAA,IAC1C,YAAY,CAAC,SAAS;AAAA,IACtB,GAAG;AAAA,EACL,CAAC;AACH;AAEO,SAAS,WAAW,QAAsC;AAC/D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAO,GAAG,GAAG,SAAS,MAAM;AAC1B,aAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH,CAAC;AACH;",
6
+ "names": []
7
+ }
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@tamagui/cli",
3
+ "version": "1.0.1-rc.1.4",
4
+ "source": "src/index.ts",
5
+ "types": "./types/index.d.ts",
6
+ "module": "dist/esm",
7
+ "main": "dist/cjs",
8
+ "bin": {
9
+ "tama": "./dist/cjs/index.js",
10
+ "tamagui": "./dist/cjs/index.js"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "types",
18
+ "dist"
19
+ ],
20
+ "exports": {
21
+ "./package.json": "./package.json",
22
+ ".": {
23
+ "import": "./dist/esm/index.js",
24
+ "require": "./dist/cjs/index.js"
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "tamagui-build",
29
+ "watch": "tamagui-build --watch",
30
+ "clean": "tamagui-build clean",
31
+ "clean:build": "tamagui-build clean:build"
32
+ },
33
+ "dependencies": {
34
+ "@tamagui/build": "^1.0.1-rc.1.4",
35
+ "@tamagui/static": "^1.0.1-rc.1.4",
36
+ "@tamagui/vite-plugin": "^1.0.1-rc.1.4",
37
+ "@types/compression": "^1.7.2",
38
+ "@types/morgan": "^1.9.3",
39
+ "arg": "^5.0.2",
40
+ "chalk": "^4.1.2",
41
+ "chokidar": "^3.5.2",
42
+ "compression": "^1.7.4",
43
+ "esbuild": "^0.15.11",
44
+ "execa": "^5.0.0",
45
+ "express": "^4.18.1",
46
+ "express-http-proxy": "^1.6.3",
47
+ "fast-glob": "^3.2.11",
48
+ "fs-extra": "^10.1.0",
49
+ "get-port": "^6.1.2",
50
+ "graphology": "^0.24.1",
51
+ "lodash.debounce": "^4.0.8",
52
+ "morgan": "^1.10.0",
53
+ "ts-morph": "^15.1.0",
54
+ "typescript": "^4.7.4",
55
+ "url": "^0.11.0",
56
+ "vite": "4.0.0-beta.0",
57
+ "zx": "^7.1.1"
58
+ },
59
+ "devDependencies": {
60
+ "@takeout/studio": "^1.0.1-rc.1.4"
61
+ }
62
+ }
package/src/build.ts ADDED
@@ -0,0 +1,63 @@
1
+ import { basename, dirname, join, resolve } from 'path'
2
+
3
+ import { createExtractor, extractToClassNames, loadTamagui } from '@tamagui/static'
4
+ import chokidar from 'chokidar'
5
+ import { readFile } from 'fs-extra'
6
+
7
+ import { ResolvedOptions } from './types.js'
8
+
9
+ export const build = async (options: ResolvedOptions) => {
10
+ // const tamagui = await loadTamagui(options.tamaguiOptions)
11
+
12
+ const entry = options.pkgJson.source
13
+ if (!entry) {
14
+ throw new Error(`Must add "source" to package.json pointing to your source directory`)
15
+ }
16
+ const sourceDir = dirname(entry)
17
+ const promises: Promise<void>[] = []
18
+ const targets = ['web']
19
+
20
+ await new Promise<void>((res) => {
21
+ chokidar
22
+ // prevent infinite loop but cause race condition if you just build directly
23
+ .watch(sourceDir, {
24
+ // persistent: true,
25
+ })
26
+ .on('add', (relativePath) => {
27
+ const sourcePath = resolve(process.cwd(), relativePath)
28
+
29
+ // testing..
30
+ if (!sourcePath.endsWith('Layouts.tsx')) return
31
+
32
+ promises.push(
33
+ (async () => {
34
+ await Promise.all(
35
+ targets.map(async (target) => {
36
+ process.env.TAMAGUI_TARGET = target
37
+ if (options.debug) {
38
+ process.env.NODE_ENV ||= 'development'
39
+ }
40
+ console.log('go', sourcePath)
41
+ const source = await readFile(sourcePath, 'utf-8')
42
+ const extractor = createExtractor()
43
+ const out = await extractToClassNames({
44
+ extractor,
45
+ source,
46
+ sourcePath,
47
+ options: options.tamaguiOptions,
48
+ shouldPrintDebug: options.debug || false,
49
+ })
50
+
51
+ console.log('gotem', out?.js)
52
+ })
53
+ )
54
+ })()
55
+ )
56
+ })
57
+ .on('ready', () => {
58
+ res()
59
+ })
60
+ })
61
+
62
+ await Promise.all(promises)
63
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,153 @@
1
+ /* eslint-disable no-console */
2
+ import arg from 'arg'
3
+ import chalk from 'chalk'
4
+
5
+ import { getOptions } from './utils.js'
6
+
7
+ const commandMap = {
8
+ build: {
9
+ shorthands: ['b'],
10
+ description: `Use to pre-build a Tamagui component directory`,
11
+ flags: {
12
+ '--help': Boolean,
13
+ '--debug': Boolean,
14
+ '--verbose': Boolean,
15
+ },
16
+ async run() {
17
+ const { _, ...flags } = arg(this.flags)
18
+ const { build } = await import('./build.js')
19
+ const options = await getOptions({
20
+ debug: flags['--debug'] ? (flags['--verbose'] ? 'verbose' : true) : false,
21
+ })
22
+ await build(options)
23
+ },
24
+ },
25
+ }
26
+
27
+ type CommandDefinitions = typeof commandMap
28
+ type CommandKey = keyof typeof commandMap
29
+ type CommandDefinition = CommandDefinitions[CommandKey]
30
+
31
+ const commandEntries = Object.keys(commandMap).flatMap((command) => {
32
+ const definition = commandMap[command as CommandKey]
33
+ const entries = [command, ...definition.shorthands].map((cmd) => {
34
+ return [cmd, definition] as const
35
+ })
36
+ return entries
37
+ })
38
+
39
+ const commands = Object.fromEntries(commandEntries) as any as Record<CommandKey, CommandDefinition>
40
+
41
+ const {
42
+ _: [command],
43
+ ...flags
44
+ } = arg(
45
+ {
46
+ '--help': Boolean,
47
+ '--version': Boolean,
48
+ },
49
+ {
50
+ permissive: true,
51
+ }
52
+ )
53
+
54
+ if (flags['--version']) {
55
+ console.log(require('../package.json').version)
56
+ process.exit(0)
57
+ }
58
+
59
+ if (!command && flags['--help']) {
60
+ console.log(`$ tamagui
61
+
62
+ commands:
63
+
64
+ ${Object.keys(commandMap)
65
+ .map((key) => {
66
+ return ` ${key}`
67
+ })
68
+ .join('\n')}`)
69
+ process.exit(0)
70
+ }
71
+
72
+ if (!(command in commands)) {
73
+ console.error()
74
+ console.warn(chalk.yellow(`Not a valid command: ${command}`))
75
+ process.exit(1)
76
+ }
77
+
78
+ const definition = commands[command] as CommandDefinition
79
+
80
+ main()
81
+
82
+ async function main() {
83
+ if (flags['--help']) {
84
+ console.log(`\n$ tamagui ${command}: ${definition.description}\n`)
85
+ console.log(`Flags: ${Object.entries(definition.flags).map(([k, v]) => `${k} (${v.name})`)}`)
86
+ process.exit(0)
87
+ }
88
+
89
+ await definition.run()
90
+ process.exit(0)
91
+ }
92
+
93
+ // async function main() {
94
+ // const options = await getOptions({
95
+ // host: flags['--host'],
96
+ // })
97
+
98
+ // switch (command) {
99
+ // // build
100
+ // case 'b':
101
+ // case 'build': {
102
+ // const { build } = await import('./build.js')
103
+ // break
104
+ // }
105
+
106
+ // // generate
107
+ // case 'generate':
108
+ // case 'gen': {
109
+ // const { generateTamaguiConfig: generateTamgauiConfig } = await import(
110
+ // './tamaguiConfigUtils.js'
111
+ // )
112
+ // const { generateTypes } = await import('./generate.js')
113
+
114
+ // if (props[0] === 'types') {
115
+ // await generateTypes(options)
116
+ // return
117
+ // }
118
+ // if (props[0] === 'config') {
119
+ // await generateTamgauiConfig(options)
120
+ // return
121
+ // }
122
+
123
+ // await Promise.all([
124
+ // // all
125
+ // generateTypes(options),
126
+ // generateTamgauiConfig(options),
127
+ // ])
128
+ // break
129
+ // }
130
+
131
+ // // studio
132
+ // case 'studio': {
133
+ // const { studio } = await import('./studio.js')
134
+ // await studio(options)
135
+ // break
136
+ // }
137
+
138
+ // // for now, dev === serve, eventually serve can be just prod mode
139
+ // case 'dev': {
140
+ // const { dev } = await import('./dev.js')
141
+ // await dev(options)
142
+ // break
143
+ // }
144
+
145
+ // default: {
146
+ // if (!command || flags['--help']) {
147
+ // }
148
+ // // eslint-disable-next-line no-console
149
+ // console.warn(chalk.yellow(`No command found ${command}`))
150
+ // process.exit(1)
151
+ // }
152
+ // }
153
+ // }
package/src/create.ts ADDED
File without changes
package/src/dev.ts ADDED
@@ -0,0 +1,60 @@
1
+ import { AddressInfo } from 'net'
2
+
3
+ import chalk from 'chalk'
4
+ import express from 'express'
5
+ import proxy from 'express-http-proxy'
6
+ import fs from 'fs-extra'
7
+ import morgan from 'morgan'
8
+ import { createServer } from 'vite'
9
+
10
+ import { watchTamaguiConfig } from './tamaguiConfigUtils.js'
11
+ import { ResolvedOptions } from './types.js'
12
+ import { closeEvent } from './utils.js'
13
+
14
+ export const dev = async (options: ResolvedOptions) => {
15
+ const { default: getPort } = await import('get-port')
16
+ const { root, mode, paths } = options
17
+ const server = await createServer({
18
+ root,
19
+ server: {
20
+ open: true,
21
+ host: options.host,
22
+ },
23
+ })
24
+
25
+ // these can be lazy loaded (eventually should put in own process)
26
+ await Promise.all([
27
+ server.listen(),
28
+ //
29
+ watchTamaguiConfig(options),
30
+ // generateTypes(options),
31
+ ])
32
+
33
+ const info = server.httpServer?.address() as AddressInfo
34
+
35
+ const port = await getPort({
36
+ port: info.port + 1,
37
+ })
38
+
39
+ const app = express()
40
+
41
+ app.disable('x-powered-by')
42
+ app.use(express.static(paths.dotDir, { maxAge: '2h' }))
43
+ app.use(morgan('tiny'))
44
+
45
+ // studio specific - move out eventually to studioPlugin
46
+
47
+ app.get('/conf', async (req, res) => {
48
+ const conf = await fs.readJSON(paths.conf)
49
+ res.status(200).json(conf)
50
+ })
51
+
52
+ app.use('/', proxy(`${info.address}:${info.port}`))
53
+
54
+ app.listen(port)
55
+
56
+ console.log(`Listening on`, chalk.green(`http://localhost:${port}`))
57
+ server.printUrls()
58
+
59
+ await closeEvent(server)
60
+ }
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs-extra'
4
+ import { Project } from 'ts-morph'
5
+
6
+ import { ResolvedOptions } from './types.js'
7
+ import { loadTamagui } from './utils.js'
8
+
9
+ export async function generateTypes(options: ResolvedOptions) {
10
+ const types = await getTypes(options)
11
+ await fs.writeJSON(options.paths.types, types, {
12
+ spaces: 2,
13
+ })
14
+ }
15
+
16
+ export async function getTypes(options: ResolvedOptions) {
17
+ const tamagui = await loadTamagui(options.tamaguiOptions)
18
+
19
+ const uniqueViewExportingPaths = new Set(
20
+ Object.keys(tamagui.nameToPaths).map((name) => {
21
+ return `${[...tamagui.nameToPaths[name]][0]}.ts*`
22
+ })
23
+ )
24
+
25
+ const project = new Project({
26
+ compilerOptions: {
27
+ noEmit: false,
28
+ declaration: true,
29
+ emitDeclarationOnly: true,
30
+ },
31
+ skipAddingFilesFromTsConfig: true,
32
+ tsConfigFilePath: options.tsconfigPath,
33
+ })
34
+
35
+ const files = project.addSourceFilesAtPaths([...uniqueViewExportingPaths])
36
+
37
+ return Object.fromEntries(
38
+ files.flatMap((x) => {
39
+ return [...x.getExportedDeclarations()].map(([k, v]) => {
40
+ return [
41
+ k,
42
+ v[0]
43
+ .getType()
44
+ .getApparentType()
45
+ .getProperties()
46
+ .map((prop) => {
47
+ return [prop.getEscapedName(), prop.getValueDeclaration()?.getType().getText()]
48
+ }),
49
+ ]
50
+ })
51
+ })
52
+ )
53
+
54
+ // console.log(
55
+ // 'project',
56
+ // files.map((x) => x.getFilePath()),
57
+ // files.map((x) => {
58
+ // return x.getExportedDeclarations()
59
+ // }),
60
+ // Object.fromEntries(
61
+ // files.flatMap((x) => {
62
+ // return [...x.getExportedDeclarations()].map(([k, v]) => {
63
+ // return [k, v[0].getType().getApparentType().getText()]
64
+ // })
65
+ // })
66
+ // ),
67
+
68
+ // // files.map((f) => f.getExportSymbols())
69
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import './cli.js'
package/src/studio.ts ADDED
@@ -0,0 +1,69 @@
1
+ import { createRequire } from 'module'
2
+ import { AddressInfo } from 'net'
3
+ import { dirname } from 'path'
4
+
5
+ import { tamaguiPlugin } from '@tamagui/vite-plugin'
6
+ import chalk from 'chalk'
7
+ import express from 'express'
8
+ import proxy from 'express-http-proxy'
9
+ import fs from 'fs-extra'
10
+ import morgan from 'morgan'
11
+ import { createServer } from 'vite'
12
+
13
+ import { watchTamaguiConfig } from './tamaguiConfigUtils.js'
14
+ import { ResolvedOptions } from './types.js'
15
+ import { closeEvent } from './utils.js'
16
+
17
+ const resolve = 'url' in import.meta ? createRequire(import.meta.url).resolve : require.resolve
18
+
19
+ export const studio = async (options: ResolvedOptions) => {
20
+ const { default: getPort } = await import('get-port')
21
+ const { paths } = options
22
+ const root = dirname(resolve('@takeout/studio/entry'))
23
+ const server = await createServer({
24
+ root,
25
+ server: {
26
+ // open: true,
27
+ host: options.host,
28
+ },
29
+ plugins: [
30
+ tamaguiPlugin({
31
+ components: ['tamagui'],
32
+ }),
33
+ ],
34
+ })
35
+
36
+ // these can be lazy loaded (eventually should put in own process)
37
+ await Promise.all([
38
+ server.listen(),
39
+ //
40
+ watchTamaguiConfig(options),
41
+ // generateTypes(options),
42
+ ])
43
+
44
+ const info = server.httpServer?.address() as AddressInfo
45
+ console.log('devServerInfo', info)
46
+
47
+ const port = await getPort({
48
+ port: info.port + 1,
49
+ })
50
+
51
+ const app = express()
52
+
53
+ app.disable('x-powered-by')
54
+ app.use(express.static(paths.dotDir, { maxAge: '2h' }))
55
+ app.use(morgan('tiny'))
56
+
57
+ app.get('/conf', async (req, res) => {
58
+ const conf = await fs.readJSON(paths.conf)
59
+ res.status(200).json(conf)
60
+ })
61
+
62
+ app.use('/', proxy(`${info.address}:${info.port}`))
63
+
64
+ app.listen(port)
65
+
66
+ console.log(`Listening on`, chalk.green(`http://localhost:${port}`))
67
+
68
+ await closeEvent(server)
69
+ }
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { getVariableValue } from '@tamagui/core-node'
4
+ import esbuild from 'esbuild'
5
+ import fs, { ensureDir } from 'fs-extra'
6
+
7
+ import { ResolvedOptions } from './types.js'
8
+ import { loadTamagui } from './utils.js'
9
+
10
+ export async function generateTamaguiConfig(options: ResolvedOptions) {
11
+ await ensureDir(options.paths.dotDir)
12
+ const config = await getTamaguiConfig(options)
13
+ const { components, nameToPaths } = config
14
+ const { themes, tokens } = config.tamaguiConfig
15
+
16
+ // reduce down to usable, smaller json
17
+
18
+ // slim themes, add name
19
+ for (const key in themes) {
20
+ const theme = themes[key]
21
+ // @ts-ignore
22
+ theme.id = key
23
+ for (const tkey in theme) {
24
+ theme[tkey] = getVariableValue(theme[tkey])
25
+ }
26
+ }
27
+
28
+ // flatten variables
29
+ for (const key in tokens) {
30
+ const token = tokens[key]
31
+ for (const tkey in token) {
32
+ token[tkey] = getVariableValue(token[tkey])
33
+ }
34
+ }
35
+
36
+ // remove bulky stuff in components
37
+ for (const key in components) {
38
+ const component = components[key]
39
+ for (const _ in component.nameToInfo) {
40
+ delete component.nameToInfo[_].staticConfig['validStyles']
41
+ }
42
+ }
43
+
44
+ // set to array
45
+ for (const key in nameToPaths) {
46
+ // @ts-ignore
47
+ nameToPaths[key] = [...nameToPaths[key]]
48
+ }
49
+
50
+ // cleanup other stuff
51
+ // @ts-ignore
52
+ delete config.tamaguiConfig['Provider']
53
+ // @ts-ignore
54
+ delete config.tamaguiConfig['fontsParsed']
55
+ // @ts-ignore
56
+ delete config.tamaguiConfig['getCSS']
57
+ // @ts-ignore
58
+ delete config.tamaguiConfig['tokensParsed']
59
+ // @ts-ignore
60
+ delete config.tamaguiConfig['themeConfig']
61
+
62
+ await fs.writeJSON(options.paths.conf, config, {
63
+ spaces: 2,
64
+ })
65
+ }
66
+
67
+ async function getTamaguiConfig(options: ResolvedOptions) {
68
+ return loadTamagui(options.tamaguiOptions)
69
+ }
70
+
71
+ export async function watchTamaguiConfig(options: ResolvedOptions) {
72
+ if (!options.tamaguiOptions.config) return
73
+ await generateTamaguiConfig(options)
74
+ await esbuild.build({
75
+ entryPoints: [options.tamaguiOptions.config],
76
+ sourcemap: false,
77
+ // dont output just use esbuild as a watcher
78
+ write: false,
79
+ watch: {
80
+ onRebuild(err, result) {
81
+ generateTamaguiConfig(options)
82
+ },
83
+ },
84
+ })
85
+ }