@tscircuit/cli 0.0.59 → 0.0.60

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.
@@ -9,6 +9,11 @@ export default withEdgeSpec({
9
9
  export_name: z.string().nullable().optional(),
10
10
  export_parameters: z.object({
11
11
  should_export_gerber_zip: z.boolean().default(false),
12
+ gerbers_zip_file_name: z
13
+ .string()
14
+ .nullable()
15
+ .optional()
16
+ .default("gerbers.zip"),
12
17
  }),
13
18
  }),
14
19
  jsonResponse: z.object({
Binary file
@@ -16,6 +16,7 @@
16
16
  "update-deps": "bun add @tscircuit/pcb-viewer @tscircuit/builder @tscircuit/schematic-viewer"
17
17
  },
18
18
  "dependencies": {
19
+ "@headlessui/react": "^1.7.18",
19
20
  "@radix-ui/react-alert-dialog": "^1.0.5",
20
21
  "@radix-ui/react-context-menu": "^2.1.5",
21
22
  "@radix-ui/react-dialog": "^1.0.5",
@@ -17,6 +17,7 @@ import toast from "react-hot-toast"
17
17
  import { useGlobalStore } from "./hooks/use-global-store"
18
18
  import packageJson from "../package.json"
19
19
  import cliPackageJson from "../../package.json"
20
+ import { useGerberExportDialog } from "./components/dialogs/gerber-export-dialog"
20
21
 
21
22
  export const HeaderMenu = () => {
22
23
  const [viewMode, setViewMode] = useGlobalStore((s) => [
@@ -28,209 +29,212 @@ export const HeaderMenu = () => {
28
29
  s.setSplitMode,
29
30
  ])
30
31
  const [inDebugMode, setInDebugMode] = useState(false)
32
+ const gerberExportDialog = useGerberExportDialog()
31
33
 
32
34
  return (
33
- <Menubar className="border-none shadow-none">
34
- <MenubarMenu>
35
- <MenubarTrigger>File</MenubarTrigger>
36
- <MenubarContent>
37
- <MenubarItem disabled>seveibar/arduino@1.0.0</MenubarItem>
38
- <MenubarSeparator />
39
- <MenubarItem
40
- onSelect={() => {
41
- toast.error("Not yet implemented!")
42
- }}
43
- >
44
- New Circuit
45
- </MenubarItem>
46
- <MenubarSeparator />
47
- <MenubarSub>
48
- <MenubarSubTrigger>Export</MenubarSubTrigger>
49
- <MenubarSubContent>
50
- <MenubarItem
51
- onSelect={() => {
52
- toast.error("Not yet implemented!")
53
- }}
54
- >
55
- Gerbers
56
- </MenubarItem>
57
- <MenubarItem
58
- onSelect={() => {
59
- toast.error("Not yet implemented!")
60
- }}
61
- >
62
- Bill of Materials
63
- </MenubarItem>
64
- <MenubarItem
65
- onSelect={() => {
66
- toast.error("Not yet implemented!")
67
- }}
35
+ <>
36
+ <Menubar className="border-none shadow-none">
37
+ <MenubarMenu>
38
+ <MenubarTrigger>File</MenubarTrigger>
39
+ <MenubarContent>
40
+ <MenubarItem disabled>seveibar/arduino@1.0.0</MenubarItem>
41
+ <MenubarSeparator />
42
+ <MenubarItem
43
+ onSelect={() => {
44
+ toast.error("Not yet implemented!")
45
+ }}
46
+ >
47
+ New Circuit
48
+ </MenubarItem>
49
+ <MenubarSeparator />
50
+ <MenubarSub>
51
+ <MenubarSubTrigger>Export</MenubarSubTrigger>
52
+ <MenubarSubContent>
53
+ <MenubarItem onSelect={() => gerberExportDialog.openDialog()}>
54
+ Gerbers
55
+ </MenubarItem>
56
+ <MenubarItem
57
+ onSelect={() => {
58
+ toast.error("Not yet implemented!")
59
+ }}
60
+ >
61
+ Bill of Materials
62
+ </MenubarItem>
63
+ <MenubarItem
64
+ onSelect={() => {
65
+ toast.error("Not yet implemented!")
66
+ }}
67
+ >
68
+ Netlist
69
+ </MenubarItem>
70
+ <MenubarItem
71
+ onSelect={() => {
72
+ toast.error("Not yet implemented!")
73
+ }}
74
+ >
75
+ Schematic (PDF)
76
+ </MenubarItem>
77
+ </MenubarSubContent>
78
+ </MenubarSub>
79
+ </MenubarContent>
80
+ </MenubarMenu>
81
+ <MenubarMenu>
82
+ <MenubarTrigger>View</MenubarTrigger>
83
+ <MenubarContent>
84
+ <MenubarRadioGroup
85
+ value={viewMode}
86
+ onValueChange={(v) => setViewMode(v as any)}
87
+ >
88
+ <MenubarRadioItem value="schematic">Schematic</MenubarRadioItem>
89
+ <MenubarRadioItem value="pcb">PCB</MenubarRadioItem>
90
+ <MenubarRadioItem value="split">Split View</MenubarRadioItem>
91
+ </MenubarRadioGroup>
92
+ <MenubarSeparator />
93
+ <MenubarRadioGroup
94
+ value={viewMode === "split" ? splitMode : "neither"}
95
+ onValueChange={(v) => setSplitMode(v as any)}
96
+ >
97
+ <MenubarRadioItem
98
+ disabled={viewMode !== "split"}
99
+ value="horizontal"
68
100
  >
69
- Netlist
70
- </MenubarItem>
71
- <MenubarItem
72
- onSelect={() => {
73
- toast.error("Not yet implemented!")
74
- }}
101
+ Horizontal Split
102
+ </MenubarRadioItem>
103
+ <MenubarRadioItem
104
+ disabled={viewMode !== "split"}
105
+ value="vertical"
75
106
  >
76
- Schematic (PDF)
77
- </MenubarItem>
78
- </MenubarSubContent>
79
- </MenubarSub>
80
- </MenubarContent>
81
- </MenubarMenu>
82
- <MenubarMenu>
83
- <MenubarTrigger>View</MenubarTrigger>
84
- <MenubarContent>
85
- <MenubarRadioGroup
86
- value={viewMode}
87
- onValueChange={(v) => setViewMode(v as any)}
88
- >
89
- <MenubarRadioItem value="schematic">Schematic</MenubarRadioItem>
90
- <MenubarRadioItem value="pcb">PCB</MenubarRadioItem>
91
- <MenubarRadioItem value="split">Split View</MenubarRadioItem>
92
- </MenubarRadioGroup>
93
- <MenubarSeparator />
94
- <MenubarRadioGroup
95
- value={viewMode === "split" ? splitMode : "neither"}
96
- onValueChange={(v) => setSplitMode(v as any)}
97
- >
98
- <MenubarRadioItem
99
- disabled={viewMode !== "split"}
100
- value="horizontal"
107
+ Vertical Split
108
+ </MenubarRadioItem>
109
+ </MenubarRadioGroup>
110
+ <MenubarSeparator />
111
+ <MenubarCheckboxItem
112
+ checked={inDebugMode}
113
+ onSelect={() => setInDebugMode(!inDebugMode)}
114
+ >
115
+ Debug Mode
116
+ </MenubarCheckboxItem>
117
+ </MenubarContent>
118
+ </MenubarMenu>
119
+ <MenubarMenu>
120
+ <MenubarTrigger>Package</MenubarTrigger>
121
+ <MenubarContent>
122
+ <MenubarItem disabled>seveibar/arduino@1.0.0</MenubarItem>
123
+ <MenubarSeparator />
124
+ <MenubarCheckboxItem
125
+ checked
126
+ onSelect={() => toast.error("Not yet implemented!")}
127
+ >
128
+ Published
129
+ </MenubarCheckboxItem>
130
+ <MenubarCheckboxItem
131
+ onSelect={() => toast.error("Not yet implemented!")}
132
+ >
133
+ Locked
134
+ </MenubarCheckboxItem>
135
+ <MenubarItem onSelect={() => toast.error("Not yet implemented!")}>
136
+ Publish New Version
137
+ </MenubarItem>
138
+ <MenubarSeparator />
139
+ <MenubarItem
140
+ onSelect={() => {
141
+ toast.error("Not yet implemented!")
142
+ // window.open(`https://registry.tscircuit.com/${}`)
143
+ }}
144
+ >
145
+ View on Registry
146
+ </MenubarItem>
147
+ <MenubarItem
148
+ onSelect={() => {
149
+ toast.error("Not yet implemented!")
150
+ // window.open(`https://registry.tscircuit.com/${}`)
151
+ }}
152
+ >
153
+ Edit Registry Settings
154
+ </MenubarItem>
155
+ </MenubarContent>
156
+ </MenubarMenu>
157
+ <MenubarMenu>
158
+ <MenubarTrigger>About</MenubarTrigger>
159
+ <MenubarContent>
160
+ <MenubarItem
161
+ onSelect={() => {
162
+ window.open("https://github.com/tscircuit/tscircuit", "_blank")
163
+ }}
164
+ >
165
+ Github
166
+ </MenubarItem>
167
+ <MenubarItem
168
+ onSelect={() => {
169
+ toast.error("Not yet implemented!")
170
+ }}
171
+ >
172
+ Tutorials
173
+ </MenubarItem>
174
+ <MenubarItem
175
+ onSelect={() => {
176
+ toast.error("Not yet implemented!")
177
+ }}
178
+ >
179
+ tscircuit.com
180
+ </MenubarItem>
181
+ <MenubarItem
182
+ onSelect={() => {
183
+ toast.error("Not yet implemented!")
184
+ }}
185
+ >
186
+ registry.tscircuit.com
187
+ </MenubarItem>
188
+ <MenubarItem
189
+ onSelect={() => {
190
+ window.open("https://tscircuit.com/changelog", "_blank")
191
+ }}
101
192
  >
102
- Horizontal Split
103
- </MenubarRadioItem>
104
- <MenubarRadioItem disabled={viewMode !== "split"} value="vertical">
105
- Vertical Split
106
- </MenubarRadioItem>
107
- </MenubarRadioGroup>
108
- <MenubarSeparator />
109
- <MenubarCheckboxItem
110
- checked={inDebugMode}
111
- onSelect={() => setInDebugMode(!inDebugMode)}
112
- >
113
- Debug Mode
114
- </MenubarCheckboxItem>
115
- </MenubarContent>
116
- </MenubarMenu>
117
- <MenubarMenu>
118
- <MenubarTrigger>Package</MenubarTrigger>
119
- <MenubarContent>
120
- <MenubarItem disabled>seveibar/arduino@1.0.0</MenubarItem>
121
- <MenubarSeparator />
122
- <MenubarCheckboxItem
123
- checked
124
- onSelect={() => toast.error("Not yet implemented!")}
125
- >
126
- Published
127
- </MenubarCheckboxItem>
128
- <MenubarCheckboxItem
129
- onSelect={() => toast.error("Not yet implemented!")}
130
- >
131
- Locked
132
- </MenubarCheckboxItem>
133
- <MenubarItem onSelect={() => toast.error("Not yet implemented!")}>
134
- Publish New Version
135
- </MenubarItem>
136
- <MenubarSeparator />
137
- <MenubarItem
138
- onSelect={() => {
139
- toast.error("Not yet implemented!")
140
- // window.open(`https://registry.tscircuit.com/${}`)
141
- }}
142
- >
143
- View on Registry
144
- </MenubarItem>
145
- <MenubarItem
146
- onSelect={() => {
147
- toast.error("Not yet implemented!")
148
- // window.open(`https://registry.tscircuit.com/${}`)
149
- }}
150
- >
151
- Edit Registry Settings
152
- </MenubarItem>
153
- </MenubarContent>
154
- </MenubarMenu>
155
- <MenubarMenu>
156
- <MenubarTrigger>About</MenubarTrigger>
157
- <MenubarContent>
158
- <MenubarItem
159
- onSelect={() => {
160
- window.open("https://github.com/tscircuit/tscircuit", "_blank")
161
- }}
162
- >
163
- Github
164
- </MenubarItem>
165
- <MenubarItem
166
- onSelect={() => {
167
- toast.error("Not yet implemented!")
168
- }}
169
- >
170
- Tutorials
171
- </MenubarItem>
172
- <MenubarItem
173
- onSelect={() => {
174
- toast.error("Not yet implemented!")
175
- }}
176
- >
177
- tscircuit.com
178
- </MenubarItem>
179
- <MenubarItem
180
- onSelect={() => {
181
- toast.error("Not yet implemented!")
182
- }}
183
- >
184
- registry.tscircuit.com
185
- </MenubarItem>
186
- <MenubarItem
187
- onSelect={() => {
188
- window.open("https://tscircuit.com/changelog", "_blank")
189
- }}
190
- >
191
- Changelog
192
- </MenubarItem>
193
- <MenubarSeparator />
194
- <MenubarItem disabled>
195
- @tscircuit/cli v{cliPackageJson.version}
196
- </MenubarItem>
197
- <MenubarItem disabled>
198
- @tscircuit/builder (cli) v
199
- {cliPackageJson.dependencies?.["@tscircuit/builder"]?.replace(
200
- /\^/g,
201
- ""
202
- )}
203
- </MenubarItem>
204
- <MenubarItem disabled>
205
- @tscircuit/builder (ui) v
206
- {packageJson.dependencies?.["@tscircuit/builder"]?.replace(
207
- /\^/g,
208
- ""
209
- )}
210
- </MenubarItem>
211
- <MenubarItem disabled>
212
- @tscircuit/react-fiber v
213
- {cliPackageJson.dependencies["@tscircuit/react-fiber"].replace(
214
- /\^/g,
215
- ""
216
- )}
217
- </MenubarItem>
218
- <MenubarItem disabled>
219
- @tscircuit/schematic-viewer v
220
- {packageJson.dependencies["@tscircuit/schematic-viewer"].replace(
221
- /\^/g,
222
- ""
223
- )}
224
- </MenubarItem>
225
- <MenubarItem disabled>
226
- @tscircuit/pcb-viewer v
227
- {packageJson.dependencies["@tscircuit/pcb-viewer"].replace(
228
- /\^/g,
229
- ""
230
- )}
231
- </MenubarItem>
232
- </MenubarContent>
233
- </MenubarMenu>
234
- </Menubar>
193
+ Changelog
194
+ </MenubarItem>
195
+ <MenubarSeparator />
196
+ <MenubarItem disabled>
197
+ @tscircuit/cli v{cliPackageJson.version}
198
+ </MenubarItem>
199
+ <MenubarItem disabled>
200
+ @tscircuit/builder (cli) v
201
+ {cliPackageJson.dependencies?.["@tscircuit/builder"]?.replace(
202
+ /\^/g,
203
+ ""
204
+ )}
205
+ </MenubarItem>
206
+ <MenubarItem disabled>
207
+ @tscircuit/builder (ui) v
208
+ {packageJson.dependencies?.["@tscircuit/builder"]?.replace(
209
+ /\^/g,
210
+ ""
211
+ )}
212
+ </MenubarItem>
213
+ <MenubarItem disabled>
214
+ @tscircuit/react-fiber v
215
+ {cliPackageJson.dependencies["@tscircuit/react-fiber"].replace(
216
+ /\^/g,
217
+ ""
218
+ )}
219
+ </MenubarItem>
220
+ <MenubarItem disabled>
221
+ @tscircuit/schematic-viewer v
222
+ {packageJson.dependencies["@tscircuit/schematic-viewer"].replace(
223
+ /\^/g,
224
+ ""
225
+ )}
226
+ </MenubarItem>
227
+ <MenubarItem disabled>
228
+ @tscircuit/pcb-viewer v
229
+ {packageJson.dependencies["@tscircuit/pcb-viewer"].replace(
230
+ /\^/g,
231
+ ""
232
+ )}
233
+ </MenubarItem>
234
+ </MenubarContent>
235
+ </MenubarMenu>
236
+ </Menubar>
237
+ {<gerberExportDialog.Component />}
238
+ </>
235
239
  )
236
240
  }
@@ -9,7 +9,7 @@ import {
9
9
  CommandShortcut,
10
10
  } from "./ui/command"
11
11
  import { useGlobalStore } from "src/hooks/use-global-store"
12
- import { useDevPackageExamples } from "./select-example-search"
12
+ import { useDevPackageExamples } from "../hooks/use-dev-package-examples"
13
13
  import { CommandSeparator } from "cmdk"
14
14
 
15
15
  export const CommandK = () => {
@@ -0,0 +1,131 @@
1
+ import { useMemo, useState } from "react"
2
+ import { Dialog } from "@headlessui/react"
3
+ import { useGlobalStore } from "src/hooks/use-global-store"
4
+ import { useActiveDevPackageExampleLite } from "src/hooks/use-active-dev-package-example-lite"
5
+ import { Button } from "../ui/button"
6
+ import axios from "axios"
7
+
8
+ export const useGerberExportDialog = () => {
9
+ const [open, setIsOpen] = useState(false)
10
+ const activeDevExamplePackage = useActiveDevPackageExampleLite()
11
+ const [isExporting, setIsExporting] = useState(false)
12
+ const [exportError, setExportError] = useState<string | null>(null)
13
+
14
+ return useMemo(() => {
15
+ const openDialog = () => {
16
+ setIsOpen(true)
17
+ }
18
+ const closeDialog = () => {
19
+ setIsOpen(false)
20
+ setIsExporting(false)
21
+ }
22
+ if (!activeDevExamplePackage)
23
+ return {
24
+ openDialog,
25
+ closeDialog,
26
+ Component: () => null,
27
+ }
28
+ const { file_path, export_name } = activeDevExamplePackage
29
+ const outputName = `${
30
+ file_path.split("/").pop()?.split(".")[0]
31
+ }-${export_name}-gerbers.zip`
32
+
33
+ return {
34
+ openDialog,
35
+ closeDialog,
36
+ Component: () => (
37
+ <GerberExportDialog
38
+ open={open}
39
+ isExporting={isExporting}
40
+ filePath={file_path}
41
+ exportName={export_name}
42
+ outputName={outputName}
43
+ exportError={exportError}
44
+ onClickExport={async () => {
45
+ setExportError(null)
46
+ setIsExporting(true)
47
+ try {
48
+ await axios.post("/api/export_requests/create", {
49
+ example_file_path: activeDevExamplePackage.file_path,
50
+ export_name: activeDevExamplePackage.export_name,
51
+ export_parameters: {
52
+ should_export_gerber_zip: true,
53
+ gerbers_zip_file_name: outputName,
54
+ },
55
+ })
56
+ } catch (e: any) {
57
+ console.error(e)
58
+ setExportError(
59
+ `${e.toString()}\n\n${e.response?.data?.error?.message}`
60
+ )
61
+ setIsExporting(false)
62
+ }
63
+ }}
64
+ onClose={() => closeDialog()}
65
+ />
66
+ ),
67
+ }
68
+ }, [open, isExporting, exportError])
69
+ }
70
+
71
+ export const GerberExportDialog = ({
72
+ open,
73
+ isExporting,
74
+ filePath,
75
+ exportName,
76
+ outputName,
77
+ exportError,
78
+ onClose,
79
+ onClickExport,
80
+ }: {
81
+ open: boolean
82
+ filePath: string
83
+ exportName: string
84
+ isExporting: boolean
85
+ outputName: string
86
+ exportError?: string | null
87
+ onClose: (value: boolean) => void
88
+ onClickExport: () => any
89
+ }) => {
90
+ return (
91
+ <Dialog open={open} onClose={onClose} className="relative z-50">
92
+ <div className="fixed inset-0 bg-black/30" aria-hidden="true" />
93
+ <div className="fixed inset-0 flex w-screen items-center justify-center p-4">
94
+ <Dialog.Panel className="w-full max-w-lg rounded bg-white p-6 border border-[rgba(0,0,0,0.3)]">
95
+ <Dialog.Title className="text-lg font-semibold tracking-tight text-black">
96
+ Export Gerbers
97
+ </Dialog.Title>
98
+ <Dialog.Description className="text-sm font-medium text-muted-foreground">
99
+ Export your PCB design to Gerber files.
100
+ </Dialog.Description>
101
+ {exportError && (
102
+ <div className="text-red-700 bg-red-100 border-red-200 border whitespace-pre-wrap font-mono text-xs p-4 mt-8">
103
+ {exportError}
104
+ </div>
105
+ )}
106
+ <div className="text-xs font-medium grid grid-cols-4 font-mono mt-8 gap-4">
107
+ <div className="text-muted-foreground font-sans">Status</div>
108
+ <div className="col-span-3 text-muted-foreground font-sans">
109
+ {isExporting ? "Exporting" : "Not Started"}
110
+ </div>
111
+ <div className="text-muted-foreground font-sans">File Path</div>
112
+ <div className="col-span-3">{filePath.split("/examples/")[1]}</div>
113
+ <div className="text-muted-foreground font-sans">Export Name</div>
114
+ <div className="col-span-3">{exportName}</div>
115
+ <div className="text-muted-foreground font-sans">Output Name</div>
116
+ <div className="col-span-3">{outputName}</div>
117
+ </div>
118
+ <div className="flex mt-8 justify-end">
119
+ <Button
120
+ variant={isExporting ? "ghost" : "default"}
121
+ disabled={isExporting}
122
+ onClick={onClickExport}
123
+ >
124
+ {isExporting ? `Exporting...` : `Export`}
125
+ </Button>
126
+ </div>
127
+ </Dialog.Panel>
128
+ </div>
129
+ </Dialog>
130
+ )
131
+ }
@@ -2,8 +2,6 @@
2
2
 
3
3
  import * as React from "react"
4
4
  import { CaretSortIcon, CheckIcon } from "@radix-ui/react-icons"
5
- import { useQuery } from "react-query"
6
- import axios from "axios"
7
5
 
8
6
  import { cn } from "src/lib/utils"
9
7
  import { Button } from "src/components/ui/button"
@@ -22,22 +20,10 @@ import {
22
20
  PopoverTrigger,
23
21
  } from "src/components/ui/popover"
24
22
  import { useGlobalStore } from "src/hooks/use-global-store"
23
+ import { useDevPackageExamples } from "../hooks/use-dev-package-examples"
24
+ import { useActiveDevPackageExampleLite } from "src/hooks/use-active-dev-package-example-lite"
25
25
 
26
- export const useDevPackageExamples = () => {
27
- return useQuery("examples", async () => {
28
- const { data } = await axios.get("/api/dev_package_examples/list")
29
- return data.dev_package_examples.map(inflatePackageExample) as Array<{
30
- dev_package_example_id: number
31
- searchable_id: string
32
- file_path: string
33
- expath: string
34
- export_name: string
35
- last_updated_at: string
36
- }>
37
- })
38
- }
39
-
40
- function inflatePackageExample(ex: any) {
26
+ export function inflatePackageExample(ex: any) {
41
27
  if (!ex) return ex
42
28
  return {
43
29
  ...ex,
@@ -57,12 +43,7 @@ export const SelectExampleSearch = () => {
57
43
  s.setActiveDevExamplePackageId,
58
44
  ])
59
45
 
60
- const activeDevExamplePackage = inflatePackageExample(
61
- examples?.find(
62
- (ex) =>
63
- ex.dev_package_example_id.toString() === active_dev_example_package_id
64
- )
65
- )
46
+ const activeDevExamplePackage = useActiveDevPackageExampleLite()
66
47
 
67
48
  React.useEffect(() => {
68
49
  const down = (e: KeyboardEvent) => {
@@ -0,0 +1,39 @@
1
+ import { useDevPackageExamples } from "./use-dev-package-examples"
2
+ import { useGlobalStore } from "./use-global-store"
3
+
4
+ export function inflatePackageExample(ex: any): {
5
+ dev_package_example_id: number
6
+ searchable_id: string
7
+ file_path: string
8
+ expath: string
9
+ export_name: string
10
+ last_updated_at: string
11
+ } {
12
+ if (!ex) return ex
13
+ return {
14
+ ...ex,
15
+ expath: ex.file_path.replace(/.*examples\//, ""),
16
+ searchable_id: `${ex.file_path.replace(/.*examples\//, "")} | ${
17
+ ex.export_name
18
+ }`,
19
+ }
20
+ }
21
+
22
+ export const useActiveDevPackageExampleLite = () => {
23
+ const { data: examples } = useDevPackageExamples()
24
+
25
+ const [active_dev_example_package_id, setActiveDevExamplePackageId] =
26
+ useGlobalStore((s) => [
27
+ s.active_dev_example_package_id,
28
+ s.setActiveDevExamplePackageId,
29
+ ])
30
+
31
+ const activeDevExamplePackage = inflatePackageExample(
32
+ examples?.find(
33
+ (ex) =>
34
+ ex.dev_package_example_id.toString() === active_dev_example_package_id
35
+ )
36
+ )
37
+
38
+ return activeDevExamplePackage
39
+ }