Skip to content

Commit eeb1e64

Browse files
committed
Add AI scaffolding script and corresponding make commands
1 parent 91763a3 commit eeb1e64

File tree

5 files changed

+348
-0
lines changed

5 files changed

+348
-0
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#!/usr/bin/env bash
2+
#
3+
# @license Apache-2.0
4+
#
5+
# Copyright (c) 2022 The Stdlib Authors.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
# Script for scaffolding a package based off a README.md file via AI.
20+
#
21+
# Usage: scaffold.h
22+
#
23+
# Environment Variables:
24+
#
25+
# STDLIB_SCAFFOLDING_API_KEY: API key for the AI service.
26+
27+
## USER-DEFINED VARIABLES ##
28+
29+
# Use supplied package path:
30+
pkg=${1}
31+
32+
33+
## COMPUTED VARIABLES ##
34+
35+
# Determine the root project directory:
36+
root_dir="$(git rev-parse --show-toplevel)"
37+
38+
# Define the project source code directory:
39+
base_dir="${root_dir}/lib/node_modules"
40+
41+
# Define the destination path:
42+
dest_dir="${base_dir}/@stdlib/${pkg}"
43+
44+
# Azure stdlib scaffolding API endpoint:
45+
endpoint="https://stdlib-scaffolding.azurewebsites.net/api"
46+
47+
# Get git user email:
48+
git_email="$(git config --global user.email)"
49+
50+
# `README.md` of the package to scaffold:
51+
readme="${dest_dir}/README.md"
52+
53+
54+
# FUNCTIONS #
55+
56+
# Make a request to the Azure stdlib scaffolding API and write the response to a file.
57+
#
58+
# $1 - file path (e.g., 'examples/index.js')
59+
# $2 - JSON request body
60+
function scaffold_request() {
61+
echo "Scaffolding file: ${1}..."
62+
63+
# Get function name from file path:
64+
func_name=$(echo "$1" | sed 's/[\/.]/-/g')
65+
66+
# Authentication query string:
67+
auth="clientId=${git_email}&code=${STDLIB_SCAFFOLDING_API_KEY}"
68+
69+
# Endpoint URL:
70+
url="${endpoint}/${func_name}?${auth}"
71+
72+
# Make a request to the Azure stdlib scaffolding API:
73+
response=$(curl -s -X POST -H "Content-Type: application/json" -d "$2" "${url}")
74+
75+
# Create the file directory if it does not exist yet:
76+
mkdir -p ${dest_dir}/$(dirname "$1")
77+
78+
# Write the response to the respective file:
79+
echo "$response" > ${dest_dir}/"$1"
80+
}
81+
82+
# MAIN #
83+
84+
# Main execution sequence.
85+
main() {
86+
if [ -z "${pkg}" ]; then
87+
echo "Error: must provide a package name." >&2
88+
exit 1
89+
fi
90+
echo '' >&2
91+
echo "Scaffolding package: ${pkg}" >&2
92+
echo '' >&2
93+
94+
# `README.md` contents:
95+
readme_file=$(cat ${readme} | jq -Rs)
96+
97+
# JSON payload for the API:
98+
README='{"readme": '$readme_file'}'
99+
100+
# Bail if the destination directory does not exist:
101+
if [ ! -d "${dest_dir}" ]; then
102+
echo "Destination directory does not exist: ${dest_dir}" >&2
103+
exit 1
104+
fi
105+
106+
# Bail if the README.md file does not exist:
107+
if [ ! -f "${readme}" ]; then
108+
echo "README.md file does not exist: ${readme}" >&2
109+
exit 1
110+
fi
111+
112+
# Check whether authentication key is set:
113+
if [ -z "${STDLIB_SCAFFOLDING_API_KEY}" ]; then
114+
echo "Error: missing environment variable 'STDLIB_SCAFFOLDING_API_KEY'." >&2
115+
exit 1
116+
fi
117+
118+
if [[ ! -f "${dest_dir}/package.json" ]]; then
119+
scaffold_request "package.json" "$README"
120+
fi
121+
if [[ ! -f "${dest_dir}/examples/index.js" ]]; then
122+
scaffold_request "examples/index.js" "$README"
123+
fi
124+
if [[ ! -f "${dest_dir}/lib/index.js" ]]; then
125+
scaffold_request "lib/index.js" "$README"
126+
fi
127+
if [[ ! -f "${dest_dir}/lib/main.js" ]]; then
128+
scaffold_request "lib/main.js" "$README"
129+
fi
130+
if [[ ! -f "${dest_dir}/test/test.js" ]]; then
131+
scaffold_request "test/test.js" "$README"
132+
fi
133+
if [[ ! -f "${dest_dir}/docs/repl.txt" ]]; then
134+
scaffold_request "docs/repl.txt" "$README"
135+
fi
136+
jsdoc_file=$(cat ${dest_dir}/lib/main.js | jq -Rs)
137+
JSDOC='{"jsdoc": '$jsdoc_file'}'
138+
if [[ ! -f "${dest_dir}/benchmark/benchmark.js" ]]; then
139+
scaffold_request "benchmark/benchmark.js" "$JSDOC"
140+
fi
141+
if [[ ! -f "${dest_dir}/docs/types/index.d.ts" ]]; then
142+
scaffold_request "docs/types/index.d.ts" "$JSDOC"
143+
fi
144+
if [[ ! -f "${dest_dir}/docs/types/test.ts" ]]; then
145+
ts_file=$(cat ${dest_dir}/lib/main.js | jq -Rs)
146+
TYPESCRIPT='{"typescript": '$ts_file'}'
147+
scaffold_request "docs/types/test.ts" "$TYPESCRIPT"
148+
fi
149+
if grep -q "## CLI" "${readme}"; then
150+
echo "CLI detected. Scaffold CLI package contents."
151+
if [[ ! -f "${dest_dir}/bin/cli" ]]; then
152+
scaffold_request "bin/cli" "$README"
153+
fi
154+
if [[ ! -f "${dest_dir}/docs/usage.txt" ]]; then
155+
scaffold_request "docs/usage.txt" "$README"
156+
fi
157+
if [[ ! -f "${dest_dir}/etc/cli_opts.json" ]]; then
158+
scaffold_request "etc/cli_opts.json" "$README"
159+
fi
160+
if [[ ! -f "${dest_dir}/test/test.cli.js" ]]; then
161+
scaffold_request "test/test.cli.js" "$README"
162+
fi
163+
if [[ ! -f "${dest_dir}/test/fixtures/stdin_error.js.txt" ]]; then
164+
mkdir -p ${dest_dir}/test/fixtures
165+
curl -s "${endpoint}/test-fixtures-stdlib-error-js-txt" > ${dest_dir}/test/fixtures/stdin_error.js.txt
166+
fi
167+
fi
168+
if grep -q "\`\`\`c" "${readme}"; then
169+
echo "C API detected. Scaffold C package contents via AI."
170+
if [[ ! -f "${dest_dir}/binding.gyp" ]]; then
171+
curl -s "${endpoint}/binding-gyp" > ${dest_dir}/binding.gyp
172+
fi
173+
if [[ ! -f "${dest_dir}/include.gypi" ]]; then
174+
curl -s "${endpoint}/include-gypi" > ${dest_dir}/include.gypi
175+
fi
176+
if [[ ! -f "${dest_dir}/benchmark/benchmark.native.js" ]]; then
177+
benchmark_file=$(cat ${dest_dir}/benchmark/benchmark.js | jq -Rs)
178+
BENCHMARK='{"benchmark": '$benchmark_file'}'
179+
scaffold_request "benchmark/benchmark.native.js" "$BENCHMARK"
180+
fi
181+
if [[ ! -f "${dest_dir}/benchmark/c/benchmark.c" ]]; then
182+
scaffold_request "benchmark/c/benchmark.c" "$README"
183+
fi
184+
if [[ ! -f "${dest_dir}/benchmark/c/Makefile" ]]; then
185+
curl -s "${endpoint}/benchmark-c-makefile" > ${dest_dir}/benchmark/c/Makefile
186+
fi
187+
if [[ ! -f "${dest_dir}/examples/c/example.c" ]]; then
188+
scaffold_request "examples/c/example.c" "$README"
189+
fi
190+
if [[ ! -f "${dest_dir}/examples/c/Makefile" ]]; then
191+
curl -s "${endpoint}/examples-c-makefile" > ${dest_dir}/examples/c/Makefile
192+
fi
193+
main_file=$(cat ${dest_dir}/lib/main.js | jq -Rs)
194+
MAIN='{"main": '$main_file'}'
195+
if [[ ! -f "${dest_dir}/lib/native.js" ]]; then
196+
scaffold_request "lib/native.js" "$MAIN"
197+
fi
198+
if [[ ! -f "${dest_dir}/src/main.c" ]]; then
199+
scaffold_request "src/main.c" "$MAIN"
200+
fi
201+
if [[ ! -f "${dest_dir}/src/addon.c" ]]; then
202+
scaffold_request "src/addon.c" "$MAIN"
203+
fi
204+
if [[ ! -f "${dest_dir}/src/Makefile" ]]; then
205+
curl -s "${endpoint}/src-makefile" > ${dest_dir}/src/Makefile
206+
fi
207+
if [[ ! -f "${dest_dir}/test/test.native.js" ]]; then
208+
test_file=$(cat ${dest_dir}/test/test.js | jq -Rs)
209+
TEST='{"test": '$test_file'}'
210+
scaffold_request "test/test.native.js" "$TEST"
211+
fi
212+
fi
213+
echo 'Successfully scaffolded package.' >&2
214+
echo '' >&2
215+
exit 0
216+
}
217+
218+
# Run main:
219+
main

