@parlor/scaffold 0.0.0-stage → 0.2.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.
Files changed (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -2
  3. package/dist/add/addon.d.ts +103 -0
  4. package/dist/add/addon.d.ts.map +1 -0
  5. package/dist/add/addon.js +12 -0
  6. package/dist/add/addon.js.map +1 -0
  7. package/dist/add/plan.d.ts +72 -0
  8. package/dist/add/plan.d.ts.map +1 -0
  9. package/dist/add/plan.js +237 -0
  10. package/dist/add/plan.js.map +1 -0
  11. package/dist/add/run.d.ts +92 -0
  12. package/dist/add/run.d.ts.map +1 -0
  13. package/dist/add/run.js +167 -0
  14. package/dist/add/run.js.map +1 -0
  15. package/dist/add/transaction.d.ts +67 -0
  16. package/dist/add/transaction.d.ts.map +1 -0
  17. package/dist/add/transaction.js +181 -0
  18. package/dist/add/transaction.js.map +1 -0
  19. package/dist/addons/agent.d.ts +58 -0
  20. package/dist/addons/agent.d.ts.map +1 -0
  21. package/dist/addons/agent.js +50 -0
  22. package/dist/addons/agent.js.map +1 -0
  23. package/dist/addons/auth.d.ts +103 -0
  24. package/dist/addons/auth.d.ts.map +1 -0
  25. package/dist/addons/auth.js +93 -0
  26. package/dist/addons/auth.js.map +1 -0
  27. package/dist/addons/index.d.ts +159 -0
  28. package/dist/addons/index.d.ts.map +1 -0
  29. package/dist/addons/index.js +8 -0
  30. package/dist/addons/index.js.map +1 -0
  31. package/dist/catalog.d.ts +3 -0
  32. package/dist/catalog.d.ts.map +1 -0
  33. package/dist/catalog.js +23 -0
  34. package/dist/catalog.js.map +1 -0
  35. package/dist/create.d.ts +45 -0
  36. package/dist/create.d.ts.map +1 -0
  37. package/dist/create.js +162 -0
  38. package/dist/create.js.map +1 -0
  39. package/dist/docs.d.ts +12 -0
  40. package/dist/docs.d.ts.map +1 -0
  41. package/dist/docs.js +70 -0
  42. package/dist/docs.js.map +1 -0
  43. package/dist/edit/inspect.d.ts +15 -0
  44. package/dist/edit/inspect.d.ts.map +1 -0
  45. package/dist/edit/inspect.js +73 -0
  46. package/dist/edit/inspect.js.map +1 -0
  47. package/dist/edit/ops.d.ts +92 -0
  48. package/dist/edit/ops.d.ts.map +1 -0
  49. package/dist/edit/ops.js +516 -0
  50. package/dist/edit/ops.js.map +1 -0
  51. package/dist/edit/source.d.ts +24 -0
  52. package/dist/edit/source.d.ts.map +1 -0
  53. package/dist/edit/source.js +36 -0
  54. package/dist/edit/source.js.map +1 -0
  55. package/dist/edit/syntax.d.ts +39 -0
  56. package/dist/edit/syntax.d.ts.map +1 -0
  57. package/dist/edit/syntax.js +129 -0
  58. package/dist/edit/syntax.js.map +1 -0
  59. package/dist/errors.d.ts +5 -0
  60. package/dist/errors.d.ts.map +1 -0
  61. package/dist/errors.js +5 -0
  62. package/dist/errors.js.map +1 -0
  63. package/dist/files.d.ts +15 -0
  64. package/dist/files.d.ts.map +1 -0
  65. package/dist/files.js +65 -0
  66. package/dist/files.js.map +1 -0
  67. package/dist/fixtures.d.ts +28 -0
  68. package/dist/fixtures.d.ts.map +1 -0
  69. package/dist/fixtures.js +66 -0
  70. package/dist/fixtures.js.map +1 -0
  71. package/dist/git.d.ts +22 -0
  72. package/dist/git.d.ts.map +1 -0
  73. package/dist/git.js +56 -0
  74. package/dist/git.js.map +1 -0
  75. package/dist/identity.d.ts +9 -0
  76. package/dist/identity.d.ts.map +1 -0
  77. package/dist/identity.js +23 -0
  78. package/dist/identity.js.map +1 -0
  79. package/dist/index.d.ts +9 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +8 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/package-manager.d.ts +49 -0
  84. package/dist/package-manager.d.ts.map +1 -0
  85. package/dist/package-manager.js +118 -0
  86. package/dist/package-manager.js.map +1 -0
  87. package/dist/version.d.ts +6 -0
  88. package/dist/version.d.ts.map +1 -0
  89. package/dist/version.js +9 -0
  90. package/dist/version.js.map +1 -0
  91. package/package.json +46 -3
  92. package/templates/auth/auth.ts +19 -0
  93. package/templates/auth/schema/auth.ts +1 -0
  94. package/templates/auth/src/auth/client.ts +3 -0
  95. package/templates/auth/src/auth/sign-in-gate.tsx +17 -0
  96. package/templates/auth/src/auth/sign-out-button.tsx +17 -0
  97. package/templates/auth/src/routes/link.tsx +92 -0
  98. package/templates/auth/src/routes/sign-in.tsx +117 -0
  99. package/templates/default/_gitignore +7 -0
  100. package/templates/default/actions/index.ts +58 -0
  101. package/templates/default/actions/todos.spec.ts +38 -0
  102. package/templates/default/index.html +13 -0
  103. package/templates/default/migrations/0000_init.sql +9 -0
  104. package/templates/default/migrations/meta/0000_snapshot.json +87 -0
  105. package/templates/default/migrations/meta/_journal.json +13 -0
  106. package/templates/default/package.json +44 -0
  107. package/templates/default/parlor.config.ts +12 -0
  108. package/templates/default/schema/index.ts +1 -0
  109. package/templates/default/schema/todos.ts +13 -0
  110. package/templates/default/server.ts +13 -0
  111. package/templates/default/src/agent/agent-button.tsx +120 -0
  112. package/templates/default/src/agent/agent-sidebar.tsx +828 -0
  113. package/templates/default/src/agent/agent.css +5 -0
  114. package/templates/default/src/agent/confirmation-card.tsx +42 -0
  115. package/templates/default/src/agent/sidebar-view.ts +36 -0
  116. package/templates/default/src/agent/views.ts +9 -0
  117. package/templates/default/src/app.css +1 -0
  118. package/templates/default/src/header-actions.tsx +9 -0
  119. package/templates/default/src/main.tsx +27 -0
  120. package/templates/default/src/parlor.d.ts +9 -0
  121. package/templates/default/src/routeTree.gen.ts +59 -0
  122. package/templates/default/src/routes/__root.tsx +29 -0
  123. package/templates/default/src/routes/index.tsx +141 -0
  124. package/templates/default/tsconfig.json +8 -0
  125. package/templates/default/vitest.config.ts +5 -0
@@ -0,0 +1,103 @@
1
+ import { SERVER_ENTRY } from "../add/addon.js";
2
+ export declare const auth: {
3
+ readonly summary: "Sign-in with email and password; each user sees only their own data.";
4
+ readonly requires: {
5
+ readonly serverAtRoot: true;
6
+ readonly schemaDir: "schema";
7
+ readonly routesDir: "src/routes";
8
+ };
9
+ readonly dependencies: {
10
+ readonly "@parlor/auth": "framework";
11
+ readonly "better-auth": {
12
+ readonly fromPackage: "@parlor/auth";
13
+ readonly dependency: "better-auth";
14
+ };
15
+ };
16
+ readonly files: readonly [{
17
+ readonly template: "auth";
18
+ readonly dir: "";
19
+ }];
20
+ readonly edits: readonly [{
21
+ readonly file: typeof SERVER_ENTRY;
22
+ readonly ops: readonly [{
23
+ readonly kind: "import";
24
+ readonly names: readonly ["createAuth"];
25
+ readonly from: "./auth.js";
26
+ }, {
27
+ readonly kind: "set-property";
28
+ readonly call: {
29
+ readonly callee: "createServer";
30
+ readonly from: "@parlor/server";
31
+ };
32
+ readonly path: readonly ["auth"];
33
+ readonly value: "createAuth($database)";
34
+ readonly onConflict: "unsafe";
35
+ }];
36
+ }, {
37
+ readonly file: "schema/index.ts";
38
+ readonly ops: readonly [{
39
+ readonly kind: "export-all";
40
+ readonly from: "./auth.js";
41
+ }];
42
+ }, {
43
+ readonly file: "src/main.tsx";
44
+ readonly ops: readonly [{
45
+ readonly kind: "import";
46
+ readonly names: readonly ["auth"];
47
+ readonly from: "./auth/client.js";
48
+ }, {
49
+ readonly kind: "set-property";
50
+ readonly call: {
51
+ readonly callee: "createActionClient";
52
+ readonly from: "@parlor/client";
53
+ };
54
+ readonly path: readonly ["headers"];
55
+ readonly value: "auth.headers";
56
+ readonly onConflict: "unsafe";
57
+ }, {
58
+ readonly kind: "jsx-attribute";
59
+ readonly element: "FrameworkProvider";
60
+ readonly name: "auth";
61
+ readonly value: "{auth}";
62
+ }];
63
+ }, {
64
+ readonly file: "src/routes/__root.tsx";
65
+ readonly ops: readonly [{
66
+ readonly kind: "import";
67
+ readonly names: readonly ["withSignIn"];
68
+ readonly from: "../auth/sign-in-gate.js";
69
+ }, {
70
+ readonly kind: "wrap-property";
71
+ readonly call: import("../edit/syntax.js").CallSite;
72
+ readonly path: readonly ["component"];
73
+ readonly wrapper: "withSignIn";
74
+ }];
75
+ }];
76
+ readonly mounts: readonly [{
77
+ readonly component: "SignOutButton";
78
+ readonly module: "src/auth/sign-out-button.tsx";
79
+ readonly into: {
80
+ readonly file: "src/header-actions.tsx";
81
+ readonly parent: "HeaderActions";
82
+ };
83
+ }];
84
+ readonly env: readonly [{
85
+ readonly name: "PARLOR_ORIGIN";
86
+ readonly example: "https://your-app.example.com";
87
+ readonly description: "The public origin the app is served from. `parlor dev` sets it for you.";
88
+ }, {
89
+ readonly name: "BETTER_AUTH_SECRET";
90
+ readonly example: "";
91
+ readonly description: "Signs sessions in production. Generate one with: openssl rand -base64 32";
92
+ }];
93
+ readonly generate: readonly [{
94
+ readonly kind: "route-tree";
95
+ readonly routes: readonly ["/sign-in", "/link"];
96
+ }, {
97
+ readonly kind: "migration";
98
+ readonly name: "auth";
99
+ readonly tables: readonly ["user", "session", "account", "verification"];
100
+ }];
101
+ readonly notes: readonly ["Rows created before sign-in belong to the scope \"default\", which no signed-in user sees.", "The sidebar now connects agents with `npx @parlor/agent-host connect`, shown in the sidebar.", "In production set PARLOR_ORIGIN and BETTER_AUTH_SECRET; see .env.example."];
102
+ };
103
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/addons/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAExE,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Ff,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { defineAddon, ROOT_ROUTE, SERVER_ENTRY } from "../add/addon.js";
2
+ export const auth = defineAddon({
3
+ summary: "Sign-in with email and password; each user sees only their own data.",
4
+ requires: { serverAtRoot: true, schemaDir: "schema", routesDir: "src/routes" },
5
+ dependencies: {
6
+ "@parlor/auth": "framework",
7
+ "better-auth": { fromPackage: "@parlor/auth", dependency: "better-auth" },
8
+ },
9
+ files: [{ template: "auth", dir: "" }],
10
+ edits: [
11
+ {
12
+ file: SERVER_ENTRY,
13
+ ops: [
14
+ { kind: "import", names: ["createAuth"], from: "./auth.js" },
15
+ {
16
+ kind: "set-property",
17
+ call: { callee: "createServer", from: "@parlor/server" },
18
+ path: ["auth"],
19
+ value: "createAuth($database)",
20
+ onConflict: "unsafe",
21
+ },
22
+ ],
23
+ },
24
+ {
25
+ file: "schema/index.ts",
26
+ ops: [{ kind: "export-all", from: "./auth.js" }],
27
+ },
28
+ {
29
+ file: "src/main.tsx",
30
+ ops: [
31
+ { kind: "import", names: ["auth"], from: "./auth/client.js" },
32
+ {
33
+ kind: "set-property",
34
+ call: { callee: "createActionClient", from: "@parlor/client" },
35
+ path: ["headers"],
36
+ value: "auth.headers",
37
+ onConflict: "unsafe",
38
+ },
39
+ {
40
+ kind: "jsx-attribute",
41
+ element: "FrameworkProvider",
42
+ name: "auth",
43
+ value: "{auth}",
44
+ },
45
+ ],
46
+ },
47
+ {
48
+ file: "src/routes/__root.tsx",
49
+ ops: [
50
+ { kind: "import", names: ["withSignIn"], from: "../auth/sign-in-gate.js" },
51
+ {
52
+ kind: "wrap-property",
53
+ call: ROOT_ROUTE,
54
+ path: ["component"],
55
+ wrapper: "withSignIn",
56
+ },
57
+ ],
58
+ },
59
+ ],
60
+ mounts: [
61
+ {
62
+ component: "SignOutButton",
63
+ module: "src/auth/sign-out-button.tsx",
64
+ into: { file: "src/header-actions.tsx", parent: "HeaderActions" },
65
+ },
66
+ ],
67
+ env: [
68
+ {
69
+ name: "PARLOR_ORIGIN",
70
+ example: "https://your-app.example.com",
71
+ description: "The public origin the app is served from. `parlor dev` sets it for you.",
72
+ },
73
+ {
74
+ name: "BETTER_AUTH_SECRET",
75
+ example: "",
76
+ description: "Signs sessions in production. Generate one with: openssl rand -base64 32",
77
+ },
78
+ ],
79
+ generate: [
80
+ { kind: "route-tree", routes: ["/sign-in", "/link"] },
81
+ {
82
+ kind: "migration",
83
+ name: "auth",
84
+ tables: ["user", "session", "account", "verification"],
85
+ },
86
+ ],
87
+ notes: [
88
+ 'Rows created before sign-in belong to the scope "default", which no signed-in user sees.',
89
+ "The sidebar now connects agents with `npx @parlor/agent-host connect`, shown in the sidebar.",
90
+ "In production set PARLOR_ORIGIN and BETTER_AUTH_SECRET; see .env.example.",
91
+ ],
92
+ });
93
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/addons/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAddon, ROOT_ROUTE, SERVER_ENTRY } from \"../add/addon.js\";\n\nexport const auth = defineAddon({\n summary: \"Sign-in with email and password; each user sees only their own data.\",\n requires: { serverAtRoot: true, schemaDir: \"schema\", routesDir: \"src/routes\" },\n dependencies: {\n \"@parlor/auth\": \"framework\",\n \"better-auth\": { fromPackage: \"@parlor/auth\", dependency: \"better-auth\" },\n },\n files: [{ template: \"auth\", dir: \"\" }],\n edits: [\n {\n file: SERVER_ENTRY,\n ops: [\n { kind: \"import\", names: [\"createAuth\"], from: \"./auth.js\" },\n {\n kind: \"set-property\",\n call: { callee: \"createServer\", from: \"@parlor/server\" },\n path: [\"auth\"],\n value: \"createAuth($database)\",\n onConflict: \"unsafe\",\n },\n ],\n },\n {\n file: \"schema/index.ts\",\n ops: [{ kind: \"export-all\", from: \"./auth.js\" }],\n },\n {\n file: \"src/main.tsx\",\n ops: [\n { kind: \"import\", names: [\"auth\"], from: \"./auth/client.js\" },\n {\n kind: \"set-property\",\n call: { callee: \"createActionClient\", from: \"@parlor/client\" },\n path: [\"headers\"],\n value: \"auth.headers\",\n onConflict: \"unsafe\",\n },\n {\n kind: \"jsx-attribute\",\n element: \"FrameworkProvider\",\n name: \"auth\",\n value: \"{auth}\",\n },\n ],\n },\n {\n file: \"src/routes/__root.tsx\",\n ops: [\n { kind: \"import\", names: [\"withSignIn\"], from: \"../auth/sign-in-gate.js\" },\n {\n kind: \"wrap-property\",\n call: ROOT_ROUTE,\n path: [\"component\"],\n wrapper: \"withSignIn\",\n },\n ],\n },\n ],\n mounts: [\n {\n component: \"SignOutButton\",\n module: \"src/auth/sign-out-button.tsx\",\n into: { file: \"src/header-actions.tsx\", parent: \"HeaderActions\" },\n },\n ],\n env: [\n {\n name: \"PARLOR_ORIGIN\",\n example: \"https://your-app.example.com\",\n description:\n \"The public origin the app is served from. `parlor dev` sets it for you.\",\n },\n {\n name: \"BETTER_AUTH_SECRET\",\n example: \"\",\n description:\n \"Signs sessions in production. Generate one with: openssl rand -base64 32\",\n },\n ],\n generate: [\n { kind: \"route-tree\", routes: [\"/sign-in\", \"/link\"] },\n {\n kind: \"migration\",\n name: \"auth\",\n tables: [\"user\", \"session\", \"account\", \"verification\"],\n },\n ],\n notes: [\n 'Rows created before sign-in belong to the scope \"default\", which no signed-in user sees.',\n \"The sidebar now connects agents with `npx @parlor/agent-host connect`, shown in the sidebar.\",\n \"In production set PARLOR_ORIGIN and BETTER_AUTH_SECRET; see .env.example.\",\n ],\n});\n"]}
@@ -0,0 +1,159 @@
1
+ export declare const ADDONS: {
2
+ readonly agent: {
3
+ readonly summary: "The agent sidebar: chat with your own coding agent inside the app.";
4
+ readonly requires: {
5
+ readonly routesDir: "src/routes";
6
+ };
7
+ readonly dependencies: {
8
+ readonly "@parlor/chat": "framework";
9
+ };
10
+ readonly files: readonly [{
11
+ readonly template: "default";
12
+ readonly dir: "src/agent";
13
+ }];
14
+ readonly edits: readonly [{
15
+ readonly file: typeof import("../add/addon.js").SERVER_ENTRY;
16
+ readonly ops: readonly [{
17
+ readonly kind: "import";
18
+ readonly names: readonly ["chat"];
19
+ readonly from: "@parlor/chat/server";
20
+ }, {
21
+ readonly kind: "append-element";
22
+ readonly call: {
23
+ readonly callee: "createServer";
24
+ readonly from: "@parlor/server";
25
+ };
26
+ readonly path: readonly ["plugins"];
27
+ readonly element: "chat()";
28
+ }];
29
+ }, {
30
+ readonly file: "src/routes/__root.tsx";
31
+ readonly ops: readonly [{
32
+ readonly kind: "import";
33
+ readonly names: readonly ["agentPanel"];
34
+ readonly from: "../agent/views.js";
35
+ }, {
36
+ readonly kind: "append-element";
37
+ readonly call: import("../edit/syntax.js").CallSite;
38
+ readonly path: readonly ["staticData", "views"];
39
+ readonly element: "agentPanel";
40
+ }];
41
+ }];
42
+ readonly mounts: readonly [{
43
+ readonly component: "AgentButton";
44
+ readonly module: "src/agent/agent-button.tsx";
45
+ readonly into: {
46
+ readonly file: "src/header-actions.tsx";
47
+ readonly parent: "HeaderActions";
48
+ };
49
+ }];
50
+ readonly env: readonly [];
51
+ readonly generate: readonly [];
52
+ readonly notes: readonly ["Restart the dev server. Open the Agent button to chat with the coding agents on this computer."];
53
+ };
54
+ readonly auth: {
55
+ readonly summary: "Sign-in with email and password; each user sees only their own data.";
56
+ readonly requires: {
57
+ readonly serverAtRoot: true;
58
+ readonly schemaDir: "schema";
59
+ readonly routesDir: "src/routes";
60
+ };
61
+ readonly dependencies: {
62
+ readonly "@parlor/auth": "framework";
63
+ readonly "better-auth": {
64
+ readonly fromPackage: "@parlor/auth";
65
+ readonly dependency: "better-auth";
66
+ };
67
+ };
68
+ readonly files: readonly [{
69
+ readonly template: "auth";
70
+ readonly dir: "";
71
+ }];
72
+ readonly edits: readonly [{
73
+ readonly file: typeof import("../add/addon.js").SERVER_ENTRY;
74
+ readonly ops: readonly [{
75
+ readonly kind: "import";
76
+ readonly names: readonly ["createAuth"];
77
+ readonly from: "./auth.js";
78
+ }, {
79
+ readonly kind: "set-property";
80
+ readonly call: {
81
+ readonly callee: "createServer";
82
+ readonly from: "@parlor/server";
83
+ };
84
+ readonly path: readonly ["auth"];
85
+ readonly value: "createAuth($database)";
86
+ readonly onConflict: "unsafe";
87
+ }];
88
+ }, {
89
+ readonly file: "schema/index.ts";
90
+ readonly ops: readonly [{
91
+ readonly kind: "export-all";
92
+ readonly from: "./auth.js";
93
+ }];
94
+ }, {
95
+ readonly file: "src/main.tsx";
96
+ readonly ops: readonly [{
97
+ readonly kind: "import";
98
+ readonly names: readonly ["auth"];
99
+ readonly from: "./auth/client.js";
100
+ }, {
101
+ readonly kind: "set-property";
102
+ readonly call: {
103
+ readonly callee: "createActionClient";
104
+ readonly from: "@parlor/client";
105
+ };
106
+ readonly path: readonly ["headers"];
107
+ readonly value: "auth.headers";
108
+ readonly onConflict: "unsafe";
109
+ }, {
110
+ readonly kind: "jsx-attribute";
111
+ readonly element: "FrameworkProvider";
112
+ readonly name: "auth";
113
+ readonly value: "{auth}";
114
+ }];
115
+ }, {
116
+ readonly file: "src/routes/__root.tsx";
117
+ readonly ops: readonly [{
118
+ readonly kind: "import";
119
+ readonly names: readonly ["withSignIn"];
120
+ readonly from: "../auth/sign-in-gate.js";
121
+ }, {
122
+ readonly kind: "wrap-property";
123
+ readonly call: import("../edit/syntax.js").CallSite;
124
+ readonly path: readonly ["component"];
125
+ readonly wrapper: "withSignIn";
126
+ }];
127
+ }];
128
+ readonly mounts: readonly [{
129
+ readonly component: "SignOutButton";
130
+ readonly module: "src/auth/sign-out-button.tsx";
131
+ readonly into: {
132
+ readonly file: "src/header-actions.tsx";
133
+ readonly parent: "HeaderActions";
134
+ };
135
+ }];
136
+ readonly env: readonly [{
137
+ readonly name: "PARLOR_ORIGIN";
138
+ readonly example: "https://your-app.example.com";
139
+ readonly description: "The public origin the app is served from. `parlor dev` sets it for you.";
140
+ }, {
141
+ readonly name: "BETTER_AUTH_SECRET";
142
+ readonly example: "";
143
+ readonly description: "Signs sessions in production. Generate one with: openssl rand -base64 32";
144
+ }];
145
+ readonly generate: readonly [{
146
+ readonly kind: "route-tree";
147
+ readonly routes: readonly ["/sign-in", "/link"];
148
+ }, {
149
+ readonly kind: "migration";
150
+ readonly name: "auth";
151
+ readonly tables: readonly ["user", "session", "account", "verification"];
152
+ }];
153
+ readonly notes: readonly ["Rows created before sign-in belong to the scope \"default\", which no signed-in user sees.", "The sidebar now connects agents with `npx @parlor/agent-host connect`, shown in the sidebar.", "In production set PARLOR_ORIGIN and BETTER_AUTH_SECRET; see .env.example."];
154
+ };
155
+ };
156
+ export type AddonName = keyof typeof ADDONS;
157
+ export declare const ADDON_NAMES: readonly AddonName[];
158
+ export declare function isAddonName(name: string): name is AddonName;
159
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/addons/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAA2B,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,MAAM,CAAC;AAE5C,eAAO,MAAM,WAAW,EAA0B,SAAS,SAAS,EAAE,CAAC;AAEvE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,SAAS,CAE3D"}
@@ -0,0 +1,8 @@
1
+ import { agent } from "./agent.js";
2
+ import { auth } from "./auth.js";
3
+ export const ADDONS = { agent, auth };
4
+ export const ADDON_NAMES = Object.keys(ADDONS);
5
+ export function isAddonName(name) {
6
+ return Object.hasOwn(ADDONS, name);
7
+ }
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/addons/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,EAAW,CAAC;AAI/C,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAyB,CAAC;AAEvE,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { agent } from \"./agent.js\";\nimport { auth } from \"./auth.js\";\n\nexport const ADDONS = { agent, auth } as const;\n\nexport type AddonName = keyof typeof ADDONS;\n\nexport const ADDON_NAMES = Object.keys(ADDONS) as readonly AddonName[];\n\nexport function isAddonName(name: string): name is AddonName {\n return Object.hasOwn(ADDONS, name);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ /** Generated from the `catalog` in the repo's `pnpm-workspace.yaml` by `scripts/write-catalog.ts`; `catalog.spec.ts` fails when they differ. */
2
+ export declare const CATALOG: Readonly<Record<string, string>>;
3
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,gJAAgJ;AAChJ,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoBpD,CAAC"}
@@ -0,0 +1,23 @@
1
+ /** Generated from the `catalog` in the repo's `pnpm-workspace.yaml` by `scripts/write-catalog.ts`; `catalog.spec.ts` fails when they differ. */
2
+ export const CATALOG = {
3
+ "@standard-schema/spec": "^1.1.0",
4
+ "@tanstack/react-query": "^5.104.1",
5
+ "@tanstack/react-router": "^1.170.45",
6
+ "@tanstack/router-core": "^1.171.38",
7
+ "@tanstack/router-generator": "^1.167.45",
8
+ "@tanstack/router-plugin": "^1.168.47",
9
+ "@testing-library/react": "^16.3.3",
10
+ "@types/node": "^24.14.0",
11
+ "@types/react": "^19.3.0",
12
+ "@types/react-dom": "^19.3.0",
13
+ "@vitejs/plugin-react": "^6.1.2",
14
+ h3: "^2.0.1",
15
+ "happy-dom": "^20.14.5",
16
+ react: "^19.3.0",
17
+ "react-dom": "^19.3.0",
18
+ typescript: "^7.0.2",
19
+ vite: "^8.3.5",
20
+ vitest: "^5.0.3",
21
+ zod: "^4.6.5",
22
+ };
23
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,gJAAgJ;AAChJ,MAAM,CAAC,MAAM,OAAO,GAAqC;IACvD,uBAAuB,EAAE,QAAQ;IACjC,uBAAuB,EAAE,UAAU;IACnC,wBAAwB,EAAE,WAAW;IACrC,uBAAuB,EAAE,WAAW;IACpC,4BAA4B,EAAE,WAAW;IACzC,yBAAyB,EAAE,WAAW;IACtC,wBAAwB,EAAE,SAAS;IACnC,aAAa,EAAE,UAAU;IACzB,cAAc,EAAE,SAAS;IACzB,kBAAkB,EAAE,SAAS;IAC7B,sBAAsB,EAAE,QAAQ;IAChC,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,UAAU;IACvB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,SAAS;IACtB,UAAU,EAAE,QAAQ;IACpB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,QAAQ;CACd,CAAC","sourcesContent":["/** Generated from the `catalog` in the repo's `pnpm-workspace.yaml` by `scripts/write-catalog.ts`; `catalog.spec.ts` fails when they differ. */\nexport const CATALOG: Readonly<Record<string, string>> = {\n \"@standard-schema/spec\": \"^1.1.0\",\n \"@tanstack/react-query\": \"^5.104.1\",\n \"@tanstack/react-router\": \"^1.170.45\",\n \"@tanstack/router-core\": \"^1.171.38\",\n \"@tanstack/router-generator\": \"^1.167.45\",\n \"@tanstack/router-plugin\": \"^1.168.47\",\n \"@testing-library/react\": \"^16.3.3\",\n \"@types/node\": \"^24.14.0\",\n \"@types/react\": \"^19.3.0\",\n \"@types/react-dom\": \"^19.3.0\",\n \"@vitejs/plugin-react\": \"^6.1.2\",\n h3: \"^2.0.1\",\n \"happy-dom\": \"^20.14.5\",\n react: \"^19.3.0\",\n \"react-dom\": \"^19.3.0\",\n typescript: \"^7.0.2\",\n vite: \"^8.3.5\",\n vitest: \"^5.0.3\",\n zod: \"^4.6.5\",\n};\n"]}
@@ -0,0 +1,45 @@
1
+ import type { AddonName } from "./addons/index.js";
2
+ import { type Op } from "./edit/ops.js";
3
+ import { type TemplateFiles } from "./files.js";
4
+ import { type GitOutcome } from "./git.js";
5
+ import { type AppIdentity } from "./identity.js";
6
+ import { type InstallOutcome, type PackageManager } from "./package-manager.js";
7
+ export interface CreateOptions {
8
+ readonly directory: string;
9
+ readonly packageManager: PackageManager;
10
+ readonly mode: "apply" | "dry-run";
11
+ readonly install: boolean;
12
+ readonly git: boolean;
13
+ /** Run through the project's own CLI after a successful install, so create needs no toolchain. */
14
+ readonly addons: readonly AddonName[];
15
+ readonly log: (line: string) => void;
16
+ }
17
+ export interface CreatedProject {
18
+ readonly directory: string;
19
+ readonly identity: AppIdentity;
20
+ readonly packageManager: PackageManager;
21
+ readonly files: readonly string[];
22
+ readonly install: InstallOutcome | {
23
+ readonly kind: "skipped";
24
+ };
25
+ readonly addons: {
26
+ readonly applied: readonly AddonName[];
27
+ /** Still to run as `<pm> exec parlor add <name>`; the next steps print the command. */
28
+ readonly deferred: readonly AddonName[];
29
+ };
30
+ readonly git: GitOutcome | {
31
+ readonly kind: "disabled";
32
+ };
33
+ }
34
+ export declare const CREATE_SAFE_ENTRIES: ReadonlySet<string>;
35
+ /**
36
+ * The default template's `parlor.config.ts` names itself; create renames it through the same
37
+ * edit engine `parlor add` uses, so the template stays a plain project with no placeholders.
38
+ */
39
+ export declare function identityOps(identity: AppIdentity): readonly Op[];
40
+ export declare function renderProject(identity: AppIdentity, packageManager: PackageManager, templates: TemplateFiles, version?: string): Promise<ReadonlyMap<string, string>>;
41
+ /** `catalog:` takes the range the framework was published with, so the project resolves one zod and one React. */
42
+ export declare function rewritePackageJson(text: string, identity: AppIdentity, packageManager: PackageManager, version: string): string;
43
+ /** Install and git failures are reported, never thrown: the files are already a working project. */
44
+ export declare function createProject(options: CreateOptions): Promise<CreatedProject>;
45
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAGnD,OAAO,EAAc,KAAK,EAAE,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,KAAK,aAAa,EAA6B,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,KAAK,UAAU,EAAiB,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,eAAe,CAAC;AAC9D,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,cAAc,EAIpB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;IAChE,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;QACvC,uFAAuF;QACvF,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;KACzC,CAAC;IACF,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC;CAC1D;AAED,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CASlD,CAAC;AAIH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,EAAE,EAAE,CAkBhE;AAcD,wBAAsB,aAAa,CACjC,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,aAAa,EACxB,OAAO,GAAE,MAA0B,GAClC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBtC;AAYD,kHAAkH;AAClH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,MAAM,GACd,MAAM,CA8BR;AAeD,oGAAoG;AACpG,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CA0BnF"}
package/dist/create.js ADDED
@@ -0,0 +1,162 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdir, readdir } from "node:fs/promises";
3
+ import { basename } from "node:path";
4
+ import { CATALOG } from "./catalog.js";
5
+ import { renderAgentsMd, renderReadme } from "./docs.js";
6
+ import { editSource } from "./edit/ops.js";
7
+ import { parseSource } from "./edit/source.js";
8
+ import { CreateError } from "./errors.js";
9
+ import { templateFiles, writeFiles } from "./files.js";
10
+ import { initialCommit } from "./git.js";
11
+ import { identityFor } from "./identity.js";
12
+ import { commandsFor, execCommand, packageManagerField, packageManagerFiles, runInstall, } from "./package-manager.js";
13
+ import { FRAMEWORK_VERSION } from "./version.js";
14
+ export const CREATE_SAFE_ENTRIES = new Set([
15
+ ".git",
16
+ ".DS_Store",
17
+ ".idea",
18
+ ".vscode",
19
+ ".claude",
20
+ ".cursor",
21
+ "LICENSE",
22
+ "Thumbs.db",
23
+ ]);
24
+ const DEFAULT_TEMPLATE = "default";
25
+ /**
26
+ * The default template's `parlor.config.ts` names itself; create renames it through the same
27
+ * edit engine `parlor add` uses, so the template stays a plain project with no placeholders.
28
+ */
29
+ export function identityOps(identity) {
30
+ const call = { callee: "defineConfig", from: "@parlor/config" };
31
+ return [
32
+ {
33
+ kind: "set-property",
34
+ call,
35
+ path: ["app", "id"],
36
+ value: JSON.stringify(identity.appId),
37
+ onConflict: "replace",
38
+ },
39
+ {
40
+ kind: "set-property",
41
+ call,
42
+ path: ["app", "name"],
43
+ value: JSON.stringify(identity.appName),
44
+ onConflict: "replace",
45
+ },
46
+ ];
47
+ }
48
+ const CONFIG_FILE = "parlor.config.ts";
49
+ function renameApp(text, identity) {
50
+ const outcome = editSource(parseSource(CONFIG_FILE, text), identityOps(identity));
51
+ if (outcome.status === "unsafe") {
52
+ throw new Error(`The default template's ${CONFIG_FILE} cannot be renamed: ${outcome.unsafe.map((entry) => entry.reason).join(" ")}`);
53
+ }
54
+ return outcome.status === "edit" ? outcome.text : text;
55
+ }
56
+ export async function renderProject(identity, packageManager, templates, version = FRAMEWORK_VERSION) {
57
+ const files = new Map();
58
+ for (const path of await templates.list(DEFAULT_TEMPLATE, "")) {
59
+ const text = await templates.read(DEFAULT_TEMPLATE, path);
60
+ files.set(path, path === "package.json"
61
+ ? rewritePackageJson(text, identity, packageManager, version)
62
+ : path === CONFIG_FILE
63
+ ? renameApp(text, identity)
64
+ : text);
65
+ }
66
+ const docs = { identity, packageManager, version };
67
+ files.set("README.md", renderReadme(docs));
68
+ files.set("AGENTS.md", renderAgentsMd(docs));
69
+ for (const [path, text] of packageManagerFiles(packageManager))
70
+ files.set(path, text);
71
+ return new Map([...files].sort(([a], [b]) => a.localeCompare(b)));
72
+ }
73
+ const UNINSTALLABLE = /^(?:workspace|catalog|link|file|portal):/;
74
+ /** `catalog:` takes the range the framework was published with, so the project resolves one zod and one React. */
75
+ export function rewritePackageJson(text, identity, packageManager, version) {
76
+ const manifest = JSON.parse(text);
77
+ const resolve = (dependencies) => Object.fromEntries(Object.entries(dependencies).map(([name, range]) => {
78
+ const resolved = range.startsWith("workspace:")
79
+ ? version
80
+ : range === "catalog:"
81
+ ? (CATALOG[name] ?? range)
82
+ : range;
83
+ if (UNINSTALLABLE.test(resolved)) {
84
+ throw new Error(`${name}@${range} cannot be installed outside the Parlor repo.`);
85
+ }
86
+ return [name, resolved];
87
+ }));
88
+ const field = packageManagerField(packageManager);
89
+ const { name: _name, packageManager: _manager, ...rest } = manifest;
90
+ const rewritten = {
91
+ name: identity.packageName,
92
+ ...rest,
93
+ ...(field ? { packageManager: field } : {}),
94
+ ...(manifest.dependencies ? { dependencies: resolve(manifest.dependencies) } : {}),
95
+ ...(manifest.devDependencies
96
+ ? { devDependencies: resolve(manifest.devDependencies) }
97
+ : {}),
98
+ };
99
+ return `${JSON.stringify(rewritten, null, 2)}\n`;
100
+ }
101
+ async function checkTarget(directory) {
102
+ const entries = await readdir(directory).catch((error) => {
103
+ if (error.code === "ENOENT")
104
+ return [];
105
+ throw error;
106
+ });
107
+ const blocking = entries.filter((entry) => !CREATE_SAFE_ENTRIES.has(entry)).sort();
108
+ if (blocking.length > 0) {
109
+ throw new CreateError(`${basename(directory)} is not empty (${blocking.join(", ")}). Pick a new folder name.`);
110
+ }
111
+ }
112
+ /** Install and git failures are reported, never thrown: the files are already a working project. */
113
+ export async function createProject(options) {
114
+ const { directory, packageManager } = options;
115
+ await checkTarget(directory);
116
+ const identity = identityFor(basename(directory));
117
+ const files = await renderProject(identity, packageManager, templateFiles());
118
+ const result = {
119
+ directory,
120
+ identity,
121
+ packageManager,
122
+ files: [...files.keys()],
123
+ install: { kind: "skipped" },
124
+ addons: { applied: [], deferred: options.addons },
125
+ git: { kind: "disabled" },
126
+ };
127
+ if (options.mode === "dry-run")
128
+ return result;
129
+ await mkdir(directory, { recursive: true });
130
+ await writeFiles(directory, files);
131
+ const install = options.install
132
+ ? await runInstall(directory, commandsFor(packageManager).install, options.log)
133
+ : result.install;
134
+ const addons = install.kind === "installed" || install.kind === "ignored-builds"
135
+ ? await applyAddons(directory, packageManager, options.addons)
136
+ : result.addons;
137
+ const git = options.git ? await initialCommit(directory) : result.git;
138
+ return { ...result, install, addons, git };
139
+ }
140
+ /** `--no-git-check`: the files are about to be committed as one, so they are untracked now. */
141
+ async function applyAddons(directory, packageManager, addons) {
142
+ const applied = [];
143
+ const deferred = [];
144
+ for (const addon of addons) {
145
+ const command = execCommand(packageManager, "parlor", [
146
+ "add",
147
+ addon,
148
+ "--no-git-check",
149
+ ]);
150
+ const code = await new Promise((resolve) => {
151
+ const child = spawn(command.bin, command.args, {
152
+ cwd: directory,
153
+ stdio: "inherit",
154
+ });
155
+ child.once("error", () => resolve(null));
156
+ child.once("close", resolve);
157
+ });
158
+ (code === 0 ? applied : deferred).push(addon);
159
+ }
160
+ return { applied, deferred };
161
+ }
162
+ //# sourceMappingURL=create.js.map