tools/make/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ include $(TOOLS_MAKE_LIB_DIR)/ls/Makefile
8888
include $(TOOLS_MAKE_LIB_DIR)/markdown/Makefile
8989
include $(TOOLS_MAKE_LIB_DIR)/notes/Makefile
9090
include $(TOOLS_MAKE_LIB_DIR)/repl/Makefile
91+
include $(TOOLS_MAKE_LIB_DIR)/scaffold/Makefile
9192
include $(TOOLS_MAKE_LIB_DIR)/stats/Makefile
9293
include $(TOOLS_MAKE_LIB_DIR)/test/Makefile
9394
include $(TOOLS_MAKE_LIB_DIR)/test-browsers/Makefile

tools/make/common.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,3 +600,6 @@ DEPS_CPPCHECK_BUILD_OUT ?= $(DEPS_BUILD_DIR)/cppcheck_$(deps_cppcheck_version_sl
600600

601601
# Host platform:
602602
DEPS_CPPCHECK_PLATFORM := $(shell command -v $(NODE) >/dev/null 2>&1 && $(NODE_HOST_PLATFORM))
603+
604+
# API key for the stdlib scaffolding service:
605+
STDLIB_SCAFFOLDING_API_KEY ?= $$STDLIB_SCAFFOLDING_API_KEY

tools/make/lib/scaffold/Makefile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#/
2+
# @license Apache-2.0
3+
#
4+
# Copyright (c) 2022 The Stdlib Authors.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#/
18+
19+
# VARIABLES #
20+
21+
# Define the script to be executed:
22+
SCAFFOLD_SCRIPT ?= $(TOOLS_PKGS_DIR)/scaffold/scripts/scaffold_ai.sh
23+
24+
25+
# RULES #
26+
27+
#/
28+
# Scaffolds required files for a new or existing package.
29+
#
30+
# ## Notes
31+
#
32+
# - The package directory has to exist and must contain at least the package's `README.md` file for the command to work.
33+
#
34+
# @param {string} PKG - package to scaffold (e.g., `math/base/special/sin`)
35+
# @param {string} STDLIB_SCAFFOLDING_API_KEY - API key for accessing the stdlib scaffolding service
36+
#
37+
# @example
38+
# make scaffold PKG=math/base/special/sin
39+
#/
40+
scaffold:
41+
$(QUIET) $(STDLIB_SCAFFOLDING_API_KEY) $(SCAFFOLD_SCRIPT) $(PKG)
42+
43+
.PHONY: scaffold

tools/make/lib/scaffold/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2022 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# Scaffolding
22+
23+
> Package scaffolding commands.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
This directory contains [`make`][make] rules for scaffolding package files.
30+
31+
</section>
32+
33+
<!-- /.intro -->
34+
35+
<!-- Usage documentation. -->
36+
37+
<section class="usage">
38+
39+
## Usage
40+
41+
```text
42+
Usage: make <command> [<ENV_VAR>=<value> <ENV_VAR>=<value> ...]
43+
```
44+
45+
### Commands
46+
47+
#### scaffold
48+
49+
Scaffold required files for a new or existing package. The package directory has to exist and must contain at least the package's `README.md` file for the command to work.
50+
51+
<!-- run-disable -->
52+
53+
```bash
54+
$ make scaffold PKG=<pkg>
55+
```
56+
57+
The command expects the following environment variables to be set:
58+
59+
- **PKG**: package to scaffold, e.g., `math/base/special/sin`.
60+
- **STDLIB_SCAFFOLDING_API_KEY**: API key for accessing the stdlib scaffolding service.
61+
62+
</section>
63+
64+
<!-- /.usage -->
65+
66+
<!-- Section to include notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
67+
68+
<section class="notes">
69+
70+
</section>
71+
72+
<!-- /.notes -->
73+
74+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
75+
76+
<section class="links">
77+
78+
[make]: https://www.gnu.org/software/make/
79+
80+
</section>
81+
82+
<!-- /.links -->

0 commit comments

Comments
 (0)